Пример #1
0
    def _test_volume_attach(self, driver_bdm, bdm_dict,
                            fake_volume, check_attach=True,
                            fail_check_attach=False, driver_attach=False,
                            fail_driver_attach=False, access_mode='rw'):
        elevated_context = self.context.elevated()
        self.stubs.Set(self.context, 'elevated',
                       lambda: elevated_context)
        self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save')
        self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata')
        instance = {'id': 'fake_id', 'uuid': 'fake_uuid'}
        connector = {'ip': 'fake_ip', 'host': 'fake_host'}
        connection_info = {'data': {'access_mode': access_mode}}
        expected_conn_info = {'data': {'access_mode': access_mode},
                              'serial': fake_volume['id']}
        enc_data = {'fake': 'enc_data'}

        self.volume_api.get(self.context,
                            fake_volume['id']).AndReturn(fake_volume)
        if check_attach:
            if not fail_check_attach:
                self.volume_api.check_attach(self.context, fake_volume,
                                    instance=instance).AndReturn(None)
            else:
                self.volume_api.check_attach(self.context, fake_volume,
                                    instance=instance).AndRaise(
                                            test.TestingException)
                return instance, expected_conn_info

        self.virt_driver.get_volume_connector(instance).AndReturn(connector)
        self.volume_api.initialize_connection(
            elevated_context, fake_volume['id'],
            connector).AndReturn(connection_info)
        if driver_attach:
            encryptors.get_encryption_metadata(
                    elevated_context, self.volume_api, fake_volume['id'],
                    connection_info).AndReturn(enc_data)
            if not fail_driver_attach:
                self.virt_driver.attach_volume(
                        elevated_context, expected_conn_info, instance,
                        bdm_dict['device_name'],
                        disk_bus=bdm_dict['disk_bus'],
                        device_type=bdm_dict['device_type'],
                        encryption=enc_data).AndReturn(None)
            else:
                self.virt_driver.attach_volume(
                        elevated_context, expected_conn_info, instance,
                        bdm_dict['device_name'],
                        disk_bus=bdm_dict['disk_bus'],
                        device_type=bdm_dict['device_type'],
                        encryption=enc_data).AndRaise(test.TestingException)
                self.volume_api.terminate_connection(
                        elevated_context, fake_volume['id'],
                        expected_conn_info).AndReturn(None)
                return instance, expected_conn_info

        self.volume_api.attach(elevated_context, fake_volume['id'],
                          'fake_uuid', bdm_dict['device_name'],
                          mode=access_mode).AndReturn(None)
        driver_bdm._bdm_obj.save(self.context).AndReturn(None)
        return instance, expected_conn_info
Пример #2
0
    def driver_detach(self, context, instance, volume_api, virt_driver):
        connection_info = self['connection_info']
        mp = self['mount_device']
        volume_id = self.volume_id

        LOG.info(_LI('Attempting to driver detach volume %(volume_id)s from '
                     ' mountpoint %(mp)s'), {'volume_id': volume_id, 'mp': mp},
                     instance=instance)
        try:
            if not virt_driver.instance_exists(instance):
                LOG.warning(_LW('Detaching volume from unknown instance'),
                                instance=instance)

            encryption = encryptors.get_encryption_metadata(context,
                    volume_api, volume_id, connection_info)
            virt_driver.detach_volume(connection_info, instance, mp,
                                      encryption=encryption)
        except exception.DiskNotFound as err:
            LOG.warning(_LW('Ignoring DiskNotFound exception while '
                            'detaching volume %(volume_id)s from '
                            '%(mp)s : %(err)s'),
                        {'volume_id': volume_id, 'mp': mp,
                         'err': err}, instance=instance)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE('Failed to detach volume '
                                  '%(volume_id)s from %(mp)s'),
                              {'volume_id': volume_id, 'mp': mp},
                              instance=instance)
                volume_api.roll_detaching(context, volume_id)
