Example #1
0
    def create_share(self, share, share_server=None):
        """Create a share."""
        share_name = share['name']
        share_proto = share['share_proto']

        pool_name = share_utils.extract_host(share['host'], level='pool')

        if not pool_name:
            msg = _("Pool is not available in the share host field.")
            raise exception.InvalidHost(reason=msg)

        result = self.helper._find_all_pool_info()
        poolinfo = self.helper._find_pool_info(pool_name, result)
        if not poolinfo:
            msg = (_("Can not find pool info by pool name: %s") % pool_name)
            raise exception.InvalidHost(reason=msg)

        fs_id = None
        # We sleep here to ensure the newly created filesystem can be read.
        wait_interval = self._get_wait_interval()
        timeout = self._get_timeout()

        try:
            fs_id = self.allocate_container(share, poolinfo)
            fs = self.helper._get_fs_info_by_id(fs_id)
            end_time = time.time() + timeout

            while not (self.check_fs_status(fs['HEALTHSTATUS'],
                                            fs['RUNNINGSTATUS'])
                       or time.time() > end_time):
                time.sleep(wait_interval)
                fs = self.helper._get_fs_info_by_id(fs_id)

            if not self.check_fs_status(fs['HEALTHSTATUS'],
                                        fs['RUNNINGSTATUS']):
                raise exception.InvalidShare(
                    reason=(_('Invalid status of filesystem: %(health)s '
                              '%(running)s.')
                            % {'health': fs['HEALTHSTATUS'],
                               'running': fs['RUNNINGSTATUS']}))
        except Exception as err:
            if fs_id is not None:
                self.helper._delete_fs(fs_id)
            message = (_('Failed to create share %(name)s.'
                         'Reason: %(err)s.')
                       % {'name': share_name,
                          'err': err})
            raise exception.InvalidShare(reason=message)

        try:
            self.helper._create_share(share_name, fs_id, share_proto)
        except Exception as err:
            if fs_id is not None:
                self.helper._delete_fs(fs_id)
            raise exception.InvalidShare(
                reason=(_('Failed to create share %(name)s. Reason: %(err)s.')
                        % {'name': share_name, 'err': err}))

        location = self._get_location_path(share_name, share_proto)
        return location
Example #2
0
    def delete(self, context, share, force=False):
        """Delete share."""
        share = self.db.share_get(context, share['id'])
        if context.is_admin and context.project_id != share['project_id']:
            project_id = share['project_id']
        else:
            project_id = context.project_id

        share_id = share['id']

        statuses = (constants.STATUS_AVAILABLE, constants.STATUS_ERROR,
                    constants.STATUS_INACTIVE)
        if not (force or share['status'] in statuses):
            msg = _("Share status must be one of %(statuses)s") % {
                "statuses": statuses
            }
            raise exception.InvalidShare(reason=msg)

        snapshots = self.db.share_snapshot_get_all_for_share(context, share_id)
        if len(snapshots):
            msg = _("Share still has %d dependent snapshots") % len(snapshots)
            raise exception.InvalidShare(reason=msg)

        cgsnapshot_members_count = self.db.count_cgsnapshot_members_in_share(
            context, share_id)
        if cgsnapshot_members_count:
            msg = (_("Share still has %d dependent cgsnapshot members") %
                   cgsnapshot_members_count)
            raise exception.InvalidShare(reason=msg)

        # Make sure share is not part of a migration
        if share['task_state'] not in (
                None, constants.STATUS_TASK_STATE_MIGRATION_ERROR,
                constants.STATUS_TASK_STATE_MIGRATION_SUCCESS):
            msg = _("Share %s is busy as part of an active "
                    "task.") % share['id']
            LOG.error(msg)
            raise exception.InvalidShare(reason=msg)

        try:
            reservations = QUOTAS.reserve(context,
                                          project_id=project_id,
                                          shares=-1,
                                          gigabytes=-share['size'])
        except Exception as e:
            reservations = None
            LOG.exception(_LE("Failed to update quota for deleting share: %s"),
                          six.text_type(e))

        ownername = context.user_id
        #lease.delete_success(share['id'], ownername)

        for share_instance in share.instances:
            if share_instance['host']:
                self.delete_instance(context, share_instance, force=force)
            else:
                self.db.share_instance_delete(context, share_instance['id'])

        if reservations:
            QUOTAS.commit(context, reservations, project_id=project_id)
