Beispiel #1
0
    def execute(self, context, volume_ref, volume_spec):
        volume_spec = dict(volume_spec)
        volume_id = volume_spec.pop('volume_id', None)

        # we can't do anything if the driver didn't init
        if not self.driver.initialized:
            driver_name = self.driver.__class__.__name__
            LOG.error(
                _("Unable to create volume. "
                  "Volume driver %s not initialized") % driver_name)
            # NOTE(flaper87): Set the error status before
            # raising any exception.
            self.db.volume_update(context, volume_id, dict(status='error'))
            raise exception.DriverNotInitialized()

        create_type = volume_spec.pop('type', None)
        create_functor = self._create_func_mapping.get(create_type)
        if not create_functor:
            raise exception.VolumeTypeNotFound(volume_type_id=create_type)

        if not volume_id:
            volume_id = volume_ref['id']
        LOG.info(
            _("Volume %(volume_id)s: being created using %(functor)s "
              "with specification: %(volume_spec)s") % {
                  'volume_spec': volume_spec,
                  'volume_id': volume_id,
                  'functor': common.make_pretty_name(create_functor)
              })

        # Call the given functor to make the volume.
        model_update = create_functor(context,
                                      volume_ref=volume_ref,
                                      **volume_spec)

        # Persist any model information provided on creation.
        try:
            if model_update:
                volume_ref = self.db.volume_update(context, volume_ref['id'],
                                                   model_update)
        except exception.CinderException as ex:
            # If somehow the update failed we want to ensure that the
            # failure is logged (but not try rescheduling since the volume at
            # this point has been created).
            if model_update:
                LOG.exception(
                    _("Failed updating model of volume %(volume_id)s"
                      " with creation provided model %(model)s") % {
                          'volume_id': volume_id,
                          'model': model_update
                      })
                raise exception.ExportFailure(reason=ex)

        return volume_ref
Beispiel #2
0
    def create_export(self, context, volume, connector):
        model_update = {}

        try:
            if self.common.is_lun_mapped(volume['name']):
                return model_update
            iqn, trg_id, provider_auth = (self.common.create_iscsi_export(
                volume['name'], volume['id']))
        except Exception as e:
            LOG.exception('Failed to remove_export.')
            raise exception.ExportFailure(reason=e)

        model_update['provider_location'] = (self.common.get_provider_location(
            iqn, trg_id))
        model_update['provider_auth'] = provider_auth

        return model_update
Beispiel #3
0
    def _attach_volume(self, context, volume, properties, remote=False):
        """Attach the volume."""
        if remote:
            # Call remote manager's initialize_connection which includes
            # driver's create_export and initialize_connection
            rpcapi = volume_rpcapi.VolumeAPI()
            conn = rpcapi.initialize_connection(context, volume, properties)
        else:
            # Call local driver's create_export and initialize_connection.
            # NOTE(avishay) This is copied from the manager's code - need to
            # clean this up in the future.
            model_update = None
            try:
                LOG.debug(_("Volume %s: creating export"), volume['id'])
                model_update = self.create_export(context, volume)
                if model_update:
                    volume = self.db.volume_update(context, volume['id'],
                                                   model_update)
            except exception.CinderException as ex:
                if model_update:
                    LOG.exception(
                        _("Failed updating model of volume "
                          "%(volume_id)s with driver provided model "
                          "%(model)s") % {
                              'volume_id': volume['id'],
                              'model': model_update
                          })
                    raise exception.ExportFailure(reason=ex)

            try:
                conn = self.initialize_connection(volume, properties)
            except Exception as err:
                try:
                    err_msg = (_('Unable to fetch connection information from '
                                 'backend: %(err)s') % {
                                     'err': err
                                 })
                    LOG.error(err_msg)
                    LOG.debug("Cleaning up failed connect initialization.")
                    self.remove_export(context, volume)
                except Exception as ex:
                    ex_msg = (_('Error encountered during cleanup '
                                'of a failed attach: %(ex)s') % {
                                    'ex': ex
                                })
                    LOG.error(err_msg)
                    raise exception.VolumeBackendAPIException(data=ex_msg)
                raise exception.VolumeBackendAPIException(data=err_msg)

        # Use Brick's code to do attach/detach
        use_multipath = self.configuration.use_multipath_for_image_xfer
        device_scan_attempts = self.configuration.num_volume_device_scan_tries
        protocol = conn['driver_volume_type']
        connector = utils.brick_get_connector(
            protocol,
            use_multipath=use_multipath,
            device_scan_attempts=device_scan_attempts,
            conn=conn)
        device = connector.connect_volume(conn['data'])
        host_device = device['path']

        if not connector.check_valid_device(host_device):
            raise exception.DeviceUnavailable(path=host_device,
                                              reason=(_("Unable to access "
                                                        "the backend storage "
                                                        "via the path "
                                                        "%(path)s.") % {
                                                            'path': host_device
                                                        }))
        return {'conn': conn, 'device': device, 'connector': connector}