Esempio n. 1
0
 def extend_volume(self, volume, new_size):
     volume_name = self._get_vol_name(volume['id'])
     old_size = volume['size']
     growth_size = int(new_size) - old_size
     LOG.debug(
         "Extending Volume %(volume_name)s from %(old_size)s to "
         "%(new_size)s, by %(growth_size)s GB." % {
             'volume_name': volume_name,
             'old_size': old_size,
             'new_size': new_size,
             'growth_size': growth_size
         })
     try:
         self.client.extend_volume(volume_name, "%dGB" % growth_size)
     except msa.HPMSARequestError as ex:
         LOG.error(ex)
         raise exception.Invalid(ex)
Esempio n. 2
0
    def manage_existing_get_size(self, volume, existing_ref):
        """Return size of volume to be managed by manage_existing.

        existing_ref is a dictionary of the form:
        {'source-name': <name of the volume>}
        """
        target_vol_name = existing_ref['source-name']

        self.client_login()
        try:
            size = self.client.get_volume_size(target_vol_name)
            return size
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Error manage existing get volume size."))
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 3
0
    def migrate_volume(self, volume, host):
        """Migrate directly if source and dest are managed by same storage.

        :param volume: A dictionary describing the volume to migrate
        :param host: A dictionary describing the host to migrate to, where
                     host['host'] is its name, and host['capabilities'] is a
                     dictionary of its reported capabilities.
        :returns: (False, None) if the driver does not support migration,
                 (True, None) if successful

        """
        false_ret = (False, None)
        if volume['attach_status'] == "attached":
            return false_ret
        if 'location_info' not in host['capabilities']:
            return false_ret
        info = host['capabilities']['location_info']
        try:
            (dest_type, dest_id,
             dest_back_name, dest_owner) = info.split(':')
        except ValueError:
            return false_ret

        if not (dest_type == 'DotHillVolumeDriver' and
                dest_id == self.serialNumber and
                dest_owner == self.owner):
            return false_ret
        if volume['name_id']:
            source_name = self._get_vol_name(volume['name_id'])
        else:
            source_name = self._get_vol_name(volume['id'])
        # DotHill Array does not support duplicate names
        dest_name = "m%s" % source_name[1:]

        self.client_login()
        try:
            self.client.copy_volume(source_name, dest_name,
                                    dest_back_name, self.backend_type)
            self.client.delete_volume(source_name)
            self.client.modify_volume_name(dest_name, source_name)
            return (True, None)
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Error migrating volume: %s"), source_name)
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 4
0
    def unmap_volume(self, volume, connector, connector_element):
        self._assert_connector_ok(connector, connector_element)
        if volume['name_id']:
            volume_name = self._get_vol_name(volume['name_id'])
        else:
            volume_name = self._get_vol_name(volume['id'])

        self.client_login()
        try:
            self.client.unmap_volume(volume_name,
                                     connector,
                                     connector_element)
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Error unmapping volume: %s"), volume_name)
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
    def _get_encryption_key_id(self, key_manager, context, volume_type_id,
                               snapshot, source_volume,
                               image_metadata):
        encryption_key_id = None
        if volume_types.is_encrypted(context, volume_type_id):
            if snapshot is not None:  # creating from snapshot
                encryption_key_id = snapshot['encryption_key_id']
            elif source_volume is not None:  # cloning volume
                encryption_key_id = source_volume['encryption_key_id']
            elif image_metadata is not None:
                # creating from image
                encryption_key_id = image_metadata.get(
                    'cinder_encryption_key_id')

            # NOTE(joel-coffman): References to the encryption key should *not*
            # be copied because the key is deleted when the volume is deleted.
            # Clone the existing key and associate a separate -- but
            # identical -- key with each volume.
            if encryption_key_id is not None:
                encryption_key_id = key_manager.store(
                    context, key_manager.get(context, encryption_key_id))
            else:
                volume_type_encryption = (
                    volume_types.get_volume_type_encryption(context,
                                                            volume_type_id))
                cipher = volume_type_encryption.cipher
                length = volume_type_encryption.key_size

                # NOTE(kaitlin-farr): dm-crypt expects the cipher in a
                # hyphenated format (aes-xts-plain64). The algorithm needs
                # to be parsed out to pass to the key manager (aes).
                algorithm = cipher.split('-')[0] if cipher else None
                try:
                    encryption_key_id = key_manager.create_key(
                        context,
                        algorithm=algorithm,
                        length=length)
                except castellan_exc.KeyManagerError:
                    # The messaging back to the client here is
                    # purposefully terse, so we don't leak any sensitive
                    # details.
                    LOG.exception("Key manager error")
                    raise exception.Invalid(message="Key manager error")

        return encryption_key_id