Example #3
0
    def shrink_share(self, share, new_size, share_server):
        """Shrinks size of existing share."""
        share_proto = share['share_proto']
        share_name = share['name']

        # The unit is in sectors.
        size = int(new_size) * units.Mi * 2
        share_url_type = self.helper._get_share_url_type(share_proto)

        share = self.helper._get_share_by_name(share_name, share_url_type)
        if not share:
            err_msg = (_("Can not get share ID by share %s.") % share_name)
            LOG.error(err_msg)
            raise exception.InvalidShare(reason=err_msg)

        fsid = share['FSID']
        fs_info = self.helper._get_fs_info_by_id(fsid)
        if not fs_info:
            err_msg = (_("Can not get filesystem info by filesystem ID: %s.") %
                       fsid)
            LOG.error(err_msg)
            raise exception.InvalidShare(reason=err_msg)

        current_size = int(fs_info['CAPACITY']) / units.Mi / 2
        if current_size < new_size:
            err_msg = (_("New size for shrink must be less than current "
                         "size on array. (current: %(size)s, "
                         "new: %(new_size)s).") % {
                             'size': current_size,
                             'new_size': new_size
                         })
            LOG.error(err_msg)
            raise exception.InvalidShare(reason=err_msg)

        self.helper._change_share_size(fsid, size)
Example #4
0
 def xml_response_check(self, xmlout, command, countpath=None):
     """Sanity check for GlusterFS XML response."""
     commandstr = ' '.join(command)
     ret = {}
     for e in 'opRet', 'opErrno':
         ret[e] = int(volxml_get(xmlout, e))
     if ret == {'opRet': -1, 'opErrno': 0}:
         raise exception.GlusterfsException(_(
             'GlusterFS command %(command)s on volume %(volume)s failed'
         ) % {'volume': self.volume, 'command': command})
     if list(six.itervalues(ret)) != [0, 0]:
         errdct = {'volume': self.volume, 'command': commandstr,
                   'opErrstr': volxml_get(xmlout, 'opErrstr', default=None)}
         errdct.update(ret)
         raise exception.InvalidShare(_(
             'GlusterFS command %(command)s on volume %(volume)s got '
             'unexpected response: '
             'opRet=%(opRet)s, opErrno=%(opErrno)s, opErrstr=%(opErrstr)s'
         ) % errdct)
     if not countpath:
         return
     count = volxml_get(xmlout, countpath)
     if count != '1':
         raise exception.InvalidShare(
             _('GlusterFS command %(command)s on volume %(volume)s got '
               'ambiguous response: '
               '%(count)s records') % {
                 'volume': self.volume, 'command': commandstr,
                 'count': count})
Example #5
0
 def allow_access(self, ctx, share, access_type, access_to):
     """Allow access to share."""
     if not share['host']:
         msg = _("Share host is None")
         raise exception.InvalidShare(reason=msg)
     if share['status'] not in ["available"]:
         msg = _("Share status must be available")
         raise exception.InvalidShare(reason=msg)
     policy.check_policy(ctx, 'share', 'allow_access')
     values = {
         'share_id': share['id'],
         'access_type': access_type,
         'access_to': access_to
     }
     access = [
         a for a in self.db.share_access_get_all_by_type_and_access(
             ctx, share['id'], access_type, access_to)
         if a['state'] != 'error'
     ]
     if access:
         raise exception.ShareAccessExists(access_type=access_type,
                                           access=access_to)
     access = self.db.share_access_create(ctx, values)
     self.share_rpcapi.allow_access(ctx, share, access)
     return access
