Example #1
0
    def update(self, req, id, body):
        """Update specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'update')

        if not body or RESOURCE_NAME not in body:
            raise exc.HTTPUnprocessableEntity()

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            msg = "%s" % e
            raise exc.HTTPNotFound(explanation=msg)

        if share_network['share_servers']:
            msg = _("Cannot update share network %s."
                    " It is used by share servers") % share_network['id']
            raise exc.HTTPForbidden(explanation=msg)

        update_values = body[RESOURCE_NAME]

        try:
            share_network = db_api.share_network_update(context,
                                                        id,
                                                        update_values)
        except db_exception.DBError:
            msg = "Could not save supplied data due to database error"
            raise exc.HTTPBadRequest(explanation=msg)

        return self._view_builder.build_share_network(share_network)
Example #2
0
    def update(self, req, id, body):
        """Update specified share network."""
        context = req.environ["manila.context"]
        policy.check_policy(context, RESOURCE_NAME, "update")

        if not body or RESOURCE_NAME not in body:
            raise exc.HTTPUnprocessableEntity()

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            msg = "%s" % e
            raise exc.HTTPNotFound(explanation=msg)

        if share_network["status"] == constants.STATUS_ACTIVE:
            msg = "Network %s is in use" % id
            raise exc.HTTPBadRequest(explanation=msg)

        update_values = body[RESOURCE_NAME]

        try:
            share_network = db_api.share_network_update(context, id, update_values)
        except exception.DBError:
            msg = "Could not save supplied data due to database error"
            raise exc.HTTPBadRequest(explanation=msg)

        return self._view_builder.build_share_network(share_network)
Example #3
0
    def shrink(self, context, share, new_size):
        policy.check_policy(context, 'share', 'shrink')

        status = six.text_type(share['status']).lower()
        valid_statuses = (constants.STATUS_AVAILABLE,
                          constants.STATUS_SHRINKING_POSSIBLE_DATA_LOSS_ERROR)

        if status not in valid_statuses:
            msg_params = {
                'valid_status': ", ".join(valid_statuses),
                'share_id': share['id'],
                'status': status,
            }
            msg = _("Share %(share_id)s status must in (%(valid_status)s) "
                    "to shrink, but current status is: "
                    "%(status)s.") % msg_params
            raise exception.InvalidShare(reason=msg)

        size_decrease = int(share['size']) - int(new_size)
        if size_decrease <= 0 or new_size <= 0:
            msg = (_("New size for shrink must be less "
                     "than current size and greater than 0 (current: %(size)s,"
                     " new: %(new_size)s)") % {'new_size': new_size,
                                               'size': share['size']})
            raise exception.InvalidInput(reason=msg)

        self.update(context, share, {'status': constants.STATUS_SHRINKING})
        self.share_rpcapi.shrink_share(context, share, new_size)
        LOG.info(_LI("Shrink share (id=%(id)s) request issued successfully."
                     " New size: %(size)s") % {'id': share['id'],
                                               'size': new_size})
Example #4
0
    def update(self, req, id, body):
        """Update specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'update')

        if not body or RESOURCE_NAME not in body:
            raise exc.HTTPUnprocessableEntity()

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))

        update_values = body[RESOURCE_NAME]

        self._verify_no_mutually_exclusive_data(share_network, update_values)
        if share_network['share_servers']:
            for value in update_values:
                if value not in ['name', 'description']:
                    msg = _("Cannot update share network %s. It is used by "
                            "share servers. Only 'name' and 'description' "
                            "fields are available for update")\
                        % share_network['id']
                    raise exc.HTTPForbidden(explanation=msg)

        try:
            share_network = db_api.share_network_update(context,
                                                        id,
                                                        update_values)
        except db_exception.DBError:
            msg = "Could not save supplied data due to database error"
            raise exc.HTTPBadRequest(explanation=msg)

        return self._view_builder.build_share_network(share_network)
Example #5
0
 def allow_access(self, ctx, share, access_type, access_to,
                  access_level=None):
     """Allow access to share."""
     if not share['host']:
         msg = _("Share host is None")
         raise exception.InvalidShare(reason=msg)
     if share['status'] != constants.STATUS_AVAILABLE:
         msg = _("Share status must be %s") % constants.STATUS_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_level': access_level,
     }
     for access in self.db.share_access_get_all_by_type_and_access(
             ctx, share['id'], access_type, access_to):
         if access['state'] != constants.STATUS_ERROR:
             raise exception.ShareAccessExists(access_type=access_type,
                                               access=access_to)
     if access_level not in constants.ACCESS_LEVELS + (None, ):
         msg = _("Invalid share access level: %s.") % access_level
         raise exception.InvalidShareAccess(reason=msg)
     access = self.db.share_access_create(ctx, values)
     self.share_rpcapi.allow_access(ctx, share, access)
     return access
Example #6
0
    def _add_security_service(self, req, id, data):
        """Associate share network with a given security service."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'add_security_service')
        share_network = db_api.share_network_get(context, id)
        if share_network['share_servers']:
            msg = _("Cannot add security services. Share network is used.")
            raise exc.HTTPForbidden(explanation=msg)
        security_service = db_api.security_service_get(
            context, data['security_service_id'])
        for attached_service in share_network['security_services']:
            if attached_service['type'] == security_service['type']:
                msg = _("Cannot add security service to share network. "
                        "Security service with '%(ss_type)s' type already "
                        "added to '%(sn_id)s' share network") % {
                            'ss_type': security_service['type'],
                            'sn_id': share_network['id']}
                raise exc.HTTPConflict(explanation=msg)
        try:
            share_network = db_api.share_network_add_security_service(
                context,
                id,
                data['security_service_id'])
        except KeyError:
            msg = "Malformed request body"
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.NotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))
        except exception.ShareNetworkSecurityServiceAssociationError as e:
            raise exc.HTTPBadRequest(explanation=six.text_type(e))

        return self._view_builder.build_share_network(share_network)
Example #7
0
    def delete(self, req, id):
        """Delete specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'delete')

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            msg = "%s" % e
            raise exc.HTTPNotFound(explanation=msg)
        if share_network['share_servers']:
            msg = _("Cannot delete share network %s. "
                    "There are share servers using it") % id
            raise exc.HTTPForbidden(explanation=msg)
        db_api.share_network_delete(context, id)

        try:
            reservations = QUOTAS.reserve(
                context, project_id=share_network['project_id'],
                share_networks=-1)
        except Exception:
            msg = _("Failed to update usages deleting share-network.")
            LOG.exception(msg)
        else:
            QUOTAS.commit(context, reservations,
                          project_id=share_network['project_id'])
        return webob.Response(status_int=202)
Example #8
0
    def index(self, req):
        """Returns a list of share servers."""

        context = req.environ["manila.context"]
        policy.check_policy(context, RESOURCE_NAME, "index")

        search_opts = {}
        search_opts.update(req.GET)

        share_servers = db_api.share_server_get_all(context)
        for s in share_servers:
            s.project_id = s.share_network["project_id"]
            if s.share_network["name"]:
                s.share_network_name = s.share_network["name"]
            else:
                s.share_network_name = s.share_network_id
        if search_opts:
            for k, v in six.iteritems(search_opts):
                share_servers = [
                    s
                    for s in share_servers
                    if (
                        hasattr(s, k)
                        and s[k] == v
                        or k == "share_network"
                        and v in [s.share_network["name"], s.share_network["id"]]
                    )
                ]
        return self._view_builder.build_share_servers(share_servers)