Esempio n. 6
0
    def create_volume_from_snapshot(self, volume, snapshot):
        self.get_volume_stats(True)
        self._assert_enough_space_for_copy(volume['size'])

        LOG.debug("Creating Volume from snapshot %(source_id)s "
                  "(%(dest_id)s)" %
                  {'source_id': snapshot['id'], 'dest_id': volume['id']})

        orig_name = self._get_snap_name(snapshot['id'])
        dest_name = self._get_vol_name(volume['id'])
        try:
            self.client.copy_volume(orig_name, dest_name,
                                    self.config.msa_vdisk)
        except msa.HPMSARequestError as ex:
            LOG.error(ex)
            raise exception.Invalid(ex)

        return None
Esempio n. 7
0
    def create_volume(self, volume):
        volume_id = self._get_vol_name(volume['id'])
        LOG.debug("Create Volume (%(display_name)s: %(name)s %(id)s)" %
                  {'display_name': volume['display_name'],
                   'name': volume['name'], 'id': volume_id})

        # use base64 to encode the volume name (UUID is too long for MSA)
        volume_name = self._get_vol_name(volume['id'])
        volume_size = "%dGB" % volume['size']
        try:
            metadata = self.client.create_volume(self.config.msa_vdisk,
                                                 volume_name,
                                                 volume_size)
        except msa.HPMSARequestError as ex:
            LOG.error(ex)
            raise exception.Invalid(ex)

        return metadata
Esempio n. 8
0
    def delete_volume(self, volume):
        LOG.debug("Deleting Volume: %s", volume['id'])
        if volume['name_id']:
            volume_name = self._get_vol_name(volume['name_id'])
        else:
            volume_name = self._get_vol_name(volume['id'])

        self.client_login()
        try:
            self.client.delete_volume(volume_name)
        except exception.DotHillRequestError as ex:
            # if the volume wasn't found, ignore the error
            if 'The volume was not found on this system.' in ex:
                return
            LOG.exception(_LE("Deletion of volume %s failed."), volume['id'])
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 9
0
    def manage_existing(self, volume, existing_ref):
        """Manage an existing non-openstack DotHill volume

        existing_ref is a dictionary of the form:
        {'source-name': <name of the existing DotHill volume>}
        """
        target_vol_name = existing_ref['source-name']
        modify_target_vol_name = self._get_vol_name(volume['id'])

        self.client_login()
        try:
            self.client.modify_volume_name(target_vol_name,
                                           modify_target_vol_name)
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Error manage existing volume."))
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 10
0
    def create_cloned_volume(self, volume, src_vref):
        self.get_volume_stats(True)
        self._assert_enough_space_for_copy(volume['size'])
        self._assert_source_detached(src_vref)

        LOG.debug("Cloning Volume %(source_id)s (%(dest_id)s)" %
                  {'source_id': volume['source_volid'],
                   'dest_id': volume['id']})

        orig_name = self._get_vol_name(volume['source_volid'])
        dest_name = self._get_vol_name(volume['id'])
        try:
            self.client.copy_volume(orig_name, dest_name,
                                    self.config.msa_vdisk)
        except msa.HPMSARequestError as ex:
            LOG.error(ex)
            raise exception.Invalid(ex)

        return None
Esempio n. 11
0
    def delete_volume(self, ctxt, volume, unmanage_only=False, cascade=False):
        msg_args = {'volume_id': volume.id, 'unmanage_only': unmanage_only}

        version = '1.15'

        if self.client.can_send_version('1.33'):
            version = '1.33'
            msg_args['volume'] = volume

        if self.client.can_send_version('1.40'):
            version = '1.40'
            if cascade:
                msg_args['cascade'] = cascade
        elif cascade:
            msg = _('Cascade option is not supported.')
            raise exception.Invalid(reason=msg)

        cctxt = self._get_cctxt(volume.host, version)
        cctxt.cast(ctxt, 'delete_volume', **msg_args)