Example #6
0
    def unmanage_share(self, context, share_id):
        context = context.elevated()
        share_ref = self.db.share_get(context, share_id)
        share_server = self._get_share_server(context, share_ref)
        project_id = share_ref['project_id']

        def share_manage_set_error_status(msg, exception):
            status = {'status': constants.STATUS_UNMANAGE_ERROR}
            self.db.share_update(context, share_id, status)
            LOG.error(msg, six.text_type(exception))

        try:
            if self.driver.driver_handles_share_servers:
                msg = _("Unmanage share is not supported for "
                        "driver_handles_share_servers=True mode.")
                raise exception.InvalidShare(reason=msg)

            if share_server:
                msg = _("Unmanage share is not supported for "
                        "shares with share servers.")
                raise exception.InvalidShare(reason=msg)

            self.driver.unmanage(share_ref)

        except exception.InvalidShare as e:
            share_manage_set_error_status(
                _LE("Share can not be unmanaged: %s."), e)
            return

        try:
            reservations = QUOTAS.reserve(context,
                                          project_id=project_id,
                                          shares=-1,
                                          gigabytes=-share_ref['size'])
            QUOTAS.commit(context, reservations, project_id=project_id)
        except Exception as e:
            # Note(imalinovskiy):
            # Quota reservation errors here are not fatal, because
            # unmanage is administrator API and he/she could update user
            # quota usages later if it's required.
            LOG.warning(_LE("Failed to update quota usages: %s."),
                        six.text_type(e))

        if self.configuration.safe_get('unmanage_remove_access_rules'):
            try:
                self._remove_share_access_rules(context, share_ref,
                                                share_server)
            except Exception as e:
                share_manage_set_error_status(
                    _LE("Can not remove access rules of share: %s."), e)
                return

        self.db.share_update(context, share_id,
                             {'status': constants.STATUS_UNMANAGED,
                              'deleted': True})
Example #7
0
File: api.py Project: wzhmei/manila
    def delete(self, context, share, force=False):
        """Delete share."""
        share = self.db.share_get(context, share['id'])
        if context.is_admin and context.project_id != share['project_id']:
            project_id = share['project_id']
        else:
            project_id = context.project_id

        share_id = share['id']

        statuses = (constants.STATUS_AVAILABLE, constants.STATUS_ERROR,
                    constants.STATUS_INACTIVE)
        if not (force or share['status'] in statuses):
            msg = _("Share status must be one of %(statuses)s") % {
                "statuses": statuses
            }
            raise exception.InvalidShare(reason=msg)

        snapshots = self.db.share_snapshot_get_all_for_share(context, share_id)
        if len(snapshots):
            msg = _("Share still has %d dependent snapshots") % len(snapshots)
            raise exception.InvalidShare(reason=msg)

        cgsnapshot_members_count = self.db.count_cgsnapshot_members_in_share(
            context, share_id)
        if cgsnapshot_members_count:
            msg = (_("Share still has %d dependent cgsnapshot members") %
                   cgsnapshot_members_count)
            raise exception.InvalidShare(reason=msg)

        self._check_is_share_busy(share)

        try:
            reservations = QUOTAS.reserve(context,
                                          project_id=project_id,
                                          shares=-1,
                                          gigabytes=-share['size'])
        except Exception as e:
            reservations = None
            LOG.exception(_LE("Failed to update quota for deleting share: %s"),
                          six.text_type(e))

        for share_instance in share.instances:
            if share_instance['host']:
                self.delete_instance(context, share_instance, force=force)
            else:
                self.db.share_instance_delete(context, share_instance['id'])

        if reservations:
            QUOTAS.commit(context, reservations, project_id=project_id)
Example #8
0
    def delete(self, context, share, force=False):
        """Delete share."""
        if context.is_admin and context.project_id != share['project_id']:
            project_id = share['project_id']
        else:
            project_id = context.project_id

        share_id = share['id']
        if not share['host']:
            try:
                reservations = QUOTAS.reserve(context,
                                              project_id=project_id,
                                              shares=-1,
                                              gigabytes=-share['size'])
            except Exception:
                reservations = None
                LOG.exception(_LE("Failed to update quota for deleting share"))
            self.db.share_delete(context.elevated(), share_id)

            if reservations:
                QUOTAS.commit(context, reservations, project_id=project_id)
            return

        if not (force or share['status'] in ["available", "error"]):
            msg = _("Share status must be available or error")
            raise exception.InvalidShare(reason=msg)

        snapshots = self.db.share_snapshot_get_all_for_share(context, share_id)
        if len(snapshots):
            msg = _("Share still has %d dependent snapshots") % len(snapshots)
            raise exception.InvalidShare(reason=msg)

        now = timeutils.utcnow()
        share = self.db.share_update(context, share_id, {
            'status': 'deleting',
            'terminated_at': now
        })

        self.share_rpcapi.delete_share(context, share)

        # NOTE(u_glide): 'updated_at' timestamp is used to track last usage of
        # share server. This is required for automatic share servers cleanup
        # because we should track somehow period of time when share server
        # doesn't have shares (unused). We do this update only on share
        # deletion because share server with shares cannot be deleted, so no
        # need to do this update on share creation or any other share operation
        if share['share_server_id']:
            self.db.share_server_update(context, share['share_server_id'],
                                        {'updated_at': timeutils.utcnow()})