Example #9
0
 def get_all(self, context, search_opts=None):
     policy.check_policy(context, 'share', 'get_all')
     if search_opts is None:
         search_opts = {}
     if 'share_server_id' in search_opts:
         # NOTE(vponomaryov): this is project_id independent
         policy.check_policy(context, 'share', 'list_by_share_server_id')
         shares = self.db.share_get_all_by_share_server(
             context, search_opts.pop('share_server_id'))
     elif (context.is_admin and 'all_tenants' in search_opts):
         shares = self.db.share_get_all(context)
     else:
         shares = self.db.share_get_all_by_project(context,
                                                   context.project_id)
     # NOTE(vponomaryov): we do not need 'all_tenants' opt anymore
     search_opts.pop('all_tenants', None)
     if search_opts:
         LOG.debug("Searching for shares by: %s" % str(search_opts))
         results = []
         for s in shares:
             # values in search_opts can be only strings
             if all(s.get(k, None) == v for k, v in search_opts.items()):
                 results.append(s)
         shares = results
     return shares
Example #10
0
    def delete(self, req, id):
        """Delete specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'delete')

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))

        shares = db_api.share_get_all_by_share_network(context, id)
        if shares:
            msg = _("Can not delete share network %(id)s, it has "
                    "%(len)s share(s).") % {'id': id, 'len': len(shares)}
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)
        for share_server in share_network['share_servers']:
            self.share_rpcapi.delete_share_server(context, share_server)
        db_api.share_network_delete(context, id)

        try:
            reservations = QUOTAS.reserve(
                context, project_id=share_network['project_id'],
                share_networks=-1)
        except Exception:
            LOG.exception(_LE("Failed to update usages deleting "
                              "share-network."))
        else:
            QUOTAS.commit(context, reservations,
                          project_id=share_network['project_id'])
        return webob.Response(status_int=202)
Example #11
0
    def delete_instance(self, context, share_instance, force=False):
        policy.check_policy(context, 'share', 'delete')

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

        share_instance = self.db.share_instance_update(
            context, share_instance['id'],
            {'status': constants.STATUS_DELETING,
             'terminated_at': timeutils.utcnow()}
        )

        self.share_rpcapi.delete_share_instance(context, share_instance)

        # 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_instance['share_server_id']:
            self.db.share_server_update(
                context,
                share_instance['share_server_id'],
                {'updated_at': timeutils.utcnow()})
Example #12
0
    def deny_access(self, ctx, share, access):
        """Deny access to share."""
        policy.check_policy(ctx, 'share', 'deny_access')
        # First check state of the target share
        share = self.db.share_get(ctx, share['id'])
        if not (share.instances and share.instance['host']):
            msg = _("Share doesn't have any instances")
            raise exception.InvalidShare(reason=msg)
        if share['status'] != constants.STATUS_AVAILABLE:
            msg = _("Share status must be %s") % constants.STATUS_AVAILABLE
            raise exception.InvalidShare(reason=msg)

        # Then check state of the access rule
        if (access['state'] == constants.STATUS_ERROR and not
                self.db.share_instance_access_get_all(ctx, access['id'])):
            self.db.share_access_delete(ctx, access["id"])

        elif access['state'] in [constants.STATUS_ACTIVE,
                                 constants.STATUS_ERROR]:
            for share_instance in share.instances:
                try:
                    self.deny_access_to_instance(ctx, share_instance, access)
                except exception.NotFound:
                    LOG.warn(_LW("Access rule %(access_id)s not found "
                                 "for instance %(instance_id)s.") % {
                        'access_id': access['id'],
                        'instance_id': share_instance['id']})
        else:
            msg = _("Access policy should be %(active)s or in %(error)s "
                    "state") % {"active": constants.STATUS_ACTIVE,
                                "error": constants.STATUS_ERROR}
            raise exception.InvalidShareAccess(reason=msg)
Example #13
0
    def update(self, req, id, body):
        """Update a security service."""
        context = req.environ['manila.context']

        if not body or 'security_service' not in body:
            raise exc.HTTPUnprocessableEntity()

        security_service_data = body['security_service']
        valid_update_keys = (
            'description',
            'name'
        )

        try:
            security_service = db.security_service_get(context, id)
            policy.check_policy(context, RESOURCE_NAME, 'update',
                                security_service)
        except exception.NotFound:
            raise exc.HTTPNotFound()

        if self._share_servers_dependent_on_sn_exist(context, id):
            for item in security_service_data:
                if item not in valid_update_keys:
                    msg = _("Cannot update security service %s. It is "
                            "attached to share network with share server "
                            "associated. Only 'name' and 'description' "
                            "fields are available for update.") % id
                    raise exc.HTTPForbidden(explanation=msg)

        policy.check_policy(context, RESOURCE_NAME, 'update', security_service)
        security_service = db.security_service_update(
            context, id, security_service_data)
        return self._view_builder.detail(req, security_service)
Example #14
0
    def get_all_snapshots(self, context, search_opts=None):
        policy.check_policy(context, 'share', 'get_all_snapshots')

        search_opts = search_opts or {}

        if (context.is_admin and 'all_tenants' in search_opts):
            # Need to remove all_tenants to pass the filtering below.
            del search_opts['all_tenants']
            snapshots = self.db.share_snapshot_get_all(context)
        else:
            snapshots = self.db.share_snapshot_get_all_by_project(
                context, context.project_id)

        if search_opts:
            LOG.debug("Searching by: %s" % str(search_opts))

            results = []
            not_found = object()
            for snapshot in snapshots:
                for opt, value in search_opts.iteritems():
                    if snapshot.get(opt, not_found) != value:
                        break
                else:
                    results.append(snapshot)
            snapshots = results
        return snapshots
Example #15
0
    def update(self, req, id, body):
        """Update a security service."""
        context = req.environ['manila.context']

        if not body or 'security_service' not in body:
            raise exc.HTTPUnprocessableEntity()

        security_service_data = body['security_service']
        valid_update_keys = (
            'description',
            'name'
        )

        try:
            security_service = db.security_service_get(context, id)
            policy.check_policy(context, RESOURCE_NAME, 'show',
                                security_service)
        except exception.NotFound:
            raise exc.HTTPNotFound()

        if security_service['status'].lower() in ['new', 'inactive']:
            update_dict = security_service_data
        else:
            update_dict = dict([(key, security_service_data[key])
                                for key in valid_update_keys
                                if key in security_service_data])

        policy.check_policy(context, RESOURCE_NAME, 'update', security_service)
        security_service = db.security_service_update(context, id, update_dict)
        return self._view_builder.detail(req, security_service)
Example #16
0
 def access_get_all(self, context, share):
     """Returns all access rules for share."""
     policy.check_policy(context, 'share', 'access_get_all')
     rules = self.db.share_access_get_all_for_share(context, share['id'])
     return [{'id': rule.id,
              'access_type': rule.access_type,
              'access_to': rule.access_to,
              'state': rule.state} for rule in rules]
Example #17
0
    def allow_access_to_instance(self, context, share_instance, access):
        policy.check_policy(context, 'share', 'allow_access')

        if not share_instance['host']:
            msg = _("Invalid share instance host: %s") % share_instance['host']
            raise exception.InvalidShareInstance(reason=msg)

        self.share_rpcapi.allow_access(context, share_instance, access)
Example #18
0
    def index(self, req):
        """Returns the list of share types."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'index')

        limited_types = self._get_share_types(req)
        req.cache_db_share_types(limited_types)
        return self._view_builder.index(req, limited_types)
Example #19
0
    def unmanage(self, context, share):
        policy.check_policy(context, 'share', 'unmanage')

        update_data = {'status': constants.STATUS_UNMANAGING,
                       'terminated_at': timeutils.utcnow()}
        share_ref = self.db.share_update(context, share['id'], update_data)

        self.share_rpcapi.unmanage_share(context, share_ref)
Example #20
0
 def _pools(self, req, action='index'):
     context = req.environ['manila.context']
     policy.check_policy(context, POOLS_RESOURCES_NAME, action)
     search_opts = {}
     search_opts.update(req.GET)
     pools = self.scheduler_api.get_pools(context, filters=search_opts)
     detail = (action == 'detail')
     return self._view_builder.pools(pools, detail=detail)