Esempio n. 12
0
    def create_snapshot(self, snapshot):
        LOG.debug("Creating snapshot (%(snap_id)s) from %(volume_id)s)",
                  {'snap_id': snapshot['id'],
                   'volume_id': snapshot['volume_id'], })
        if snapshot['volume']['name_id']:
            vol_name = self._get_vol_name(snapshot['volume']['name_id'])
        else:
            vol_name = self._get_vol_name(snapshot['volume_id'])
        snap_name = self._get_snap_name(snapshot['id'])

        self.client_login()
        try:
            self.client.create_snapshot(vol_name, snap_name)
        except dh_exception.DotHillRequestError as ex:
            LOG.exception("Creation of snapshot failed for volume: %s",
                          snapshot['volume_id'])
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 13
0
    def create_volume_from_snapshot(self, volume, snapshot):
        self.get_volume_stats(True)
        self._assert_enough_space_for_copy(volume['size'])
        LOG.debug("Creating Volume from snapshot %(source_id)s to "
                  "(%(dest_id)s)", {'source_id': snapshot['id'],
                                    'dest_id': volume['id'], })

        orig_name = self._get_snap_name(snapshot['id'])
        dest_name = self._get_vol_name(volume['id'])
        self.client_login()
        try:
            self.client.copy_volume(orig_name, dest_name,
                                    self.backend_name, self.backend_type)
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Create volume failed from snapshot: %s"),
                          snapshot['id'])
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 14
0
    def create(self):
        if self.obj_attr_is_set('id'):
            raise exception.ObjectActionError(action='create',
                                              reason='already created')
        updates = self.cinder_obj_get_changes()

        try:
            create_ret = db.qos_specs_create(self._context, updates)
        except db_exc.DBDataError:
            msg = _('Error writing field to database')
            LOG.exception(msg)
            raise exception.Invalid(msg)
        except db_exc.DBError:
            LOG.exception('DB error occurred when creating QoS specs.')
            raise exception.QoSSpecsCreateFailed(name=self.name,
                                                 qos_specs=self.specs)
        # Save ID with the object
        updates['id'] = create_ret['id']
        self._from_db_object(self._context, self, updates)
Esempio n. 15
0
def create_encryption_key(context, key_manager, volume_type_id):
    encryption_key_id = None
    if volume_types.is_encrypted(context, volume_type_id):
        volume_type_encryption = (volume_types.get_volume_type_encryption(
            context, volume_type_id))
        cipher = volume_type_encryption.cipher
        length = volume_type_encryption.key_size
        algorithm = cipher.split('-')[0] if cipher else None
        try:
            encryption_key_id = key_manager.create_key(context,
                                                       algorithm=algorithm,
                                                       length=length)
        except castellan_exception.KeyManagerError:
            # The messaging back to the client here is
            # purposefully terse, so we don't leak any sensitive
            # details.
            LOG.exception("Key manager error")
            raise exception.Invalid(message="Key manager error")

    return encryption_key_id
Esempio n. 16
0
 def extend_volume(self, volume, new_size):
     if volume['name_id']:
         volume_name = self._get_vol_name(volume['name_id'])
     else:
         volume_name = self._get_vol_name(volume['id'])
     old_size = volume['size']
     growth_size = int(new_size) - old_size
     LOG.debug("Extending Volume %(volume_name)s from %(old_size)s to "
               "%(new_size)s, by %(growth_size)s GB.",
               {'volume_name': volume_name,
                'old_size': old_size,
                'new_size': new_size,
                'growth_size': growth_size, })
     self.client_login()
     try:
         self.client.extend_volume(volume_name, "%dGB" % growth_size)
     except exception.DotHillRequestError as ex:
         LOG.exception(_LE("Extension of volume %s failed."), volume['id'])
         raise exception.Invalid(ex)
     finally:
         self.client_logout()
Esempio n. 17
0
    def manage_existing_snapshot(self, snapshot, existing_ref):
        """Import an existing snapshot into Cinder."""

        old_snap_name = existing_ref['source-name']
        new_snap_name = self._get_snap_name(snapshot.id)
        LOG.info("Renaming existing snapshot %(old_name)s to "
                 "%(new_name)s", {
                     "old_name": old_snap_name,
                     "new_name": new_snap_name
                 })

        self.client_login()
        try:
            self.client.modify_volume_name(old_snap_name, new_snap_name)
        except stx_exception.RequestError as ex:
            LOG.exception("Error managing existing snapshot.")
            raise exception.Invalid(ex)
        finally:
            self.client_logout()

        return None