Пример #3
0
    def attach(self,
               context,
               instance,
               volume_api,
               virt_driver,
               do_check_attach=True,
               do_driver_attach=False):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume['id']
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(
            context, volume_id, connector)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(context,
                                          connection_info,
                                          instance,
                                          self['mount_device'],
                                          disk_bus=self['disk_bus'],
                                          device_type=self['device_type'],
                                          encryption=encryption)
            except Exception:  # pylint: disable=W0702
                with excutils.save_and_reraise_exception():
                    LOG.exception(_("Driver failed to attach volume "
                                    "%(volume_id)s at %(mountpoint)s"), {
                                        'volume_id': volume_id,
                                        'mountpoint': self['mount_device']
                                    },
                                  context=context,
                                  instance=instance)
                    volume_api.terminate_connection(context, volume_id,
                                                    connector)
        self['connection_info'] = connection_info

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')
        if volume['attach_status'] == "detached":
            volume_api.attach(context,
                              volume_id,
                              instance['uuid'],
                              self['mount_device'],
                              mode=mode)
Пример #4
0
    def attach(
        self, context, instance, volume_api, virt_driver, do_check_attach=True, do_driver_attach=False, **kwargs
    ):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume["id"]
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(context, volume_id, connector)
        if "serial" not in connection_info:
            connection_info["serial"] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                    context,
                    connection_info,
                    instance,
                    self["mount_device"],
                    disk_bus=self["disk_bus"],
                    device_type=self["device_type"],
                    encryption=encryption,
                )
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.exception(
                        _LE("Driver failed to attach volume " "%(volume_id)s at %(mountpoint)s"),
                        {"volume_id": volume_id, "mountpoint": self["mount_device"]},
                        context=context,
                        instance=instance,
                    )
                    volume_api.terminate_connection(context, volume_id, connector)
        self["connection_info"] = connection_info
        if self.volume_size is None:
            self.volume_size = volume.get("size")

        mode = "rw"
        if "data" in connection_info:
            mode = connection_info["data"].get("access_mode", "rw")
        if volume["attach_status"] == "detached":
            # NOTE(mriedem): save our current state so connection_info is in
            # the database before the volume status goes to 'in-use' because
            # after that we can detach and connection_info is required for
            # detach.
            self.save()
            volume_api.attach(context, volume_id, instance.uuid, self["mount_device"], mode=mode)
Пример #5
0
    def attach(self, context, instance, volume_api, virt_driver,
               do_check_attach=True, do_driver_attach=False):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume['id']
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(context,
                                                           volume_id,
                                                           connector)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                        context, connection_info, instance,
                        self['mount_device'], disk_bus=self['disk_bus'],
                        device_type=self['device_type'], encryption=encryption)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Driver failed to attach volume "
                                      "%(volume_id)s at %(mountpoint)s"),
                                  {'volume_id': volume_id,
                                   'mountpoint': self['mount_device']},
                                  context=context, instance=instance)
                    volume_api.terminate_connection(context, volume_id,
                                                    connector)
        self['connection_info'] = connection_info

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')
        if volume['attach_status'] == "detached":
            # NOTE(mriedem): save our current state so connection_info is in
            # the database before the volume status goes to 'in-use' because
            # after that we can detach and connection_info is required for
            # detach.
            self.save()
            volume_api.attach(context, volume_id, instance.uuid,
                              self['mount_device'], mode=mode)
Пример #6
0
    def attach(self, context, instance, volume_api, virt_driver,
               do_check_attach=True, do_driver_attach=False):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume['id']
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(context,
                                                           volume_id,
                                                           connector)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                        context, connection_info, instance,
                        self['mount_device'], disk_bus=self['disk_bus'],
                        device_type=self['device_type'], encryption=encryption)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Driver failed to attach volume "
                                      "%(volume_id)s at %(mountpoint)s"),
                                  {'volume_id': volume_id,
                                   'mountpoint': self['mount_device']},
                                  context=context, instance=instance)
                    volume_api.terminate_connection(context, volume_id,
                                                    connector)
        self['connection_info'] = connection_info

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')
        if volume['attach_status'] == "detached":
            # NOTE(mriedem): save our current state so connection_info is in
            # the database before the volume status goes to 'in-use' because
            # after that we can detach and connection_info is required for
            # detach.
            self.save()
            volume_api.attach(context, volume_id, instance.uuid,
                              self['mount_device'], mode=mode)
