Пример #1
0
    def test_serialize(self):
        class JSONSerializer(object):
            def serialize(self, obj):
                return 'json'

        class AtomSerializer(object):
            def serialize(self, obj):
                return 'atom'

        robj = wsgi.ResponseObject({},
                                   code=202,
                                   json=JSONSerializer,
                                   atom=AtomSerializer)
        robj['X-header1'] = 'header1'
        robj['X-header2'] = 'header2'
        robj['X-header3'] = 3
        robj['X-header-unicode'] = u'header-unicode'

        for content_type, mtype in wsgi._MEDIA_TYPE_MAP.items():
            request = wsgi.Request.blank('/tests/123')
            response = robj.serialize(request, content_type)

            self.assertEqual(response.headers['Content-Type'], content_type)
            for hdr, val in response.headers.iteritems():
                # All headers must be utf8
                self.assertIsInstance(hdr, str)
                self.assertIsInstance(val, str)
            self.assertEqual(response.headers['X-header1'], 'header1')
            self.assertEqual(response.headers['X-header2'], 'header2')
            self.assertEqual(response.headers['X-header3'], '3')
            self.assertEqual(response.status_int, 202)
            self.assertEqual(response.body, mtype)
Пример #2
0
 def test_admin_can_fetch_limits_for_a_given_tenant_id(self):
     project_id = "123456"
     user_id = "A1234"
     tenant_id = 'abcd'
     self.fake_context.project_id = project_id
     self.fake_context.user_id = user_id
     obj = {
         "limits": {
             "rate": [],
             "absolute": {},
         },
     }
     target = {"project_id": tenant_id, "user_id": user_id}
     fake_req = FakeRequest(self.fake_context)
     fake_req.GET = {'tenant_id': tenant_id}
     if self.ext_mgr is not None:
         self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(True)
         self.ext_mgr.is_loaded('os-server-group-quotas').AndReturn(
             self.include_server_group_quotas)
     self.authorize(self.fake_context, target=target)
     self.mox.StubOutWithMock(quota.QUOTAS, 'get_project_quotas')
     quota.QUOTAS.get_project_quotas(self.fake_context,
                                     '%s' % tenant_id,
                                     usages=True).AndReturn({})
     self.mox.ReplayAll()
     res = wsgi.ResponseObject(obj)
     self.controller.index(fake_req, res)
Пример #3
0
 def test_detail_without_access_ips(self):
     req = wsgi.Request({
         'patron.context':
         fakes.FakeRequestContext('fake_user', 'fake', is_admin=True)
     })
     instance1 = {
         'uuid': 'fake1',
         'access_ip_v4': None,
         'access_ip_v6': None
     }
     instance2 = {
         'uuid': 'fake2',
         'access_ip_v4': None,
         'access_ip_v6': None
     }
     req.cache_db_instance(instance1)
     req.cache_db_instance(instance2)
     resp_obj = wsgi.ResponseObject(
         {"servers": [{
             'id': 'fake1'
         }, {
             'id': 'fake2'
         }]})
     self.controller.detail(req, resp_obj)
     self.assertEqual(
         resp_obj.obj['servers'][0][access_ips.AccessIPs.v4_key], '')
     self.assertEqual(
         resp_obj.obj['servers'][0][access_ips.AccessIPs.v6_key], '')
     self.assertEqual(
         resp_obj.obj['servers'][1][access_ips.AccessIPs.v4_key], '')
     self.assertEqual(
         resp_obj.obj['servers'][1][access_ips.AccessIPs.v6_key], '')
Пример #4
0
 def test_admin_can_fetch_used_limits_for_own_project(self):
     project_id = "123456"
     user_id = "A1234"
     self.fake_context.project_id = project_id
     self.fake_context.user_id = user_id
     obj = {
         "limits": {
             "rate": [],
             "absolute": {},
         },
     }
     fake_req = FakeRequest(self.fake_context)
     fake_req.GET = {}
     if self.ext_mgr is not None:
         self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(True)
         self.ext_mgr.is_loaded('os-server-group-quotas').AndReturn(
             self.include_server_group_quotas)
     self.mox.StubOutWithMock(extensions, 'extension_authorizer')
     self.mox.StubOutWithMock(quota.QUOTAS, 'get_project_quotas')
     quota.QUOTAS.get_project_quotas(self.fake_context,
                                     '%s' % project_id,
                                     usages=True).AndReturn({})
     self.mox.ReplayAll()
     res = wsgi.ResponseObject(obj)
     self.controller.index(fake_req, res)
