Example #1
0
    def create(self, req, server_id, body):
        """Attach a volume to an instance."""
        context = req.environ['nova.context']

        if not body:
            raise exc.HTTPUnprocessableEntity()

        volume_id = body['volumeAttachment']['volumeId']
        device = body['volumeAttachment']['device']

        msg = _("Attach volume %(volume_id)s to instance %(server_id)s"
                " at %(device)s") % locals()
        LOG.audit(msg, context=context)

        try:
            instance = self.compute_api.get(context, server_id)
            self.compute_api.attach_volume(context, instance, volume_id,
                                           device)
        except exception.NotFound:
            raise exc.HTTPNotFound()

        # The attach is async
        attachment = {}
        attachment['id'] = volume_id
        attachment['volumeId'] = volume_id

        # NOTE(justinsb): And now, we have a problem...
        # The attach is async, so there's a window in which we don't see
        # the attachment (until the attachment completes).  We could also
        # get problems with concurrent requests.  I think we need an
        # attachment state, and to write to the DB here, but that's a bigger
        # change.
        # For now, we'll probably have to rely on libraries being smart

        # TODO(justinsb): How do I return "accepted" here?
        return {'volumeAttachment': attachment}
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:
            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)
Example #3
0
    def _action_reboot(self, req, id, body):
        if 'reboot' in body and 'type' in body['reboot']:
            valid_reboot_types = ['HARD', 'SOFT']
            reboot_type = body['reboot']['type'].upper()
            if not valid_reboot_types.count(reboot_type):
                msg = _("Argument 'type' for reboot is not HARD or SOFT")
                LOG.error(msg)
                raise exc.HTTPBadRequest(explanation=msg)
        else:
            msg = _("Missing argument 'type' for reboot")
            LOG.error(msg)
            raise exc.HTTPBadRequest(explanation=msg)

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

        try:
            self.compute_api.reboot(context, instance, reboot_type)
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(
                state_error, 'reboot')
        except Exception, e:
            LOG.exception(_("Error in reboot %s"), e, instance=instance)
            raise exc.HTTPUnprocessableEntity()
Example #4
0
    def create(self, req):
        """ Creates a new server for a given user """
        env = self._deserialize_create(req)
        if not env:
            return faults.Fault(exc.HTTPUnprocessableEntity())

        context = req.environ['nova.context']

        password = self._get_server_admin_password(env['server'])

        key_name = env['server'].get('key_name')
        key_data = None

        if key_name:
            try:
                key_pair = db.key_pair_get(context, context.user_id, key_name)
                key_name = key_pair['name']
                key_data = key_pair['public_key']
            except:
                msg = _("Can not load the requested key %s" % key_name)
                return faults.Fault(exc.HTTPBadRequest(msg))
        else:
            # backwards compatibility
            key_pairs = auth_manager.AuthManager.get_key_pairs(context)
            if key_pairs:
                key_pair = key_pairs[0]
                key_name = key_pair['name']
                key_data = key_pair['public_key']

        image_id = self._image_id_from_req_data(env)

        kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(
            req, image_id)

        personality = env['server'].get('personality')
        injected_files = []
        if personality:
            injected_files = self._get_injected_files(personality)

        flavor_id = self._flavor_id_from_req_data(env)

        if not 'name' in env['server']:
            msg = _("Server name is not defined")
            return exc.HTTPBadRequest(msg)
        print "4444"

        name = env['server']['name']
        self._validate_server_name(name)
        name = name.strip()

        try:
            inst_type = \
                instance_types.get_instance_type_by_flavor_id(flavor_id)
            (inst, ) = self.compute_api.create(
                context,
                inst_type,
                image_id,
                kernel_id=kernel_id,
                ramdisk_id=ramdisk_id,
                display_name=name,
                display_description=name,
                key_name=key_name,
                key_data=key_data,
                user_data=env['server'].get('user_data'),
                metadata=env['server'].get('metadata', {}),
                injected_files=injected_files,
                admin_password=password)
        except quota.QuotaError as error:
            self._handle_quota_error(error)

        inst['instance_type'] = inst_type
        inst['image_id'] = image_id

        builder = self._get_view_builder(req)
        server = builder.build(inst, is_detail=True)
        server['server']['adminPass'] = password
        return server
Example #5
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)
Example #6
0
 def bad(e):
     return exc.HTTPUnprocessableEntity(explanation=e)
Example #7
0
    def create(self, req, body):
        """Creates a new share."""
        context = req.environ['manila.context']

        if not self.is_valid_body(body, 'share'):
            raise exc.HTTPUnprocessableEntity()

        share = body['share']

        # NOTE(rushiagr): v2 API allows name instead of display_name
        if share.get('name'):
            share['display_name'] = share.get('name')
            del share['name']

        # NOTE(rushiagr): v2 API allows description instead of
        #                display_description
        if share.get('description'):
            share['display_description'] = share.get('description')
            del share['description']

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

        msg = (_LI("Create %(share_proto)s share of %(size)s GB") % {
            'share_proto': share_proto,
            'size': size
        })
        LOG.info(msg, context=context)

        kwargs = {
            'availability_zone': share.get('availability_zone'),
            'metadata': share.get('metadata'),
            'is_public': share.get('is_public', False),
        }

        snapshot_id = share.get('snapshot_id')
        if snapshot_id:
            snapshot = self.share_api.get_snapshot(context, snapshot_id)
        else:
            snapshot = None

        kwargs['snapshot'] = snapshot

        share_network_id = share.get('share_network_id')

        if snapshot:
            # Need to check that share_network_id from snapshot's
            # parents share equals to share_network_id from args.
            # If share_network_id is empty than update it with
            # share_network_id of parent share.
            parent_share = self.share_api.get(context, snapshot['share_id'])
            parent_share_net_id = parent_share['share_network_id']
            if share_network_id:
                if share_network_id != parent_share_net_id:
                    msg = "Share network ID should be the same as snapshot's" \
                          " parent share's or empty"
                    raise exc.HTTPBadRequest(explanation=msg)
            elif parent_share_net_id:
                share_network_id = parent_share_net_id

        if share_network_id:
            try:
                self.share_api.get_share_network(context, share_network_id)
            except exception.ShareNetworkNotFound as e:
                raise exc.HTTPNotFound(explanation=six.text_type(e))
            kwargs['share_network_id'] = share_network_id

        display_name = share.get('display_name')
        display_description = share.get('display_description')

        if 'share_type' in share and 'volume_type' in share:
            msg = 'Cannot specify both share_type and volume_type'
            raise exc.HTTPBadRequest(explanation=msg)
        req_share_type = share.get('share_type', share.get('volume_type'))

        if req_share_type:
            try:
                if not uuidutils.is_uuid_like(req_share_type):
                    kwargs['share_type'] = \
                        share_types.get_share_type_by_name(
                            context, req_share_type)
                else:
                    kwargs['share_type'] = share_types.get_share_type(
                        context, req_share_type)
            except exception.ShareTypeNotFound:
                msg = _("Share type not found.")
                raise exc.HTTPNotFound(explanation=msg)
        elif not snapshot:
            def_share_type = share_types.get_default_share_type()
            if def_share_type:
                kwargs['share_type'] = def_share_type

        new_share = self.share_api.create(context, share_proto, size,
                                          display_name, display_description,
                                          **kwargs)

        return self._view_builder.detail(req, dict(six.iteritems(new_share)))