Example #9
0
    def create_share_from_snapshot(self, context, share, snapshot,
                                   share_server=None):
        """Create a share from a snapshot - clone a snapshot."""
        share_name = share['id']

        share_proto = share['share_proto'].upper()

        # Validate the share protocol
        if share_proto not in ('NFS', 'CIFS'):
            raise exception.InvalidShare(
                reason=(_('Invalid NAS protocol supplied: %s.')
                        % share_proto))

        # Get the pool name from share host field
        pool_name = share_utils.extract_host(share['host'], level='pool')
        if not pool_name:
            message = (_("Pool is not available in the share host %s.") %
                       share['host'])
            raise exception.InvalidHost(reason=message)

        self._share_server_validation(share_server)

        self._allocate_container_from_snapshot(
            share, snapshot, share_server, pool_name)

        if share_proto == 'NFS':
            self._create_nfs_share(share_name, share_server)
            location = ('%(nfs_if)s:/%(share_name)s'
                        % {'nfs_if': share_server['backend_details']['nfs_if'],
                           'share_name': share_name})
        elif share_proto == 'CIFS':
            location = self._create_cifs_share(share_name, share_server)

        return location
Example #10
0
    def _get_gluster_vol_option(self, option):
        try:
            args, kw = self.gluster_address.make_gluster_args(
                '--xml',
                'volume',
                'info',
                self.gluster_address.volume
            )
            out, err = self._execute(*args, **kw)
        except exception.ProcessExecutionError as exc:
            LOG.error(_LE("Error retrieving volume info: %s"), exc.stderr)
            raise exception.GlusterfsException(exc)

        if not out:
            raise exception.GlusterfsException(
                'Empty answer from gluster command'
            )

        vix = etree.fromstring(out)
        if int(vix.find('./volInfo/volumes/count').text) != 1:
            raise exception.InvalidShare('Volume name ambiguity')
        for e in vix.findall(".//option"):
            o, v = (e.find(a).text for a in ('name', 'value'))
            if o == option:
                return v
Example #11
0
    def login(self):
        """Login huawei array."""
        login_info = self._get_login_info()
        urlstr = login_info['RestURL']
        url_list = urlstr.split(";")
        deviceid = None
        for item_url in url_list:
            url = item_url.strip('').strip('\n') + "xx/sessions"
            data = jsonutils.dumps({
                "username": login_info['UserName'],
                "password": login_info['UserPassword'],
                "scope": "0"
            })
            self.init_http_head()
            result = self.do_call(url,
                                  data,
                                  calltimeout=constants.LOGIN_SOCKET_TIMEOUT)

            if ((result['error']['code'] != 0) or ("data" not in result)
                    or (result['data']['deviceid'] is None)):
                LOG.error(_LE("Login to %s failed, try another."), item_url)
                continue

            LOG.debug('Login success: %(url)s\n', {'url': item_url})
            deviceid = result['data']['deviceid']
            self.url = item_url + deviceid
            self.headers['iBaseToken'] = result['data']['iBaseToken']
            break

        if deviceid is None:
            err_msg = _("All url login fail.")
            LOG.error(err_msg)
            raise exception.InvalidShare(reason=err_msg)

        return deviceid
Example #12
0
    def create_share(self, context, share, share_server=None):
        """Create a share and export it based on protocol used."""
        size = share["size"] * units.Gi
        share_name = self._make_share_name(share)

        if share["share_proto"] == "NFS":
            flashblade_fs = purity_fb.FileSystem(
                name=share_name,
                provisioned=size,
                hard_limit_enabled=True,
                fast_remove_directory_enabled=True,
                snapshot_directory_enabled=True,
                nfs=purity_fb.NfsRule(v3_enabled=True,
                                      rules="",
                                      v4_1_enabled=True),
            )
            self._sys.file_systems.create_file_systems(flashblade_fs)
            location = self._get_full_nfs_export_path(share_name)
        else:
            message = _("Unsupported share protocol: %(proto)s.") % {
                "proto": share["share_proto"]
            }
            LOG.exception(message)
            raise exception.InvalidShare(reason=message)
        LOG.info("FlashBlade created share %(name)s", {"name": share_name})

        return location