Пример #5
0
    def show(self, req, domain_id, id):
        """Return the DNS entry that corresponds to domain_id and id."""
        context = req.environ['patron.context']
        authorize(context)
        domain = _unquote_domain(domain_id)

        floating_ip = None
        # Check whether id is a valid ipv4/ipv6 address.
        if netutils.is_valid_ip(id):
            floating_ip = id

        try:
            if floating_ip:
                entries = self.network_api.get_dns_entries_by_address(
                    context, floating_ip, domain)
            else:
                entries = self.network_api.get_dns_entries_by_name(
                    context, id, domain)
        except NotImplementedError:
            msg = _("Unable to get dns entry")
            raise webob.exc.HTTPNotImplemented(explanation=msg)

        if not entries:
            explanation = _("DNS entries not found.")
            raise webob.exc.HTTPNotFound(explanation=explanation)

        if floating_ip:
            entrylist = [_create_dns_entry(floating_ip, entry, domain)
                         for entry in entries]
            dns_entries = _translate_dns_entries_view(entrylist)
            return wsgi.ResponseObject(dns_entries)

        entry = _create_dns_entry(entries[0], id, domain)
        return _translate_dns_entry_view(entry)
Пример #6
0
    def test_used_ram_added(self):
        fake_req = FakeRequest(self.fake_context)
        obj = {
            "limits": {
                "rate": [],
                "absolute": {
                    "maxTotalRAMSize": 512,
                },
            },
        }
        res = wsgi.ResponseObject(obj)

        def stub_get_project_quotas(context, project_id, usages=True):
            return {'ram': {'limit': 512, 'in_use': 256}}

        if self.ext_mgr is not None:
            self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(False)
            self.ext_mgr.is_loaded('os-server-group-quotas').AndReturn(
                self.include_server_group_quotas)
        self.stubs.Set(quota.QUOTAS, "get_project_quotas",
                       stub_get_project_quotas)
        self.mox.ReplayAll()

        self.controller.index(fake_req, res)
        abs_limits = res.obj['limits']['absolute']
        self.assertIn('totalRAMUsed', abs_limits)
        self.assertEqual(abs_limits['totalRAMUsed'], 256)
Пример #7
0
 def test_get_serializer_defaults(self):
     robj = wsgi.ResponseObject({})
     default_serializers = dict(json='json', xml='xml', atom='atom')
     for content_type, mtype in wsgi._MEDIA_TYPE_MAP.items():
         self.assertRaises(exception.InvalidContentType,
                           robj.get_serializer, content_type)
         _mtype, serializer = robj.get_serializer(content_type,
                                                  default_serializers)
         self.assertEqual(serializer, mtype)
Пример #8
0
    def create(self, req, body):
        """Creates a new volume."""
        context = req.environ['patron.context']
        authorize(context)

        if not self.is_valid_body(body, 'volume'):
            msg = _("volume not specified")
            raise exc.HTTPBadRequest(explanation=msg)

        vol = body['volume']

        vol_type = vol.get('volume_type', None)

        metadata = vol.get('metadata', None)

        snapshot_id = vol.get('snapshot_id')

        if snapshot_id is not None:
            snapshot = self.volume_api.get_snapshot(context, snapshot_id)
        else:
            snapshot = None

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

        LOG.info(_LI("Create volume of %s GB"), size, context=context)

        availability_zone = vol.get('availability_zone', None)

        try:
            new_volume = self.volume_api.create(
                context,
                size,
                vol.get('display_name'),
                vol.get('display_description'),
                snapshot=snapshot,
                volume_type=vol_type,
                metadata=metadata,
                availability_zone=availability_zone
                )
        except exception.InvalidInput as err:
            raise exc.HTTPBadRequest(explanation=err.format_message())

        # 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))
        result = {'volume': retval}

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

        return wsgi.ResponseObject(result, headers=dict(location=location))