Esempio n. 18
0
    def _update_volume_stats(self):
        # storage_protocol and volume_backend_name are
        # set in the child classes
        stats = {'driver_version': self.VERSION,
                 'free_capacity_gb': 'unknown',
                 'reserved_percentage': 0,
                 'storage_protocol': None,
                 'total_capacity_gb': 'unknown',
                 'QoS_support': False,
                 'vendor_name': 'Hewlett-Packard',
                 'volume_backend_name': None}

        try:
            vdisk_stats = self.client.vdisk_stats(self.config.msa_vdisk)
            stats.update(vdisk_stats)
        except msa.HPMSARequestError:
            err = (_("Unable to get stats for VDisk (%s)")
                   % self.config.msa_vdisk)
            LOG.error(err)
            raise exception.Invalid(reason=err)

        self.stats = stats
Esempio n. 19
0
    def create_volume(self, volume):
        self.client_login()
        # Use base64 to encode the volume name (UUID is too long for DotHill)
        volume_name = self._get_vol_name(volume['id'])
        volume_size = "%dGiB" % volume['size']
        LOG.debug("Create Volume having display_name: %(display_name)s "
                  "name: %(name)s id: %(id)s size: %(size)s",
                  {'display_name': volume['display_name'],
                   'name': volume['name'],
                   'id': volume_name,
                   'size': volume_size, })
        try:
            self.client.create_volume(volume_name,
                                      volume_size,
                                      self.backend_name,
                                      self.backend_type)
        except dh_exception.DotHillRequestError as ex:
            LOG.exception("Creation of volume %s failed.", volume['id'])
            raise exception.Invalid(ex)

        finally:
            self.client_logout()
Esempio n. 20
0
def create(context, name, specs=None):
    """Creates qos_specs.

    :param specs dictionary that contains specifications for QoS
          e.g. {'consumer': 'front-end',
                'total_iops_sec': 1000,
                'total_bytes_sec': 1024000}
    """
    _verify_prepare_qos_specs(specs)

    values = dict(name=name, qos_specs=specs)

    LOG.debug("Dict for qos_specs: %s", values)

    try:
        qos_specs_ref = db.qos_specs_create(context, values)
    except db_exc.DBDataError:
        msg = _('Error writing field to database')
        LOG.exception(msg)
        raise exception.Invalid(msg)
    except db_exc.DBError:
        LOG.exception(_LE('DB error:'))
        raise exception.QoSSpecsCreateFailed(name=name, qos_specs=specs)
    return qos_specs_ref
    def create_cloned_volume(self, volume, src_vref):
        self.get_volume_stats(True)
        self._assert_enough_space_for_copy(volume['size'])
        self._assert_source_detached(src_vref)
        LOG.debug("Cloning Volume %(source_id)s to (%(dest_id)s)", {
            'source_id': src_vref['id'],
            'dest_id': volume['id'],
        })

        if src_vref['name_id']:
            orig_name = self._get_vol_name(src_vref['name_id'])
        else:
            orig_name = self._get_vol_name(src_vref['id'])
        dest_name = self._get_vol_name(volume['id'])

        self.client_login()
        try:
            self.client.copy_volume(orig_name, dest_name, self.backend_name,
                                    self.backend_type)
        except exception.DotHillRequestError as ex:
            LOG.exception(_LE("Cloning of volume %s failed."), src_vref['id'])
            raise exception.Invalid(ex)
        finally:
            self.client_logout()
Esempio n. 22
0
 def _test_with_mock(self, mock, method, args, expected=None):
     func = getattr(self.driver, method)
     mock.side_effect = [exception.Invalid(), None]
     self.assertRaises(exception.Invalid, func, *args)
     self.assertEqual(expected, func(*args))