Example #13
0
    def allocate_container(self, share, poolinfo):
        """Creates filesystem associated to share by name."""
        opts = huawei_utils.get_share_extra_specs_params(
            share['share_type_id'])

        smartx_opts = constants.OPTS_CAPABILITIES
        if opts is not None:
            smart = smartx.SmartX()
            smartx_opts = smart.get_smartx_extra_specs_opts(opts)

        fileParam = self._init_filesys_para(share, poolinfo, smartx_opts)
        fsid = self.helper._create_filesystem(fileParam)

        try:
            smartpartition = smartx.SmartPartition(self.helper)
            smartpartition.add(opts, fsid)

            smartcache = smartx.SmartCache(self.helper)
            smartcache.add(opts, fsid)
        except Exception as err:
            if fsid is not None:
                self.helper._delete_fs(fsid)
            message = (_('Failed to add smartx. Reason: %(err)s.')
                       % {'err': err})
            raise exception.InvalidShare(reason=message)
        return fsid
Example #14
0
 def _get_helper(self, share):
     if share['share_proto'].startswith('NFS'):
         return self._helpers['NFS']
     elif share['share_proto'].startswith('CIFS'):
         return self._helpers['CIFS']
     else:
         raise exception.InvalidShare(reason='Wrong share type')
Example #15
0
 def _get_helper(self, share):
     if share['share_proto'].lower().startswith('nfs'):
         return self._helpers['NFS']
     elif share['share_proto'].lower().startswith('cifs'):
         return self._helpers['CIFS']
     else:
         raise exception.InvalidShare(reason='Wrong share protocol')
Example #16
0
 def _get_helper(self, share):
     helper = self._helpers.get(share['share_proto'])
     if helper:
         return helper
     else:
         raise exception.InvalidShare(
             reason="Wrong, unsupported or disabled protocol")
Example #17
0
    def create_share(self, context, share, share_server=None):
        LOG.debug("Creating share in HSP: %(shr)s", {'shr': share['id']})

        if share['share_proto'].lower() != 'nfs':
            msg = _("Only NFS protocol is currently supported.")
            raise exception.InvalidShare(reason=msg)

        self.hsp.add_file_system(share['id'], share['size'] * units.Gi)
        filesystem_id = self.hsp.get_file_system(share['id'])['id']

        try:
            self.hsp.add_share(share['id'], filesystem_id)
        except exception.HSPBackendException:
            with excutils.save_and_reraise_exception():
                self.hsp.delete_file_system(filesystem_id)
                msg = _LE("Could not create share %s on HSP.")
                LOG.exception(msg, share['id'])

        uri = self.hsp_host + ':/' + share['id']

        LOG.debug("Share created successfully on path: %(uri)s.", {'uri': uri})
        return [{
            "path": uri,
            "metadata": {},
            "is_admin_only": False,
        }]
Example #18
0
    def _get_login_info(self):
        """Get login IP, username and password from config file."""
        logininfo = {}
        filename = self.configuration.manila_huawei_conf_file
        tree = ET.parse(filename)
        root = tree.getroot()
        RestURL = root.findtext('Storage/RestURL')
        logininfo['RestURL'] = RestURL.strip()

        # Prefix !$$$ means encoded already.
        prefix_name = '!$$$'
        need_encode = False
        for key in ['UserName', 'UserPassword']:
            node = root.find('Storage/%s' % key)
            if node.text.find(prefix_name) > -1:
                logininfo[key] = base64.b64decode(six.b(node.text[4:]))
            else:
                logininfo[key] = node.text
                node.text = prefix_name + six.text_type(
                    base64.b64encode(six.b(node.text)))
                need_encode = True
        if need_encode:
            self._change_file_mode(filename)
            try:
                tree.write(filename, 'UTF-8')
            except Exception as err:
                err_msg = (_('File write error %s.') % err)
                LOG.error(err_msg)
                raise exception.InvalidShare(reason=err_msg)

        return logininfo
Example #19
0
 def _verify_share_protocol(self, share):
     if share['share_proto'] != 'NFS':
         reason = (_('Unsupported share protocol: %(proto)s.') % {
             'proto': share['share_proto']
         })
         LOG.error(reason)
         raise exception.InvalidShare(reason=reason)
