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)
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)
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], '')
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)
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)
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)
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)
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))
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], '')
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)
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)
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)
def test_default_code(self): robj = wsgi.ResponseObject({}) self.assertEqual(robj.code, 200)
def test_modified_code(self): robj = wsgi.ResponseObject({}) robj._default_code = 202 self.assertEqual(robj.code, 202)
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'))
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)
def test_default_serializers(self): robj = wsgi.ResponseObject({}) self.assertEqual(robj.serializers, {})
def test_header_isolation(self): robj = wsgi.ResponseObject({}) robj['Header'] = 'foo' hdrs = robj.headers hdrs['hEADER'] = 'bar' self.assertEqual(robj['hEADER'], 'foo')
def test_del_header(self): robj = wsgi.ResponseObject({}) robj['Header'] = 'foo' del robj['hEADER'] self.assertNotIn('header', robj.headers)
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)
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)
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)
def test_override_modified_code(self): robj = wsgi.ResponseObject({}, code=404) robj._default_code = 202 self.assertEqual(robj.code, 404)
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)
def test_set_header(self): robj = wsgi.ResponseObject({}) robj['Header'] = 'foo' self.assertEqual(robj.headers, {'header': 'foo'})
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
def test_get_header(self): robj = wsgi.ResponseObject({}) robj['Header'] = 'foo' self.assertEqual(robj['hEADER'], 'foo')