Пример #1
0
    def create(self, req, body):
        """Creates a new server group."""
        context = _authorize_context(req)

        try:
            self._validate_input_body(body, 'server_group')
        except jacket.compute.exception.InvalidInput as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        quotas = None
        if self.ext_mgr.is_loaded('os-server-group-quotas'):
            quotas = objects.Quotas(context=context)
            try:
                quotas.reserve(project_id=context.project_id,
                               user_id=context.user_id, server_groups=1)
            except jacket.compute.exception.OverQuota:
                msg = _("Quota exceeded, too many server groups.")
                raise exc.HTTPForbidden(explanation=msg)

        vals = body['server_group']
        sg = objects.InstanceGroup(context)
        sg.project_id = context.project_id
        sg.user_id = context.user_id
        try:
            sg.name = vals.get('name')
            sg.policies = vals.get('policies')
            sg.create()
        except ValueError as e:
            if quotas:
                quotas.rollback()
            raise exc.HTTPBadRequest(explanation=e)

        if quotas:
            quotas.commit()

        return {'server_group': self._format_server_group(context, sg)}
Пример #2
0
    def create(self, req, body):
        """Creates a new snapshot."""
        context = req.environ['nova.context']
        context.can(vol_policies.BASE_POLICY_NAME)

        snapshot = body['snapshot']
        volume_id = snapshot['volume_id']

        force = snapshot.get('force', False)
        force = strutils.bool_from_string(force, strict=True)
        if force:
            create_func = self.volume_api.create_snapshot_force
        else:
            create_func = self.volume_api.create_snapshot

        try:
            new_snapshot = create_func(context, volume_id,
                                       snapshot.get('display_name'),
                                       snapshot.get('display_description'))
        except exception.OverQuota as e:
            raise exc.HTTPForbidden(explanation=e.format_message())

        retval = _translate_snapshot_detail_view(context, new_snapshot)
        return {'snapshot': retval}
Пример #3
0
 def perform_import(self,
                    doc=None,
                    username_mapping=None,
                    default_username=None,
                    create_users=False,
                    **kw):
     require_access(c.project, 'admin')
     if username_mapping is None:
         username_mapping = '{}'
     if not c.api_token.can_import_forum():
         log.error('Import capability is not enabled for %s',
                   c.project.shortname)
         raise exc.HTTPForbidden(detail='Import is not allowed')
     try:
         doc = json.loads(doc)
         username_mapping = json.loads(username_mapping)
         warnings = import_support.perform_import(doc, username_mapping,
                                                  default_username,
                                                  create_users)
         return dict(warnings=warnings, errors=[])
     except Exception, e:
         raise
         log.exception(e)
         return dict(status=False, errors=[str(e)])
Пример #4
0
    def _migrate(self, req, id, body):
        """Permit admins to migrate a server to a new host."""
        context = req.environ['nova.context']
        authorize(context, 'migrate')

        instance = common.get_instance(self.compute_api,
                                       context,
                                       id,
                                       want_objects=True)
        try:
            self.compute_api.resize(req.environ['nova.context'], instance)
        except (exception.TooManyInstances, exception.QuotaError) as e:
            raise exc.HTTPForbidden(explanation=e.format_message())
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'migrate', id)
        except exception.InstanceNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.NoValidHost as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        return webob.Response(status_int=202)
Пример #5
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]

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

        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(req, share_network)
Пример #6
0
    def update(self, req, id, body):
        """
        Updates an existing image with the registry.

        :param req: wsgi Request object
        :param body: Dictionary of information about the image
        :param id:  The opaque internal identifier for the image

        :retval Returns the updated image information as a mapping,
        """
        if req.context.read_only:
            raise exc.HTTPForbidden()

        image_data = body['image']

        # Prohibit modification of 'owner'
        if not req.context.is_admin and 'owner' in image_data:
            del image_data['owner']

        purge_props = req.headers.get("X-Glance-Registry-Purge-Props", "false")
        try:
            logger.debug(
                _("Updating image %(id)s with metadata: "
                  "%(image_data)r") % locals())
            if purge_props == "true":
                updated_image = db_api.image_update(req.context, id,
                                                    image_data, True)
            else:
                updated_image = db_api.image_update(req.context, id,
                                                    image_data)
            return dict(image=make_image_dict(updated_image))
        except exception.Invalid, e:
            msg = (_("Failed to update image metadata. "
                     "Got error: %(e)s") % locals())
            logger.error(msg)
            return exc.HTTPBadRequest(msg)
Пример #7
0
    def create(self, req, body):
        """Create a child cell entry."""
        context = req.environ['nova.context']

        authorize(context)
        authorize(context, action="create")
        # NOTE(eliqiao): back-compatible with db layer hard-code admin
        # permission checks.
        nova_context.require_admin_context(context)

        if 'cell' not in body:
            msg = _("No cell information in request")
            raise exc.HTTPBadRequest(explanation=msg)
        cell = body['cell']
        if 'name' not in cell:
            msg = _("No cell name in request")
            raise exc.HTTPBadRequest(explanation=msg)
        self._validate_cell_name(cell['name'])
        self._normalize_cell(cell)
        try:
            cell = self.cells_rpcapi.cell_create(context, cell)
        except exception.CellsUpdateUnsupported as e:
            raise exc.HTTPForbidden(explanation=e.format_message())
        return dict(cell=_scrub_cell(cell))
Пример #8
0
 def index(self, version=None, page=0, limit=None, **kw):
     if not self.page:
         redirect(c.app.url + h.urlquote(self.title) + '/edit')
     c.confirmation = W.confirmation
     c.thread = W.thread
     c.attachment_list = W.attachment_list
     c.subscribe_form = W.page_subscribe_form
     post_count = self.page.discussion_thread.post_count
     limit, pagenum, _ = g.handle_paging(limit, page)
     limit, pagenum = h.paging_sanitizer(limit, pagenum, post_count)
     page = self.get_version(version)
     if page is None:
         if version:
             redirect('.?version=%d' % (version - 1))
         else:
             redirect('.')
     elif 'all' not in page.viewable_by and c.user.username not in page.viewable_by:
         raise exc.HTTPForbidden(detail="You may not view this page.")
     cur = page.version
     if cur > 1:
         prev = cur - 1
     else:
         prev = None
     next = cur + 1
     hide_left_bar = not (c.app.show_left_bar)
     subscribed_to_page = M.Mailbox.subscribed(artifact=self.page)
     return dict(page=page,
                 cur=cur,
                 prev=prev,
                 next=next,
                 page_subscribed=subscribed_to_page,
                 hide_left_bar=hide_left_bar,
                 show_meta=c.app.show_right_bar,
                 pagenum=pagenum,
                 limit=limit,
                 count=post_count)
