Пример #1
0
    def _get_docker_volume(self, docker_volume_name):
        search_opts = {
            'name': docker_volume_name,
            'metadata': {
                consts.VOLUME_FROM: CONF.volume_from
            }
        }
        try:
            docker_shares = self.manilaclient.shares.list(
                search_opts=search_opts)
        except manila_exception.ClientException as e:
            LOG.error("Could not retrieve Manila share list. Error: %s", e)
            raise

        if not docker_shares:
            raise exceptions.NotFound("Could not find share with "
                                      "search_opts: {0}".format(search_opts))
        elif len(docker_shares) > 1:
            raise exceptions.TooManyResources(
                "Find too many shares with search_opts: {0}, while "
                "for Fuxi, should get only one share with provided "
                "search_opts".format(docker_shares))

        docker_share = docker_shares[0]
        if self.connector.check_access_allowed(docker_share):
            return docker_share, ATTACH_TO_THIS
        else:
            return docker_share, NOT_ATTACH
Пример #2
0
    def show(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume {0} {1} with state "
                     "{2}").format(docker_volume_name, cinder_volume, state))

        if state == ATTACH_TO_THIS:
            devpath = os.path.realpath(
                self._get_connector().get_device_path(cinder_volume))
            mp = self._get_mountpoint(docker_volume_name)
            LOG.info("Expected devpath: {0} and mountpoint: {1} for volume: "
                     "{2} {3}".format(devpath, mp, docker_volume_name,
                                      cinder_volume))
            mounter = mount.Mounter()
            return {"Name": docker_volume_name,
                    "Mountpoint": mp if mp in mounter.get_mps_by_device(
                        	      devpath) else ''}
        elif state in (NOT_ATTACH, ATTACH_TO_OTHER):
            return {'Name': docker_volume_name, 'Mountpoint': ''}
        elif state == UNKNOWN:
            msg = _LW("Can't find this volume '{0}' in "
                      "OpenSDS").format(docker_volume_name)
            LOG.warning(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _LE("Volume '{0}' exists, but not attached to this volume,"
                      "and current state is {1}").format(docker_volume_name,
                                                         state)
            raise exceptions.NotMatchedState(msg)
Пример #3
0
    def test_check_exist(self):
        with mock.patch('fuxi.volumeprovider.manila.Manila._get_docker_volume',
                        side_effect=exceptions.NotFound()):
            self.assertFalse(self.provider.check_exist('fake-vol'))

        with mock.patch.object(manila.Manila,
                               '_get_docker_volume',
                               return_value=(fake_object.FakeManilaShare(),
                                             consts.ATTACH_TO_THIS)):
            self.assertTrue(self.provider.check_exist('fake-vol'))
Пример #4
0
    def test_volumedriver_get_with_volume_not_exist(self):
        self.volume_providers_setup(['cinder'])
        fake_docker_volume_name = u'test-vol'
        fake_request = {u'Name': fake_docker_volume_name}
        for provider in app.volume_providers.values():
            provider.show = mock.MagicMock(side_effect=exceptions.NotFound())

        response = self.app.post('/VolumeDriver.Get',
                                 content_type='application/json',
                                 data=jsonutils.dumps(fake_request))
        fake_response = {u'Err': u'Volume Not Found'}
        self.assertEqual(200, response.status_code)
        self.assertEqual(fake_response, jsonutils.loads(response.data))
Пример #5
0
    def show(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume %(d_v)s %(vol)s with state %(st)s"), {
            'd_v': docker_volume_name,
            'vol': cinder_volume,
            'st': state
        })

        if state == ATTACH_TO_THIS:
            devpath = os.path.realpath(
                self._get_connector().get_device_path(cinder_volume))
            mp = self._get_mountpoint(docker_volume_name)
            LOG.info(
                _LI("Expected devpath: %(dp)s and mountpoint: %(mp)s for"
                    " volume: %(d_v)s %(vol)s"), {
                        'dp': devpath,
                        'mp': mp,
                        'd_v': docker_volume_name,
                        'vol': cinder_volume
                    })
            mounter = mount.Mounter()
            return {
                "Name":
                docker_volume_name,
                "Mountpoint":
                mp if mp in mounter.get_mps_by_device(devpath) else ''
            }
        elif state in (NOT_ATTACH, ATTACH_TO_OTHER):
            return {'Name': docker_volume_name, 'Mountpoint': ''}
        elif state == UNKNOWN:
            msg = _LW("Can't find this volume '{0}' in "
                      "Cinder").format(docker_volume_name)
            LOG.warning(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _LE("Volume '{0}' exists, but not attached to this volume,"
                      "and current state is {1}").format(
                          docker_volume_name, state)
            raise exceptions.NotMatchedState(msg)
Пример #6
0
    def connect_volume(self, volume, **connect_opts):
        bdm = blockdevice.BlockerDeviceManager()
        ori_devices = bdm.device_scan()

        # Do volume-attach
        try:
            server_id = connect_opts.get('server_id', None)
            if not server_id:
                server_id = utils.get_instance_uuid()

            LOG.info("Start to connect to volume %s", volume)
            nova_volume = self.novaclient.volumes.create_server_volume(
                server_id=server_id, volume_id=volume.id, device=None)

            volume_monitor = state_monitor.StateMonitor(
                self.cinderclient, nova_volume, 'in-use', (
                    'available',
                    'attaching',
                ))
            attached_volume = volume_monitor.monitor_cinder_volume()
        except nova_exception.ClientException as ex:
            LOG.error(
                "Attaching volume %(vol)s to server %(s)s "
                "failed. Error: %(err)s", {
                    'vol': volume.id,
                    's': server_id,
                    'err': ex
                })
            raise

        # Get all devices on host after do volume-attach,
        # and then find attached device.
        LOG.info("After connected to volume, scan the added "
                 "block device on host")
        curr_devices = bdm.device_scan()
        start_time = time.time()
        delta_devices = list(set(curr_devices) - set(ori_devices))
        while not delta_devices:
            time.sleep(consts.DEVICE_SCAN_TIME_DELAY)
            curr_devices = bdm.device_scan()
            delta_devices = list(set(curr_devices) - set(ori_devices))
            if time.time() - start_time > consts.DEVICE_SCAN_TIMEOUT:
                msg = _("Could not detect added device with " "limited time")
                raise exceptions.FuxiException(msg)
        LOG.info("Get extra added block device %s", delta_devices)

        for device in delta_devices:
            if bdm.get_device_size(device) == volume.size:
                device = device.replace('/sys/block', '/dev')
                LOG.info(
                    "Find attached device %(dev)s"
                    " for volume %(at)s %(vol)s", {
                        'dev': device,
                        'at': attached_volume.name,
                        'vol': volume
                    })

                link_path = os.path.join(consts.VOLUME_LINK_DIR, volume.id)
                try:
                    utils.execute('ln',
                                  '-s',
                                  device,
                                  link_path,
                                  run_as_root=True)
                except processutils.ProcessExecutionError as e:
                    LOG.error(
                        "Error happened when create link file for"
                        " block device attached by Nova."
                        " Error: %s", e)
                    raise
                return {'path': link_path}

        LOG.warning("Could not find matched device")
        raise exceptions.NotFound("Not Found Matched Device")
Пример #7
0
class TestManila(base.TestCase):
    def setUp(self):
        super(TestManila, self).setUp()
        self._set_up_provider()

    @mock.patch.object(utils,
                       'get_manilaclient',
                       return_value=fake_client.FakeManilaClient())
    def _set_up_provider(self, mock_client):
        self.provider = manila.Manila()
        self.provider.manilaclient = fake_client.FakeManilaClient()
        self.provider.connector = FakeManilaConnector()

    def test_create_exist(self):
        fake_share = fake_object.FakeManilaShare(name='fake-vol',
                                                 id='fake-id',
                                                 export_location='fake-el')

        for status in [consts.NOT_ATTACH, consts.ATTACH_TO_THIS]:
            with mock.patch.object(manila.Manila,
                                   '_get_docker_volume',
                                   return_value=(fake_share, status)):
                self.assertEqual('fake-el',
                                 self.provider.create('fake-vol', {})['path'])

    @mock.patch('fuxi.volumeprovider.manila.Manila._get_docker_volume',
                side_effect=exceptions.NotFound())
    def test_create_from_id(self, mock_docker_volume):
        fake_vol_opts = {'volume_id': 'fake-id'}
        fake_share = fake_object.FakeManilaShare(name='fake-vol',
                                                 id='fake-id',
                                                 export_location='fake-el',
                                                 status='available',
                                                 metadata={})
        with mock.patch.object(fake_client.FakeManilaClient.Shares,
                               'get',
                               return_value=fake_share):
            self.assertEqual(
                'fake-el',
                self.provider.create('fake-vol', fake_vol_opts)['path'])

    @mock.patch('fuxi.volumeprovider.manila.Manila._get_docker_volume',
                side_effect=exceptions.NotFound())
    def test_create_not_exist(self, mock_docker_volume):
        fake_vol_opts = {'share_network': 'fake-share-network'}
        fake_share = fake_object.FakeManilaShare(name='fake-vol',
                                                 id='fake-id',
                                                 export_location='fake-el',
                                                 status='creating')
        with mock.patch.object(fake_client.FakeManilaClient.Shares,
                               'create',
                               return_value=fake_share):
            fake_share.status = 'available'
            with mock.patch.object(state_monitor.StateMonitor,
                                   'monitor_manila_share',
                                   return_value=fake_share):
                self.assertEqual(
                    'fake-el',
                    self.provider.create('fake-vol', fake_vol_opts)['path'])

    @mock.patch.object(utils, 'execute')
    @mock.patch.object(mount.Mounter, 'get_mps_by_device', return_value=[])
    def test_delete(self, mock_execute, mock_mps):
        fake_share = fake_object.FakeManilaShare(name='fake-vol',
                                                 id='fake-id',
                                                 export_location='fake-el')

        with mock.patch.object(manila.Manila,
                               '_get_docker_volume',
                               return_value=(fake_share,
                                             consts.ATTACH_TO_THIS)):
            with mock.patch.object(manila.Manila, '_delete_share'):
                self.assertTrue(self.provider.delete('fake-vol'))

    def test_mount(self):
        fake_share = fake_object.FakeManilaShare(name='fake-vol',
                                                 id='fake-id',
                                                 export_location='fake-el',
                                                 share_proto='nfs')

        with mock.patch.object(manila.Manila,
                               '_get_docker_volume',
                               return_value=(fake_share,
                                             consts.ATTACH_TO_THIS)):
            self.assertEqual('fake-vol', self.provider.mount('fake-vol'))

    def test_unmount(self):
        self.assertIsNone(self.provider.unmount('fake-vol'))

    def test_show(self):
        fake_vol = fake_object.DEFAULT_VOLUME_NAME
        with mock.patch.object(manila.Manila,
                               '_get_docker_volume',
                               return_value=(fake_object.FakeManilaShare(),
                                             consts.ATTACH_TO_THIS)):
            self.assertEqual({
                'Name': fake_vol,
                'Mountpoint': fake_vol
            }, self.provider.show(fake_vol))

    @mock.patch('fuxi.tests.unit.fake_client.FakeManilaClient.Shares.list',
                side_effect=manila_exception.ClientException(500))
    def test_show_list_failed(self, mock_list):
        self.assertRaises(manila_exception.ClientException, self.provider.show,
                          'fake-vol')

    @mock.patch.object(fake_client.FakeManilaClient.Shares,
                       'list',
                       return_value=[])
    def test_show_no_share(self, mock_list):
        self.assertRaises(exceptions.NotFound, self.provider.show, 'fake-vol')

    @mock.patch.object(fake_client.FakeManilaClient.Shares,
                       'list',
                       return_value=[
                           fake_object.FakeManilaShare(id='1'),
                           fake_object.FakeManilaShare(id='2')
                       ])
    def test_show_too_many_shares(self, mock_list):
        self.assertRaises(exceptions.TooManyResources, self.provider.show,
                          'fake-vol')

    @mock.patch.object(manila.Manila,
                       '_get_docker_volume',
                       return_value=(fake_object.FakeManilaShare(),
                                     consts.NOT_ATTACH))
    def test_show_not_attach(self, mock_docker_volume):
        fake_vol = fake_object.DEFAULT_VOLUME_NAME
        self.assertEqual({
            'Name': fake_vol,
            'Mountpoint': fake_vol
        }, self.provider.show(fake_vol))

    @mock.patch.object(manila.Manila,
                       '_get_docker_volume',
                       return_value=(fake_object.FakeManilaShare(),
                                     consts.ATTACH_TO_THIS))
    def test_show_not_mount(self, mock_dokcer_volume):
        fake_vol = fake_object.DEFAULT_VOLUME_NAME
        self.assertEqual({
            'Name': fake_vol,
            'Mountpoint': fake_vol
        }, self.provider.show(fake_vol))

    def test_list(self):
        share_dict = [{
            'id': 'fake-id1',
            'name': 'fake-name1',
            'export_location': 'fake-el1'
        }, {
            'id': 'fake-id2',
            'name': 'fake-name2',
            'export_location': 'fake-el2'
        }]
        fake_shares = [fake_object.FakeManilaShare(**s) for s in share_dict]
        fake_volumes = [{
            'Name': 'fake-name1',
            'Mountpoint': 'fake-name1'
        }, {
            'Name': 'fake-name2',
            'Mountpoint': 'fake-name2'
        }]
        with mock.patch.object(fake_client.FakeManilaClient.Shares,
                               'list',
                               return_value=fake_shares):
            with mock.patch.object(mount.Mounter,
                                   'get_mps_by_device',
                                   return_value=[]):
                self.assertEqual(fake_volumes, self.provider.list())

    def test_list_failed(self):
        with mock.patch(
                'fuxi.tests.unit.fake_client.FakeManilaClient'
                '.Shares.list',
                side_effect=manila_exception.ClientException):
            self.assertRaises(manila_exception.ClientException,
                              self.provider.list)

    def test_check_exist(self):
        with mock.patch('fuxi.volumeprovider.manila.Manila._get_docker_volume',
                        side_effect=exceptions.NotFound()):
            self.assertFalse(self.provider.check_exist('fake-vol'))

        with mock.patch.object(manila.Manila,
                               '_get_docker_volume',
                               return_value=(fake_object.FakeManilaShare(),
                                             consts.ATTACH_TO_THIS)):
            self.assertTrue(self.provider.check_exist('fake-vol'))