Esempio n. 23
0
    def __init__(self,
                 vg_name,
                 root_helper,
                 create_vg=False,
                 physical_volumes=None,
                 lvm_type='default',
                 executor=putils.execute,
                 lvm_conf=None,
                 suppress_fd_warn=False):
        """Initialize the LVM object.

        The LVM object is based on an LVM VolumeGroup, one instantiation
        for each VolumeGroup you have/use.

        :param vg_name: Name of existing VG or VG to create
        :param root_helper: Execution root_helper method to use
        :param create_vg: Indicates the VG doesn't exist
                          and we want to create it
        :param physical_volumes: List of PVs to build VG on
        :param lvm_type: VG and Volume type (default, or thin)
        :param executor: Execute method to use, None uses common/processutils
        :param suppress_fd_warn: Add suppress FD Warn to LVM env

        """
        super(LVM, self).__init__(execute=executor, root_helper=root_helper)
        self.vg_name = vg_name
        self.pv_list = []
        self.vg_size = 0.0
        self.vg_free_space = 0.0
        self.vg_lv_count = 0
        self.vg_uuid = None
        self.vg_thin_pool = None
        self.vg_thin_pool_size = 0.0
        self.vg_thin_pool_free_space = 0.0
        self._supports_snapshot_lv_activation = None
        self._supports_lvchange_ignoreskipactivation = None
        self.vg_provisioned_capacity = 0.0

        if lvm_type not in ['default', 'thin']:
            raise exception.Invalid('lvm_type must be "default" or "thin"')

        # Ensure LVM_SYSTEM_DIR has been added to LVM.LVM_CMD_PREFIX
        # before the first LVM command is executed, and use the directory
        # where the specified lvm_conf file is located as the value.

        # NOTE(jdg): We use the temp var here because LVM_CMD_PREFIX is a
        # class global and if you use append here, you'll literally just keep
        # appending values to the global.
        _lvm_cmd_prefix = ['env', 'LC_ALL=C']

        if lvm_conf and os.path.isfile(lvm_conf):
            lvm_sys_dir = os.path.dirname(lvm_conf)
            _lvm_cmd_prefix.append('LVM_SYSTEM_DIR=' + lvm_sys_dir)

        if suppress_fd_warn:
            _lvm_cmd_prefix.append('LVM_SUPPRESS_FD_WARNINGS=1')
        LVM.LVM_CMD_PREFIX = _lvm_cmd_prefix

        lvm_version = LVM.get_lvm_version(root_helper)
        if LVM.get_lvm_version(root_helper) < MINIMUM_LVM_VERSION:
            LOG.warning(
                "LVM version %(current)s is lower than the minimum "
                "supported version: %(supported)s", {
                    'current': lvm_version,
                    'supported': MINIMUM_LVM_VERSION
                })

        if create_vg and physical_volumes is not None:
            try:
                self._create_vg(physical_volumes)
            except putils.ProcessExecutionError as err:
                LOG.exception('Error creating Volume Group')
                LOG.error('Cmd     :%s', err.cmd)
                LOG.error('StdOut  :%s', err.stdout)
                LOG.error('StdErr  :%s', err.stderr)
                raise exception.VolumeGroupCreationFailed(vg_name=self.vg_name)

        if self._vg_exists() is False:
            LOG.error('Unable to locate Volume Group %s', vg_name)
            raise exception.VolumeGroupNotFound(vg_name=vg_name)

        # NOTE: we assume that the VG has been activated outside of Cinder

        if lvm_type == 'thin':
            pool_name = "%s-pool" % self.vg_name
            if self.get_volume(pool_name) is None:
                try:
                    self.create_thin_pool(pool_name)
                except putils.ProcessExecutionError:
                    # Maybe we just lost the race against another copy of
                    # this driver being in init in parallel - e.g.
                    # cinder-volume and cinder-backup starting in parallel
                    if self.get_volume(pool_name) is None:
                        raise

            self.vg_thin_pool = pool_name
            self.activate_lv(self.vg_thin_pool)
        self.pv_list = self.get_all_physical_volumes(root_helper, vg_name)
Esempio n. 24
0
 def get_active_iscsi_target_iqns(self):
     try:
         return self.client.get_active_iscsi_target_iqns()
     except exception.DotHillRequestError as ex:
         LOG.exception(_LE("Error getting active ISCSI target iqns."))
         raise exception.Invalid(ex)
Esempio n. 25
0
 def get_active_fc_target_ports(self):
     try:
         return self.client.get_active_fc_target_ports()
     except exception.DotHillRequestError as ex:
         LOG.exception(_LE("Error getting active FC target ports."))
         raise exception.Invalid(ex)