Пример #7
0
    def attach(self, context, instance, volume_api, virt_driver,
               do_check_attach=True, do_driver_attach=False):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume['id']
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        host = self._get_host(connector)
        connection_info = volume_api.initialize_connection(context,
                                                           volume_id,
                                                           connector,
                                                           instance['uuid'],
                                                           host)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                        context, connection_info, instance,
                        self['mount_device'], disk_bus=self['disk_bus'],
                        device_type=self['device_type'], encryption=encryption)
            except Exception:  # pylint: disable=W0702
                with excutils.save_and_reraise_exception():
                    LOG.exception(_("Driver failed to attach volume "
                                    "%(volume_id)s at %(mountpoint)s"),
                                  {'volume_id': volume_id,
                                   'mountpoint': self['mount_device']},
                                  context=context, instance=instance)
                    volume_api.terminate_connection(context, volume_id,
                                                    connector,
                                                    instance['uuid'],
                                                    host)
        self['connection_info'] = connection_info

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')
        volume_api.attach(context, volume_id, instance['uuid'],
                          self['mount_device'], mode=mode)
Пример #8
0
    def attach(self, context, instance, volume_api, virt_driver, do_check_attach=True, do_driver_attach=False):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume["id"]
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(context, volume_id, connector)
        if "serial" not in connection_info:
            connection_info["serial"] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                    context,
                    connection_info,
                    instance,
                    self["mount_device"],
                    disk_bus=self["disk_bus"],
                    device_type=self["device_type"],
                    encryption=encryption,
                )
            except Exception:  # pylint: disable=W0702
                with excutils.save_and_reraise_exception():
                    LOG.exception(
                        _("Driver failed to attach volume " "%(volume_id)s at %(mountpoint)s"),
                        {"volume_id": volume_id, "mountpoint": self["mount_device"]},
                        context=context,
                        instance=instance,
                    )
                    volume_api.terminate_connection(context, volume_id, connector)
        self["connection_info"] = connection_info

        mode = "rw"
        if "data" in connection_info:
            mode = connection_info["data"].get("access_mode", "rw")
        if volume["attach_status"] == "detached":
            volume_api.attach(context, volume_id, instance["uuid"], self["mount_device"], mode=mode)
Пример #9
0
    def driver_detach(self, context, instance, volume_api, virt_driver):
        connection_info = self['connection_info']
        mp = self['mount_device']
        volume_id = self.volume_id

        LOG.info(_LI('Attempting to driver detach volume %(volume_id)s from '
                     ' mountpoint %(mp)s'), {
                         'volume_id': volume_id,
                         'mp': mp
                     },
                 instance=instance)
        try:
            if not virt_driver.instance_exists(instance):
                LOG.warning(_LW('Detaching volume from unknown instance'),
                            instance=instance)

            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)
            virt_driver.detach_volume(connection_info,
                                      instance,
                                      mp,
                                      encryption=encryption)
        except exception.DiskNotFound as err:
            LOG.warning(_LW('Ignoring DiskNotFound exception while '
                            'detaching volume %(volume_id)s from '
                            '%(mp)s : %(err)s'), {
                                'volume_id': volume_id,
                                'mp': mp,
                                'err': err
                            },
                        instance=instance)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE('Failed to detach volume '
                                  '%(volume_id)s from %(mp)s'), {
                                      'volume_id': volume_id,
                                      'mp': mp
                                  },
                              instance=instance)
                volume_api.roll_detaching(context, volume_id)