Example #21
0
 def wrapper(self, req, *args, **kwargs):
     action = action_name or f.__name__
     context = req.environ['manila.context']
     try:
         policy.check_policy(context, self.resource_name, action)
     except exception.PolicyNotAuthorized:
         raise webob.exc.HTTPForbidden()
     return f(self, req, *args, **kwargs)
 def _verify_snapshot(self, context, snapshot_id):
     try:
         snapshot = db_api.share_snapshot_get(context, snapshot_id)
         share = db_api.share_get(context, snapshot['share_id'])
         if not share['is_public']:
             policy.check_policy(context, 'share', 'get', share)
     except exception.NotFound:
         msg = _("Snapshot '%s' not found.") % snapshot_id
         raise exc.HTTPNotFound(explanation=msg)
     return snapshot
Example #23
0
 def details(self, req, id):
     """Return details for requested share server."""
     context = req.environ['manila.context']
     policy.check_policy(context, RESOURCE_NAME, 'details')
     try:
         db_api.share_server_get(context, id)
     except exception.ShareServerNotFound as e:
         raise exc.HTTPNotFound(explanation=six.text_type(e))
     details = db_api.share_server_backend_details_get(context, id)
     return self._view_builder.build_share_server_details(details)
Example #24
0
    def delete(self, req, id):
        """Delete specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'delete')

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))

        share_instances = (
            db_api.share_instances_get_all_by_share_network(context, id)
        )
        if share_instances:
            msg = _("Can not delete share network %(id)s, it has "
                    "%(len)s share(s).") % {'id': id,
                                            'len': len(share_instances)}
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        # NOTE(ameade): Do not allow deletion of share network used by share
        # group
        sg_count = db_api.count_share_groups_in_share_network(context, id)
        if sg_count:
            msg = _("Can not delete share network %(id)s, it has %(len)s "
                    "share group(s).") % {'id': id, 'len': sg_count}
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        # NOTE(silvacarlose): Do not allow the deletion of any share server
        # if one of them has the flag is_auto_deletable = False
        if not self._all_share_servers_are_auto_deletable(share_network):
            msg = _("The service cannot determine if there are any "
                    "non-managed shares on the share network %(id)s, so it "
                    "cannot be deleted. Please contact the cloud "
                    "administrator to rectify.") % {'id': id}
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        for share_server in share_network['share_servers']:
            self.share_rpcapi.delete_share_server(context, share_server)
        db_api.share_network_delete(context, id)

        try:
            reservations = QUOTAS.reserve(
                context, project_id=share_network['project_id'],
                share_networks=-1, user_id=share_network['user_id'])
        except Exception:
            LOG.exception("Failed to update usages deleting "
                          "share-network.")
        else:
            QUOTAS.commit(context, reservations,
                          project_id=share_network['project_id'],
                          user_id=share_network['user_id'])
        return webob.Response(status_int=http_client.ACCEPTED)
Example #25
0
    def show(self, req, id):
        """Return data about the given security service."""
        context = req.environ['manila.context']
        try:
            security_service = db.security_service_get(context, id)
            policy.check_policy(context, RESOURCE_NAME, 'show',
                                security_service)
        except exception.NotFound:
            raise exc.HTTPNotFound()

        return self._view_builder.detail(req, security_service)
Example #26
0
    def show(self, req, id):
        """Return data about the requested network info."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'show')

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))

        return self._view_builder.build_share_network(share_network)
Example #27
0
    def _get_security_services(self, req, is_detail):
        """Returns a transformed list of security services.

        The list gets transformed through view builder.
        """
        context = req.environ['manila.context']

        search_opts = {}
        search_opts.update(req.GET)

        # NOTE(vponomaryov): remove 'status' from search opts
        # since it was removed from security service model.
        search_opts.pop('status', None)
        if 'share_network_id' in search_opts:
            share_nw = db.share_network_get(context,
                                            search_opts['share_network_id'])
            security_services = share_nw['security_services']
            del search_opts['share_network_id']
        else:
            if 'all_tenants' in search_opts and context.is_admin:
                policy.check_policy(context, RESOURCE_NAME,
                                    'get_all_security_services')
                security_services = db.security_service_get_all(context)
            else:
                security_services = db.security_service_get_all_by_project(
                    context, context.project_id)
        search_opts.pop('all_tenants', None)
        common.remove_invalid_options(
            context,
            search_opts,
            self._get_security_services_search_options())
        if search_opts:
            results = []
            not_found = object()
            for ss in security_services:
                if all(ss.get(opt, not_found) == value for opt, value in
                       search_opts.items()):
                    results.append(ss)
            security_services = results

        limited_list = common.limited(security_services, req)

        if is_detail:
            security_services = self._view_builder.detail_list(
                req, limited_list)
            for ss in security_services['security_services']:
                share_networks = db.share_network_get_all_by_security_service(
                    context,
                    ss['id'])
                ss['share_networks'] = [sn['id'] for sn in share_networks]
        else:
            security_services = self._view_builder.summary_list(
                req, limited_list)
        return security_services
Example #28
0
    def show(self, req, id):
        """Return data about the requested network info."""
        context = req.environ["manila.context"]
        policy.check_policy(context, RESOURCE_NAME, "show")

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            msg = "%s" % e
            raise exc.HTTPNotFound(explanation=msg)

        return self._view_builder.build_share_network(share_network)
Example #29
0
 def delete_share_server(self, context, server):
     """Delete share server."""
     policy.check_policy(context, 'share_server', 'delete', server)
     shares = self.db.share_get_all_by_share_server(context, server['id'])
     if shares:
         raise exception.ShareServerInUse(share_server_id=server['id'])
     # NOTE(vponomaryov): There is no share_server status update here,
     # it is intentional.
     # Status will be changed in manila.share.manager after verification
     # for race condition between share creation on server
     # and server deletion.
     self.share_rpcapi.delete_share_server(context, server)
Example #30
0
    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)