Пример #9
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        body = body['rebuild']

        try:
            image_href = body["imageRef"]
        except (KeyError, TypeError):
            msg = _("Could not parse imageRef from request.")
            raise exc.HTTPBadRequest(explanation=msg)

        image_href = self._image_uuid_from_href(image_href)

        password = self._get_server_admin_password(body)

        context = req.environ['nova.context']
        instance = self._get_server(context, req, id)

        attr_map = {
            'personality': 'files_to_inject',
            'name': 'display_name',
            'accessIPv4': 'access_ip_v4',
            'accessIPv6': 'access_ip_v6',
            'metadata': 'metadata',
            'auto_disk_config': 'auto_disk_config',
        }

        kwargs = {}

        # take the preserve_ephemeral value into account only when the
        # corresponding extension is active
        if (self.ext_mgr.is_loaded('os-preserve-ephemeral-rebuild')
                and 'preserve_ephemeral' in body):
            kwargs['preserve_ephemeral'] = strutils.bool_from_string(
                body['preserve_ephemeral'], strict=True)

        if 'accessIPv4' in body:
            self._validate_access_ipv4(body['accessIPv4'])

        if 'accessIPv6' in body:
            self._validate_access_ipv6(body['accessIPv6'])

        if 'name' in body:
            self._validate_server_name(body['name'])

        for request_attribute, instance_attribute in attr_map.items():
            try:
                kwargs[instance_attribute] = body[request_attribute]
            except (KeyError, TypeError):
                pass

        self._validate_metadata(kwargs.get('metadata', {}))

        if 'files_to_inject' in kwargs:
            personality = kwargs.pop('files_to_inject')
            files_to_inject = self._get_injected_files(personality)
        else:
            files_to_inject = None

        try:
            self.compute_api.rebuild(context,
                                     instance,
                                     image_href,
                                     password,
                                     files_to_inject=files_to_inject,
                                     **kwargs)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'rebuild', id)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
        except exception.InvalidMetadataSize as error:
            raise exc.HTTPRequestEntityTooLarge(
                explanation=error.format_message())
        except exception.ImageNotFound:
            msg = _("Cannot find image for rebuild")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except (exception.ImageNotActive, exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall, exception.InvalidMetadata,
                exception.AutoDiskConfigDisabledByImage) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        instance = self._get_server(context, req, id)

        view = self._view_builder.show(req, instance)

        # Add on the adminPass attribute since the view doesn't do it
        # unless instance passwords are disabled
        if CONF.enable_instance_password:
            view['server']['adminPass'] = password

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Пример #10
0
    def _get_servers(self, req, is_detail):
        """Returns a list of servers, based on any search options specified."""

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

        context = req.environ['nova.context']
        remove_invalid_options(context, search_opts,
                               self._get_server_search_options())

        # Verify search by 'status' contains a valid status.
        # Convert it to filter by vm_state or task_state for compute_api.
        search_opts.pop('status', None)
        if 'status' in req.GET.keys():
            statuses = req.GET.getall('status')
            states = common.task_and_vm_state_from_status(statuses)
            vm_state, task_state = states
            if not vm_state and not task_state:
                return {'servers': []}
            search_opts['vm_state'] = vm_state
            # When we search by vm state, task state will return 'default'.
            # So we don't need task_state search_opt.
            if 'default' not in task_state:
                search_opts['task_state'] = task_state

        if 'changes-since' in search_opts:
            try:
                parsed = timeutils.parse_isotime(search_opts['changes-since'])
            except ValueError:
                msg = _('Invalid changes-since value')
                raise exc.HTTPBadRequest(explanation=msg)
            search_opts['changes-since'] = parsed

        # By default, compute's get_all() will return deleted instances.
        # If an admin hasn't specified a 'deleted' search option, we need
        # to filter out deleted instances by setting the filter ourselves.
        # ... Unless 'changes-since' is specified, because 'changes-since'
        # should return recently deleted images according to the API spec.

        if 'deleted' not in search_opts:
            if 'changes-since' not in search_opts:
                # No 'changes-since', so we only want non-deleted servers
                search_opts['deleted'] = False

        if search_opts.get("vm_state") == ['deleted']:
            if context.is_admin:
                search_opts['deleted'] = True
            else:
                msg = _("Only administrators may list deleted instances")
                raise exc.HTTPForbidden(explanation=msg)

        # If all tenants is passed with 0 or false as the value
        # then remove it from the search options. Nothing passed as
        # the value for all_tenants is considered to enable the feature
        all_tenants = search_opts.get('all_tenants')
        if all_tenants:
            try:
                if not strutils.bool_from_string(all_tenants, True):
                    del search_opts['all_tenants']
            except ValueError as err:
                raise exception.InvalidInput(six.text_type(err))

        if 'all_tenants' in search_opts:
            policy.enforce(context, 'compute:get_all_tenants', {
                'project_id': context.project_id,
                'user_id': context.user_id
            })
            del search_opts['all_tenants']
        else:
            if context.project_id:
                search_opts['project_id'] = context.project_id
            else:
                search_opts['user_id'] = context.user_id

        limit, marker = common.get_limit_and_marker(req)
        # Sorting by multiple keys and directions is conditionally enabled
        sort_keys, sort_dirs = None, None
        if self.ext_mgr.is_loaded('os-server-sort-keys'):
            sort_keys, sort_dirs = common.get_sort_params(req.params)
        try:
            instance_list = self.compute_api.get_all(context,
                                                     search_opts=search_opts,
                                                     limit=limit,
                                                     marker=marker,
                                                     want_objects=True,
                                                     sort_keys=sort_keys,
                                                     sort_dirs=sort_dirs)
        except exception.MarkerNotFound:
            msg = _('marker [%s] not found') % marker
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.FlavorNotFound:
            LOG.debug("Flavor '%s' could not be found", search_opts['flavor'])
            instance_list = objects.InstanceList()

        if is_detail:
            instance_list.fill_faults()
            response = self._view_builder.detail(req, instance_list)
        else:
            response = self._view_builder.index(req, instance_list)
        req.cache_db_instances(instance_list)
        return response