Пример #10
0
    def _test_volume_attach(self,
                            driver_bdm,
                            bdm_dict,
                            fake_volume,
                            check_attach=True,
                            fail_check_attach=False,
                            driver_attach=False,
                            fail_driver_attach=False,
                            volume_attach=True,
                            fail_volume_attach=False,
                            access_mode='rw'):
        elevated_context = self.context.elevated()
        self.stubs.Set(self.context, 'elevated', lambda: elevated_context)
        self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save')
        self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata')
        instance_detail = {'id': '123', 'uuid': 'fake_uuid'}
        instance = fake_instance.fake_instance_obj(self.context,
                                                   **instance_detail)
        connector = {'ip': 'fake_ip', 'host': 'fake_host'}
        connection_info = {'data': {'access_mode': access_mode}}
        expected_conn_info = {
            'data': {
                'access_mode': access_mode
            },
            'serial': fake_volume['id']
        }
        enc_data = {'fake': 'enc_data'}

        self.volume_api.get(self.context,
                            fake_volume['id']).AndReturn(fake_volume)
        if check_attach:
            if not fail_check_attach:
                self.volume_api.check_attach(self.context,
                                             fake_volume,
                                             instance=instance).AndReturn(None)
            else:
                self.volume_api.check_attach(self.context,
                                             fake_volume,
                                             instance=instance).AndRaise(
                                                 test.TestingException)
                driver_bdm._bdm_obj.save().AndReturn(None)
                return instance, expected_conn_info

        self.virt_driver.get_volume_connector(instance).AndReturn(connector)
        self.volume_api.initialize_connection(
            elevated_context, fake_volume['id'],
            connector).AndReturn(connection_info)
        if driver_attach:
            encryptors.get_encryption_metadata(
                elevated_context, self.volume_api, fake_volume['id'],
                connection_info).AndReturn(enc_data)
            if not fail_driver_attach:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict['device_name'],
                    disk_bus=bdm_dict['disk_bus'],
                    device_type=bdm_dict['device_type'],
                    encryption=enc_data).AndReturn(None)
            else:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict['device_name'],
                    disk_bus=bdm_dict['disk_bus'],
                    device_type=bdm_dict['device_type'],
                    encryption=enc_data).AndRaise(test.TestingException)
                self.volume_api.terminate_connection(elevated_context,
                                                     fake_volume['id'],
                                                     connector).AndReturn(None)
                driver_bdm._bdm_obj.save().AndReturn(None)
                return instance, expected_conn_info

        if volume_attach:
            driver_bdm._bdm_obj.save().AndReturn(None)
            if not fail_volume_attach:
                self.volume_api.attach(elevated_context,
                                       fake_volume['id'],
                                       'fake_uuid',
                                       bdm_dict['device_name'],
                                       mode=access_mode).AndReturn(None)
            else:
                self.volume_api.attach(elevated_context,
                                       fake_volume['id'],
                                       'fake_uuid',
                                       bdm_dict['device_name'],
                                       mode=access_mode).AndRaise(
                                           test.TestingException)
        driver_bdm._bdm_obj.save().AndReturn(None)
        return instance, expected_conn_info
Пример #11
0
    def _test_volume_attach(self, driver_bdm, bdm_dict,
                            fake_volume, check_attach=True,
                            fail_check_attach=False, driver_attach=False,
                            fail_driver_attach=False, volume_attach=True,
                            access_mode='rw'):
        elevated_context = self.context.elevated()
        self.stubs.Set(self.context, 'elevated',
                       lambda: elevated_context)
        self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save')
        self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata')
        instance = {'id': 'fake_id', 'uuid': 'fake_uuid'}
        connector = {'ip': 'fake_ip', 'host': 'fake_host'}
        connection_info = {'data': {'access_mode': access_mode}}
        expected_conn_info = {'data': {'access_mode': access_mode},
                              'serial': fake_volume['id']}
        enc_data = {'fake': 'enc_data'}

        self.volume_api.get(self.context,
                            fake_volume['id']).AndReturn(fake_volume)
        if check_attach:
            if not fail_check_attach:
                self.volume_api.check_attach(self.context, fake_volume,
                                    instance=instance).AndReturn(None)
            else:
                self.volume_api.check_attach(self.context, fake_volume,
                                    instance=instance).AndRaise(
                                            test.TestingException)
                return instance, expected_conn_info

        self.virt_driver.get_volume_connector(instance).AndReturn(connector)
        self.volume_api.initialize_connection(
            elevated_context, fake_volume['id'],
            connector).AndReturn(connection_info)
        if driver_attach:
            encryptors.get_encryption_metadata(
                    elevated_context, self.volume_api, fake_volume['id'],
                    connection_info).AndReturn(enc_data)
            if not fail_driver_attach:
                self.virt_driver.attach_volume(
                        elevated_context, expected_conn_info, instance,
                        bdm_dict['device_name'],
                        disk_bus=bdm_dict['disk_bus'],
                        device_type=bdm_dict['device_type'],
                        encryption=enc_data).AndReturn(None)
            else:
                self.virt_driver.attach_volume(
                        elevated_context, expected_conn_info, instance,
                        bdm_dict['device_name'],
                        disk_bus=bdm_dict['disk_bus'],
                        device_type=bdm_dict['device_type'],
                        encryption=enc_data).AndRaise(test.TestingException)
                self.volume_api.terminate_connection(
                        elevated_context, fake_volume['id'],
                        expected_conn_info).AndReturn(None)
                return instance, expected_conn_info

        if volume_attach:
            self.volume_api.attach(elevated_context, fake_volume['id'],
                                   'fake_uuid', bdm_dict['device_name'],
                                   mode=access_mode).AndReturn(None)
        # NOTE(mriedem): save() is called with the elevated context within
        # attach() and with the original context from the update_db decorator
        # so we ignore which arg it is in test.
        driver_bdm._bdm_obj.save(
            mox.IgnoreArg()).MultipleTimes().AndReturn(None)
        return instance, expected_conn_info