Пример #9
0
 def _test_without_access_ips(self, func, kwargs={'id': 'fake'}):
     req = wsgi.Request({
         'patron.context':
         fakes.FakeRequestContext('fake_user', 'fake', is_admin=True)
     })
     instance = {'uuid': 'fake', 'access_ip_v4': None, 'access_ip_v6': None}
     req.cache_db_instance(instance)
     resp_obj = wsgi.ResponseObject({"server": {'id': 'fake'}})
     func(req, resp_obj, **kwargs)
     self.assertEqual(resp_obj.obj['server'][access_ips.AccessIPs.v4_key],
                      '')
     self.assertEqual(resp_obj.obj['server'][access_ips.AccessIPs.v6_key],
                      '')
Пример #10
0
    def _do_test_used_limits(self, reserved):
        fake_req = FakeRequest(self.fake_context, reserved=reserved)
        obj = {
            "limits": {
                "rate": [],
                "absolute": {},
            },
        }
        res = wsgi.ResponseObject(obj)
        quota_map = {
            'totalRAMUsed': 'ram',
            'totalCoresUsed': 'cores',
            'totalInstancesUsed': 'instances',
            'totalFloatingIpsUsed': 'floating_ips',
            'totalSecurityGroupsUsed': 'security_groups',
            'totalServerGroupsUsed': 'server_groups',
        }
        limits = {}
        expected_abs_limits = []
        for display_name, q in quota_map.iteritems():
            limits[q] = {
                'limit': len(display_name),
                'in_use': len(display_name) / 2,
                'reserved': len(display_name) / 3
            }
            if (self.include_server_group_quotas
                    or display_name != 'totalServerGroupsUsed'):
                expected_abs_limits.append(display_name)

        def stub_get_project_quotas(context, project_id, usages=True):
            return limits

        self.stubs.Set(quota.QUOTAS, "get_project_quotas",
                       stub_get_project_quotas)
        if self.ext_mgr is not None:
            self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(False)
            self.ext_mgr.is_loaded('os-server-group-quotas').AndReturn(
                self.include_server_group_quotas)
            self.mox.ReplayAll()

        self.controller.index(fake_req, res)
        abs_limits = res.obj['limits']['absolute']
        for limit in expected_abs_limits:
            value = abs_limits[limit]
            r = limits[quota_map[limit]]['reserved'] if reserved else 0
            self.assertEqual(value, limits[quota_map[limit]]['in_use'] + r)
Пример #11
0
 def test_used_limits_fetched_for_context_project_id(self):
     project_id = "123456"
     self.fake_context.project_id = project_id
     obj = {
         "limits": {
             "rate": [],
             "absolute": {},
         },
     }
     fake_req = FakeRequest(self.fake_context)
     if self.ext_mgr is not None:
         self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(False)
         self.ext_mgr.is_loaded('os-server-group-quotas').AndReturn(
             self.include_server_group_quotas)
     self.mox.StubOutWithMock(quota.QUOTAS, 'get_project_quotas')
     quota.QUOTAS.get_project_quotas(self.fake_context,
                                     project_id,
                                     usages=True).AndReturn({})
     self.mox.ReplayAll()
     res = wsgi.ResponseObject(obj)
     self.controller.index(fake_req, res)