Esempio n. 26
0
    def create_volume(self, volume, client):
        LOG.debug("CREATE VOLUME (%s : %s %s)" %
                  (volume['display_name'], volume['name'],
                   self._get_3par_vol_name(volume['id'])))
        try:
            comments = {
                'volume_id': volume['id'],
                'name': volume['name'],
                'type': 'OpenStack'
            }

            name = volume.get('display_name', None)
            if name:
                comments['display_name'] = name

            # get the options supported by volume types
            volume_type = None
            type_id = volume.get('volume_type_id', None)
            if type_id is not None:
                volume_type = self._get_volume_type(type_id)

            cpg = self._get_volume_type_value(volume_type, 'cpg',
                                              self.config.hp3par_cpg)

            # if provisioning is not set use thin
            default_prov = self.valid_prov_values[0]
            prov_value = self._get_volume_type_value(volume_type,
                                                     'provisioning',
                                                     default_prov)
            # check for valid provisioning type
            if prov_value not in self.valid_prov_values:
                err = _("Must specify a valid provisioning type %(valid)s, "
                        "value '%(prov)s' is invalid.") % \
                       ({'valid': self.valid_prov_values,
                         'prov': prov_value})
                raise exception.InvalidInput(reason=err)

            ttpv = True
            if prov_value == "full":
                ttpv = False

            # default to hp3par_cpg if hp3par_cpg_snap is not set.
            if self.config.hp3par_cpg_snap == "":
                snap_default = self.config.hp3par_cpg
            else:
                snap_default = self.config.hp3par_cpg_snap
            snap_cpg = self._get_volume_type_value(volume_type, 'snap_cpg',
                                                   snap_default)

            # check for valid persona even if we don't use it until
            # attach time, this will given end user notice that the
            # persona type is invalid at volume creation time
            self.get_persona_type(volume)

            if type_id is not None:
                comments['volume_type_name'] = volume_type.get('name')
                comments['volume_type_id'] = type_id

            extras = {
                'comment': json.dumps(comments),
                'snapCPG': snap_cpg,
                'tpvv': ttpv
            }

            capacity = self._capacity_from_size(volume['size'])
            volume_name = self._get_3par_vol_name(volume['id'])
            client.createVolume(volume_name, cpg, capacity, extras)

        except hpexceptions.HTTPConflict:
            raise exception.Duplicate(
                _("Volume (%s) already exists on array") % volume_name)
        except hpexceptions.HTTPBadRequest as ex:
            LOG.error(str(ex))
            raise exception.Invalid(ex.get_description())
        except exception.InvalidInput as ex:
            LOG.error(str(ex))
            raise ex
        except Exception as ex:
            LOG.error(str(ex))
            raise exception.CinderException(ex.get_description())

        metadata = {
            '3ParName': volume_name,
            'CPG': self.config.hp3par_cpg,
            'snapCPG': extras['snapCPG']
        }
        return metadata
Esempio n. 27
0
 def get_chap_record(self, initiator_name):
     try:
         return self.client.get_chap_record(initiator_name)
     except exception.DotHillRequestError as ex:
         LOG.exception(_LE("Error getting chap record."))
         raise exception.Invalid(ex)
Esempio n. 28
0
    def create_volume(self, volume):
        LOG.debug("CREATE VOLUME (%s : %s %s)" %
                  (volume['display_name'], volume['name'],
                   self._get_3par_vol_name(volume['id'])))
        try:
            comments = {'volume_id': volume['id'],
                        'name': volume['name'],
                        'type': 'OpenStack'}

            name = volume.get('display_name', None)
            if name:
                comments['display_name'] = name

            # get the options supported by volume types
            type_info = self.get_volume_settings_from_type(volume)
            volume_type = type_info['volume_type']
            vvs_name = type_info['vvs_name']
            qos = type_info['qos']
            cpg = type_info['cpg']
            snap_cpg = type_info['snap_cpg']
            tpvv = type_info['tpvv']

            type_id = volume.get('volume_type_id', None)
            if type_id is not None:
                comments['volume_type_name'] = volume_type.get('name')
                comments['volume_type_id'] = type_id
                if vvs_name is not None:
                    comments['vvs'] = vvs_name
                else:
                    comments['qos'] = qos

            extras = {'comment': json.dumps(comments),
                      'snapCPG': snap_cpg,
                      'tpvv': tpvv}

            capacity = self._capacity_from_size(volume['size'])
            volume_name = self._get_3par_vol_name(volume['id'])
            self.client.createVolume(volume_name, cpg, capacity, extras)
            if qos or vvs_name is not None:
                try:
                    self._add_volume_to_volume_set(volume, volume_name,
                                                   cpg, vvs_name, qos)
                except exception.InvalidInput as ex:
                    # Delete the volume if unable to add it to the volume set
                    self.client.deleteVolume(volume_name)
                    LOG.error(str(ex))
                    raise exception.CinderException(str(ex))
        except hpexceptions.HTTPConflict:
            msg = _("Volume (%s) already exists on array") % volume_name
            LOG.error(msg)
            raise exception.Duplicate(msg)
        except hpexceptions.HTTPBadRequest as ex:
            LOG.error(str(ex))
            raise exception.Invalid(ex.get_description())
        except exception.InvalidInput as ex:
            LOG.error(str(ex))
            raise ex
        except exception.CinderException as ex:
            LOG.error(str(ex))
            raise ex
        except Exception as ex:
            LOG.error(str(ex))
            raise exception.CinderException(str(ex))