Example #20
0
    def get_smartprovisioning_opts(self, opts):
        thin_provision = opts.get('thin_provisioning')
        if thin_provision is None:
            root = self.helper._read_xml()
            fstype = root.findtext('Filesystem/AllocType')
            if fstype:
                fstype = fstype.strip().strip('\n')
                if fstype == 'Thin':
                    opts['LUNType'] = constants.ALLOC_TYPE_THIN_FLAG
                elif fstype == 'Thick':
                    opts['LUNType'] = constants.ALLOC_TYPE_THICK_FLAG
                else:
                    err_msg = (_(
                        'Huawei config file is wrong. AllocType type must be '
                        'set to "Thin" or "Thick". AllocType:%(fetchtype)s') %
                               {
                                   'fetchtype': fstype
                               })
                    raise exception.InvalidShare(reason=err_msg)
            else:
                opts['LUNType'] = constants.ALLOC_TYPE_THICK_FLAG
        else:
            if strutils.bool_from_string(thin_provision):
                opts['LUNType'] = constants.ALLOC_TYPE_THIN_FLAG
            else:
                opts['LUNType'] = constants.ALLOC_TYPE_THICK_FLAG

        return opts
Example #21
0
    def create_share_from_snapshot(self,
                                   emc_share_driver,
                                   context,
                                   share,
                                   snapshot,
                                   share_server=None):
        """Is called to create share from snapshot."""
        share_name = share['name']
        vdm_ref = self.share_server_validation(share_server)
        self.allocate_container_from_snapshot(share, snapshot, vdm_ref)

        if share['share_proto'].startswith('NFS'):
            self._create_nfs_share(share_name, vdm_ref['name'], share_server)
            location = ('%(nfs_if)s:/%(share_name)s' % {
                'nfs_if': share_server['backend_details']['nfs_if'],
                'share_name': share_name
            })
        elif share['share_proto'].startswith('CIFS'):
            location = self._create_cifs_share(share_name, vdm_ref)
        else:
            raise exception.InvalidShare(
                reason=(_('Invalid NAS protocol supplied: %s.') %
                        share['share_proto']))

        return location
Example #22
0
    def create_share(self, ctx, share, share_server=None):
        """Create new share on HDS Scale-out Platform."""
        sharesize = int(six.text_type(share['size']))

        httpclient = httplib2.Http(disable_ssl_certificate_validation=True,
                                   timeout=None)

        if share['share_proto'] != 'NFS':
            raise exception.InvalidShare(
                reason=(_('Invalid NAS protocol supplied: %s.') %
                        share['share_proto']))

        payload = {
            'quota': sharesize * units.Gi,
            'enabled': True,
            'description': '',
            'record-access-time': True,
            'tags': '',
            'space-hwm': 90,
            'space-lwm': 70,
            'name': share['id'],
        }
        self._add_file_system_sopapi(httpclient, payload)
        payload = {
            'description': '',
            'type': 'NFS',
            'enabled': True,
            'tags': '',
            'name': share['id'],
            'file-system-id': self._get_file_system_id_by_name(
                httpclient, share['id']),
        }
        return self.sop_target + ':/' + self._add_share_sopapi(
            httpclient, payload)
Example #23
0
 def _get_helper(self, share):
     """Choose a protocol specific helper class."""
     if share['share_proto'] == 'NFS':
         return self._helpers['NFS']
     else:
         raise exception.InvalidShare(
             reason=(_('Unsupported share type, %s.') %
                     share['share_proto']))
Example #24
0
 def _get_location_path(self, path, protocol):
     location = None
     if protocol == 'NFS':
         location = {'path': '%s:/volumes/%s' % (self.nms_host, path)}
     else:
         raise exception.InvalidShare(
             reason=(_('Only NFS protocol is currently supported.')))
     return location
Example #25
0
 def test_create_share_error_unsupported_share_type(self):
     self.mock_object(
         self._driver, '_get_helper',
         mock.Mock(side_effect=exception.InvalidShare(
             reason="Unsupported Share type")))
     self.assertRaises(exception.InvalidShare, self._driver.create_share,
                       self._context, self.share)
     self._driver._get_helper.assert_called_once_with(self.share)