Example #31
0
    def create(self, req, body):
        """Creates a new share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'create')

        if not body or RESOURCE_NAME not in body:
            raise exc.HTTPUnprocessableEntity()

        share_network_values = body[RESOURCE_NAME]
        share_network_subnet_values = copy.deepcopy(share_network_values)
        share_network_values['project_id'] = context.project_id
        share_network_values['user_id'] = context.user_id

        if 'nova_net_id' in share_network_values:
            msg = _("nova networking is not supported starting in Ocata.")
            raise exc.HTTPBadRequest(explanation=msg)

        share_network_values.pop('availability_zone', None)
        share_network_values.pop('neutron_net_id', None)
        share_network_values.pop('neutron_subnet_id', None)

        if req.api_version_request >= api_version.APIVersionRequest("2.51"):
            if 'availability_zone' in share_network_subnet_values:
                try:
                    az = db_api.availability_zone_get(
                        context,
                        share_network_subnet_values['availability_zone'])
                    share_network_subnet_values['availability_zone_id'] = (
                        az['id'])
                    share_network_subnet_values.pop('availability_zone')
                except exception.AvailabilityZoneNotFound:
                    msg = (_("The provided availability zone %s does not "
                             "exist.") %
                           share_network_subnet_values['availability_zone'])
                    raise exc.HTTPBadRequest(explanation=msg)

        common.check_net_id_and_subnet_id(share_network_subnet_values)

        try:
            reservations = QUOTAS.reserve(context, share_networks=1)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

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

            if 'share_networks' in overs:
                LOG.warning(
                    "Quota exceeded for %(s_pid)s, "
                    "tried to create "
                    "share-network (%(d_consumed)d of %(d_quota)d "
                    "already consumed).", {
                        's_pid': context.project_id,
                        'd_consumed': _consumed('share_networks'),
                        'd_quota': quotas['share_networks']
                    })
                raise exception.ShareNetworksLimitExceeded(
                    allowed=quotas['share_networks'])
        else:
            # Tries to create the new share network
            try:
                share_network = db_api.share_network_create(
                    context, share_network_values)
            except db_exception.DBError as e:
                LOG.exception(e)
                msg = "Could not create share network."
                raise exc.HTTPInternalServerError(explanation=msg)

            share_network_subnet_values['share_network_id'] = (
                share_network['id'])
            share_network_subnet_values.pop('id', None)

            # Try to create the share network subnet. If it fails, the service
            # must rollback the share network creation.
            try:
                db_api.share_network_subnet_create(
                    context, share_network_subnet_values)
            except db_exception.DBError:
                db_api.share_network_delete(context, share_network['id'])
                msg = _('Could not create share network.')
                raise exc.HTTPInternalServerError(explanation=msg)

            QUOTAS.commit(context, reservations)
            share_network = db_api.share_network_get(context,
                                                     share_network['id'])
            return self._view_builder.build_share_network(req, share_network)
Example #32
0
File: api.py Project: wzhmei/manila
    def create(self,
               context,
               share_proto,
               size,
               name,
               description,
               snapshot=None,
               availability_zone=None,
               metadata=None,
               share_network_id=None,
               share_type=None,
               is_public=False,
               consistency_group_id=None,
               cgsnapshot_member=None):
        """Create new share."""
        policy.check_policy(context, 'share', 'create')

        self._check_metadata_properties(context, metadata)

        if snapshot is not None:
            if snapshot['status'] != constants.STATUS_AVAILABLE:
                msg = _("status must be '%s'") % constants.STATUS_AVAILABLE
                raise exception.InvalidShareSnapshot(reason=msg)
            if not size:
                size = snapshot['size']

            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        def as_int(s):
            try:
                return int(s)
            except (ValueError, TypeError):
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (_("Share size '%s' must be an integer and greater than 0") %
                   size)
            raise exception.InvalidInput(reason=msg)

        if snapshot and size < snapshot['size']:
            msg = (_("Share size '%s' must be equal or greater "
                     "than snapshot size") % size)
            raise exception.InvalidInput(reason=msg)

        if snapshot is None:
            share_type_id = share_type['id'] if share_type else None
        else:
            source_share = self.db.share_get(context, snapshot['share_id'])
            availability_zone = source_share['availability_zone']
            if share_type is None:
                share_type_id = source_share['share_type_id']
            else:
                share_type_id = share_type['id']
                if share_type_id != source_share['share_type_id']:
                    msg = _("Invalid share type specified: the requested "
                            "share type must match the type of the source "
                            "share. If a share type is not specified when "
                            "requesting a new share from a snapshot, the "
                            "share type of the source share will be applied "
                            "to the new share.")
                    raise exception.InvalidInput(reason=msg)

        supported_share_protocols = (proto.upper()
                                     for proto in CONF.enabled_share_protocols)
        if not (share_proto
                and share_proto.upper() in supported_share_protocols):
            msg = (_("Invalid share protocol provided: %(provided)s. "
                     "It is either disabled or unsupported. Available "
                     "protocols: %(supported)s") %
                   dict(provided=share_proto,
                        supported=CONF.enabled_share_protocols))
            raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context, shares=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

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

            if 'gigabytes' in overs:
                LOG.warning(
                    _LW("Quota exceeded for %(s_pid)s, "
                        "tried to create "
                        "%(s_size)sG share (%(d_consumed)dG of "
                        "%(d_quota)dG already consumed)."), {
                            's_pid': context.project_id,
                            's_size': size,
                            'd_consumed': _consumed('gigabytes'),
                            'd_quota': quotas['gigabytes']
                        })
                raise exception.ShareSizeExceedsAvailableQuota()
            elif 'shares' in overs:
                LOG.warning(
                    _LW("Quota exceeded for %(s_pid)s, "
                        "tried to create "
                        "share (%(d_consumed)d shares "
                        "already consumed)."), {
                            's_pid': context.project_id,
                            'd_consumed': _consumed('shares')
                        })
                raise exception.ShareLimitExceeded(allowed=quotas['shares'])

        try:
            is_public = strutils.bool_from_string(is_public, strict=True)
            snapshot_support = strutils.bool_from_string(
                share_type.get('extra_specs', {}).get('snapshot_support', True)
                if share_type else True,
                strict=True)
        except ValueError as e:
            raise exception.InvalidParameterValue(six.text_type(e))

        consistency_group = None
        if consistency_group_id:
            try:
                consistency_group = self.db.consistency_group_get(
                    context, consistency_group_id)
            except exception.NotFound as e:
                raise exception.InvalidParameterValue(six.text_type(e))

            if (not cgsnapshot_member and not (consistency_group['status']
                                               == constants.STATUS_AVAILABLE)):
                params = {
                    'avail': constants.STATUS_AVAILABLE,
                    'cg_status': consistency_group['status'],
                }
                msg = _("Consistency group status must be %(avail)s, got"
                        "%(cg_status)s.") % params
                raise exception.InvalidConsistencyGroup(message=msg)

            if share_type_id:
                cg_st_ids = [
                    st['share_type_id']
                    for st in consistency_group.get('share_types', [])
                ]
                if share_type_id not in cg_st_ids:
                    params = {
                        'type': share_type_id,
                        'cg': consistency_group_id
                    }
                    msg = _("The specified share type (%(type)s) is not "
                            "supported by the specified consistency group "
                            "(%(cg)s).") % params
                    raise exception.InvalidParameterValue(msg)

            if (not consistency_group.get('share_network_id')
                    == share_network_id):
                params = {'net': share_network_id, 'cg': consistency_group_id}
                msg = _("The specified share network (%(net)s) is not "
                        "supported by the specified consistency group "
                        "(%(cg)s).") % params
                raise exception.InvalidParameterValue(msg)

        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'snapshot_support': snapshot_support,
            'metadata': metadata,
            'display_name': name,
            'display_description': description,
            'share_proto': share_proto,
            'share_type_id': share_type_id,
            'is_public': is_public,
            'consistency_group_id': consistency_group_id,
        }
        if cgsnapshot_member:
            options['source_cgsnapshot_member_id'] = cgsnapshot_member['id']

        try:
            share = self.db.share_create(context,
                                         options,
                                         create_share_instance=False)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.share_delete(context, share['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        host = None
        if snapshot and not CONF.use_scheduler_creating_share_from_snapshot:
            # Shares from snapshots with restriction - source host only.
            # It is common situation for different types of backends.
            host = snapshot['share']['host']

        self.create_instance(context,
                             share,
                             share_network_id=share_network_id,
                             host=host,
                             availability_zone=availability_zone,
                             consistency_group=consistency_group,
                             cgsnapshot_member=cgsnapshot_member)

        return share
Example #33
0
File: api.py Project: wzhmei/manila
    def migrate_share(self, context, share, host, force_host_copy):
        """Migrates share to a new host."""

        policy.check_policy(context, 'share', 'migrate')

        share_instance = share.instance

        # We only handle "available" share for now
        if share_instance['status'] != constants.STATUS_AVAILABLE:
            msg = _('Share instance %(instance_id)s status must be available, '
                    'but current status is: %(instance_status)s.') % {
                        'instance_id': share_instance['id'],
                        'instance_status': share_instance['status']
                    }
            raise exception.InvalidShare(reason=msg)

        self._check_is_share_busy(share)

        # Make sure the destination host is different than the current one
        if host == share_instance['host']:
            msg = _('Destination host %(dest_host)s must be different '
                    'than the current host %(src_host)s.') % {
                        'dest_host': host,
                        'src_host': share_instance['host']
                    }
            raise exception.InvalidHost(reason=msg)

        # We only handle shares without snapshots for now
        snaps = self.db.share_snapshot_get_all_for_share(context, share['id'])
        if snaps:
            msg = _("Share %s must not have snapshots.") % share['id']
            raise exception.InvalidShare(reason=msg)

        # Make sure the host is in the list of available hosts
        utils.validate_service_host(context, share_utils.extract_host(host))

        # NOTE(ganso): there is the possibility of an error between here and
        # manager code, which will cause the share to be stuck in
        # MIGRATION_STARTING status. According to Liberty Midcycle discussion,
        # this kind of scenario should not be cleaned up, the administrator
        # should be issued to clear this status before a new migration request
        # is made
        self.update(
            context, share,
            {'task_state': constants.STATUS_TASK_STATE_MIGRATION_STARTING})

        share_type = {}
        share_type_id = share['share_type_id']
        if share_type_id:
            share_type = share_types.get_share_type(context, share_type_id)
        request_spec = {
            'share_properties': share,
            'share_instance_properties': share_instance.to_dict(),
            'share_type': share_type,
            'share_id': share['id']
        }

        try:
            self.scheduler_rpcapi.migrate_share_to_host(
                context, share['id'], host, force_host_copy, request_spec)
        except Exception:
            self.update(
                context, share,
                {'task_state': constants.STATUS_TASK_STATE_MIGRATION_ERROR})
            raise
Example #34
0
    def create(self,
               context,
               share_proto,
               size,
               name,
               description,
               snapshot=None,
               availability_zone=None,
               metadata=None,
               share_network_id=None,
               volume_type=None):
        """Create new share."""
        policy.check_policy(context, 'share', 'create')

        self._check_metadata_properties(context, metadata)

        if snapshot is not None:
            if snapshot['status'] != 'available':
                msg = _('status must be available')
                raise exception.InvalidShareSnapshot(reason=msg)
            if not size:
                size = snapshot['size']

            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        def as_int(s):
            try:
                return int(s)
            except (ValueError, TypeError):
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (_("Share size '%s' must be an integer and greater than 0") %
                   size)
            raise exception.InvalidInput(reason=msg)

        if snapshot and size < snapshot['size']:
            msg = (_("Share size '%s' must be equal or greater "
                     "than snapshot size") % size)
            raise exception.InvalidInput(reason=msg)

        if snapshot and volume_type:
            source_share = self.db.share_get(context, snapshot['share_id'])
            if volume_type['id'] != source_share['volume_type_id']:
                msg = _("Invalid volume_type provided (requested type "
                        "must match source snapshot, or be omitted). "
                        "You should omit the argument.")
                raise exception.InvalidInput(reason=msg)

        # TODO(rushiagr): Find a suitable place to keep all the allowed
        #                 share types so that it becomes easier to add one
        if share_proto.lower() not in ['nfs', 'cifs', 'glusterfs']:
            msg = (_("Invalid share type provided: %s") % share_proto)
            raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context, shares=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

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

            if 'gigabytes' in overs:
                LOG.warn(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG share (%(d_consumed)dG of "
                        "%(d_quota)dG already consumed)"), {
                            's_pid': context.project_id,
                            's_size': size,
                            'd_consumed': _consumed('gigabytes'),
                            'd_quota': quotas['gigabytes']
                        })
                raise exception.ShareSizeExceedsAvailableQuota()
            elif 'shares' in overs:
                LOG.warn(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "share (%(d_consumed)d shares "
                        "already consumed)"), {
                            's_pid': context.project_id,
                            'd_consumed': _consumed('shares')
                        })
                raise exception.ShareLimitExceeded(allowed=quotas['shares'])

        if availability_zone is None:
            availability_zone = CONF.storage_availability_zone

        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'share_network_id': share_network_id,
            'availability_zone': availability_zone,
            'metadata': metadata,
            'status': "creating",
            'scheduled_at': timeutils.utcnow(),
            'display_name': name,
            'display_description': description,
            'share_proto': share_proto,
            'volume_type_id': volume_type['id'] if volume_type else None
        }

        try:
            share = self.db.share_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.share_delete(context, share['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        request_spec = {
            'share_properties': options,
            'share_proto': share_proto,
            'share_id': share['id'],
            'snapshot_id': snapshot_id,
            'volume_type': volume_type,
        }
        filter_properties = {}

        if (snapshot and not CONF.use_scheduler_creating_share_from_snapshot):
            # Shares from snapshots with restriction - source host only.
            # It is common situation for different types of backends.
            host = snapshot['share']['host']
            share = self.db.share_update(context, share['id'], {'host': host})
            self.share_rpcapi.create_share(
                context,
                share,
                host,
                request_spec=request_spec,
                filter_properties=filter_properties,
                snapshot_id=snapshot_id,
            )
        else:
            # Shares from scratch and from snapshots when source host is not
            # the only allowed, it is possible, for example, in multibackend
            # installation with Generic drivers only.
            self.scheduler_rpcapi.create_share(
                context,
                CONF.share_topic,
                share['id'],
                snapshot_id,
                request_spec=request_spec,
                filter_properties=filter_properties,
            )

        return share
Example #35
0
File: api.py Project: wzhmei/manila
 def get(self, context, share_id):
     rv = self.db.share_get(context, share_id)
     if not rv['is_public']:
         policy.check_policy(context, 'share', 'get', rv)
     return rv
Example #36
0
 def index(self, req):
     """Returns a summary list of security services."""
     policy.check_policy(req.environ['manila.context'], RESOURCE_NAME,
                         'index')
     return self._get_security_services(req, is_detail=False)
Example #37
0
    def _get_share_networks(self, req, is_detail=True):
        """Returns a list of share networks."""
        context = req.environ['manila.context']
        search_opts = {}
        search_opts.update(req.GET)

        if ('all_tenants' in search_opts
                or ('project_id' in search_opts
                    and search_opts['project_id'] != context.project_id)):
            policy.check_policy(context, RESOURCE_NAME,
                                'get_all_share_networks')

        if 'security_service_id' in search_opts:
            networks = db_api.share_network_get_all_by_security_service(
                context, search_opts['security_service_id'])
        elif ('project_id' in search_opts
              and search_opts['project_id'] != context.project_id):
            networks = db_api.share_network_get_all_by_project(
                context, search_opts['project_id'])
        elif 'all_tenants' in search_opts:
            networks = db_api.share_network_get_all(context)
        else:
            networks = db_api.share_network_get_all_by_project(
                context, context.project_id)

        date_parsing_error_msg = '''%s is not in yyyy-mm-dd format.'''
        if 'created_since' in search_opts:
            try:
                created_since = timeutils.parse_strtime(
                    search_opts['created_since'], fmt="%Y-%m-%d")
            except ValueError:
                msg = date_parsing_error_msg % search_opts['created_since']
                raise exc.HTTPBadRequest(explanation=msg)
            networks = [
                network for network in networks
                if network['created_at'] >= created_since
            ]
        if 'created_before' in search_opts:
            try:
                created_before = timeutils.parse_strtime(
                    search_opts['created_before'], fmt="%Y-%m-%d")
            except ValueError:
                msg = date_parsing_error_msg % search_opts['created_before']
                raise exc.HTTPBadRequest(explanation=msg)
            networks = [
                network for network in networks
                if network['created_at'] <= created_before
            ]
        opts_to_remove = [
            'all_tenants',
            'created_since',
            'created_before',
            'limit',
            'offset',
            'security_service_id',
        ]
        for opt in opts_to_remove:
            search_opts.pop(opt, None)
        if search_opts:
            for key, value in search_opts.items():
                if key in ['ip_version', 'segmentation_id']:
                    value = int(value)
                networks = [
                    network for network in networks if network[key] == value
                ]

        limited_list = common.limited(networks, req)
        return self._view_builder.build_share_networks(limited_list, is_detail)
Example #38
0
 def access_get(self, context, access_id):
     """Returns access rule with the id."""
     policy.check_policy(context, 'share', 'access_get')
     rule = self.db.share_access_get(context, access_id)
     return rule
Example #39
0
 def get(self, context, cg_id):
     policy.check_policy(context, 'consistency_group', 'get')
     return self.db.consistency_group_get(context, cg_id)
Example #40
0
File: api.py Project: wzhmei/manila
    def create_instance(self,
                        context,
                        share,
                        share_network_id=None,
                        host=None,
                        availability_zone=None,
                        consistency_group=None,
                        cgsnapshot_member=None):
        policy.check_policy(context, 'share', 'create')

        availability_zone_id = None
        if availability_zone:
            availability_zone_id = self.db.availability_zone_get(
                context, availability_zone).id

        # TODO(u_glide): Add here validation that provided share network
        # doesn't conflict with provided availability_zone when Neutron
        # will have AZ support.

        share_instance = self.db.share_instance_create(
            context, share['id'], {
                'share_network_id': share_network_id,
                'status': constants.STATUS_CREATING,
                'scheduled_at': timeutils.utcnow(),
                'host': host if host else '',
                'availability_zone_id': availability_zone_id,
            })

        if cgsnapshot_member:
            host = cgsnapshot_member['share']['host']
            share = self.db.share_instance_update(context,
                                                  share_instance['id'],
                                                  {'host': host})
            # NOTE(ameade): Do not cast to driver if creating from cgsnapshot
            return

        share_dict = share.to_dict()
        share_dict.update(
            {'metadata': self.db.share_metadata_get(context, share['id'])})

        share_type = None
        if share['share_type_id']:
            share_type = self.db.share_type_get(context,
                                                share['share_type_id'])

        request_spec = {
            'share_properties': share_dict,
            'share_instance_properties': share_instance.to_dict(),
            'share_proto': share['share_proto'],
            'share_id': share['id'],
            'snapshot_id': share['snapshot_id'],
            'share_type': share_type,
            'consistency_group': consistency_group,
        }

        if host:
            self.share_rpcapi.create_share_instance(
                context,
                share_instance,
                host,
                request_spec=request_spec,
                filter_properties={},
                snapshot_id=share['snapshot_id'],
            )
        else:
            # Create share instance from scratch or from snapshot could happen
            # on hosts other than the source host.
            self.scheduler_rpcapi.create_share_instance(
                context, request_spec=request_spec, filter_properties={})

        return share_instance
Example #41
0
    def get_all_cgsnapshot_members(self, context, cgsnapshot_id):
        policy.check_policy(context, 'consistency_group', 'get_cgsnapshot')
        members = self.db.cgsnapshot_members_get_all(context, cgsnapshot_id)

        return members
Example #42
0
    def delete(self, req, id):
        """Delete specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'delete')

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=e.msg)

        share_instances = (db_api.share_instances_get_all_by_share_network(
            context, id))
        if share_instances:
            msg = _("Can not delete share network %(id)s, it has "
                    "%(len)s share(s).") % {
                        'id': id,
                        'len': len(share_instances)
                    }
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        # NOTE(ameade): Do not allow deletion of share network used by share
        # group
        sg_count = db_api.count_share_groups_in_share_network(context, id)
        if sg_count:
            msg = _("Can not delete share network %(id)s, it has %(len)s "
                    "share group(s).") % {
                        'id': id,
                        'len': sg_count
                    }
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        # NOTE(silvacarlose): Do not allow the deletion of share networks
        # if it still contains two or more subnets
        if self._share_network_contains_subnets(share_network):
            msg = _("The share network %(id)s has more than one subnet "
                    "attached. Please remove the subnets untill you have one "
                    "or no subnets remaining.") % {
                        'id': id
                    }
            LOG.error(msg)
            raise exc.HTTPConflict(explanation=msg)

        for subnet in share_network['share_network_subnets']:
            if not self._all_share_servers_are_auto_deletable(subnet):
                msg = _("The service cannot determine if there are any "
                        "non-managed shares on the share network subnet "
                        "%(id)s, so it cannot be deleted. Please contact the "
                        "cloud administrator to rectify.") % {
                            'id': subnet['id']
                        }
                LOG.error(msg)
                raise exc.HTTPConflict(explanation=msg)

        for subnet in share_network['share_network_subnets']:
            for share_server in subnet['share_servers']:
                self.share_rpcapi.delete_share_server(context, share_server)

        db_api.share_network_delete(context, id)

        try:
            reservations = QUOTAS.reserve(
                context,
                project_id=share_network['project_id'],
                share_networks=-1,
                user_id=share_network['user_id'])
        except Exception:
            LOG.exception("Failed to update usages deleting " "share-network.")
        else:
            QUOTAS.commit(context,
                          reservations,
                          project_id=share_network['project_id'],
                          user_id=share_network['user_id'])
        return webob.Response(status_int=http_client.ACCEPTED)