Example #8
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 #9
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['nova.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                    context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(
                context, snapshot_id)
        else:
            kwargs['snapshot'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            image_href = volume.get('imageRef')
            if snapshot_id and image_href:
                msg = _("Snapshot and image cannot be specified together.")
                raise exc.HTTPBadRequest(explanation=msg)
            if image_href:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context, size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume),
                                               image_uuid)

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))
Example #10
0
    def checkpoints_create(self, req, provider_id, body):
        """Creates a new checkpoint."""
        if not self.is_valid_body(body, 'checkpoint'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['karbor.context']

        LOG.debug('Create checkpoint request '
                  'body: %s provider_id:%s', body, provider_id)

        context.can(provider_policy.CHECKPOINT_CREATE_POLICY)
        checkpoint = body['checkpoint']
        LOG.debug('Create checkpoint request checkpoint: %s',
                  checkpoint)

        if not provider_id:
            msg = _("provider_id must be provided when creating "
                    "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        plan_id = checkpoint.get("plan_id")

        if not plan_id:
            msg = _("plan_id must be provided when creating "
                    "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        if not uuidutils.is_uuid_like(plan_id):
            msg = _("Invalid plan id provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        plan = objects.Plan.get_by_id(context, plan_id)
        if not plan:
            raise exception.PlanNotFound(plan_id=plan_id)

        # check the provider_id
        if provider_id != plan.get("provider_id"):
            msg = _("The parameter provider_id is not the same as "
                    "the value in the plan.")
            raise exception.InvalidPlan(reason=msg)

        extra_info = checkpoint.get("extra_info", None)
        if extra_info is not None:
            if not isinstance(extra_info, dict):
                msg = _("The extra_info in checkpoint must be a dict when "
                        "creating a checkpoint.")
                raise exception.InvalidInput(reason=msg)
            elif not all(map(lambda s: isinstance(s, six.string_types),
                             extra_info.keys())):
                msg = _("Key of extra_info in checkpoint must be string when"
                        "creating a checkpoint.")
                raise exception.InvalidInput(reason=msg)
        else:
            extra_info = {
                'created_by': constants.MANUAL
            }

        checkpoint_extra_info = None
        if extra_info is not None:
            checkpoint_extra_info = jsonutils.dumps(extra_info)
        checkpoint_properties = {
            'project_id': context.project_id,
            'status': constants.CHECKPOINT_STATUS_PROTECTING,
            'provider_id': provider_id,
            "protection_plan": {
                "id": plan.get("id"),
                "name": plan.get("name"),
                "resources": plan.get("resources"),
            },
            "extra_info": checkpoint_extra_info
        }
        try:
            checkpoint_id = self.protection_api.protect(context, plan,
                                                        checkpoint_properties)
        except Exception as error:
            msg = _("Create checkpoint failed: %s") % error
            raise exc.HTTPBadRequest(explanation=msg)

        checkpoint_properties['id'] = checkpoint_id

        LOG.info("Create the checkpoint successfully. checkpoint_id:%s",
                 checkpoint_id)
        returnval = self._checkpoint_view_builder.detail(
            req, checkpoint_properties)
        return returnval
Example #11
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create volume request body: %s', body)
        context = req.environ['cinder.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            # Not found exception will be handled at the wsgi level
            kwargs['volume_type'] = (volume_types.get_by_name_or_id(
                context, req_volume_type))

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            # Not found exception will be handled at the wsgi level
            kwargs['snapshot'] = self.volume_api.get_snapshot(
                context, snapshot_id)
        else:
            kwargs['snapshot'] = None

        source_volid = volume.get('source_volid')
        if source_volid is not None:
            # Not found exception will be handled at the wsgi level
            kwargs['source_volume'] = self.volume_api.get_volume(
                context, source_volid)
        else:
            kwargs['source_volume'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']
        elif size is None and kwargs['source_volume'] is not None:
            size = kwargs['source_volume']['size']

        LOG.info(_LI("Create volume of %s GB"), size)
        multiattach = volume.get('multiattach', False)
        kwargs['multiattach'] = multiattach

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            # NOTE(jdg): misleading name "imageRef" as it's an image-id
            image_href = volume.get('imageRef')
            if image_href is not None:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context, size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        retval = _translate_volume_detail_view(context, new_volume, image_uuid)

        return {'volume': retval}
Example #12
0
    def create(self, req, body):
        if not body:
            raise exc.HTTPUnprocessableEntity()

        context = req.environ["nova.context"]
        authorize(context)

        network = body["network"]
        keys = [
            "cidr", "cidr_v6", "ipam", "vlan_start", "network_size",
            "num_networks"
        ]
        kwargs = {k: network.get(k) for k in keys}

        if not network.get("label"):
            msg = _("Network label is required")
            raise exc.HTTPBadRequest(explanation=msg)
        label = network["label"]

        if not (kwargs["cidr"] or kwargs["cidr_v6"]):
            msg = _("No CIDR requested")
            raise exc.HTTPBadRequest(explanation=msg)
        if kwargs["cidr"]:
            try:
                net = netaddr.IPNetwork(kwargs["cidr"])
                if net.size < 4:
                    msg = _("Requested network does not contain "
                            "enough (2+) usable hosts")
                    raise exc.HTTPBadRequest(explanation=msg)
            except netexc.AddrFormatError:
                msg = _("CIDR is malformed.")
                raise exc.HTTPBadRequest(explanation=msg)
            except netexc.AddrConversionError:
                msg = _("Address could not be converted.")
                raise exc.HTTPBadRequest(explanation=msg)

        networks = []
        try:
            if CONF.enable_network_quota:
                reservation = QUOTAS.reserve(context, networks=1)
        except exception.OverQuota:
            msg = _("Quota exceeded, too many networks.")
            raise exc.HTTPBadRequest(explanation=msg)

        kwargs['project_id'] = context.project_id

        try:
            networks = self.network_api.create(context, label=label, **kwargs)
            if CONF.enable_network_quota:
                QUOTAS.commit(context, reservation)
        except exception.PolicyNotAuthorized as e:
            raise exc.HTTPForbidden(explanation=six.text_type(e))
        except exception.CidrConflict as e:
            raise exc.HTTPConflict(explanation=e.format_message())
        except Exception:
            if CONF.enable_network_quota:
                QUOTAS.rollback(context, reservation)
            msg = _("Create networks failed")
            LOG.exception(msg, extra=network)
            raise exc.HTTPServiceUnavailable(explanation=msg)
        return {"network": network_dict(networks[0])}
Example #13
0
    def create(self, req, body):
        """Creates a new plan."""
        if not self.is_valid_body(body, 'plan'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create plan request body: %s', body)
        context = req.environ['karbor.context']
        context.can(plan_policy.CREATE_POLICY)
        plan = body['plan']
        LOG.debug('Create plan request plan: %s', plan)

        if not plan.get("provider_id"):
            msg = _("provider_id must be provided when creating " "a plan.")
            raise exception.InvalidInput(reason=msg)

        parameters = plan.get("parameters", None)

        if parameters is None:
            msg = _("parameters must be provided when creating " "a plan.")
            raise exception.InvalidInput(reason=msg)

        if not isinstance(parameters, dict):
            msg = _("parameters must be a dict when creating a plan.")
            raise exception.InvalidInput(reason=msg)

        self.validate_name_and_description(plan)
        self.validate_plan_resources(plan)
        self.validate_plan_parameters(context, plan)

        resources = plan.get('resources', None)
        if resources:
            for resource in resources:
                extra_info = resource.get('extra_info', None)
                if extra_info is not None:
                    resource['extra_info'] = jsonutils.dumps(extra_info)

        plan_properties = {
            'name': plan.get('name', None),
            'description': plan.get('description', None),
            'provider_id': plan.get('provider_id', None),
            'project_id': context.project_id,
            'status': constants.PLAN_STATUS_SUSPENDED,
            'resources': resources,
            'parameters': parameters,
        }

        try:
            reserve_opts = {'plans': 1}
            reservations = QUOTAS.reserve(context, **reserve_opts)
        except exception.OverQuota as e:
            quota.process_reserve_over_quota(context, e, resource='plans')
        try:
            plan = objects.Plan(context=context, **plan_properties)
            plan.create()
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    if plan and 'id' in plan:
                        plan.destroy()
                finally:
                    QUOTAS.rollback(context, reservations)

        retval = self._view_builder.detail(req, plan)

        return retval
Example #14
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 = None
        if (self.ext_mgr.is_loaded('os-networks') or utils.is_neutron()):
            requested_networks = server_dict.get('networks')

        if requested_networks is not None:
            if not isinstance(requested_networks, list):
                expl = _('Bad networks format')
                raise exc.HTTPBadRequest(explanation=expl)
            requested_networks = self._get_requested_networks(
                requested_networks)

        (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)

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

        # optional openstack extensions:
        key_name = None
        if self.ext_mgr.is_loaded('os-keypairs'):
            key_name = server_dict.get('key_name')

        user_data = None
        if self.ext_mgr.is_loaded('os-user-data'):
            user_data = server_dict.get('user_data')
        self._validate_user_data(user_data)

        availability_zone = None
        if self.ext_mgr.is_loaded('os-availability-zone'):
            availability_zone = server_dict.get('availability_zone')

        block_device_mapping = None
        block_device_mapping_v2 = None
        legacy_bdm = True
        if self.ext_mgr.is_loaded('os-volumes'):
            block_device_mapping = server_dict.get('block_device_mapping', [])
            if not isinstance(block_device_mapping, list):
                msg = _('block_device_mapping must be a list')
                raise exc.HTTPBadRequest(explanation=msg)
            for bdm in block_device_mapping:
                try:
                    block_device.validate_device_name(bdm.get("device_name"))
                    block_device.validate_and_default_volume_size(bdm)
                except exception.InvalidBDMFormat as e:
                    raise exc.HTTPBadRequest(explanation=e.format_message())

                if 'delete_on_termination' in bdm:
                    bdm['delete_on_termination'] = strutils.bool_from_string(
                        bdm['delete_on_termination'])

            if self.ext_mgr.is_loaded('os-block-device-mapping-v2-boot'):
                # Consider the new data format for block device mapping
                block_device_mapping_v2 = server_dict.get(
                    'block_device_mapping_v2', [])
                # NOTE (ndipanov):  Disable usage of both legacy and new
                #                   block device format in the same request
                if block_device_mapping and block_device_mapping_v2:
                    expl = _('Using different block_device_mapping syntaxes '
                             'is not allowed in the same request.')
                    raise exc.HTTPBadRequest(explanation=expl)

                if not isinstance(block_device_mapping_v2, list):
                    msg = _('block_device_mapping_v2 must be a list')
                    raise exc.HTTPBadRequest(explanation=msg)

                # Assume legacy format
                legacy_bdm = not bool(block_device_mapping_v2)

                try:
                    block_device_mapping_v2 = [
                        block_device.BlockDeviceDict.from_api(bdm_dict)
                        for bdm_dict in block_device_mapping_v2
                    ]
                except exception.InvalidBDMFormat as e:
                    raise exc.HTTPBadRequest(explanation=e.format_message())

        block_device_mapping = (block_device_mapping
                                or block_device_mapping_v2)

        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 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 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.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.InstanceExists,
                exception.NoUniqueMatch) as error:
            raise exc.HTTPConflict(explanation=error.format_message())
        except exception.Invalid as error:
            raise exc.HTTPBadRequest(explanation=error.format_message())

        # 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)
    def create(self, req, body=None):
        """Create a storage pool."""
        LOG.info(body)

        #{'pool':
        #    {'replicationFactor': 3,
        #    'name': 'test',
        #    'enablePoolQuota': False,
        #    'storageGroupId': '1',
        #    'u'replicatedStorageGroupId': '1',
        #    'clusterId': '0',
        #    'tag': 'abc',
        #    'createdBy': 'VSM',
        #    'ecProfileId': '1',
        #    'ecFailureDomain': 'osd',
        #    'poolQuota': 0
        #    }
        #}

        if not self.is_valid_body(body, 'pool'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['vsm.context']
        pool_dict = body['pool']

        for key in ('name', 'createdBy', 'storageGroupId'):
            if not key in pool_dict:
                msg = _("%s is not defined in pool" % key)
                raise exc.HTTPBadRequest(explanation=msg)

        name = pool_dict['name'].strip()
        created_by = pool_dict['createdBy'].strip()
        storage_group_id = pool_dict['storageGroupId']
        tag = pool_dict['tag'].strip()
        cluster_id = pool_dict['clusterId']

        try:
            cluster_id = int(str(cluster_id))
        except ValueError:
            msg = _('cluster_id must be an interger value')
            raise exc.HTTPBadRequest(explanation=msg)

        osd_num = self.conductor_api.get_osd_num(context, storage_group_id)
        storage_group = db.storage_group_get(context, storage_group_id)
        is_ec_pool = pool_dict.get('ecProfileId')
        if is_ec_pool:
            #erasure code pool 
            body_info = {'name': name,
                        'cluster_id':cluster_id,
                        'storage_group_id':storage_group_id,
                        'ec_profile_id':pool_dict['ecProfileId'],
                        'ec_ruleset_root':storage_group['name'],
                        'ec_failure_domain':pool_dict['ecFailureDomain'],
                        'created_by':created_by,
                        'tag':tag}
             
        else:
            #replicated pool 
            crush_ruleset = self.conductor_api.get_ruleset_id(context, storage_group_id)
            if crush_ruleset < 0:
                msg = _('crush_ruleset must be a non-negative integer value')
                raise exc.HTTPBadRequest(explanation=msg)

            size = pool_dict['replicationFactor']
            replica_storage_group_id = pool_dict['replicatedStorageGroupId']
            try:
                size = int(str(size))
                if size < 1:
                    msg = _('size must be > 1')
                    raise exc.HTTPBadRequest(explanation=msg)

                host_num = self.conductor_api.count_hosts_by_storage_group_id(context, storage_group_id) 
                LOG.info("storage_group_id:%s,host_num:%s", storage_group_id, host_num)
                if size > host_num:
                    msg = "The replication factor must be less than or equal to the number of storage nodes in the specific storage group in cluster!"
                    return {'message': msg}
            except ValueError:
                msg = _('size must be an interger value')
                raise exc.HTTPBadRequest(explanation=msg)

            pg_num = self._compute_pg_num(context, osd_num, size)

            #vsm_id = str(uuid.uuid1()).split('-')[0]
            body_info = {'name': name, #+ "-vsm" + vsm_id,
                        'cluster_id':cluster_id,
                        'storage_group_id':storage_group_id,
                        'replica_storage_group_id':replica_storage_group_id,
                        'crush_ruleset':crush_ruleset,
                        'pg_num':pg_num,
                        'pgp_num':pg_num,
                        'size':size,
                        'min_size':size,
                        'created_by':created_by,
                        'tag':tag}

        body_info.update({
            "quota": pool_dict.get("poolQuota"),
            "enable_quota": pool_dict.get("enablePoolQuota"),
        })

        return self.scheduler_api.create_storage_pool(context, body_info)
Example #16
0
    def create(self, req, body):
        """Creates a new restore."""
        if not self.is_valid_body(body, 'restore'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create restore request body: %s', body)
        context = req.environ['karbor.context']
        check_policy(context, 'create')
        restore = body['restore']
        LOG.debug('Create restore request : %s', restore)

        if not restore.get("provider_id"):
            msg = _("provider_id must be provided when creating "
                    "a restore.")
            raise exception.InvalidInput(reason=msg)

        if not restore.get("checkpoint_id"):
            msg = _("checkpoint_id must be provided when creating "
                    "a restore.")
            raise exception.InvalidInput(reason=msg)

        parameters = restore.get("parameters")
        if not isinstance(parameters, dict):
            msg = _("parameters must be a dict when creating"
                    " a restore.")
            raise exception.InvalidInput(reason=msg)

        # restore_auth and restore_target are optional
        # Heat client can be initialized using current login tenant when the
        # restore_target and restore_auth is not provided.
        restore_auth = restore.get("restore_auth")
        if restore_auth is not None:
            if not isinstance(restore_auth, dict):
                msg = _("restore_auth must be a dict when creating"
                        " a restore.")
                raise exception.InvalidInput(reason=msg)

        restore_properties = {
            'project_id': context.project_id,
            'provider_id': restore.get('provider_id'),
            'checkpoint_id': restore.get('checkpoint_id'),
            'restore_target': restore.get('restore_target'),
            'parameters': parameters,
            'status': constants.RESTORE_STATUS_IN_PROGRESS,
        }

        restoreobj = objects.Restore(context=context,
                                     **restore_properties)
        restoreobj.create()
        LOG.debug('call restore RPC  : restoreobj:%s', restoreobj)

        # call restore rpc API of protection service
        try:
            self.protection_api.restore(context, restoreobj, restore_auth)
        except Exception:
            # update the status of restore
            update_dict = {
                "status": constants.RESTORE_STATUS_FAILURE
            }
            check_policy(context, 'update', restoreobj)
            restoreobj = self._restore_update(context,
                                              restoreobj.get("id"),
                                              update_dict)

        retval = self._view_builder.detail(req, restoreobj)

        return retval
Example #17
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create volume request body: %s', body)
        context = req.environ['cinder.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                if not uuidutils.is_uuid_like(req_volume_type):
                    kwargs['volume_type'] = \
                        volume_types.get_volume_type_by_name(
                            context, req_volume_type)
                else:
                    kwargs['volume_type'] = volume_types.get_volume_type(
                        context, req_volume_type)
            except exception.VolumeTypeNotFound:
                explanation = 'Volume type not found.'
                raise exc.HTTPNotFound(explanation=explanation)

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        source_volid = volume.get('source_volid')
        if source_volid is not None:
            kwargs['source_volume'] = self.volume_api.get_volume(context,
                                                                 source_volid)
        else:
            kwargs['source_volume'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']
        elif size is None and kwargs['source_volume'] is not None:
            size = kwargs['source_volume']['size']

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            # NOTE(jdg): misleading name "imageRef" as it's an image-id
            image_href = volume.get('imageRef')
            if image_href:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        new_volume = dict(new_volume.iteritems())

        self._add_visible_admin_metadata(context, new_volume)

        retval = _translate_volume_detail_view(context, new_volume, image_uuid)

        return {'volume': retval}
Example #18
0
    def create(self, req, body):
        context = req.environ['nova.context']
        authorize(context)
        if not body:
            raise exc.HTTPUnprocessableEntity()

        if not "network" in body:
            raise exc.HTTPUnprocessableEntity()

        network_params = body["network"]
        str_args = ("bridge", "bridge_interface", "cidr", "cidr_v6", "dns1",
                    "dns2", "fixed_cidr", "gateway", "gateway_v6", "label",
                    "multi_host", "priority", "project_id")
        int_args = ("network_size", "num_networks", "vlan_start", "vpn_start")
        ctor_args = str_args + int_args
        for key in int_args:
            try:
                network_params[key] = int(network_params[key])
            except ValueError:
                raise exc.HTTPBadRequest(
                    explanation=_("%s must be an integer") % key)
            except KeyError:
                pass

        # check for certain required inputs
        if not network_params["label"]:
            raise exc.HTTPBadRequest(
                explanation=_("Network label is required"))
        if not (network_params["cidr"] or network_params["cidr_v6"]):
            raise exc.HTTPBadRequest(
                explanation=_("cidr or cidr_v6 is required"))

        kwargs = dict(((k, network_params.get(k, None)) for k in ctor_args))

        bridge = kwargs["bridge"] or FLAGS.flat_network_bridge
        if not bridge:
            bridge_required = [
                'nova.network.manager.FlatManager',
                'nova.network.manager.FlatDHCPManager'
            ]
            if FLAGS.network_manager in bridge_required:
                raise exc.HTTPBadRequest(explanation=_("bridge is required"))
        kwargs["bridge"] = bridge

        bridge_interface = (kwargs["bridge_interface"] or FLAGS.flat_interface
                            or FLAGS.vlan_interface)
        if not bridge_interface:
            interface_required = ['nova.network.manager.VlanManager']
            if FLAGS.network_manager in interface_required:
                raise exc.HTTPBadRequest(
                    explanation=_("bridge_interface is required"))
        kwargs["bridge_interface"] = bridge_interface

        # sanitize other input using FLAGS if necessary
        num_networks = kwargs["num_networks"] or FLAGS.num_networks
        network_size = kwargs["network_size"]
        cidr = kwargs["cidr"]
        if not network_size and cidr:
            fixnet = netaddr.IPNetwork(cidr)
            each_subnet_size = fixnet.size / num_networks
            if each_subnet_size > FLAGS.network_size:
                network_size = FLAGS.network_size
                subnet = 32 - int(math.log(network_size, 2))
                oversize_msg = _(
                    'Subnet(s) too large, defaulting to /%s.'
                    '  To override, specify network_size flag.') % subnet
                LOG.warn(oversize_msg)
            else:
                network_size = fixnet.size
        kwargs["num_networks"] = num_networks
        kwargs["network_size"] = network_size

        kwargs["multi_host"] = kwargs["multi_host"] or FLAGS.multi_host
        kwargs["vlan_start"] = kwargs["vlan_start"] or FLAGS.vlan_start
        kwargs["vpn_start"] = kwargs["vpn_start"] or FLAGS.vpn_start
        kwargs["dns1"] = kwargs["dns1"] or FLAGS.flat_network_dns
        kwargs["network_size"] = kwargs["network_size"] or FLAGS.network_size

        if kwargs["fixed_cidr"]:
            kwargs["fixed_cidr"] = netaddr.IPNetwork(fixed_cidr)

        # create the network
        LOG.debug(_("Creating network with label %s") % kwargs["label"])
        try:
            networks = self.network_api.create(context, **kwargs)
        except Exception as ex:
            raise exc.HTTPBadRequest(
                explanation=_("Cannot create network. %s") %
                getattr(ex, "value", str(ex)))
        result = [network_dict(context, net_ref) for net_ref in networks]
        return {'networks': result}
Example #19
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
Example #20
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['cinder.context']
        volume = body['volume']

        kwargs = {}

        # NOTE(thingee): v2 API allows name instead of display_name
        if volume.get('name'):
            volume['display_name'] = volume.get('name')
            del volume['name']

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                    context, req_volume_type)
            except exception.VolumeTypeNotFound:
                explanation = 'Volume type not found.'
                raise exc.HTTPNotFound(explanation=explanation)

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        source_volid = volume.get('source_volid')
        if source_volid is not None:
            kwargs['source_volume'] = self.volume_api.get_volume(context,
                                                                 source_volid)
        else:
            kwargs['source_volume'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']
        elif size is None and kwargs['source_volume'] is not None:
            size = kwargs['source_volume']['size']

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            image_href = volume.get('imageRef')
            if snapshot_id and image_href:
                msg = _("Snapshot and image cannot be specified together.")
                raise exc.HTTPBadRequest(explanation=msg)
            if image_href:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = self._view_builder.summary(req, dict(new_volume.iteritems()))

        return retval
Example #21
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)
Example #22
0
    def create(self, req, body):
        """Creates a new share."""
        context = req.environ['manila.context']

        if not self.is_valid_body(body, 'share'):
            raise exc.HTTPUnprocessableEntity()

        share = body['share']

        # NOTE(rushiagr): v2 API allows name instead of display_name
        if share.get('name'):
            share['display_name'] = share.get('name')
            del share['name']

        # NOTE(rushiagr): v2 API allows description instead of
        #                display_description
        if share.get('description'):
            share['display_description'] = share.get('description')
            del share['description']

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

        msg = (_("Create %(share_proto)s share of %(size)s GB") % {
            'share_proto': share_proto,
            'size': size
        })
        LOG.info(msg, context=context)

        kwargs = {}
        kwargs['availability_zone'] = share.get('availability_zone')

        kwargs['metadata'] = share.get('metadata', None)

        snapshot_id = share.get('snapshot_id')
        if snapshot_id:
            snapshot = self.share_api.get_snapshot(context, snapshot_id)
        else:
            snapshot = None

        kwargs['snapshot'] = snapshot

        share_network_id = share.get('share_network_id')

        if snapshot:
            # Need to check that share_network_id from snapshot's
            # parents share equals to share_network_id from args.
            # If share_network_id is empty than update it with
            # share_network_id of parent share.
            parent_share = self.share_api.get(context, snapshot['share_id'])
            parent_share_net_id = parent_share['share_network_id']
            if share_network_id:
                if share_network_id != parent_share_net_id:
                    msg = "Share network ID should be the same as snapshot's" \
                          " parent share's or empty"
                    raise exc.HTTPBadRequest(explanation=msg)
            elif parent_share_net_id:
                share_network_id = parent_share_net_id

        if share_network_id:
            try:
                self.share_api.get_share_network(context, share_network_id)
            except exception.ShareNetworkNotFound as e:
                msg = "%s" % e
                raise exc.HTTPNotFound(explanation=msg)
            kwargs['share_network_id'] = share_network_id

        display_name = share.get('display_name')
        display_description = share.get('display_description')

        req_volume_type = share.get('volume_type', None)
        if req_volume_type:
            try:
                if not uuidutils.is_uuid_like(req_volume_type):
                    kwargs['volume_type'] = \
                        volume_types.get_volume_type_by_name(
                            context, req_volume_type)
                else:
                    kwargs['volume_type'] = volume_types.get_volume_type(
                        context, req_volume_type)
            except exception.VolumeTypeNotFound:
                msg = _("Volume type not found.")
                raise exc.HTTPNotFound(explanation=msg)

        new_share = self.share_api.create(context, share_proto, size,
                                          display_name, display_description,
                                          **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        return self._view_builder.summary(req, dict(six.iteritems(new_share)))
Example #23
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create volume request body: %s', body)
        context = req.environ['storage.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                if not uuidutils.is_uuid_like(req_volume_type):
                    kwargs['volume_type'] = \
                        volume_types.get_volume_type_by_name(
                            context, req_volume_type)
                else:
                    kwargs['volume_type'] = volume_types.get_volume_type(
                        context, req_volume_type)
            except exception.VolumeTypeNotFound:
                explanation = 'Volume type not found.'
                raise exc.HTTPNotFound(explanation=explanation)

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            try:
                kwargs['snapshot'] = self.volume_api.get_snapshot(
                    context, snapshot_id)
            except exception.NotFound:
                explanation = _('snapshot id:%s not found') % snapshot_id
                raise exc.HTTPNotFound(explanation=explanation)

        else:
            kwargs['snapshot'] = None

        source_volid = volume.get('source_volid')
        if source_volid is not None:
            try:
                kwargs['source_volume'] = \
                    self.volume_api.get_volume(context,
                                               source_volid)
            except exception.NotFound:
                explanation = _('source vol id:%s not found') % source_volid
                raise exc.HTTPNotFound(explanation=explanation)
        else:
            kwargs['source_volume'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']
        elif size is None and kwargs['source_volume'] is not None:
            size = kwargs['source_volume']['size']

        LOG.info(_LI("Create volume of %s GB"), size, context=context)
        multiattach = volume.get('multiattach', False)
        kwargs['multiattach'] = multiattach

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            # NOTE(jdg): misleading name "imageRef" as it's an image-id
            image_href = volume.get('imageRef')
            if image_href is not None:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context, size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        retval = _translate_volume_detail_view(context, new_volume, image_uuid)

        return {'volume': retval}
Example #24
0
    def create(self, req, body):
        context = req.environ['nova.context']
        authorize(context)

        if not body:
            raise exc.HTTPUnprocessableEntity()

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

        self.compute_api.ensure_default_security_group(context)

        sg_rule = body['security_group_rule']
        parent_group_id = sg_rule.get('parent_group_id', None)
        try:
            parent_group_id = int(parent_group_id)
            security_group = db.security_group_get(context, parent_group_id)
        except ValueError:
            msg = _("Parent group id is not integer")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.NotFound as exp:
            msg = _("Security group (%s) not found") % parent_group_id
            raise exc.HTTPNotFound(explanation=msg)

        msg = _("Authorize security group ingress %s")
        LOG.audit(msg, security_group['name'], context=context)

        try:
            values = self._rule_args_to_dict(
                context,
                to_port=sg_rule.get('to_port'),
                from_port=sg_rule.get('from_port'),
                parent_group_id=sg_rule.get('parent_group_id'),
                ip_protocol=sg_rule.get('ip_protocol'),
                cidr=sg_rule.get('cidr'),
                group_id=sg_rule.get('group_id'))
        except Exception as exp:
            raise exc.HTTPBadRequest(explanation=unicode(exp))

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

        values['parent_group_id'] = security_group.id

        if self._security_group_rule_exists(security_group, values):
            msg = _('This rule already exists in group %s') % parent_group_id
            raise exc.HTTPBadRequest(explanation=msg)

        allowed = quota.allowed_security_group_rules(context, parent_group_id,
                                                     1)
        if allowed < 1:
            msg = _("Quota exceeded, too many security group rules.")
            raise exc.HTTPBadRequest(explanation=msg)

        security_group_rule = db.security_group_rule_create(context, values)
        self.sgh.trigger_security_group_rule_create_refresh(
            context, [security_group_rule['id']])
        self.compute_api.trigger_security_group_rules_refresh(
            context, security_group_id=security_group['id'])

        return {
            "security_group_rule":
            self._format_security_group_rule(context, security_group_rule)
        }
Example #25
0
    def _create(self,
                req,
                body,
                check_create_share_from_snapshot_support=False):
        """Creates a new share."""
        context = req.environ['manila.context']

        if not self.is_valid_body(body, 'share'):
            raise exc.HTTPUnprocessableEntity()

        share = body['share']
        availability_zone_id = None

        # NOTE(rushiagr): Manila API allows 'name' instead of 'display_name'.
        if share.get('name'):
            share['display_name'] = share.get('name')
            del share['name']

        # NOTE(rushiagr): Manila API allows 'description' instead of
        #                 'display_description'.
        if share.get('description'):
            share['display_description'] = share.get('description')
            del share['description']

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

        msg = ("Create %(share_proto)s share of %(size)s GB" % {
            'share_proto': share_proto,
            'size': size
        })
        LOG.info(msg, context=context)

        availability_zone = share.get('availability_zone')
        if availability_zone:
            try:
                availability_zone_id = db.availability_zone_get(
                    context, availability_zone).id
            except exception.AvailabilityZoneNotFound as e:
                raise exc.HTTPNotFound(explanation=six.text_type(e))

        share_group_id = share.get('share_group_id')
        if share_group_id:
            try:
                share_group = db.share_group_get(context, share_group_id)
            except exception.ShareGroupNotFound as e:
                raise exc.HTTPNotFound(explanation=six.text_type(e))
            sg_az_id = share_group['availability_zone_id']
            if availability_zone and availability_zone_id != sg_az_id:
                msg = _("Share cannot have AZ ('%(s_az)s') different than "
                        "share group's one (%(sg_az)s).") % {
                            's_az': availability_zone_id,
                            'sg_az': sg_az_id
                        }
                raise exception.InvalidInput(msg)
            availability_zone_id = sg_az_id

        kwargs = {
            'availability_zone': availability_zone_id,
            'metadata': share.get('metadata'),
            'is_public': share.get('is_public', False),
            'share_group_id': share_group_id,
        }

        snapshot_id = share.get('snapshot_id')
        if snapshot_id:
            snapshot = self.share_api.get_snapshot(context, snapshot_id)
        else:
            snapshot = None

        kwargs['snapshot_id'] = snapshot_id

        share_network_id = share.get('share_network_id')

        if snapshot:
            # Need to check that share_network_id from snapshot's
            # parents share equals to share_network_id from args.
            # If share_network_id is empty then update it with
            # share_network_id of parent share.
            parent_share = self.share_api.get(context, snapshot['share_id'])
            parent_share_net_id = parent_share.instance['share_network_id']
            if share_network_id:
                if share_network_id != parent_share_net_id:
                    msg = ("Share network ID should be the same as snapshot's"
                           " parent share's or empty")
                    raise exc.HTTPBadRequest(explanation=msg)
            elif parent_share_net_id:
                share_network_id = parent_share_net_id

            # Verify that share can be created from a snapshot
            if (check_create_share_from_snapshot_support and
                    not parent_share['create_share_from_snapshot_support']):
                msg = (_("A new share may not be created from snapshot '%s', "
                         "because the snapshot's parent share does not have "
                         "that capability.") % snapshot_id)
                LOG.error(msg)
                raise exc.HTTPBadRequest(explanation=msg)

        if share_network_id:
            try:
                self.share_api.get_share_network(context, share_network_id)
            except exception.ShareNetworkNotFound as e:
                raise exc.HTTPNotFound(explanation=six.text_type(e))
            kwargs['share_network_id'] = share_network_id

        display_name = share.get('display_name')
        display_description = share.get('display_description')

        if 'share_type' in share and 'volume_type' in share:
            msg = 'Cannot specify both share_type and volume_type'
            raise exc.HTTPBadRequest(explanation=msg)
        req_share_type = share.get('share_type', share.get('volume_type'))

        share_type = None
        if req_share_type:
            try:
                if not uuidutils.is_uuid_like(req_share_type):
                    share_type = share_types.get_share_type_by_name(
                        context, req_share_type)
                else:
                    share_type = share_types.get_share_type(
                        context, req_share_type)
            except exception.ShareTypeNotFound:
                msg = _("Share type not found.")
                raise exc.HTTPNotFound(explanation=msg)
        elif not snapshot:
            def_share_type = share_types.get_default_share_type()
            if def_share_type:
                share_type = def_share_type

        # Only use in create share feature. Create share from snapshot
        # and create share with share group features not
        # need this check.
        if (not share_network_id and not snapshot and not share_group_id
                and share_type and share_type.get('extra_specs')
                and (strutils.bool_from_string(
                    share_type.get('extra_specs').get(
                        'driver_handles_share_servers')))):
            msg = _('Share network must be set when the '
                    'driver_handles_share_servers is true.')
            raise exc.HTTPBadRequest(explanation=msg)

        if share_type:
            kwargs['share_type'] = share_type
        new_share = self.share_api.create(context, share_proto, size,
                                          display_name, display_description,
                                          **kwargs)

        return self._view_builder.detail(req, new_share)
Example #26
0
    def create(self, req, body):
        """Creates a new scheduled operation."""

        LOG.debug('Create scheduled operation start')

        if not self.is_valid_body(body, 'scheduled_operation'):
            raise exc.HTTPUnprocessableEntity()
        LOG.debug('Create a scheduled operation, request body: %s', body)

        context = req.environ['karbor.context']
        check_policy(context, 'create')
        operation_info = body['scheduled_operation']

        name = operation_info.get("name", None)
        operation_type = operation_info.get("operation_type", None)
        operation_definition = operation_info.get("operation_definition", None)
        if name is None:
            msg = _("Operation name or type or definition is not provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        self.validate_name_and_description(operation_info)

        try:
            OPERATION_MANAGER.check_operation_definition(
                operation_type, operation_definition)
        except exception.Invalid as ex:
            raise exc.HTTPBadRequest(explanation=ex.msg)
        except Exception as ex:
            self._raise_unknown_exception(ex)

        trigger_id = operation_info.get("trigger_id", None)
        trigger = self._get_trigger_by_id(context, trigger_id)
        if context.project_id != trigger.project_id:
            msg = _("Invalid trigger id provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        operation_obj = {
            'name': operation_info.get('name', None),
            'description': operation_info.get('description', None),
            'operation_type': operation_type,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'trigger_id': trigger_id,
            'operation_definition': operation_definition,
        }
        try:
            operation = objects.ScheduledOperation(context=context,
                                                   **operation_obj)
            operation.create()
        except Exception as ex:
            self._raise_unknown_exception(ex)

        try:
            self._create_scheduled_operation(context, operation.id, trigger_id)
        except Exception:
            try:
                operation.destroy()
            except Exception:
                pass

            raise

        return self._view_builder.detail(req, operation)
Example #27
0
    def create(self, req, body):
        """ Creates a new server for a given user """
        if not body:
            raise exc.HTTPUnprocessableEntity()

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

        body['server']['key_name'] = self._get_key_name(req, body)

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

        if not 'name' 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_href = self._image_ref_from_req_data(body)

        # If the image href was generated by engine api, strip image_href
        # down to an id and use the default tank connection params
        if str(image_href).startswith(req.application_url):
            image_href = image_href.split('/').pop()

        personality = server_dict.get('personality')
        config_drive = server_dict.get('config_drive')

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

        sg_names = []
        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 = 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)

        zone_blob = server_dict.get('blob')

        # optional x7 extensions:
        key_name = server_dict.get('key_name')
        user_data = server_dict.get('user_data')
        self._validate_user_data(user_data)

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

        block_device_mapping = self._get_block_device_mapping(server_dict)

        # Only allow admins to specify their own reservation_ids
        # This is really meant to allow zones to work.
        reservation_id = server_dict.get('reservation_id')
        if all([
                reservation_id is not None, reservation_id != '',
                not context.is_admin
        ]):
            reservation_id = None

        ret_resv_id = server_dict.get('return_reservation_id', False)

        min_count = server_dict.get('min_count')
        max_count = server_dict.get('max_count')
        # min_count and max_count are optional.  If they exist, they come
        # in as strings.  We want to default 'min_count' to 1, and default
        # 'max_count' to be 'min_count'.
        min_count = int(min_count) if min_count else 1
        max_count = int(max_count) if max_count else min_count
        if min_count > max_count:
            min_count = max_count

        auto_disk_config = server_dict.get('auto_disk_config')

        try:
            inst_type = \
                    instance_types.get_instance_type_by_flavor_id(flavor_id)

            (instances, resv_id) = self.compute_api.create(
                context,
                inst_type,
                image_href,
                display_name=name,
                display_description=name,
                key_name=key_name,
                metadata=server_dict.get('metadata', {}),
                access_ip_v4=server_dict.get('accessIPv4'),
                access_ip_v6=server_dict.get('accessIPv6'),
                injected_files=injected_files,
                admin_password=password,
                zone_blob=zone_blob,
                reservation_id=reservation_id,
                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)
        except exception.QuotaError as error:
            self._handle_quota_error(error)
        except exception.InstanceTypeMemoryTooSmall as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        except exception.InstanceTypeDiskTooSmall as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        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.SecurityGroupNotFound as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        except rpc_common.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % \
                  {'err_type': err.exc_type, 'err_msg': err.value}
            raise exc.HTTPBadRequest(explanation=msg)
        # Let the caller deal with unhandled exceptions.

        # If the caller wanted a reservation_id, return it
        if ret_resv_id:
            return {'reservation_id': resv_id}

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

        if '_is_precooked' in server['server'].keys():
            del server['server']['_is_precooked']
        else:
            server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Example #28
0
    def create(self, req, body=None):
        """Create a storage pool."""
        LOG.info(body)

        #{'pool':
        #    {'replicationFactor': 3,
        #    'name': 'test',
        #    'enablePoolQuota': False,
        #    'storageGroupId': '1',
        #    'u'replicatedStorageGroupId': '1',
        #    'clusterId': '0',
        #    'tag': 'abc',
        #    'createdBy': 'VSM',
        #    'ecProfileId': '1',
        #    'ecFailureDomain': 'osd',
        #    'poolQuota': 0
        #    }
        #}

        if not self.is_valid_body(body, 'pool'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['vsm.context']
        pool_dict = body['pool']

        for key in ('name', 'createdBy', 'storageGroupName'):
            if not key in pool_dict:
                msg = _("%s is not defined in pool" % key)
                raise exc.HTTPBadRequest(explanation=msg)

        name = pool_dict['name'].strip()
        created_by = pool_dict['createdBy'].strip()

        storage_group_name = pool_dict['storageGroupName']
        tag = pool_dict['tag'].strip()
        cluster_id = pool_dict['clusterId']

        try:
            cluster_id = int(str(cluster_id))
        except ValueError:
            msg = _('cluster_id must be an interger value')
            raise exc.HTTPBadRequest(explanation=msg)

        storage_group = db.storage_group_get_by_name(context,
                                                     storage_group_name)
        rule_id = storage_group['rule_id']
        storage_group_id = storage_group['id']
        size = db.get_size_by_storage_group_name(context, storage_group_name)
        size = int(size)
        if size == 0:
            pool_default_size = db.vsm_settings_get_by_name(
                context, 'osd_pool_default_size')
            size = int(pool_default_size.value)
        #LOG.info('size=====%s'%size)
        #osd_num = 2 #TODO self.scheduler_api.get_osd_num_from_crushmap_by_rule(context, rule_id)
        is_ec_pool = pool_dict.get('ecProfileId')
        if is_ec_pool:
            #erasure code pool
            body_info = {
                'name': name,
                'cluster_id': cluster_id,
                'storage_group_id': storage_group_id,
                'storage_group_name': storage_group_name,
                'ec_profile_id': pool_dict['ecProfileId'],
                'ec_ruleset_root': storage_group['name'],
                'ec_failure_domain': pool_dict['ecFailureDomain'],
                'created_by': created_by,
                'tag': tag
            }

        else:
            #replicated pool
            crush_ruleset = rule_id  #self.conductor_api.get_ruleset_id(context, storage_group_id)
            if crush_ruleset < 0:
                msg = _('crush_ruleset must be a non-negative integer value')
                raise exc.HTTPBadRequest(explanation=msg)

            #size = pool_dict['replicationFactor']
            #replica_storage_group_id = pool_dict['replicatedStorageGroupId']
            #try:
            #     size = int(str(size))
            #     if size < 1:
            #         msg = _('size must be > 1')
            #         raise exc.HTTPBadRequest(explanation=msg)
            #
            #     host_num = self.conductor_api.count_hosts_by_storage_group_id(context, storage_group_id)
            #     LOG.info("storage_group_id:%s,host_num:%s", storage_group_id, host_num)
            #     if size > host_num:
            #         msg = "The replication factor must be less than or equal to the number of storage nodes in the specific storage group in cluster!"
            #         return {'message': msg}
            # except ValueError:
            #     msg = _('size must be an interger value')
            #     raise exc.HTTPBadRequest(explanation=msg)

            #pg_num = self._compute_pg_num(context, osd_num, size)

            #vsm_id = str(uuid.uuid1()).split('-')[0]
            pg_num = 64
            auto_growth_pg = pool_dict.get("auto_growth_pg", 0)
            if auto_growth_pg and int(auto_growth_pg) < pg_num and int(
                    auto_growth_pg) > 0:
                pg_num = int(auto_growth_pg)
            #self._compute_pg_num(context, osd_num, size)
            body_info = {
                'name': name,  #+ "-vsm" + vsm_id,
                'cluster_id': cluster_id,
                'storage_group_id': storage_group_id,
                'storage_group_name': storage_group_name,
                'pool_type': 'replicated',
                'crush_ruleset': crush_ruleset,
                'pg_num': pg_num,
                'pgp_num': pg_num,
                'size': size,
                'min_size': size,
                'created_by': created_by,
                'tag': tag
            }

        body_info.update({
            "quota":
            pool_dict.get("poolQuota"),
            "enable_quota":
            pool_dict.get("enablePoolQuota"),
            "max_pg_num_per_osd":
            pool_dict.get("max_pg_num_per_osd") or 100,
            "auto_growth_pg":
            pool_dict.get("auto_growth_pg") or 0,
        })
        #LOG.info('body_info=====%s'%body_info)
        return self.scheduler_api.create_storage_pool(context, body_info)
    def create(self, req, body):
        """ Creates a new server for a given user """
        if not body:
            raise exc.HTTPUnprocessableEntity()

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

        body['server']['key_name'] = self._get_key_name(req, body)

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

        if not 'name' 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_href = self._image_ref_from_req_data(body)
        image_href = self._image_uuid_from_href(image_href)

        personality = server_dict.get('personality')
        config_drive = server_dict.get('config_drive')

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

        sg_names = []
        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 = server_dict.get('networks')
        if requested_networks is not None:
            requested_networks = self._get_requested_networks(
                requested_networks)

        (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)

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

        # optional openstack extensions:
        key_name = server_dict.get('key_name')
        user_data = server_dict.get('user_data')
        self._validate_user_data(user_data)

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

        block_device_mapping = self._get_block_device_mapping(server_dict)

        ret_resv_id = server_dict.get('return_reservation_id', False)

        min_count = server_dict.get('min_count')
        max_count = server_dict.get('max_count')
        # min_count and max_count are optional.  If they exist, they come
        # in as strings.  We want to default 'min_count' to 1, and default
        # 'max_count' to be 'min_count'.
        min_count = int(min_count) if min_count else 1
        max_count = int(max_count) if max_count else min_count
        if min_count > max_count:
            min_count = max_count

        auto_disk_config = server_dict.get('auto_disk_config')
        scheduler_hints = server_dict.get('scheduler_hints', {})

        try:
            _get_inst_type = instance_types.get_instance_type_by_flavor_id
            inst_type = _get_inst_type(flavor_id)

            (instances, resv_id) = self.compute_api.create(
                context,
                inst_type,
                image_href,
                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)
        except exception.QuotaError as error:
            self._handle_quota_error(error)
        except exception.InstanceTypeMemoryTooSmall as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        except exception.InstanceTypeDiskTooSmall as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        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.SecurityGroupNotFound as error:
            raise exc.HTTPBadRequest(explanation=unicode(error))
        except rpc_common.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {
                'err_type': err.exc_type,
                'err_msg': err.value
            }
            raise exc.HTTPBadRequest(explanation=msg)
        # Let the caller deal with unhandled exceptions.

        # If the caller wanted a reservation_id, return it
        if ret_resv_id:
            return {'reservation_id': resv_id}

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

        if '_is_precooked' in server['server'].keys():
            del server['server']['_is_precooked']
        else:
            if FLAGS.enable_instance_password:
                server['server']['adminPass'] = password

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Example #30
0
    def update(self, req, id, body):
        """Update server then pass on to version-specific controller."""
        #modified by silenceli
        flag = 0
        if not self.is_valid_body(body, 'server'):
            raise exc.HTTPUnprocessableEntity()

        ctxt = req.environ['nova.context']
        update_dict = {}

        if 'name' in body['server']:
            name = body['server']['name']
            self._validate_server_name(name)
            update_dict['display_name'] = name.strip()
            flag = 1

        if 'accessIPv4' in body['server']:
            access_ipv4 = body['server']['accessIPv4']
            if access_ipv4:
                self._validate_access_ipv4(access_ipv4)
            update_dict['access_ip_v4'] = (access_ipv4 and access_ipv4.strip()
                                           or None)

        if 'accessIPv6' in body['server']:
            access_ipv6 = body['server']['accessIPv6']
            if access_ipv6:
                self._validate_access_ipv6(access_ipv6)
            update_dict['access_ip_v6'] = (access_ipv6 and access_ipv6.strip()
                                           or None)

        if 'auto_disk_config' in body['server']:
            auto_disk_config = strutils.bool_from_string(
                body['server']['auto_disk_config'])
            update_dict['auto_disk_config'] = auto_disk_config

        if 'hostId' in body['server']:
            msg = _("HostId cannot be updated.")
            raise exc.HTTPBadRequest(explanation=msg)

        if 'personality' in body['server']:
            msg = _("Personality cannot be updated.")
            raise exc.HTTPBadRequest(explanation=msg)

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

        if flag == 1:
            try:
                self.compute_api.rename(ctxt, instance, name.strip())
            except NotImplementedError:
                msg = _("Unable to set password on instance")
                raise exc.HTTPNotImplemented(explanation=msg)

        try:
            policy.enforce(ctxt, 'compute:update', instance)
            instance.update(update_dict)
            # Note instance.save can throw a NotFound exception
            instance.save()
        except exception.NotFound:
            msg = _("Instance could not be found")
            raise exc.HTTPNotFound(explanation=msg)
        return self._view_builder.show(req, instance)