Пример #12
0
    def _test_volume_attach(self,
                            driver_bdm,
                            bdm_dict,
                            fake_volume,
                            check_attach=True,
                            fail_check_attach=False,
                            driver_attach=False,
                            fail_driver_attach=False,
                            volume_attach=True,
                            access_mode='rw'):
        elevated_context = self.context.elevated()
        self.stubs.Set(self.context, 'elevated', lambda: elevated_context)
        self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save')
        self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata')
        instance = {'id': 'fake_id', 'uuid': 'fake_uuid'}
        connector = {'ip': 'fake_ip', 'host': 'fake_host'}
        connection_info = {'data': {'access_mode': access_mode}}
        expected_conn_info = {
            'data': {
                'access_mode': access_mode
            },
            'serial': fake_volume['id']
        }
        enc_data = {'fake': 'enc_data'}

        self.volume_api.get(self.context,
                            fake_volume['id']).AndReturn(fake_volume)
        if check_attach:
            if not fail_check_attach:
                self.volume_api.check_attach(self.context,
                                             fake_volume,
                                             instance=instance).AndReturn(None)
            else:
                self.volume_api.check_attach(self.context,
                                             fake_volume,
                                             instance=instance).AndRaise(
                                                 test.TestingException)
                return instance, expected_conn_info

        self.virt_driver.get_volume_connector(instance).AndReturn(connector)
        self.volume_api.initialize_connection(
            elevated_context, fake_volume['id'],
            connector).AndReturn(connection_info)
        if driver_attach:
            encryptors.get_encryption_metadata(
                elevated_context, self.volume_api, fake_volume['id'],
                connection_info).AndReturn(enc_data)
            if not fail_driver_attach:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict['device_name'],
                    disk_bus=bdm_dict['disk_bus'],
                    device_type=bdm_dict['device_type'],
                    encryption=enc_data).AndReturn(None)
            else:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict['device_name'],
                    disk_bus=bdm_dict['disk_bus'],
                    device_type=bdm_dict['device_type'],
                    encryption=enc_data).AndRaise(test.TestingException)
                self.volume_api.terminate_connection(
                    elevated_context, fake_volume['id'],
                    expected_conn_info).AndReturn(None)
                return instance, expected_conn_info

        if volume_attach:
            self.volume_api.attach(elevated_context,
                                   fake_volume['id'],
                                   'fake_uuid',
                                   bdm_dict['device_name'],
                                   mode=access_mode).AndReturn(None)
        # NOTE(mriedem): save() is called with the elevated context within
        # attach() and with the original context from the update_db decorator
        # so we ignore which arg it is in test.
        driver_bdm._bdm_obj.save(
            mox.IgnoreArg()).MultipleTimes().AndReturn(None)
        return instance, expected_conn_info