Example #43
0
    def create_snapshot(self, context, share, name, description, force=False):
        policy.check_policy(context, 'share', 'create_snapshot', share)

        if ((not force) and (share['status'] != "available")):
            msg = _("must be available")
            raise exception.InvalidShare(reason=msg)

        size = share['size']

        try:
            reservations = QUOTAS.reserve(context, snapshots=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

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

            if 'gigabytes' in overs:
                msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                          "%(s_size)sG snapshot (%(d_consumed)dG of "
                          "%(d_quota)dG already consumed)")
                LOG.warn(
                    msg, {
                        's_pid': context.project_id,
                        's_size': size,
                        'd_consumed': _consumed('gigabytes'),
                        'd_quota': quotas['gigabytes']
                    })
                raise exception.ShareSizeExceedsAvailableQuota()
            elif 'snapshots' in overs:
                msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                          "snapshot (%(d_consumed)d snapshots "
                          "already consumed)")
                LOG.warn(
                    msg, {
                        's_pid': context.project_id,
                        'd_consumed': _consumed('snapshots')
                    })
                raise exception.SnapshotLimitExceeded(
                    allowed=quotas['snapshots'])
        options = {
            'share_id': share['id'],
            'size': share['size'],
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'progress': '0%',
            'share_size': share['size'],
            'display_name': name,
            'display_description': description,
            'share_proto': share['share_proto'],
            'export_location': share['export_location']
        }

        try:
            snapshot = self.db.share_snapshot_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.snapshot_delete(context, share['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        self.share_rpcapi.create_snapshot(context, share, snapshot)
        return snapshot
Example #44
0
 def get_snapshot(self, context, snapshot_id):
     policy.check_policy(context, 'share', 'get_snapshot')
     rv = self.db.share_snapshot_get(context, snapshot_id)
     return dict(six.iteritems(rv))
Example #45
0
 def get(self, context, share_id):
     rv = self.db.share_get(context, share_id)
     policy.check_policy(context, 'share', 'get', rv)
     return rv
Example #46
0
    def get_all(self,
                context,
                search_opts=None,
                sort_key='created_at',
                sort_dir='desc'):
        policy.check_policy(context, 'share', 'get_all')

        if search_opts is None:
            search_opts = {}

        LOG.debug("Searching for shares by: %s", six.text_type(search_opts))

        # Prepare filters
        filters = {}
        if 'metadata' in search_opts:
            filters['metadata'] = search_opts.pop('metadata')
            if not isinstance(filters['metadata'], dict):
                msg = _("Wrong metadata filter provided: "
                        "%s.") % six.text_type(filters['metadata'])
                raise exception.InvalidInput(reason=msg)
        if 'extra_specs' in search_opts:
            # Verify policy for extra-specs access
            extensions.extension_authorizer('share',
                                            'types_extra_specs')(context)
            filters['extra_specs'] = search_opts.pop('extra_specs')
            if not isinstance(filters['extra_specs'], dict):
                msg = _("Wrong extra specs filter provided: "
                        "%s.") % six.text_type(filters['extra_specs'])
                raise exception.InvalidInput(reason=msg)
        if not (isinstance(sort_key, six.string_types) and sort_key):
            msg = _("Wrong sort_key filter provided: "
                    "'%s'.") % six.text_type(sort_key)
            raise exception.InvalidInput(reason=msg)
        if not (isinstance(sort_dir, six.string_types) and sort_dir):
            msg = _("Wrong sort_dir filter provided: "
                    "'%s'.") % six.text_type(sort_dir)
            raise exception.InvalidInput(reason=msg)

        # Get filtered list of shares
        if 'share_server_id' in search_opts:
            # NOTE(vponomaryov): this is project_id independent
            policy.check_policy(context, 'share', 'list_by_share_server_id')
            shares = self.db.share_get_all_by_share_server(
                context,
                search_opts.pop('share_server_id'),
                filters=filters,
                sort_key=sort_key,
                sort_dir=sort_dir)
        elif (context.is_admin and 'all_tenants' in search_opts):
            shares = self.db.share_get_all(context,
                                           filters=filters,
                                           sort_key=sort_key,
                                           sort_dir=sort_dir)
        else:
            shares = self.db.share_get_all_by_project(
                context,
                project_id=context.project_id,
                filters=filters,
                sort_key=sort_key,
                sort_dir=sort_dir)

        # NOTE(vponomaryov): we do not need 'all_tenants' opt anymore
        search_opts.pop('all_tenants', None)

        if search_opts:
            results = []
            for s in shares:
                # values in search_opts can be only strings
                if all(s.get(k, None) == v for k, v in search_opts.items()):
                    results.append(s)
            shares = results
        return shares
Example #47
0
    def create(self,
               context,
               name=None,
               description=None,
               share_type_ids=None,
               source_cgsnapshot_id=None,
               share_network_id=None):
        """Create new consistency group."""
        policy.check_policy(context, 'consistency_group', 'create')

        cgsnapshot = None
        original_cg = None
        if source_cgsnapshot_id:
            cgsnapshot = self.db.cgsnapshot_get(context, source_cgsnapshot_id)
            if cgsnapshot['status'] != constants.STATUS_AVAILABLE:
                msg = (_("Consistency group snapshot status must be %s") %
                       constants.STATUS_AVAILABLE)
                raise exception.InvalidCGSnapshot(reason=msg)

            original_cg = self.db.consistency_group_get(
                context, cgsnapshot['consistency_group_id'])
            share_type_ids = [
                s['share_type_id'] for s in original_cg['share_types']
            ]

        # Get share_type_objects
        share_type_objects = []
        driver_handles_share_servers = None
        for share_type_id in (share_type_ids or []):
            try:
                share_type_object = share_types.get_share_type(
                    context, share_type_id)
            except exception.ShareTypeNotFound:
                msg = _("Share type with id %s could not be found")
                raise exception.InvalidInput(msg % share_type_id)
            share_type_objects.append(share_type_object)

            extra_specs = share_type_object.get('extra_specs')
            if extra_specs:
                share_type_handle_ss = strutils.bool_from_string(
                    extra_specs.get(
                        constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS))
                if driver_handles_share_servers is None:
                    driver_handles_share_servers = share_type_handle_ss
                elif not driver_handles_share_servers == share_type_handle_ss:
                    # NOTE(ameade): if the share types have conflicting values
                    #  for driver_handles_share_servers then raise bad request
                    msg = _("The specified share_types cannot have "
                            "conflicting values for the "
                            "driver_handles_share_servers extra spec.")
                    raise exception.InvalidInput(reason=msg)

                if (not share_type_handle_ss) and share_network_id:
                    msg = _("When using a share types with the "
                            "driver_handles_share_servers extra spec as "
                            "False, a share_network_id must not be provided.")
                    raise exception.InvalidInput(reason=msg)

        try:
            if share_network_id:
                self.db.share_network_get(context, share_network_id)
        except exception.ShareNetworkNotFound:
            msg = _("The specified share network does not exist.")
            raise exception.InvalidInput(reason=msg)

        if (driver_handles_share_servers
                and not (source_cgsnapshot_id or share_network_id)):
            msg = _("When using a share type with the "
                    "driver_handles_share_servers extra spec as"
                    "True, a share_network_id must be provided.")
            raise exception.InvalidInput(reason=msg)

        options = {
            'source_cgsnapshot_id': source_cgsnapshot_id,
            'share_network_id': share_network_id,
            'name': name,
            'description': description,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': constants.STATUS_CREATING,
            'share_types': share_type_ids
        }
        if original_cg:
            options['host'] = original_cg['host']

        cg = self.db.consistency_group_create(context, options)

        try:
            if cgsnapshot:
                members = self.db.cgsnapshot_members_get_all(
                    context, source_cgsnapshot_id)
                for member in members:
                    share_type = share_types.get_share_type(
                        context, member['share_type_id'])
                    member['share'] = self.db.share_instance_get(
                        context,
                        member['share_instance_id'],
                        with_share_data=True)
                    self.share_api.create(context,
                                          member['share_proto'],
                                          member['size'],
                                          None,
                                          None,
                                          consistency_group_id=cg['id'],
                                          cgsnapshot_member=member,
                                          share_type=share_type,
                                          share_network_id=share_network_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                self.db.consistency_group_destroy(context.elevated(), cg['id'])

        request_spec = {'consistency_group_id': cg['id']}
        request_spec.update(options)
        request_spec['share_types'] = share_type_objects

        if cgsnapshot and original_cg:
            self.share_rpcapi.create_consistency_group(context, cg,
                                                       original_cg['host'])
        else:
            self.scheduler_rpcapi.create_consistency_group(
                context,
                cg_id=cg['id'],
                request_spec=request_spec,
                filter_properties={})

        return cg
Example #48
0
    def update(self, req, id, body):
        """Update specified share network."""
        context = req.environ['manila.context']
        policy.check_policy(context, RESOURCE_NAME, 'update')

        if not body or RESOURCE_NAME not in body:
            raise exc.HTTPUnprocessableEntity()

        try:
            share_network = db_api.share_network_get(context, id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPNotFound(explanation=e.msg)

        update_values = body[RESOURCE_NAME]

        if 'nova_net_id' in update_values:
            msg = _("nova networking is not supported starting in Ocata.")
            raise exc.HTTPBadRequest(explanation=msg)

        if self._share_network_subnets_contain_share_servers(share_network):
            for value in update_values:
                if value not in ['name', 'description']:
                    msg = (_("Cannot update share network %s. It is used by "
                             "share servers. Only 'name' and 'description' "
                             "fields are available for update") %
                           share_network['id'])
                    raise exc.HTTPForbidden(explanation=msg)
        try:
            if ('neutron_net_id' in update_values
                    or 'neutron_subnet_id' in update_values):
                subnet = db_api.share_network_subnet_get_default_subnet(
                    context, id)
                if not subnet:
                    msg = _("The share network %(id)s does not have a "
                            "'default' subnet that serves all availability "
                            "zones, so subnet details "
                            "('neutron_net_id', 'neutron_subnet_id') cannot "
                            "be updated.") % {
                                'id': id
                            }
                    raise exc.HTTPBadRequest(explanation=msg)

                # NOTE(silvacarlose): If the default share network subnet have
                # the fields neutron_net_id and neutron_subnet_id set as None,
                # we need to make sure that in the update request the user is
                # passing both parameter since a share network subnet must
                # have both fields filled or empty.
                subnet_neutron_net_and_subnet_id_are_empty = (
                    subnet['neutron_net_id'] is None
                    and subnet['neutron_subnet_id'] is None)
                update_values_without_neutron_net_or_subnet = (
                    update_values.get('neutron_net_id') is None
                    or update_values.get('neutron_subnet_id') is None)
                if (subnet_neutron_net_and_subnet_id_are_empty
                        and update_values_without_neutron_net_or_subnet):
                    msg = _("To update the share network %(id)s you need to "
                            "specify both 'neutron_net_id' and "
                            "'neutron_subnet_id'.") % {
                                'id': id
                            }
                    raise webob.exc.HTTPBadRequest(explanation=msg)
                db_api.share_network_subnet_update(context, subnet['id'],
                                                   update_values)
            share_network = db_api.share_network_update(
                context, id, update_values)
        except db_exception.DBError:
            msg = "Could not save supplied data due to database error"
            raise exc.HTTPBadRequest(explanation=msg)

        return self._view_builder.build_share_network(req, share_network)
Example #49
0
 def get_cgsnapshot(self, context, snapshot_id):
     policy.check_policy(context, 'consistency_group', 'get_cgsnapshot')
     return self.db.cgsnapshot_get(context, snapshot_id)
Example #50
0
 def detail(self, req):
     """Returns a detailed list of share networks."""
     policy.check_policy(req.environ['manila.context'], RESOURCE_NAME,
                         'detail')
     return self._get_share_networks(req)
Example #51
0
    def create_cgsnapshot(self,
                          context,
                          name=None,
                          description=None,
                          consistency_group_id=None):
        """Create new cgsnapshot."""
        policy.check_policy(context, 'consistency_group', 'create_cgsnapshot')

        options = {
            'consistency_group_id': consistency_group_id,
            'name': name,
            'description': description,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': constants.STATUS_CREATING,
        }

        cg = self.db.consistency_group_get(context, consistency_group_id)
        # Check status of CG, must be active
        if not cg['status'] == constants.STATUS_AVAILABLE:
            msg = (_("Consistency group status must be %s") %
                   constants.STATUS_AVAILABLE)
            raise exception.InvalidConsistencyGroup(reason=msg)

        # Create members for every share in the CG
        shares = self.db.share_get_all_by_consistency_group_id(
            context, consistency_group_id)

        # Check status of all shares, they must be active in order to snap
        # the CG
        for s in shares:
            if not s['status'] == constants.STATUS_AVAILABLE:
                msg = (_("Share %(s)s in consistency group must have status "
                         "of %(status)s in order to create a CG snapshot") % {
                             "s": s['id'],
                             "status": constants.STATUS_AVAILABLE
                         })
                raise exception.InvalidConsistencyGroup(reason=msg)

        snap = self.db.cgsnapshot_create(context, options)

        try:
            members = []
            for s in shares:
                member_options = {
                    'cgsnapshot_id': snap['id'],
                    'user_id': context.user_id,
                    'project_id': context.project_id,
                    'status': constants.STATUS_CREATING,
                    'size': s['size'],
                    'share_proto': s['share_proto'],
                    'share_type_id': s['share_type_id'],
                    'share_id': s['id'],
                    'share_instance_id': s.instance['id']
                }
                member = self.db.cgsnapshot_member_create(
                    context, member_options)
                members.append(member)

            # Cast to share manager
            self.share_rpcapi.create_cgsnapshot(context, snap, cg['host'])
        except Exception:
            with excutils.save_and_reraise_exception():
                # This will delete the snapshot and all of it's members
                self.db.cgsnapshot_destroy(context, snap['id'])

        return snap
Example #52
0
 def index(self, req):
     """Returns a summary list of share networks."""
     policy.check_policy(req.environ['manila.context'], RESOURCE_NAME,
                         'index')
     return self._get_share_networks(req, is_detail=False)
Example #53
0
    def create(self,
               context,
               share_proto,
               size,
               name,
               description,
               snapshot=None,
               availability_zone=None,
               metadata=None,
               share_network_id=None,
               share_type=None,
               is_public=False):
        """Create new share."""
        policy.check_policy(context, 'share', 'create')

        self._check_metadata_properties(context, metadata)

        if snapshot is not None:
            if snapshot['status'] != 'available':
                msg = _("status must be 'available'")
                raise exception.InvalidShareSnapshot(reason=msg)
            if not size:
                size = snapshot['size']

            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        def as_int(s):
            try:
                return int(s)
            except (ValueError, TypeError):
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (_("Share size '%s' must be an integer and greater than 0") %
                   size)
            raise exception.InvalidInput(reason=msg)

        if snapshot and size < snapshot['size']:
            msg = (_("Share size '%s' must be equal or greater "
                     "than snapshot size") % size)
            raise exception.InvalidInput(reason=msg)

        if snapshot is None:
            share_type_id = share_type['id'] if share_type else None
        else:
            source_share = self.db.share_get(context, snapshot['share_id'])
            if share_type is None:
                share_type_id = source_share['share_type_id']
                if share_type_id is not None:
                    share_type = share_types.get_share_type(
                        context, share_type_id)
            else:
                share_type_id = share_type['id']
                if share_type_id != source_share['share_type_id']:
                    msg = _("Invalid share type specified: the requested "
                            "share type must match the type of the source "
                            "share. If a share type is not specified when "
                            "requesting a new share from a snapshot, the "
                            "share type of the source share will be applied "
                            "to the new share.")
                    raise exception.InvalidInput(reason=msg)

        supported_share_protocols = (proto.upper()
                                     for proto in CONF.enabled_share_protocols)
        if not (share_proto
                and share_proto.upper() in supported_share_protocols):
            msg = (_("Invalid share protocol provided: %(provided)s. "
                     "It is either disabled or unsupported. Available "
                     "protocols: %(supported)s") %
                   dict(provided=share_proto,
                        supported=CONF.enabled_share_protocols))
            raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context, shares=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

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

            if 'gigabytes' in overs:
                LOG.warn(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG share (%(d_consumed)dG of "
                        "%(d_quota)dG already consumed)"), {
                            's_pid': context.project_id,
                            's_size': size,
                            'd_consumed': _consumed('gigabytes'),
                            'd_quota': quotas['gigabytes']
                        })
                raise exception.ShareSizeExceedsAvailableQuota()
            elif 'shares' in overs:
                LOG.warn(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "share (%(d_consumed)d shares "
                        "already consumed)"), {
                            's_pid': context.project_id,
                            'd_consumed': _consumed('shares')
                        })
                raise exception.ShareLimitExceeded(allowed=quotas['shares'])

        if availability_zone is None:
            availability_zone = CONF.storage_availability_zone

        try:
            is_public = strutils.bool_from_string(is_public, strict=True)
        except ValueError as e:
            raise exception.InvalidParameterValue(e.message)

        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'share_network_id': share_network_id,
            'availability_zone': availability_zone,
            'metadata': metadata,
            'status': "creating",
            'scheduled_at': timeutils.utcnow(),
            'display_name': name,
            'display_description': description,
            'share_proto': share_proto,
            'share_type_id': share_type_id,
            'is_public': is_public,
        }

        try:
            share = self.db.share_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.share_delete(context, share['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        request_spec = {
            'share_properties': options,
            'share_proto': share_proto,
            'share_id': share['id'],
            'snapshot_id': snapshot_id,
            'share_type': share_type,
        }
        filter_properties = {}

        if (snapshot and not CONF.use_scheduler_creating_share_from_snapshot):
            # Shares from snapshots with restriction - source host only.
            # It is common situation for different types of backends.
            host = snapshot['share']['host']
            share = self.db.share_update(context, share['id'], {'host': host})
            self.share_rpcapi.create_share(
                context,
                share,
                host,
                request_spec=request_spec,
                filter_properties=filter_properties,
                snapshot_id=snapshot_id,
            )
        else:
            # Shares from scratch and from snapshots when source host is not
            # the only allowed, it is possible, for example, in multibackend
            # installation with Generic drivers only.
            self.scheduler_rpcapi.create_share(
                context,
                CONF.share_topic,
                share['id'],
                snapshot_id,
                request_spec=request_spec,
                filter_properties=filter_properties,
            )

        return share
Example #54
0
 def detail(self, req):
     """Returns a detailed list of security services."""
     policy.check_policy(req.environ['manila.context'], RESOURCE_NAME,
                         'detail')
     return self._get_security_services(req, is_detail=True)