Пример #12
0
 def test_non_admin_cannot_fetch_used_limits_for_any_other_project(self):
     project_id = "123456"
     user_id = "A1234"
     tenant_id = "abcd"
     self.fake_context.project_id = project_id
     self.fake_context.user_id = user_id
     obj = {
         "limits": {
             "rate": [],
             "absolute": {},
         },
     }
     target = {"project_id": tenant_id, "user_id": user_id}
     fake_req = FakeRequest(self.fake_context)
     fake_req.GET = {'tenant_id': tenant_id}
     if self.ext_mgr is not None:
         self.ext_mgr.is_loaded('os-used-limits-for-admin').AndReturn(True)
     self.authorize(self.fake_context, target=target). \
         AndRaise(exception.PolicyNotAuthorized(
         action=self.used_limit_extension))
     self.mox.ReplayAll()
     res = wsgi.ResponseObject(obj)
     self.assertRaises(exception.PolicyNotAuthorized, self.controller.index,
                       fake_req, res)
Пример #13
0
 def test_default_code(self):
     robj = wsgi.ResponseObject({})
     self.assertEqual(robj.code, 200)
Пример #14
0
 def test_modified_code(self):
     robj = wsgi.ResponseObject({})
     robj._default_code = 202
     self.assertEqual(robj.code, 202)
Пример #15
0
 def test_bind_serializers(self):
     robj = wsgi.ResponseObject({}, json='foo')
     robj._bind_method_serializers(dict(xml='bar', json='baz'))
     self.assertEqual(robj.serializers, dict(xml='bar', json='foo'))
Пример #16
0
 def test_get_serializer(self):
     robj = wsgi.ResponseObject({}, json='json', xml='xml', atom='atom')
     for content_type, mtype in wsgi._MEDIA_TYPE_MAP.items():
         _mtype, serializer = robj.get_serializer(content_type)
         self.assertEqual(serializer, mtype)
Пример #17
0
 def test_default_serializers(self):
     robj = wsgi.ResponseObject({})
     self.assertEqual(robj.serializers, {})
Пример #18
0
 def test_header_isolation(self):
     robj = wsgi.ResponseObject({})
     robj['Header'] = 'foo'
     hdrs = robj.headers
     hdrs['hEADER'] = 'bar'
     self.assertEqual(robj['hEADER'], 'foo')
Пример #19
0
 def test_del_header(self):
     robj = wsgi.ResponseObject({})
     robj['Header'] = 'foo'
     del robj['hEADER']
     self.assertNotIn('header', robj.headers)
Пример #20
0
    def create(self, req, body):
        """Creates a new server for a given user."""

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

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

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

        availability_zone = create_kwargs.get("availability_zone")

        target = {
            'project_id': context.project_id,
            'user_id': context.user_id,
            'availability_zone': availability_zone
        }
        authorize(context, target, 'create')

        # TODO(Shao He, Feng) move this policy check to os-availabilty-zone
        # extension after refactor it.
        if availability_zone:
            _dummy, host, node = self.compute_api._handle_availability_zone(
                context, availability_zone)
            if host or node:
                authorize(context, {}, 'create:forced_host')

        block_device_mapping = create_kwargs.get("block_device_mapping")
        # TODO(Shao He, Feng) move this policy check to os-block-device-mapping
        # extension after refactor it.
        if block_device_mapping:
            authorize(context, target, 'create:attach_volume')

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

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

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

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

        if requested_networks and len(requested_networks):
            authorize(context, target, 'create:attach_network')

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

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

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

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

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

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

        robj = wsgi.ResponseObject(server)

        return self._add_location(robj)
Пример #21
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        body = body['rebuild']

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

        image_href = self._image_uuid_from_href(image_href)

        password = self._get_server_admin_password(body)

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

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

        kwargs = {}

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

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

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

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

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

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

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

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

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

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

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

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Пример #22
0
    def _action_rebuild(self, req, id, body):
        """Rebuild an instance with the given attributes."""
        rebuild_dict = body['rebuild']

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

        password = self._get_server_admin_password(rebuild_dict)

        context = req.environ['patron.context']
        authorize(context, action='rebuild')
        instance = self._get_server(context, req, id)

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

        rebuild_kwargs = {}

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

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

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

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

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

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

        robj = wsgi.ResponseObject(view)
        return self._add_location(robj)
Пример #23
0
 def test_override_modified_code(self):
     robj = wsgi.ResponseObject({}, code=404)
     robj._default_code = 202
     self.assertEqual(robj.code, 404)