Пример #13
0
    def _test_volume_attach(
        self,
        driver_bdm,
        bdm_dict,
        fake_volume,
        check_attach=True,
        fail_check_attach=False,
        driver_attach=False,
        fail_driver_attach=False,
        volume_attach=True,
        fail_volume_attach=False,
        access_mode="rw",
        availability_zone=None,
    ):
        elevated_context = self.context.elevated()
        self.stubs.Set(self.context, "elevated", lambda: elevated_context)
        self.mox.StubOutWithMock(driver_bdm._bdm_obj, "save")
        self.mox.StubOutWithMock(encryptors, "get_encryption_metadata")
        instance_detail = {"id": "123", "uuid": "fake_uuid", "availability_zone": availability_zone}
        instance = fake_instance.fake_instance_obj(self.context, **instance_detail)
        connector = {"ip": "fake_ip", "host": "fake_host"}
        connection_info = {"data": {"access_mode": access_mode}}
        expected_conn_info = {"data": {"access_mode": access_mode}, "serial": fake_volume["id"]}
        enc_data = {"fake": "enc_data"}

        self.volume_api.get(self.context, fake_volume["id"]).AndReturn(fake_volume)
        if check_attach:
            if not fail_check_attach:
                self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndReturn(None)
            else:
                self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndRaise(
                    test.TestingException
                )
                driver_bdm._bdm_obj.save().AndReturn(None)
                return instance, expected_conn_info

        self.virt_driver.get_volume_connector(instance).AndReturn(connector)
        self.volume_api.initialize_connection(elevated_context, fake_volume["id"], connector).AndReturn(connection_info)
        if driver_attach:
            encryptors.get_encryption_metadata(
                elevated_context, self.volume_api, fake_volume["id"], connection_info
            ).AndReturn(enc_data)
            if not fail_driver_attach:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict["device_name"],
                    disk_bus=bdm_dict["disk_bus"],
                    device_type=bdm_dict["device_type"],
                    encryption=enc_data,
                ).AndReturn(None)
            else:
                self.virt_driver.attach_volume(
                    elevated_context,
                    expected_conn_info,
                    instance,
                    bdm_dict["device_name"],
                    disk_bus=bdm_dict["disk_bus"],
                    device_type=bdm_dict["device_type"],
                    encryption=enc_data,
                ).AndRaise(test.TestingException)
                self.volume_api.terminate_connection(elevated_context, fake_volume["id"], connector).AndReturn(None)
                driver_bdm._bdm_obj.save().AndReturn(None)
                return instance, expected_conn_info

        if volume_attach:
            driver_bdm._bdm_obj.save().AndReturn(None)
            if not fail_volume_attach:
                self.volume_api.attach(
                    elevated_context, fake_volume["id"], "fake_uuid", bdm_dict["device_name"], mode=access_mode
                ).AndReturn(None)
            else:
                self.volume_api.attach(
                    elevated_context, fake_volume["id"], "fake_uuid", bdm_dict["device_name"], mode=access_mode
                ).AndRaise(test.TestingException)
                if driver_attach:
                    self.virt_driver.detach_volume(
                        expected_conn_info, instance, bdm_dict["device_name"], encryption=enc_data
                    ).AndReturn(None)
                self.volume_api.terminate_connection(elevated_context, fake_volume["id"], connector).AndReturn(None)
                self.volume_api.detach(elevated_context, fake_volume["id"]).AndReturn(None)

        driver_bdm._bdm_obj.save().AndReturn(None)
        return instance, expected_conn_info
Пример #14
0
    def attach(self,
               context,
               instance,
               volume_api,
               virt_driver,
               do_check_attach=True,
               do_driver_attach=False,
               **kwargs):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            volume_api.check_attach(context, volume, instance=instance)

        volume_id = volume['id']
        vol_multiattach = volume.get('multiattach', False)
        has_attachments = bool(volume.get('attachments'))
        virt_multiattach = virt_driver.capabilities['supports_multiattach']

        if vol_multiattach and has_attachments and not virt_multiattach:
            raise exception.MultiattachNotSupported(volume_id=volume_id)

        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(
            context, volume_id, connector)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        if vol_multiattach and virt_multiattach:
            connection_info['multiattach'] = True

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(context,
                                          connection_info,
                                          instance,
                                          self['mount_device'],
                                          disk_bus=self['disk_bus'],
                                          device_type=self['device_type'],
                                          encryption=encryption)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Driver failed to attach volume "
                                      "%(volume_id)s at %(mountpoint)s"), {
                                          'volume_id': volume_id,
                                          'mountpoint': self['mount_device']
                                      },
                                  context=context,
                                  instance=instance)
                    volume_api.check_and_terminate_connection(
                        context, volume_id, connector, instance.host)
        self['connection_info'] = connection_info
        if self.volume_size is None:
            self.volume_size = volume.get('size')

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')

        if (volume['attach_status'] == "detached"
                or volume['attach_status'] == 'attached' and vol_multiattach):
            # NOTE(mriedem): save our current state so connection_info is in
            # the database before the volume status goes to 'in-use' because
            # after that we can detach and connection_info is required for
            # detach.
            self.save()
            try:
                volume_api.attach(context,
                                  volume_id,
                                  instance.uuid,
                                  self['mount_device'],
                                  mode=mode)
            except Exception:
                with excutils.save_and_reraise_exception():
                    if do_driver_attach:
                        try:
                            virt_driver.detach_volume(connection_info,
                                                      instance,
                                                      self['mount_device'],
                                                      encryption=encryption)
                        except Exception:
                            LOG.warn(_LW("Driver failed to detach volume "
                                         "%(volume_id)s at %(mount_point)s."),
                                     {
                                         'volume_id': volume_id,
                                         'mount_point': self['mount_device']
                                     },
                                     exc_info=True,
                                     context=context,
                                     instance=instance)
                    volume_api.check_and_terminate_connection(
                        context, volume_id, connector, instance.host)

                    # Cinder-volume might have completed volume attach. So
                    # we should detach the volume. If the attach did not
                    # happen, the detach request will be ignored.
                    volume_api.detach(context, volume_id)
