Exemplo n.º 1
0
    def _clone_object(self, oname, coname):
        """Creates a clone of specified object

        :param: oname: name of an object to clone
        :param: coname: name of a new clone
        """
        LOG.debug('cloning %(oname)s to %(coname)s', {
            "oname": oname,
            "coname": coname
        })

        try:
            self.ra.create_snapshot(oname, coname)
        except jexc.JDSSSnapshotExistsException:
            try:
                self.ra.delete_snapshot(oname, coname)
            except jexc.JDSSSnapshotIsBusyException as jerrisbusy:
                raise exception.Duplicate() from jerrisbusy
            except jexc.JDSSException as jerr:
                raise exception.VolumeBackendAPIException(
                    (_("Unable to create volume %s.") % coname)) from jerr
        except jexc.JDSSResourceNotFoundException as jerrnotfound:
            if jcom.is_volume(oname):
                raise exception.VolumeNotFound(
                    volume_id=jcom.idname(oname)) from jerrnotfound
            raise exception.SnapshotNotFound(
                snapshot_id=jcom.idname(oname)) from jerrnotfound

        except jexc.JDSSException as jerr:
            args = {'snapshot': coname, 'object': oname, 'err': jerr}
            msg = (_('Failed to create tmp snapshot %(snapshot)s '
                     'for object %(object)s: %(err)s') % args)
            raise exception.VolumeBackendAPIException(msg)

        try:
            self.ra.create_volume_from_snapshot(coname,
                                                coname,
                                                oname,
                                                sparse=self.jovian_sparse)
        except jexc.JDSSResourceExistsException as jerr:
            raise exception.Duplicate() from jerr
        except jexc.JDSSException as jerr:
            try:
                self.ra.delete_snapshot(oname,
                                        coname,
                                        recursively_children=True,
                                        recursively_dependents=True,
                                        force_umount=True)
            except jexc.JDSSException as jerrd:
                LOG.warning(
                    "Because of %s physical snapshot %s of volume"
                    " %s have to be removed manually", jerrd, coname, oname)

            raise exception.VolumeBackendAPIException(
                _("Unable to create volume %(vol)s because of %(err)s.") % {
                    'vol': coname,
                    'err': jerr
                }) from jerr
Exemplo n.º 2
0
 def save(self, session=None):
     """Save this object."""
     if not session:
         session = get_session()
     session.add(self)
     try:
         session.flush()
     except IntegrityError, e:
         if str(e).endswith('is not unique'):
             raise exception.Duplicate(str(e))
         else:
             raise
Exemplo n.º 3
0
    def create(self, context, metadata, data=None):
        """Store the image data and return the new image id.

        :raises: Duplicate if the image already exist.

        """
        image_id = str(metadata.get('id', uuid.uuid4()))
        metadata['id'] = image_id
        if image_id in self.images:
            raise exception.Duplicate()
        self.images[image_id] = copy.deepcopy(metadata)
        if data:
            self._imagedata[image_id] = data.read()
        return self.images[image_id]
Exemplo n.º 4
0
    def _create_target(self, target_name, use_chap=True):
        """Creates target and handles exceptions

        Tryes to create target.
        :param target_name: name of target
        :param use_chap: flag for using chap
        """
        try:
            self.ra.create_target(target_name,
                                  use_chap=use_chap)

        except jexc.JDSSResourceExistsException:
            raise exception.Duplicate()
        except jexc.JDSSException as ex:

            msg = (_('Unable to create target %(target)s '
                     'because of %(error)s.') % {'target': target_name,
                                                 'error': ex})
            raise exception.VolumeBackendAPIException(msg)
Exemplo n.º 5
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
Exemplo n.º 6
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))
Exemplo n.º 7
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)
Exemplo n.º 8
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
            volume_type = None
            vvs_name = None
            hp3par_keys = {}
            qos = {}
            type_id = volume.get('volume_type_id', None)
            if type_id is not None:
                volume_type = self._get_volume_type(type_id)
                hp3par_keys = self._get_keys_by_volume_type(volume_type)
                vvs_name = self._get_key_value(hp3par_keys, 'vvs')
                if vvs_name is None:
                    qos = self._get_qos_by_volume_type(volume_type)

            cpg = self._get_key_value(hp3par_keys, 'cpg',
                                      self.config.hp3par_cpg)
            if cpg is not self.config.hp3par_cpg:
                # The cpg was specified in a volume type extra spec so it
                # needs to be validiated that it's in the correct domain.
                self.validate_cpg(cpg)
                # Also, look to see if the snap_cpg was specified in volume
                # type extra spec, if not use the extra spec cpg as the
                # default.
                snap_cpg = self._get_key_value(hp3par_keys, 'snap_cpg', cpg)
            else:
                # default snap_cpg to hp3par_cpg_snap if it's not specified
                # in the volume type extra specs.
                snap_cpg = self.config.hp3par_cpg_snap
                # if it's still not set or empty then set it to the cpg
                # specified in the cinder.conf file.
                if not self.config.hp3par_cpg_snap:
                    snap_cpg = cpg

            # if provisioning is not set use thin
            default_prov = self.valid_prov_values[0]
            prov_value = self._get_key_value(hp3par_keys, '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

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

            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': ttpv
            }

            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 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(ex.get_description())
        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())