Пример #24
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['patron.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:
                try:
                    sg_names = [
                        sg['name'] for sg in security_groups if sg.get('name')
                    ]
                except AttributeError:
                    msg = _("Invalid input for field/attribute %(path)s."
                            " Value: %(value)s. %(message)s") % {
                                'path': 'security_groups',
                                'value': security_groups,
                                'message': ''
                            }
                    raise exc.HTTPBadRequest(explanation=msg)
        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)

        image_uuid_specified = bool(image_uuid)
        legacy_bdm, block_device_mapping = self._extract_bdm(
            server_dict, image_uuid_specified)

        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)
Пример #25
0
 def test_set_header(self):
     robj = wsgi.ResponseObject({})
     robj['Header'] = 'foo'
     self.assertEqual(robj.headers, {'header': 'foo'})
Пример #26
0
    def create(self, req, body):
        """Creates a new instance event."""
        context = req.environ['patron.context']
        authorize(context, action='create')

        response_events = []
        accepted_events = []
        accepted_instances = set()
        instances = {}
        result = 200

        body_events = body.get('events', [])
        if not isinstance(body_events, list) or not len(body_events):
            raise webob.exc.HTTPBadRequest()

        for _event in body_events:
            client_event = dict(_event)
            event = objects.InstanceExternalEvent(context)

            try:
                event.instance_uuid = client_event.pop('server_uuid')
                event.name = client_event.pop('name')
                event.status = client_event.pop('status', 'completed')
                event.tag = client_event.pop('tag', None)
            except KeyError as missing_key:
                msg = _('event entity requires key %(key)s') % missing_key
                raise webob.exc.HTTPBadRequest(explanation=msg)

            if client_event:
                msg = (_('event entity contains unsupported items: %s') %
                       ', '.join(client_event.keys()))
                raise webob.exc.HTTPBadRequest(explanation=msg)

            if event.status not in external_event_obj.EVENT_STATUSES:
                raise webob.exc.HTTPBadRequest(
                    _('Invalid event status `%s\'') % event.status)

            instance = instances.get(event.instance_uuid)
            if not instance:
                try:
                    instance = objects.Instance.get_by_uuid(
                        context, event.instance_uuid)
                    instances[event.instance_uuid] = instance
                except exception.InstanceNotFound:
                    LOG.debug(
                        'Dropping event %(name)s:%(tag)s for unknown '
                        'instance %(instance_uuid)s', dict(event.iteritems()))
                    _event['status'] = 'failed'
                    _event['code'] = 404
                    result = 207

            # NOTE: before accepting the event, make sure the instance
            # for which the event is sent is assigned to a host; otherwise
            # it will not be possible to dispatch the event
            if instance:
                if instance.host:
                    accepted_events.append(event)
                    accepted_instances.add(instance)
                    LOG.info(
                        _LI('Creating event %(name)s:%(tag)s for '
                            'instance %(instance_uuid)s'),
                        dict(event.iteritems()))
                    # NOTE: as the event is processed asynchronously verify
                    # whether 202 is a more suitable response code than 200
                    _event['status'] = 'completed'
                    _event['code'] = 200
                else:
                    LOG.debug(
                        "Unable to find a host for instance "
                        "%(instance)s. Dropping event %(event)s", {
                            'instance': event.instance_uuid,
                            'event': event.name
                        })
                    _event['status'] = 'failed'
                    _event['code'] = 422
                    result = 207

            response_events.append(_event)

        if accepted_events:
            self.compute_api.external_instance_event(context,
                                                     accepted_instances,
                                                     accepted_events)
        else:
            msg = _('No instances found for any event')
            raise webob.exc.HTTPNotFound(explanation=msg)

        # FIXME(cyeoh): This needs some infrastructure support so that
        # we have a general way to do this
        robj = wsgi.ResponseObject({'events': response_events})
        robj._code = result
        return robj
Пример #27
0
 def test_get_header(self):
     robj = wsgi.ResponseObject({})
     robj['Header'] = 'foo'
     self.assertEqual(robj['hEADER'], 'foo')