Пример #15
0
    def attach(self, context, instance, volume_api, virt_driver,
               do_check_attach=True, do_driver_attach=False, **kwargs):
        volume = volume_api.get(context, self.volume_id)
        if do_check_attach:
            #song.w 12.25
            volume_api.check_attach(context, volume, instance=instance)
            #pass

        volume_id = volume['id']
        context = context.elevated()

        connector = virt_driver.get_volume_connector(instance)
        connection_info = volume_api.initialize_connection(context,
                                                           volume_id,
                                                           connector)
        if 'serial' not in connection_info:
            connection_info['serial'] = self.volume_id
        self._preserve_multipath_id(connection_info)

        # If do_driver_attach is False, we will attach a volume to an instance
        # at boot time. So actual attach is done by instance creation code.
        if do_driver_attach:
            encryption = encryptors.get_encryption_metadata(
                context, volume_api, volume_id, connection_info)

            try:
                virt_driver.attach_volume(
                        context, connection_info, instance,
                        self['mount_device'], disk_bus=self['disk_bus'],
                        device_type=self['device_type'], encryption=encryption)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("Driver failed to attach volume "
                                      "%(volume_id)s at %(mountpoint)s"),
                                  {'volume_id': volume_id,
                                   'mountpoint': self['mount_device']},
                                  instance=instance)
                    volume_api.terminate_connection(context, volume_id,
                                                    connector)
        self['connection_info'] = connection_info
        if self.volume_size is None:
            self.volume_size = volume.get('size')

        mode = 'rw'
        if 'data' in connection_info:
            mode = connection_info['data'].get('access_mode', 'rw')
        ##song.w modify 2017-12-26
        #Support the status of multiple mounts scenarios
        #begin
        if volume['multiattach']:
            if volume['attach_status'] == "detached" or volume['attach_status'] == "attached":
                self.save()
                try:
                    volume_api.attach(context, volume_id, instance.uuid,
                                      self['mount_device'], mode=mode)
                except Exception:
                    with excutils.save_and_reraise_exception():
                        if do_driver_attach:
                            try:
                                virt_driver.detach_volume(connection_info,
                                                          instance,
                                                          self['mount_device'],
                                                          encryption=encryption)
                            except Exception:
                                LOG.warning(_LW("Driver failed to detach volume "
                                                "%(volume_id)s at %(mount_point)s."),
                                            {'volume_id': volume_id,
                                             'mount_point': self['mount_device']},
                                            exc_info=True, instance=instance)
                        volume_api.terminate_connection(context, volume_id,
                                                        connector)

                        # Cinder-volume might have completed volume attach. So
                        # we should detach the volume. If the attach did not
                        # happen, the detach request will be ignored.
                        volume_api.detach(context, volume_id)
        else:
            if volume['attach_status'] == "detached":
                # NOTE(mriedem): save our current state so connection_info is in
                # the database before the volume status goes to 'in-use' because
                # after that we can detach and connection_info is required for
                # detach.
                self.save()
                try:
                    volume_api.attach(context, volume_id, instance.uuid,
                                      self['mount_device'], mode=mode)
                except Exception:
                    with excutils.save_and_reraise_exception():
                        if do_driver_attach:
                            try:
                                virt_driver.detach_volume(connection_info,
                                                          instance,
                                                          self['mount_device'],
                                                          encryption=encryption)
                            except Exception:
                                LOG.warning(_LW("Driver failed to detach volume "
                                                "%(volume_id)s at %(mount_point)s."),
                                            {'volume_id': volume_id,
                                             'mount_point': self['mount_device']},
                                            exc_info=True, instance=instance)
                        volume_api.terminate_connection(context, volume_id,
                                                        connector)

                        # Cinder-volume might have completed volume attach. So
                        # we should detach the volume. If the attach did not
                        # happen, the detach request will be ignored.
                        volume_api.detach(context, volume_id)
            # Support the status of multiple mounts scenarios
            # end
        """