Пример #11
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        rebuild_dict = body['rebuild']

        image_href = rebuild_dict["imageRef"]
        image_href = self._image_uuid_from_href(image_href)

        password = self._get_server_admin_password(rebuild_dict)

        context = req.environ['nova.context']
        instance = self._get_server(context, req, id)

        attr_map = {
            'name': 'display_name',
            'metadata': 'metadata',
        }

        rebuild_kwargs = {}

        if list(self.rebuild_extension_manager):
            self.rebuild_extension_manager.map(self._rebuild_extension_point,
                                               rebuild_dict, rebuild_kwargs)

        for request_attribute, instance_attribute in attr_map.items():
            try:
                rebuild_kwargs[instance_attribute] = rebuild_dict[
                    request_attribute]
            except (KeyError, TypeError):
                pass

        try:
            self.compute_api.rebuild(context, instance, image_href, password,
                                     **rebuild_kwargs)
        except exception.InstanceIsLocked as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'rebuild', id)
        except exception.InstanceNotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
        except exception.ImageNotFound:
            msg = _("Cannot find image for rebuild")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.QuotaError as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except (exception.ImageNotActive, exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall, exception.InvalidMetadata,
                exception.AutoDiskConfigDisabledByImage) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        instance = self._get_server(context, req, id)

        view = self._view_builder.show(req, instance)

        # Add on the admin_password attribute since the view doesn't do it
        # unless instance passwords are disabled
        if CONF.enable_instance_password:
            view['server']['adminPass'] = password

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Пример #12
0
    def _get_servers(self, req, is_detail):
        """Returns a list of servers, based on any search options specified."""

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

        context = req.environ['nova.context']
        remove_invalid_options(context, search_opts,
                               self._get_server_search_options())

        # Verify search by 'status' contains a valid status.
        # Convert it to filter by vm_state or task_state for compute_api.
        search_opts.pop('status', None)
        if 'status' in req.GET.keys():
            statuses = req.GET.getall('status')
            states = common.task_and_vm_state_from_status(statuses)
            vm_state, task_state = states
            if not vm_state and not task_state:
                return {'servers': []}
            search_opts['vm_state'] = vm_state
            # When we search by vm state, task state will return 'default'.
            # So we don't need task_state search_opt.
            if 'default' not in task_state:
                search_opts['task_state'] = task_state

        if 'changes-since' in search_opts:
            try:
                parsed = timeutils.parse_isotime(search_opts['changes-since'])
            except ValueError:
                msg = _('Invalid changes-since value')
                raise exc.HTTPBadRequest(explanation=msg)
            search_opts['changes-since'] = parsed

        # By default, compute's get_all() will return deleted instances.
        # If an admin hasn't specified a 'deleted' search option, we need
        # to filter out deleted instances by setting the filter ourselves.
        # ... Unless 'changes-since' is specified, because 'changes-since'
        # should return recently deleted images according to the API spec.

        if 'deleted' not in search_opts:
            if 'changes-since' not in search_opts:
                # No 'changes-since', so we only want non-deleted servers
                search_opts['deleted'] = False

        if search_opts.get("vm_state") == ['deleted']:
            if context.is_admin:
                search_opts['deleted'] = True
            else:
                msg = _("Only administrators may list deleted instances")
                raise exc.HTTPForbidden(explanation=msg)

        # If tenant_id is passed as a search parameter this should
        # imply that all_tenants is also enabled unless explicitly
        # disabled. Note that the tenant_id parameter is filtered out
        # by remove_invalid_options above unless the requestor is an
        # admin.

        # TODO(gmann): 'all_tenants' flag should not be required while
        # searching with 'tenant_id'. Ref bug# 1185290
        # +microversions to achieve above mentioned behavior by
        # uncommenting below code.

        # if 'tenant_id' in search_opts and 'all_tenants' not in search_opts:
        # We do not need to add the all_tenants flag if the tenant
        # id associated with the token is the tenant id
        # specified. This is done so a request that does not need
        # the all_tenants flag does not fail because of lack of
        # policy permission for compute:get_all_tenants when it
        # doesn't actually need it.
        # if context.project_id != search_opts.get('tenant_id'):
        #    search_opts['all_tenants'] = 1

        # If all tenants is passed with 0 or false as the value
        # then remove it from the search options. Nothing passed as
        # the value for all_tenants is considered to enable the feature
        all_tenants = search_opts.get('all_tenants')
        if all_tenants:
            try:
                if not strutils.bool_from_string(all_tenants, True):
                    del search_opts['all_tenants']
            except ValueError as err:
                raise exception.InvalidInput(six.text_type(err))

        if 'all_tenants' in search_opts:
            policy.enforce(context, 'compute:get_all_tenants', {
                'project_id': context.project_id,
                'user_id': context.user_id
            })
            del search_opts['all_tenants']
        else:
            if context.project_id:
                search_opts['project_id'] = context.project_id
            else:
                search_opts['user_id'] = context.user_id

        limit, marker = common.get_limit_and_marker(req)
        sort_keys, sort_dirs = common.get_sort_params(req.params)
        try:
            instance_list = self.compute_api.get_all(
                context,
                search_opts=search_opts,
                limit=limit,
                marker=marker,
                want_objects=True,
                expected_attrs=['pci_devices'],
                sort_keys=sort_keys,
                sort_dirs=sort_dirs)
        except exception.MarkerNotFound:
            msg = _('marker [%s] not found') % marker
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.FlavorNotFound:
            LOG.debug("Flavor '%s' could not be found ", search_opts['flavor'])
            instance_list = objects.InstanceList()

        if is_detail:
            instance_list.fill_faults()
            response = self._view_builder.detail(req, instance_list)
        else:
            response = self._view_builder.index(req, instance_list)
        req.cache_db_instances(instance_list)
        return response
Пример #13
0
 def _authorize(self, context, action):
     try:
         policy.check_policy(context, self.resource_name, action)
     except exception.PolicyNotAuthorized:
         raise exc.HTTPForbidden()
