# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. # Copyright 2011 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import datetime from oslo.utils import strutils from novaclient.tests import fakes from novaclient.tests.v1_1 import fakes as fakes_v1_1 from novaclient.v3 import client class FakeClient(fakes.FakeClient, client.Client): def __init__(self, *args, **kwargs): client.Client.__init__(self, 'username', 'password', 'project_id', 'auth_url', extensions=kwargs.get('extensions')) self.client = FakeHTTPClient(**kwargs) class FakeHTTPClient(fakes_v1_1.FakeHTTPClient): # # Hosts # def put_os_hosts_sample_host_1(self, body, **kw): return (200, {}, {'host': {'host': 'sample-host_1', 'status': 'enabled'}}) def put_os_hosts_sample_host_2(self, body, **kw): return (200, {}, {'host': {'host': 'sample-host_2', 'maintenance_mode': 'on_maintenance'}}) def put_os_hosts_sample_host_3(self, body, **kw): return (200, {}, {'host': {'host': 'sample-host_3', 'status': 'enabled', 'maintenance_mode': 'on_maintenance'}}) def get_os_hosts_sample_host_reboot(self, **kw): return (200, {}, {'host': {'host': 'sample_host', 'power_action': 'reboot'}}) def get_os_hosts_sample_host_startup(self, **kw): return (200, {}, {'host': {'host': 'sample_host', 'power_action': 'startup'}}) def get_os_hosts_sample_host_shutdown(self, **kw): return (200, {}, {'host': {'host': 'sample_host', 'power_action': 'shutdown'}}) # # Flavors # post_flavors_1_flavor_extra_specs = ( fakes_v1_1.FakeHTTPClient.post_flavors_1_os_extra_specs) post_flavors_4_flavor_extra_specs = ( fakes_v1_1.FakeHTTPClient.post_flavors_4_os_extra_specs) delete_flavors_1_flavor_extra_specs_k1 = ( fakes_v1_1.FakeHTTPClient.delete_flavors_1_os_extra_specs_k1) def get_flavors_detail(self, **kw): flavors = {'flavors': [ {'id': 1, 'name': '256 MB Server', 'ram': 256, 'disk': 10, 'ephemeral': 10, 'flavor-access:is_public': True, 'links': {}}, {'id': 2, 'name': '512 MB Server', 'ram': 512, 'disk': 20, 'ephemeral': 20, 'flavor-access:is_public': False, 'links': {}}, {'id': 4, 'name': '1024 MB Server', 'ram': 1024, 'disk': 10, 'ephemeral': 10, 'flavor-access:is_public': True, 'links': {}}, {'id': 'aa1', 'name': '128 MB Server', 'ram': 128, 'disk': 0, 'ephemeral': 0, 'flavor-access:is_public': True, 'links': {}} ]} if 'is_public' not in kw: filter_is_public = True else: if kw['is_public'].lower() == 'none': filter_is_public = None else: filter_is_public = strutils.bool_from_string(kw['is_public'], True) if filter_is_public is not None: if filter_is_public: flavors['flavors'] = [ v for v in flavors['flavors'] if v['flavor-access:is_public'] ] else: flavors['flavors'] = [ v for v in flavors['flavors'] if not v['flavor-access:is_public'] ] return (200, {}, flavors) # # Flavor access # get_flavors_2_flavor_access = ( fakes_v1_1.FakeHTTPClient.get_flavors_2_os_flavor_access) get_flavors_2_flavor_extra_specs = ( fakes_v1_1.FakeHTTPClient.get_flavors_2_os_extra_specs) get_flavors_aa1_flavor_extra_specs = ( fakes_v1_1.FakeHTTPClient.get_flavors_aa1_os_extra_specs) # # Images # get_v1_images_detail = fakes_v1_1.FakeHTTPClient.get_images_detail get_v1_images = fakes_v1_1.FakeHTTPClient.get_images def head_v1_images_1(self, **kw): headers = { 'x-image-meta-id': '1', 'x-image-meta-name': 'CentOS 5.2', 'x-image-meta-updated': '2010-10-10T12:00:00Z', 'x-image-meta-created': '2010-10-10T12:00:00Z', 'x-image-meta-status': 'ACTIVE', 'x-image-meta-property-test_key': 'test_value'} return 200, headers, '' # # Servers # get_servers_1234_os_server_diagnostics = ( fakes_v1_1.FakeHTTPClient.get_servers_1234_diagnostics) delete_servers_1234_os_attach_interfaces_port_id = ( fakes_v1_1.FakeHTTPClient.delete_servers_1234_os_interface_port_id) def get_servers_1234_os_attach_interfaces(self, **kw): return (200, {}, {"interface_attachments": [ {"port_state": "ACTIVE", "net_id": "net-id-1", "port_id": "port-id-1", "mac_address": "aa:bb:cc:dd:ee:ff", "fixed_ips": [{"ip_address": "1.2.3.4"}], }, {"port_state": "ACTIVE", "net_id": "net-id-1", "port_id": "port-id-1", "mac_address": "aa:bb:cc:dd:ee:ff", "fixed_ips": [{"ip_address": "1.2.3.4"}], }]}) def post_servers_1234_os_attach_interfaces(self, **kw): return (200, {}, {'interface_attachment': {}}) def post_servers(self, body, **kw): assert set(body.keys()) <= set(['server']) fakes.assert_has_keys(body['server'], required=['name', 'image_ref', 'flavor_ref'], optional=['metadata', 'personality', 'os-scheduler-hints:scheduler_hints']) if body['server']['name'] == 'some-bad-server': return (202, {}, self.get_servers_1235()[2]) else: return (202, {}, self.get_servers_1234()[2]) # # Server Actions # def post_servers_1234_action(self, body, **kw): _headers = None resp = 202 body_is_none_list = [ 'revert_resize', 'migrate', 'stop', 'start', 'force_delete', 'restore', 'pause', 'unpause', 'lock', 'unlock', 'unrescue', 'resume', 'suspend', 'lock', 'unlock', 'shelve', 'shelve_offload', 'unshelve', 'reset_network', 'rescue', 'confirm_resize'] body_return_map = { 'rescue': {'admin_password': 'RescuePassword'}, 'get_console_output': {'output': 'foo'}, 'rebuild': self.get_servers_1234()[2], } body_param_check_exists = { 'rebuild': 'image_ref', 'resize': 'flavor_ref', 'evacuate': 'on_shared_storage'} body_params_check_exact = { 'reboot': ['type'], 'add_fixed_ip': ['network_id'], 'remove_fixed_ip': ['address'], 'change_password': ['admin_password'], 'get_console_output': ['length'], 'get_vnc_console': ['type'], 'get_spice_console': ['type'], 'reset_state': ['state'], 'create_image': ['name', 'metadata'], 'migrate_live': ['host', 'block_migration', 'disk_over_commit'], 'create_backup': ['name', 'backup_type', 'rotation'], 'detach': ['volume_id'], 'swap_volume_attachment': ['old_volume_id', 'new_volume_id']} body_params_check_superset = { 'attach': ['volume_id', 'device']} assert len(body.keys()) == 1 action = list(body)[0] _body = body_return_map.get(action) if action in body_is_none_list: assert body[action] is None if action in body_param_check_exists: assert body_param_check_exists[action] in body[action] if action in body_params_check_exact: assert set(body[action]) == set(body_params_check_exact[action]) if action in body_params_check_superset: assert set(body[action]) >= set(body_params_check_superset[action]) if action == 'reboot': assert body[action]['type'] in ['HARD', 'SOFT'] elif action == 'confirm_resize': # This one method returns a different response code resp = 204 elif action == 'create_image': _headers = dict(location="http://blah/images/456") if action not in set.union(set(body_is_none_list), set(body_params_check_exact.keys()), set(body_param_check_exists.keys()), set(body_params_check_superset.keys())): raise AssertionError("Unexpected server action: %s" % action) return (resp, _headers, _body) # # Server password # def get_servers_1234_os_server_password(self, **kw): return (200, {}, {'password': ''}) def delete_servers_1234_os_server_password(self, **kw): return (202, {}, None) # # Availability Zones # def get_os_availability_zone(self, **kw): return (200, {}, {"availability_zone_info": [ {"zone_name": "zone-1", "zone_state": {"available": True}, "hosts": None}, {"zone_name": "zone-2", "zone_state": {"available": False}, "hosts": None}]}) def get_os_availability_zone_detail(self, **kw): return (200, {}, { "availability_zone_info": [ {"zone_name": "zone-1", "zone_state": {"available": True}, "hosts": { "fake_host-1": { "nova-compute": { "active": True, "available": True, "updated_at": datetime.datetime( 2012, 12, 26, 14, 45, 25, 0)}}}}, {"zone_name": "internal", "zone_state": { "available": True}, "hosts": { "fake_host-1": { "nova-sched": { "active": True, "available": True, "updated_at": datetime.datetime( 2012, 12, 26, 14, 45, 25, 0)}}, "fake_host-2": { "nova-network": { "active": True, "available": False, "updated_at": datetime.datetime( 2012, 12, 26, 14, 45, 24, 0)}}}}, {"zone_name": "zone-2", "zone_state": {"available": False}, "hosts": None}]}) # # Quotas # def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw): assert list(body) == ['quota_set'] return (200, {}, {'quota_set': { 'tenant_id': '97f4c221bff44578b0300df4ef119353', 'metadata_items': [], 'injected_file_content_bytes': 1, 'injected_file_path_bytes': 1, 'ram': 1, 'floating_ips': 1, 'instances': 1, 'injected_files': 1, 'cores': 1, 'keypairs': 1, 'security_groups': 1, 'security_group_rules': 1, 'server_groups': 1, 'server_group_members': 1}}) def get_os_quota_sets_test_detail(self, **kw): return (200, {}, {'quota_set': { 'cores': {'reserved': 0, 'in_use': 0, 'limit': 10}, 'instances': {'reserved': 0, 'in_use': 4, 'limit': 50}, 'ram': {'reserved': 0, 'in_use': 1024, 'limit': 51200}}}) # # Hypervisors # def get_os_hypervisors_search(self, **kw): if kw['query'] == 'hyper1': return (200, {}, {'hypervisors': [ {'id': 1234, 'hypervisor_hostname': 'hyper1'}]}) return (200, {}, {'hypervisors': [ {'id': 1234, 'hypervisor_hostname': 'hyper1'}, {'id': 5678, 'hypervisor_hostname': 'hyper2'}]}) def get_os_hypervisors_1234_servers(self, **kw): return (200, {}, {'hypervisor': {'id': 1234, 'hypervisor_hostname': 'hyper1', 'servers': [ {'name': 'inst1', 'id': 'uuid1'}, {'name': 'inst2', 'id': 'uuid2'}]}}) # # Keypairs # get_keypairs_test = fakes_v1_1.FakeHTTPClient.get_os_keypairs_test get_keypairs = fakes_v1_1.FakeHTTPClient.get_os_keypairs delete_keypairs_test = fakes_v1_1.FakeHTTPClient.delete_os_keypairs_test post_keypairs = fakes_v1_1.FakeHTTPClient.post_os_keypairs # # List all extensions # def get_extensions(self, **kw): exts = [ { "alias": "os-multinic", "description": "Multiple network support", "name": "Multinic", "version": 1, }, { "alias": "os-extended-server-attributes", "description": "Extended Server Attributes support.", "name": "ExtendedServerAttributes", "version": 1, }, { "alias": "os-extended-status", "description": "Extended Status support", "name": "ExtendedStatus", "version": 1, }, ] return (200, {}, { "extensions": exts, })