Esempio n. 29
0
    def _convert_to_base_volume(self, volume, new_cpg=None):
        try:
            type_info = self.get_volume_settings_from_type(volume)
            if new_cpg:
                cpg = new_cpg
            else:
                cpg = type_info['cpg']

            # Change the name such that it is unique since 3PAR
            # names must be unique across all CPGs
            volume_name = self._get_3par_vol_name(volume['id'])
            temp_vol_name = volume_name.replace("osv-", "omv-")

            # Create a physical copy of the volume
            task_id = self._copy_volume(volume_name, temp_vol_name,
                                        cpg, cpg, type_info['tpvv'])

            LOG.debug(_('Copy volume scheduled: convert_to_base_volume: '
                        'id=%s.') % volume['id'])

            # Wait for the physical copy task to complete
            def _wait_for_task(task_id):
                status = self.client.getTask(task_id)
                LOG.debug("3PAR Task id %(id)s status = %(status)s" %
                          {'id': task_id,
                           'status': status['status']})
                if status['status'] is not self.client.TASK_ACTIVE:
                    self._task_status = status
                    raise loopingcall.LoopingCallDone()

            self._task_status = None
            timer = loopingcall.FixedIntervalLoopingCall(
                _wait_for_task, task_id)
            timer.start(interval=1).wait()

            if self._task_status['status'] is not self.client.TASK_DONE:
                dbg = {'status': self._task_status, 'id': volume['id']}
                msg = _('Copy volume task failed: convert_to_base_volume: '
                        'id=%(id)s, status=%(status)s.') % dbg
                raise exception.CinderException(msg)
            else:
                LOG.debug(_('Copy volume completed: convert_to_base_volume: '
                            'id=%s.') % volume['id'])

            comment = self._get_3par_vol_comment(volume_name)
            if comment:
                self.client.modifyVolume(temp_vol_name, {'comment': comment})
            LOG.debug(_('Volume rename completed: convert_to_base_volume: '
                        'id=%s.') % volume['id'])

            # Delete source volume after the copy is complete
            self.client.deleteVolume(volume_name)
            LOG.debug(_('Delete src volume completed: convert_to_base_volume: '
                        'id=%s.') % volume['id'])

            # Rename the new volume to the original name
            self.client.modifyVolume(temp_vol_name, {'newName': volume_name})

            LOG.info(_('Completed: convert_to_base_volume: '
                       'id=%s.') % volume['id'])
        except hpexceptions.HTTPConflict:
            msg = _("Volume (%s) already exists on array.") % volume_name
            LOG.error(msg)
            raise exception.Duplicate(msg)
        except hpexceptions.HTTPBadRequest as ex:
            LOG.error(str(ex))
            raise exception.Invalid(ex.get_description())
        except exception.InvalidInput as ex:
            LOG.error(str(ex))
            raise ex
        except exception.CinderException as ex:
            LOG.error(str(ex))
            raise ex
        except Exception as ex:
            LOG.error(str(ex))
            raise exception.CinderException(ex)
Esempio n. 30
0
 def create_chap_record(self, initiator_name, chap_secret):
     try:
         self.client.create_chap_record(initiator_name, chap_secret)
     except exception.DotHillRequestError as ex:
         LOG.exception(_LE("Error creating chap record."))
         raise exception.Invalid(ex)