Пример #14
0
    def update(self, req, id, body):
        """Updates an existing image with the registry.

        :param req: wsgi Request object
        :param body: Dictionary of information about the image
        :param id:  The opaque internal identifier for the image

        :retval Returns the updated image information as a mapping,
        """
        image_data = body['image']
        from_state = body.get('from_state', None)

        # Prohibit modification of 'owner'
        if not req.context.is_admin and 'owner' in image_data:
            del image_data['owner']

        if 'location' in image_data:
            image_data['locations'] = [image_data.pop('location')]

        purge_props = req.headers.get("X-Glance-Registry-Purge-Props", "false")
        try:
            LOG.debug(
                "Updating image %(id)s with metadata: %(image_data)r", {
                    'id': id,
                    'image_data':
                    {k: v
                     for k, v in image_data.items() if k != 'locations'}
                })
            image_data = _normalize_image_location_for_db(image_data)
            if purge_props == "true":
                purge_props = True
            else:
                purge_props = False

            updated_image = self.db_api.image_update(req.context,
                                                     id,
                                                     image_data,
                                                     purge_props=purge_props,
                                                     from_state=from_state)

            LOG.info(_LI("Updating metadata for image %(id)s"), {'id': id})
            return dict(image=make_image_dict(updated_image))
        except exception.Invalid as e:
            msg = (_("Failed to update image metadata. "
                     "Got error: %s") % encodeutils.exception_to_unicode(e))
            LOG.error(msg)
            return exc.HTTPBadRequest(msg)
        except exception.ImageNotFound:
            LOG.info(_LI("Image %(id)s not found"), {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')
        except exception.ForbiddenPublicImage:
            LOG.info(_LI("Update denied for public image %(id)s"), {'id': id})
            raise exc.HTTPForbidden()
        except exception.Forbidden:
            # If it's private and doesn't belong to them, don't let on
            # that it exists
            LOG.info(
                _LI("Access denied to image %(id)s but returning"
                    " 'not found'"), {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')
        except exception.Conflict as e:
            LOG.info(encodeutils.exception_to_unicode(e))
            raise exc.HTTPConflict(body='Image operation conflicts',
                                   request=req,
                                   content_type='text/plain')
        except Exception:
            LOG.exception(_LE("Unable to update image %s") % id)
            raise
Пример #15
0
    def _validate_manage_share_server_parameters(self, context, body):

        if not (body and self.is_valid_body(body, 'share_server')):
            msg = _("Share Server entity not found in request body")
            raise exc.HTTPUnprocessableEntity(explanation=msg)

        required_parameters = ('host', 'share_network_id', 'identifier')
        data = body['share_server']

        for parameter in required_parameters:
            if parameter not in data:
                msg = _("Required parameter %s not found") % parameter
                raise exc.HTTPBadRequest(explanation=msg)
            if not data.get(parameter):
                msg = _("Required parameter %s is empty") % parameter
                raise exc.HTTPBadRequest(explanation=msg)

        identifier = data['identifier']
        host, share_network_id = data['host'], data['share_network_id']

        network_subnet_id = data.get('share_network_subnet_id')
        if network_subnet_id:
            try:
                network_subnet = db_api.share_network_subnet_get(
                    context, network_subnet_id)
            except exception.ShareNetworkSubnetNotFound:
                msg = _("The share network subnet %s does not "
                        "exist.") % network_subnet_id
                raise exc.HTTPBadRequest(explanation=msg)
        else:
            network_subnet = db_api.share_network_subnet_get_default_subnet(
                context, share_network_id)

        if network_subnet is None:
            msg = _("The share network %s does have a default subnet. Create "
                    "one or use a specific subnet to manage this share server "
                    "with API version >= 2.51.") % share_network_id
            raise exc.HTTPBadRequest(explanation=msg)

        if share_utils.extract_host(host, 'pool'):
            msg = _("Host parameter should not contain pool.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            utils.validate_service_host(context,
                                        share_utils.extract_host(host))
        except exception.ServiceNotFound as e:
            raise exc.HTTPBadRequest(explanation=e)
        except exception.PolicyNotAuthorized as e:
            raise exc.HTTPForbidden(explanation=e)
        except exception.AdminRequired as e:
            raise exc.HTTPForbidden(explanation=e)
        except exception.ServiceIsDown as e:
            raise exc.HTTPBadRequest(explanation=e)

        try:
            share_network = db_api.share_network_get(context, share_network_id)
        except exception.ShareNetworkNotFound as e:
            raise exc.HTTPBadRequest(explanation=e)

        driver_opts = data.get('driver_options')
        if driver_opts is not None and not isinstance(driver_opts, dict):
            msg = _("Driver options must be in dictionary format.")
            raise exc.HTTPBadRequest(explanation=msg)

        return identifier, host, share_network, driver_opts, network_subnet
Пример #16
0
    def update(self, req, id, body):
        """Updates an existing image with the registry.

        :param req: wsgi Request object
        :param body: Dictionary of information about the image
        :param id:  The opaque internal identifier for the image

        :retval Returns the updated image information as a mapping,
        """
        image_data = body['image']

        # Prohibit modification of 'owner'
        if not req.context.is_admin and 'owner' in image_data:
            del image_data['owner']

        if 'location' in image_data:
            image_data['locations'] = [image_data.pop('location')]

        purge_props = req.headers.get("X-Glance-Registry-Purge-Props", "false")
        try:
            LOG.debug(
                _("Updating image %(id)s with metadata: "
                  "%(image_data)r"), {
                      'id': id,
                      'image_data': image_data
                  })
            image_data = _normalize_image_location_for_db(image_data)
            if purge_props == "true":
                updated_image = self.db_api.image_update(
                    req.context, id, image_data, True)
            else:
                updated_image = self.db_api.image_update(
                    req.context, id, image_data)
            msg = _("Updating metadata for image %(id)s")
            LOG.info(msg % {'id': id})
            return dict(image=make_image_dict(updated_image))
        except exception.Invalid as e:
            msg = (_("Failed to update image metadata. "
                     "Got error: %(e)s") % {
                         'e': e
                     })
            LOG.error(msg)
            return exc.HTTPBadRequest(msg)
        except exception.NotFound:
            msg = _("Image %(id)s not found")
            LOG.info(msg % {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')
        except exception.ForbiddenPublicImage:
            msg = _("Update denied for public image %(id)s")
            LOG.info(msg % {'id': id})
            raise exc.HTTPForbidden()
        except exception.Forbidden:
            # If it's private and doesn't belong to them, don't let on
            # that it exists
            msg = _("Access denied to image %(id)s but returning 'not found'")
            LOG.info(msg % {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')
Пример #17
0
    def _evacuate(self, req, id, body):
        """Permit admins to evacuate a server from a failed host
        to a new one.
        """
        context = req.environ["nova.context"]
        instance = common.get_instance(self.compute_api, context, id)
        context.can(evac_policies.BASE_POLICY_NAME,
                    target={'user_id': instance.user_id,
                            'project_id': instance.project_id})

        evacuate_body = body["evacuate"]
        host = evacuate_body.get("host")
        force = None

        on_shared_storage = self._get_on_shared_storage(req, evacuate_body)

        if api_version_request.is_supported(req, min_version='2.29'):
            force = body["evacuate"].get("force", False)
            force = strutils.bool_from_string(force, strict=True)
            if force is True and not host:
                message = _("Can't force to a non-provided destination")
                raise exc.HTTPBadRequest(explanation=message)
        if api_version_request.is_supported(req, min_version='2.14'):
            password = self._get_password_v214(req, evacuate_body)
        else:
            password = self._get_password(req, evacuate_body,
                                          on_shared_storage)

        if host is not None:
            try:
                self.host_api.service_get_by_compute_host(context, host)
            except (exception.ComputeHostNotFound,
                    exception.HostMappingNotFound):
                msg = _("Compute host %s not found.") % host
                raise exc.HTTPNotFound(explanation=msg)

        if instance.host == host:
            msg = _("The target host can't be the same one.")
            raise exc.HTTPBadRequest(explanation=msg)

        # We could potentially move this check to conductor and avoid the
        # extra API call to neutron when we support move operations with ports
        # having resource requests.
        if (common.instance_has_port_with_resource_request(
                instance.uuid, self.network_api) and not
                common.supports_port_resource_request_during_move()):
            LOG.warning("The evacuate action on a server with ports "
                        "having resource requests, like a port with a QoS "
                        "minimum bandwidth policy, is not supported until "
                        "every nova-compute is upgraded to Ussuri")
            msg = _("The evacuate action on a server with ports having "
                    "resource requests, like a port with a QoS minimum "
                    "bandwidth policy, is not supported by this cluster right "
                    "now")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            self.compute_api.evacuate(context, instance, host,
                                      on_shared_storage, password, force)
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'evacuate', id)
        except exception.ComputeServiceInUse as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())
        except exception.ForbiddenWithAccelerators as e:
            raise exc.HTTPForbidden(explanation=e.format_message())
        except exception.OperationNotSupportedForVTPM as e:
            raise exc.HTTPConflict(explanation=e.format_message())

        if (not api_version_request.is_supported(req, min_version='2.14') and
                CONF.api.enable_instance_password):
            return {'adminPass': password}
        else:
            return None
Пример #18
0
            return dict(image=make_image_dict(updated_image))
        except exception.Invalid, e:
            msg = (_("Failed to update image metadata. "
                     "Got error: %(e)s") % locals())
            LOG.error(msg)
            return exc.HTTPBadRequest(msg)
        except exception.NotFound:
            msg = _("Image %(id)s not found")
            LOG.info(msg % {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')
        except exception.ForbiddenPublicImage:
            msg = _("Update denied for public image %(id)s")
            LOG.info(msg % {'id': id})
            raise exc.HTTPForbidden()
        except exception.Forbidden:
            # If it's private and doesn't belong to them, don't let on
            # that it exists
            msg = _("Access denied to image %(id)s but returning 'not found'")
            LOG.info(msg % {'id': id})
            raise exc.HTTPNotFound(body='Image not found',
                                   request=req,
                                   content_type='text/plain')


def make_image_dict(image):
    """
    Create a dict representation of an image which we can use to
    serialize the image.
    """
Пример #19
0
 def process(self, req):
     if not req.method == 'POST':
         raise exc.HTTPMethodNotAllowed("Only POST allowed",
                                        allowed='POST').exception
     try:
         json = loads(req.body)
     except ValueError, e:
         raise ValueError('Bad JSON: %s' % e)
     try:
         method = json['method']
         params = json['params']
         id = json['id']
     except KeyError, e:
         raise ValueError("JSON body missing parameter: %s" % e)
     if method.startswith('_'):
         raise exc.HTTPForbidden(
             "Bad method name %s: must not start with _" % method).exception
     if not isinstance(params, list):
         raise ValueError("Bad params %r: must be a list" % params)
     try:
         method = getattr(self.obj, method)
     except AttributeError:
         raise ValueError("No such method %s" % method)
     try:
         result = method(*params)
     except:
         text = traceback.format_exc()
         exc_value = sys.exc_info()[1]
         error_value = dict(name='JSONRPCError',
                            code=100,
                            message=str(exc_value),
                            error=text)
Пример #20
0
 def process_request(self, req):
     if req.headers.get('X-Auth-Token') != 'open-sesame':
         return exc.HTTPForbidden()
Пример #21
0
    def _http_request(self,
                      method,
                      url,
                      headers,
                      body,
                      ignore_result_body=False):
        """Perform an HTTP request against the server.

        method: the HTTP method to use
        url: the URL to request (not including server portion)
        headers: headers for the request
        body: body to send with the request
        ignore_result_body: the body of the result will be ignored

        Returns: a http_client response object
        """
        if self.auth_token:
            headers.setdefault('x-auth-token', self.auth_token)

        LOG.debug(
            'Request: %(method)s http://%(server)s:%(port)s'
            '%(url)s with headers %(headers)s', {
                'method': method,
                'server': self.conn.host,
                'port': self.conn.port,
                'url': url,
                'headers': repr(headers)
            })
        self.conn.request(method, url, body, headers)

        response = self.conn.getresponse()
        headers = self._header_list_to_dict(response.getheaders())
        code = response.status
        code_description = http_client.responses[code]
        LOG.debug('Response: %(code)s %(status)s %(headers)s', {
            'code': code,
            'status': code_description,
            'headers': repr(headers)
        })

        if code == 400:
            raise exc.HTTPBadRequest(explanation=response.read())

        if code == 500:
            raise exc.HTTPInternalServerError(explanation=response.read())

        if code == 401:
            raise exc.HTTPUnauthorized(explanation=response.read())

        if code == 403:
            raise exc.HTTPForbidden(explanation=response.read())

        if code == 409:
            raise exc.HTTPConflict(explanation=response.read())

        if ignore_result_body:
            # NOTE: because we are pipelining requests through a single HTTP
            # connection, http_client requires that we read the response body
            # before we can make another request. If the caller knows they
            # don't care about the body, they can ask us to do that for them.
            response.read()
        return response
Пример #22
0
 def process_request(self, req):
     if req.headers.get('X-Auth-Token') != 'rainbow':
         return exc.HTTPForbidden()
Пример #23
0
    def create(self, req, body):
        """Creates a new server for a given user."""

        context = req.environ['nova.context']
        server_dict = body['server']
        password = self._get_server_admin_password(server_dict)
        name = server_dict['name']

        # Arguments to be passed to instance create function
        create_kwargs = {}

        # Query extensions which want to manipulate the keyword
        # arguments.
        # NOTE(cyeoh): This is the hook that extensions use
        # to replace the extension specific code below.
        # When the extensions are ported this will also result
        # in some convenience function from this class being
        # moved to the extension
        if list(self.create_extension_manager):
            self.create_extension_manager.map(self._create_extension_point,
                                              server_dict, create_kwargs, body)

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

        # NOTE(cyeoh): Although an extension can set
        # return_reservation_id in order to request that a reservation
        # id be returned to the client instead of the newly created
        # instance information we do not want to pass this parameter
        # to the compute create call which always returns both. We use
        # this flag after the instance create call to determine what
        # to return to the client
        return_reservation_id = create_kwargs.pop('return_reservation_id',
                                                  False)

        requested_networks = None
        if ('os-networks' in self.extension_info.get_extensions()
                or utils.is_neutron()):
            requested_networks = server_dict.get('networks')

        if requested_networks is not None:
            requested_networks = self._get_requested_networks(
                requested_networks)

        try:
            flavor_id = self._flavor_id_from_req_data(body)
        except ValueError as error:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            inst_type = flavors.get_flavor_by_flavor_id(flavor_id,
                                                        ctxt=context,
                                                        read_deleted="no")

            (instances, resv_id) = self.compute_api.create(
                context,
                inst_type,
                image_uuid,
                display_name=name,
                display_description=name,
                metadata=server_dict.get('metadata', {}),
                admin_password=password,
                requested_networks=requested_networks,
                check_server_group_quota=True,
                **create_kwargs)
        except (exception.QuotaError, exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(explanation=error.format_message(),
                                    headers={'Retry-After': 0})
        except exception.ImageNotFound:
            msg = _("Can not find requested image")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.FlavorNotFound:
            msg = _("Invalid flavorRef provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.KeypairNotFound:
            msg = _("Invalid key_name provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ConfigDriveInvalidValue:
            msg = _("Invalid config_drive provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ExternalNetworkAttachForbidden as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {
                'err_type': err.exc_type,
                'err_msg': err.value
            }
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except (exception.ImageNotActive, exception.FlavorDiskTooSmall,
                exception.FlavorMemoryTooSmall, exception.InvalidMetadata,
                exception.InvalidRequest, exception.InvalidVolume,
                exception.MultiplePortsNotApplicable,
                exception.InvalidFixedIpAndMaxCountRequest,
                exception.InstanceUserDataMalformed,
                exception.InstanceUserDataTooLarge, exception.PortNotFound,
                exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound,
                exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet,
                exception.NetworkNotFound,
                exception.InvalidBDMVolumeNotBootable,
                exception.InvalidBDMSnapshot, exception.InvalidBDMVolume,
                exception.InvalidBDMImage, exception.InvalidBDMBootSequence,
                exception.InvalidBDMLocalsLimit,
                exception.InvalidBDMVolumeNotBootable,
                exception.AutoDiskConfigDisabledByImage,
                exception.ImageNUMATopologyIncomplete,
                exception.ImageNUMATopologyForbidden,
                exception.ImageNUMATopologyAsymmetric,
                exception.ImageNUMATopologyCPUOutOfRange,
                exception.ImageNUMATopologyCPUDuplicates,
                exception.ImageNUMATopologyCPUsUnassigned,
                exception.ImageNUMATopologyMemoryOutOfRange) as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())
        except (exception.PortInUse, exception.InstanceExists,
                exception.NetworkAmbiguous, exception.NoUniqueMatch) as error:
            raise exc.HTTPConflict(explanation=error.format_message())

        # If the caller wanted a reservation_id, return it
        if return_reservation_id:
            # NOTE(cyeoh): In v3 reservation_id was wrapped in
            # servers_reservation but this is reverted for V2 API
            # compatibility. In the long term with the tasks API we
            # will probably just drop the concept of reservation_id
            return wsgi.ResponseObject({'reservation_id': resv_id})

        req.cache_db_instances(instances)
        server = self._view_builder.create(req, instances[0])

        if CONF.enable_instance_password:
            server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Пример #24
0
 def run(self):
     
    
     #imageName=str(uuid.uuid4())
     
     #create image
     #image_meta = self.compute_api.snapshot(self.context, self.instance, name=imageId, extra_properties=None)
     
     bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
             self.context, self.instance['uuid'])
     volume_ids = [bdm.volume_id for bdm in bdms if bdm.volume_id]
     
      
     image_uuid = None
     if volume_ids is None or volume_ids == []:
         tmp_image_name = "%s@%s" % (uuid.uuid1(), self.instance.uuid)
         image_meta = self.compute_api.snapshot(self.context, self.instance, name=tmp_image_name, extra_properties=None)
         image_uuid = image_meta['id']
         try:
             filters = {'name':tmp_image_name}
             imagelist = self.image_api.get_all(self.context,filters=filters)
             image = imagelist[0]
             while image['status'] != 'active':
                 time.sleep(1) 
                 imagelist = self.image_api.get_all(self.context,filters=filters)
                 image = imagelist[0]
                 image_uuid = image['id']
                 image = self.image_api.get(self.context,image_uuid )
         except (exception.NotFound, exception.InvalidImageRef):
             explanation = _("Image not found.")
             raise webob.exc.HTTPNotFound(explanation=explanation)
          
     else :
         for volume_id in volume_ids:
             volume = self.volume_api.get(self.context, volume_id)
             #import pdb
             #pdb.set_trace()
             response = self.volume_api.upload_to_image(self.context,
                                                             volume_id,
                                                             True,
                                                             volume_id,
                                                             'bare',
                                                             'qcow2')
             image_uuid = response[1]['os-volume_upload_image']['image_id']
      
         #image_uuid = image_meta['id']
         try:
             image = self.image_api.get(self.context, image_uuid)
             cascading_image_name = image['id']
             filters = {'name':cascading_image_name}
             cascading_image = self.image_api.get_all(self.context,filters=filters)
             cascading_image_id = cascading_image[0]['id']
             cascading_image = self.image_api.get(self.context,cascading_image_id )
             while cascading_image['status'] != 'active':
                 time.sleep(1) 
                 cascading_image = self.image_api.get(self.context,cascading_image_id )
         except (exception.NotFound, exception.InvalidImageRef):
             explanation = _("Image not found.")
             raise webob.exc.HTTPNotFound(explanation=explanation)
     
     access_ip_v4 = self.instance.access_ip_v4
     if access_ip_v4 is not None:
         self._validate_access_ipv4(access_ip_v4)
         
     access_ip_v6 = self.instance.access_ip_v6
     if access_ip_v6 is not None:
         self._validate_access_ipv6(access_ip_v6)
         
     #networks = common.get_networks_for_instance(context, instance)
     min_count = 1
     max_count = 1
     
     name=self.instance.display_name
     key_name = None
     metadata = self.instance.metadata
     injected_files = []
     security_group=self.instance.security_groups
     user_data=self.instance.user_data
     
     flavor_id = self.instance.system_metadata['instance_type_flavorid']
     
     scheduler_hints = {}
     legacy_bdm = True
     #check_server_group_quota = \
     #    self.ext_mgr.is_loaded('os-server-group-quotas')
     check_server_group_quota=True
     
     requested_networks = []
     nw_info = compute_utils.get_nw_info_for_instance(self.instance)
     for vif in nw_info:
         net_uuid = vif['network']['id']
         net_ip = vif['network']['subnets'][0]['ips'][0]['address']
         requested_networks.append({'fixed_ip':net_ip, 'uuid':net_uuid})
     
     requested_networks = self._get_requested_networks(requested_networks)
     #detach port delete
     self.compute_api.delete(self.context,self.instance)
     
     while True:
         time.sleep(3)
         try:
             _get_inst_type = flavors.get_flavor_by_flavor_id
             inst_type = _get_inst_type(flavor_id, ctxt=self.context,
                                        read_deleted="no")
             (instances, resv_id) = self.compute_api.create(self.context,
                         inst_type,
                         image_uuid,
                         display_name=name,
                         display_description=name,
                         key_name=key_name,
                         metadata=metadata,
                         access_ip_v4=access_ip_v4,
                         access_ip_v6=access_ip_v6,
                         injected_files=injected_files,
                         admin_password=None,
                         min_count=min_count,
                         max_count=max_count,
                         requested_networks=requested_networks,
                         security_group=security_group,
                         user_data=user_data,
                         availability_zone=self.availability_zone,
                         config_drive=None,
                         block_device_mapping=None,
                         auto_disk_config=None,
                         scheduler_hints=scheduler_hints,
                         legacy_bdm=legacy_bdm,
                         check_server_group_quota=check_server_group_quota)
         except (exception.QuotaError,
                 exception.PortLimitExceeded) as error:
             raise exc.HTTPForbidden(
                 explanation=error.format_message(),
                 headers={'Retry-After': 0})
         except exception.InvalidMetadataSize as error:
             raise exc.HTTPRequestEntityTooLarge(
                 explanation=error.format_message())
         except exception.ImageNotFound as error:
             msg = _("Can not find requested image")
             raise exc.HTTPBadRequest(explanation=msg)
         except exception.FlavorNotFound as error:
             msg = _("Invalid flavorRef provided.")
             raise exc.HTTPBadRequest(explanation=msg)
         except exception.KeypairNotFound as error:
             msg = _("Invalid key_name provided.")
             raise exc.HTTPBadRequest(explanation=msg)
         except exception.ConfigDriveInvalidValue:
             msg = _("Invalid config_drive provided.")
             raise exc.HTTPBadRequest(explanation=msg)
         except UnicodeDecodeError as error:
             msg = "UnicodeError: %s" % unicode(error)
             raise exc.HTTPBadRequest(explanation=msg)
         except (exception.ImageNotActive,
                 exception.FlavorDiskTooSmall,
                 exception.FlavorMemoryTooSmall,
                 exception.NetworkNotFound,
                 exception.PortNotFound,
                 exception.FixedIpAlreadyInUse,
                 exception.SecurityGroupNotFound,
                 exception.InstanceUserDataTooLarge,
                 exception.InstanceUserDataMalformed) as error:
             raise exc.HTTPBadRequest(explanation=error.format_message())
         except (exception.ImageNUMATopologyIncomplete,
                 exception.ImageNUMATopologyForbidden,
                 exception.ImageNUMATopologyAsymmetric,
                 exception.ImageNUMATopologyCPUOutOfRange,
                 exception.ImageNUMATopologyCPUDuplicates,
                 exception.ImageNUMATopologyCPUsUnassigned,
                 exception.ImageNUMATopologyMemoryOutOfRange) as error:
             raise exc.HTTPBadRequest(explanation=error.format_message())
         except (exception.PortInUse,
                 exception.NoUniqueMatch) as error:
             continue
             raise exc.HTTPConflict(explanation=error.format_message())
         except exception.Invalid as error:
             raise exc.HTTPBadRequest(explanation=error.format_message())
         break
Пример #25
0
    def _revert(self, req, id, body=None):
        """Revert a share to a snapshot."""
        context = req.environ['manila.context']
        revert_data = self._validate_revert_parameters(context, body)

        try:
            share_id = id
            snapshot_id = revert_data['snapshot_id']

            share = self.share_api.get(context, share_id)
            snapshot = self.share_api.get_snapshot(context, snapshot_id)

            # Ensure share supports reverting to a snapshot
            if not share['revert_to_snapshot_support']:
                msg_args = {'share_id': share_id, 'snap_id': snapshot_id}
                msg = _('Share %(share_id)s may not be reverted to snapshot '
                        '%(snap_id)s, because the share does not have that '
                        'capability.')
                raise exc.HTTPBadRequest(explanation=msg % msg_args)

            # Ensure requested share & snapshot match.
            if share['id'] != snapshot['share_id']:
                msg_args = {'share_id': share_id, 'snap_id': snapshot_id}
                msg = _('Snapshot %(snap_id)s is not associated with share '
                        '%(share_id)s.')
                raise exc.HTTPBadRequest(explanation=msg % msg_args)

            # Ensure share status is 'available'.
            if share['status'] != constants.STATUS_AVAILABLE:
                msg_args = {
                    'share_id': share_id,
                    'state': share['status'],
                    'available': constants.STATUS_AVAILABLE,
                }
                msg = _("Share %(share_id)s is in '%(state)s' state, but it "
                        "must be in '%(available)s' state to be reverted to a "
                        "snapshot.")
                raise exc.HTTPConflict(explanation=msg % msg_args)

            # Ensure snapshot status is 'available'.
            if snapshot['status'] != constants.STATUS_AVAILABLE:
                msg_args = {
                    'snap_id': snapshot_id,
                    'state': snapshot['status'],
                    'available': constants.STATUS_AVAILABLE,
                }
                msg = _("Snapshot %(snap_id)s is in '%(state)s' state, but it "
                        "must be in '%(available)s' state to be restored.")
                raise exc.HTTPConflict(explanation=msg % msg_args)

            # Ensure a long-running task isn't active on the share
            if share.is_busy:
                msg_args = {'share_id': share_id}
                msg = _("Share %(share_id)s may not be reverted while it has "
                        "an active task.")
                raise exc.HTTPConflict(explanation=msg % msg_args)

            # Ensure the snapshot is the most recent one.
            latest_snapshot = self.share_api.get_latest_snapshot_for_share(
                context, share_id)
            if not latest_snapshot:
                msg_args = {'share_id': share_id}
                msg = _("Could not determine the latest snapshot for share "
                        "%(share_id)s.")
                raise exc.HTTPBadRequest(explanation=msg % msg_args)
            if latest_snapshot['id'] != snapshot_id:
                msg_args = {
                    'share_id': share_id,
                    'snap_id': snapshot_id,
                    'latest_snap_id': latest_snapshot['id'],
                }
                msg = _("Snapshot %(snap_id)s may not be restored because "
                        "it is not the most recent snapshot of share "
                        "%(share_id)s. Currently the latest snapshot is "
                        "%(latest_snap_id)s.")
                raise exc.HTTPConflict(explanation=msg % msg_args)

            # Ensure the access rules are not in the process of updating
            for instance in share['instances']:
                access_rules_status = instance['access_rules_status']
                if access_rules_status != constants.ACCESS_STATE_ACTIVE:
                    msg_args = {
                        'share_id': share_id,
                        'snap_id': snapshot_id,
                        'state': constants.ACCESS_STATE_ACTIVE
                    }
                    msg = _("Snapshot %(snap_id)s belongs to a share "
                            "%(share_id)s which has access rules that are"
                            "not %(state)s.")
                    raise exc.HTTPConflict(explanation=msg % msg_args)

            msg_args = {'share_id': share_id, 'snap_id': snapshot_id}
            msg = 'Reverting share %(share_id)s to snapshot %(snap_id)s.'
            LOG.info(msg, msg_args)

            self.share_api.revert_to_snapshot(context, share, snapshot)
        except exception.ShareNotFound as e:
            raise exc.HTTPNotFound(explanation=six.text_type(e))
        except exception.ShareSnapshotNotFound as e:
            raise exc.HTTPBadRequest(explanation=six.text_type(e))
        except exception.ShareSizeExceedsAvailableQuota as e:
            raise exc.HTTPForbidden(explanation=six.text_type(e))
        except exception.ReplicationException as e:
            raise exc.HTTPBadRequest(explanation=six.text_type(e))

        return webob.Response(status_int=202)
Пример #26
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]

        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)
Пример #27
0
    def create(self, req, body):
        """Creates a new server for a given user."""
        if not self.is_valid_body(body, 'server'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['nova.context']
        server_dict = body['server']
        password = self._get_server_admin_password(server_dict)

        if 'name' not in server_dict:
            msg = _("Server name is not defined")
            raise exc.HTTPBadRequest(explanation=msg)

        name = server_dict['name']
        self._validate_server_name(name)
        name = name.strip()

        image_uuid = self._image_from_req_data(body)

        personality = server_dict.get('personality')
        config_drive = None
        if self.ext_mgr.is_loaded('os-config-drive'):
            config_drive = server_dict.get('config_drive')

        injected_files = []
        if personality:
            injected_files = self._get_injected_files(personality)

        sg_names = []
        if self.ext_mgr.is_loaded('os-security-groups'):
            security_groups = server_dict.get('security_groups')
            if security_groups is not None:
                sg_names = [
                    sg['name'] for sg in security_groups if sg.get('name')
                ]
        if not sg_names:
            sg_names.append('default')

        sg_names = list(set(sg_names))

        requested_networks = self._determine_requested_networks(server_dict)

        (access_ip_v4, ) = server_dict.get('accessIPv4'),
        if access_ip_v4 is not None:
            self._validate_access_ipv4(access_ip_v4)

        (access_ip_v6, ) = server_dict.get('accessIPv6'),
        if access_ip_v6 is not None:
            self._validate_access_ipv6(access_ip_v6)

        flavor_id = self._flavor_id_from_req_data(body)

        # optional openstack extensions:
        key_name = self._extract(server_dict, 'os-keypairs', 'key_name')
        availability_zone = self._extract(server_dict, 'os-availability-zone',
                                          'availability_zone')
        user_data = self._extract(server_dict, 'os-user-data', 'user_data')
        self._validate_user_data(user_data)

        legacy_bdm, block_device_mapping = self._extract_bdm(server_dict)

        ret_resv_id = False
        # min_count and max_count are optional.  If they exist, they may come
        # in as strings.  Verify that they are valid integers and > 0.
        # Also, we want to default 'min_count' to 1, and default
        # 'max_count' to be 'min_count'.
        min_count = 1
        max_count = 1
        if self.ext_mgr.is_loaded('os-multiple-create'):
            ret_resv_id = server_dict.get('return_reservation_id', False)
            min_count = server_dict.get('min_count', 1)
            max_count = server_dict.get('max_count', min_count)

        try:
            min_count = utils.validate_integer(min_count,
                                               "min_count",
                                               min_value=1)
            max_count = utils.validate_integer(max_count,
                                               "max_count",
                                               min_value=1)
        except exception.InvalidInput as e:
            raise exc.HTTPBadRequest(explanation=e.format_message())

        if min_count > max_count:
            msg = _('min_count must be <= max_count')
            raise exc.HTTPBadRequest(explanation=msg)

        auto_disk_config = False
        if self.ext_mgr.is_loaded('OS-DCF'):
            auto_disk_config = server_dict.get('auto_disk_config')

        scheduler_hints = {}
        if self.ext_mgr.is_loaded('OS-SCH-HNT'):
            scheduler_hints = server_dict.get('scheduler_hints', {})

        check_server_group_quota = self.ext_mgr.is_loaded(
            'os-server-group-quotas')
        try:
            _get_inst_type = flavors.get_flavor_by_flavor_id
            inst_type = _get_inst_type(flavor_id,
                                       ctxt=context,
                                       read_deleted="no")

            (instances, resv_id) = self.compute_api.create(
                context,
                inst_type,
                image_uuid,
                display_name=name,
                display_description=name,
                key_name=key_name,
                metadata=server_dict.get('metadata', {}),
                access_ip_v4=access_ip_v4,
                access_ip_v6=access_ip_v6,
                injected_files=injected_files,
                admin_password=password,
                min_count=min_count,
                max_count=max_count,
                requested_networks=requested_networks,
                security_group=sg_names,
                user_data=user_data,
                availability_zone=availability_zone,
                config_drive=config_drive,
                block_device_mapping=block_device_mapping,
                auto_disk_config=auto_disk_config,
                scheduler_hints=scheduler_hints,
                legacy_bdm=legacy_bdm,
                check_server_group_quota=check_server_group_quota)
        except (exception.QuotaError, exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(explanation=error.format_message(),
                                    headers={'Retry-After': 0})
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {
                'err_type': err.exc_type,
                'err_msg': err.value
            }
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except Exception as error:
            # The remaining cases can be handled in a standard fashion.
            self._handle_create_exception(*sys.exc_info())

        # If the caller wanted a reservation_id, return it
        if ret_resv_id:
            return wsgi.ResponseObject({'reservation_id': resv_id})

        req.cache_db_instances(instances)
        server = self._view_builder.create(req, instances[0])

        if CONF.enable_instance_password:
            server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Пример #28
0
    def create(self, req, body):
        context = _authorize_context(req)

        sg_rule = self._from_body(body, 'security_group_rule')
        group_id = sg_rule.get('group_id')
        source_group = {}

        try:
            parent_group_id = self.security_group_api.validate_id(
                sg_rule.get('parent_group_id'))
            security_group = self.security_group_api.get(context, None,
                                                         parent_group_id,
                                                         map_exception=True)
            if group_id is not None:
                group_id = self.security_group_api.validate_id(group_id)

                source_group = self.security_group_api.get(
                    context, id=group_id)
            new_rule = self._rule_args_to_dict(context,
                              to_port=sg_rule.get('to_port'),
                              from_port=sg_rule.get('from_port'),
                              ip_protocol=sg_rule.get('ip_protocol'),
                              cidr=sg_rule.get('cidr'),
                              group_id=group_id)
        except (exception.Invalid, exception.InvalidCidr) as exp:
            raise exc.HTTPBadRequest(explanation=exp.format_message())
        except exception.SecurityGroupNotFound as exp:
            raise exc.HTTPNotFound(explanation=exp.format_message())

        if new_rule is None:
            msg = _("Not enough parameters to build a valid rule.")
            raise exc.HTTPBadRequest(explanation=msg)

        new_rule['parent_group_id'] = security_group['id']

        if 'cidr' in new_rule:
            net, prefixlen = netutils.get_net_and_prefixlen(new_rule['cidr'])
            if net not in ('0.0.0.0', '::') and prefixlen == '0':
                msg = _("Bad prefix for network in cidr %s") % new_rule['cidr']
                raise exc.HTTPBadRequest(explanation=msg)

        group_rule_data = None
        try:
            if group_id:
                group_rule_data = {'name': source_group.get('name'),
                                   'tenant_id': source_group.get('project_id')}

            security_group_rule = (
                self.security_group_api.create_security_group_rule(
                    context, security_group, new_rule))
        except exception.Invalid as exp:
            raise exc.HTTPBadRequest(explanation=exp.format_message())
        except exception.SecurityGroupNotFound as exp:
            raise exc.HTTPNotFound(explanation=exp.format_message())
        except exception.SecurityGroupLimitExceeded as exp:
            raise exc.HTTPForbidden(explanation=exp.format_message())

        formatted_rule = self._format_security_group_rule(context,
                                                          security_group_rule,
                                                          group_rule_data)
        return {"security_group_rule": formatted_rule}
def auth_filter(request, app):
    if request.headers.get('X-Auth-Token') != 'open-sesame':
        return exc.HTTPForbidden()
    return app(request)
Пример #30
0
    def _process(self, req):
        """
        a request URL is parsed as follow
        /object/resource?args
        object is the main python object
        GET /object is mapped to handle_get function(**kwargs)
        GET /object/resource is mapped to handle_get([resource,], **kwargs)
        GET /object/resource/resource2 is mapped to handle_get([resource,resource2], **kwargs)
        args are always passed on through **kwargs
        """
        method = req.method
        object = req.path_info_pop()
        #do some static file serving logic first before trying functions on objects
        if object == None or object == "":
            #the root / is moved to static file serving
            res = exc.HTTPMovedPermanently(location="/static/")
            return res
        elif object == "static":
            # In here we are handling real files so be careful!!!
            if method == "GET":
                # simply serving static files
                #import os
                #print(os.getcwd())
                res = static.DirectoryApp(self._httpdRoot)
                return res
            if method == "POST":
                # uploading new files
                filename = req.path_info_pop()
                filepath = os.path.join(os.path.join(self._httpdRoot,
                                                     filename))
                # if the file exists we raise an exception
                if filename == "":
                    filename = req.params['file']
                if os.path.exists(filepath):
                    raise exc.HTTPForbidden("%s already exists" % filename)
                #print(dir(req))
                #print(req.body)
                saveFile = open(os.path.join(self._httpdRoot, filename), 'wb')
                saveFile.write(req.body_file.read())
                saveFile.close()
                return Response("ok")
            if method == "PUT":
                # This will overwrite your files
                # uploading files to update
                filename = req.path_info_pop()
                filepath = os.path.join(os.path.join(self._httpdRoot,
                                                     filename))
                # if the file exists we raise an exception
                if not os.path.exists(filepath):
                    raise exc.HTTPNotFound("%s file not found" % filename)
                if filename == "":
                    filename = req.params['file']
                #print(dir(req))
                #print(req.body)
                saveFile = open(os.path.join(self._httpdRoot, filename), 'wb')
                saveFile.write(req.body_file.read())
                saveFile.close()
                return Response("ok")

        #################################################
        #
        # After this we only handle JSON type content!!!!
        #
        #################################################

        #Find the object
        obj = None
        try:
            obj = self._restObjects[object]
        except:
            #print(self._restObjects)
            #print(dir(self._restObjects))
            raise exc.HTTPNotFound('No such resource: %s' % object)

        #Find the function
        func = None
        try:
            func = getattr(obj, 'handle_' + method)
        except:
            raise exc.HTTPNotFound('No %s method on resource: %s' %
                                   (method, object))

        # Find resources:
        resources = []
        # get first resource
        res = req.path_info_pop()
        while res:
            resources.append(res)
            # get next resource
            res = req.path_info_pop()

        #optional extra headers
        #FIXME: this shouldn't be hardcoded. The appie modules should take care of this
        #http://www.w3.org/TR/cors/#syntax
        extraHeaderList = [
            ('Access-Control-Allow-Origin', '*'),
            ('Access-Control-Allow-Methods',
             'GET, PUT, POST, DELETE, OPTIONS'),
            ('Access-Control-Max-Age', '86400'),
            ('Access-Control-Allow-Headers',
             'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
             )
        ]
        #Get args
        kwargs = req.GET
        if (method == 'POST'):
            #curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d
            #curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"test" : "help" }' http://localhost:8000/bge/IcoSphere
            if req.content_type == 'application/json':
                encoding = req.charset
                body = req.body.decode(encoding)
                data = loads(body)
                #print(data)
                #print(type(data))
                kwargs = data
            else:
                kwargs = req.POST
        try:
            result = func(*resources, **kwargs)
        except:
            raise exc.HTTPInternalServerError(
                "Appie raised an exception while calling the method with %s %s"
                % (str(resources), str(kwargs)))
        resp = Response(content_type='application/json',
                        charset='utf8',
                        body=dumps(result))
        resp.headerlist.extend(extraHeaderList)
        return resp