Example #26
0
 def _assert_rest_result(self, result, err_str):
     if result['error']['code'] != 0:
         err_msg = (_('%(err)s\nresult: %(res)s.') % {
             'err': err_str,
             'res': result
         })
         LOG.error(err_msg)
         raise exception.InvalidShare(reason=err_msg)
Example #27
0
 def _get_helper(self, share):
     if share['share_proto'] == 'NFS':
         return self._helpers[self.configuration.gpfs_nfs_server_type]
     else:
         msg = (_('Share protocol %s not supported by GPFS driver.')
                % share['share_proto'])
         LOG.error(msg)
         raise exception.InvalidShare(reason=msg)
Example #28
0
    def manage_share(self, context, share_id, driver_options):
        context = context.elevated()
        share_ref = self.db.share_get(context, share_id)
        project_id = share_ref['project_id']

        try:
            if self.driver.driver_handles_share_servers:
                msg = _("Manage share is not supported for "
                        "driver_handles_share_servers=True mode.")
                raise exception.InvalidShare(reason=msg)

            share_update = (
                self.driver.manage_existing(share_ref, driver_options) or {})

            if not share_update.get('size'):
                msg = _("Driver cannot calculate share size.")
                raise exception.InvalidShare(reason=msg)

            self._update_quota_usages(context, project_id, {
                "shares": 1,
                "gigabytes": share_update['size'],
            })

            share_update.update({
                'status': 'available',
                'launched_at': timeutils.utcnow(),
            })

            # NOTE(vponomaryov): we should keep only those export locations
            # that driver has calculated to avoid incompatibilities with one
            # provided by user.
            if 'export_locations' in share_update:
                self.db.share_export_locations_update(
                    context, share_id, share_update.pop('export_locations'),
                    delete=True)

            self.db.share_update(context, share_id, share_update)
        except Exception:
            # NOTE(vponomaryov): set size as 1 because design expects size
            # to be set, it also will allow us to handle delete/unmanage
            # operations properly with this errored share according to quotas.
            self.db.share_update(
                context, share_id,
                {'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
            raise
Example #29
0
def volxml_get(xmlout, path, *default):
    """Extract a value by a path from XML."""
    value = xmlout.find(path)
    if value is None:
        if default:
            return default[0]
        raise exception.InvalidShare(
            _('Xpath %s not found in volume query response XML') % path)
    return value.text
Example #30
0
File: api.py Project: wzhmei/manila
    def extend(self, context, share, new_size):
        policy.check_policy(context, 'share', 'extend')

        if share['status'] != constants.STATUS_AVAILABLE:
            msg_params = {
                'valid_status': constants.STATUS_AVAILABLE,
                'share_id': share['id'],
                'status': share['status'],
            }
            msg = _("Share %(share_id)s status must be '%(valid_status)s' "
                    "to extend, but current status is: "
                    "%(status)s.") % msg_params
            raise exception.InvalidShare(reason=msg)

        self._check_is_share_busy(share)

        size_increase = int(new_size) - share['size']
        if size_increase <= 0:
            msg = (_("New size for extend must be greater "
                     "than current size. (current: %(size)s, "
                     "extended: %(new_size)s).") % {
                         'new_size': new_size,
                         'size': share['size']
                     })
            raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context,
                                          project_id=share['project_id'],
                                          gigabytes=size_increase)
        except exception.OverQuota as exc:
            usages = exc.kwargs['usages']
            quotas = exc.kwargs['quotas']

            def _consumed(name):
                return usages[name]['reserved'] + usages[name]['in_use']

            msg = _LE("Quota exceeded for %(s_pid)s, tried to extend share "
                      "by %(s_size)sG, (%(d_consumed)dG of %(d_quota)dG "
                      "already consumed).")
            LOG.error(
                msg, {
                    's_pid': context.project_id,
                    's_size': size_increase,
                    'd_consumed': _consumed('gigabytes'),
                    'd_quota': quotas['gigabytes']
                })
            raise exception.ShareSizeExceedsAvailableQuota(
                requested=size_increase,
                consumed=_consumed('gigabytes'),
                quota=quotas['gigabytes'])

        self.update(context, share, {'status': constants.STATUS_EXTENDING})
        self.share_rpcapi.extend_share(context, share, new_size, reservations)
        LOG.info(_LI("Extend share request issued successfully."),
                 resource=share)