diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-10-18 06:07:11 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-10-18 06:07:11 +0000 |
| commit | 5d677e204c99fbcf86e0c721ad2fd327a03c35c2 (patch) | |
| tree | 904f99038bf806c9b96465ba2dead77dee929f4f | |
| parent | 5c94eea7edae746c017372bc726977c2206bccd6 (diff) | |
| parent | e8560a76cbaaebd25f60886f5966297a94597993 (diff) | |
Merge "Add version to network rpc API."
| -rwxr-xr-x | bin/nova-dhcpbridge | 14 | ||||
| -rw-r--r-- | nova/network/api.py | 208 | ||||
| -rw-r--r-- | nova/network/manager.py | 53 | ||||
| -rw-r--r-- | nova/network/rpcapi.py | 274 | ||||
| -rw-r--r-- | nova/tests/compute/test_compute.py | 6 | ||||
| -rw-r--r-- | nova/tests/network/test_api.py | 2 | ||||
| -rw-r--r-- | nova/tests/network/test_rpcapi.py | 260 |
7 files changed, 622 insertions, 195 deletions
diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge index 0693ae27a..114dee268 100755 --- a/bin/nova-dhcpbridge +++ b/bin/nova-dhcpbridge @@ -39,6 +39,7 @@ from nova import context from nova import db from nova import flags from nova.network import linux_net +from nova.network import rpcapi as network_rpcapi from nova.openstack.common import importutils from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -57,10 +58,8 @@ def add_lease(mac, ip_address): network_manager.lease_fixed_ip(context.get_admin_context(), ip_address) else: - rpc.cast(context.get_admin_context(), - "%s.%s" % (FLAGS.network_topic, FLAGS.host), - {"method": "lease_fixed_ip", - "args": {"address": ip_address}}) + api = network_rpcapi.NetworkAPI() + api.lease_fixed_ip(context.get_admin_context(), ip_address, FLAGS.host) def old_lease(mac, ip_address): @@ -79,10 +78,9 @@ def del_lease(mac, ip_address): network_manager.release_fixed_ip(context.get_admin_context(), ip_address) else: - rpc.cast(context.get_admin_context(), - "%s.%s" % (FLAGS.network_topic, FLAGS.host), - {"method": "release_fixed_ip", - "args": {"address": ip_address}}) + api = network_rpcapi.NetworkAPI() + api.release_fixed_ip(context.get_admin_context(), ip_address, + FLAGS.host) def init_leases(network_id): diff --git a/nova/network/api.py b/nova/network/api.py index f98678ab0..6e5d8f22d 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -23,6 +23,7 @@ import inspect from nova.db import base from nova import flags from nova.network import model as network_model +from nova.network import rpcapi as network_rpcapi from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -83,96 +84,58 @@ def update_instance_cache_with_nw_info(api, context, instance, class API(base.Base): """API for interacting with the network manager.""" + def __init__(self, **kwargs): + self.network_rpcapi = network_rpcapi.NetworkAPI() + super(API, self).__init__(**kwargs) + def get_all(self, context): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_all_networks'}) + return self.network_rpcapi.get_all_networks(context) def get(self, context, network_uuid): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_network', - 'args': {'network_uuid': network_uuid}}) + return self.network_rpcapi.get_network(context, network_uuid) def create(self, context, **kwargs): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'create_networks', - 'args': kwargs}) + return self.network_rpcapi.create_networks(context, **kwargs) def delete(self, context, network_uuid): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'delete_network', - 'args': {'fixed_range': None, - 'uuid': network_uuid}}) + return self.network_rpcapi.delete_network(context, network_uuid, None) def disassociate(self, context, network_uuid): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'disassociate_network', - 'args': {'network_uuid': network_uuid}}) + return self.network_rpcapi.disassociate_network(context, network_uuid) def get_fixed_ip(self, context, id): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_fixed_ip', - 'args': {'id': id}}) + return self.network_rpcapi.get_fixed_ip(context, id) def get_fixed_ip_by_address(self, context, address): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_fixed_ip_by_address', - 'args': {'address': address}}) + return self.network_rpcapi.get_fixed_ip_by_address(context, address) def get_floating_ip(self, context, id): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_floating_ip', - 'args': {'id': id}}) + return self.network_rpcapi.get_floating_ip(context, id) def get_floating_ip_pools(self, context): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_floating_pools'}) + return self.network_rpcapi.get_floating_pools(context) def get_floating_ip_by_address(self, context, address): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_floating_ip_by_address', - 'args': {'address': address}}) + return self.network_rpcapi.get_floating_ip_by_address(context, address) def get_floating_ips_by_project(self, context): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_floating_ips_by_project'}) + return self.network_rpcapi.get_floating_ips_by_project(context) def get_floating_ips_by_fixed_address(self, context, fixed_address): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_floating_ips_by_fixed_address', - 'args': {'fixed_address': fixed_address}}) + return self.network_rpcapi.get_floating_ips_by_fixed_address(context, + fixed_address) def get_instance_id_by_floating_address(self, context, address): # NOTE(tr3buchet): i hate this - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_instance_id_by_floating_address', - 'args': {'address': address}}) + return self.network_rpcapi.get_instance_id_by_floating_address(context, + address) def get_vifs_by_instance(self, context, instance): - # NOTE(vish): When the db calls are converted to store network - # data by instance_uuid, this should pass uuid instead. - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_vifs_by_instance', - 'args': {'instance_id': instance['id']}}) + return self.network_rpcapi.get_vifs_by_instance(context, + instance['id']) def get_vif_by_mac_address(self, context, mac_address): - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_vif_by_mac_address', - 'args': {'mac_address': mac_address}}) + return self.network_rpcapi.get_vif_by_mac_address(context, mac_address) def allocate_floating_ip(self, context, pool=None): """Adds a floating ip to a project from a pool. (allocates)""" @@ -180,21 +143,14 @@ class API(base.Base): # when we allocate, so just send it to any one. This # will probably need to move into a network supervisor # at some point. - return rpc.call(context, - FLAGS.network_topic, - {'method': 'allocate_floating_ip', - 'args': {'project_id': context.project_id, - 'pool': pool, - 'auto_assigned': False}}) + return self.network_rpcapi.allocate_floating_ip(context, + context.project_id, pool, False) def release_floating_ip(self, context, address, affect_auto_assigned=False): """Removes floating ip with address from a project. (deallocates)""" - rpc.call(context, - FLAGS.network_topic, - {'method': 'deallocate_floating_ip', - 'args': {'address': address, - 'affect_auto_assigned': affect_auto_assigned}}) + return self.network_rpcapi.deallocate_floating_ip(context, address, + affect_auto_assigned) @refresh_cache def associate_floating_ip(self, context, instance, @@ -204,12 +160,8 @@ class API(base.Base): ensures floating ip is allocated to the project in context """ - orig_instance_uuid = rpc.call(context, - FLAGS.network_topic, - {'method': 'associate_floating_ip', - 'args': {'floating_address': floating_address, - 'fixed_address': fixed_address, - 'affect_auto_assigned': affect_auto_assigned}}) + orig_instance_uuid = self.network_rpcapi.associate_floating_ip(context, + floating_address, fixed_address, affect_auto_assigned) if orig_instance_uuid: msg_dict = dict(address=floating_address, @@ -226,48 +178,43 @@ class API(base.Base): def disassociate_floating_ip(self, context, instance, address, affect_auto_assigned=False): """Disassociates a floating ip from fixed ip it is associated with.""" - rpc.call(context, - FLAGS.network_topic, - {'method': 'disassociate_floating_ip', - 'args': {'address': address}}) + self.network_rpcapi.disassociate_floating_ip(context, address, + affect_auto_assigned) @refresh_cache - def allocate_for_instance(self, context, instance, **kwargs): + def allocate_for_instance(self, context, instance, vpn, + requested_networks): """Allocates all network structures for an instance. :returns: network info as from get_instance_nw_info() below """ - args = kwargs + args = {} + args['vpn'] = vpn + args['requested_networks'] = requested_networks args['instance_id'] = instance['id'] args['instance_uuid'] = instance['uuid'] args['project_id'] = instance['project_id'] args['host'] = instance['host'] args['rxtx_factor'] = instance['instance_type']['rxtx_factor'] - - nw_info = rpc.call(context, FLAGS.network_topic, - {'method': 'allocate_for_instance', - 'args': args}) + nw_info = self.network_rpcapi.allocate_for_instance(context, **args) return network_model.NetworkInfo.hydrate(nw_info) - def deallocate_for_instance(self, context, instance, **kwargs): + def deallocate_for_instance(self, context, instance): """Deallocates all network structures related to instance.""" - args = kwargs + + args = {} args['instance_id'] = instance['id'] args['project_id'] = instance['project_id'] args['host'] = instance['host'] - rpc.call(context, FLAGS.network_topic, - {'method': 'deallocate_for_instance', - 'args': args}) + self.network_rpcapi.deallocate_for_instance(context, **args) def add_fixed_ip_to_instance(self, context, instance, network_id): """Adds a fixed ip to instance from specified network.""" args = {'instance_id': instance['id'], 'host': instance['host'], 'network_id': network_id} - rpc.call(context, FLAGS.network_topic, - {'method': 'add_fixed_ip_to_instance', - 'args': args}) + self.network_rpcapi.add_fixed_ip_to_instance(context, **args) def remove_fixed_ip_from_instance(self, context, instance, address): """Removes a fixed ip from instance from specified network.""" @@ -275,16 +222,12 @@ class API(base.Base): args = {'instance_id': instance['uuid'], 'host': instance['host'], 'address': address} - rpc.call(context, FLAGS.network_topic, - {'method': 'remove_fixed_ip_from_instance', - 'args': args}) + self.network_rpcapi.remove_fixed_ip_from_instance(context, **args) def add_network_to_project(self, context, project_id, network_uuid=None): """Force adds another network to a project.""" - rpc.call(context, FLAGS.network_topic, - {'method': 'add_network_to_project', - 'args': {'project_id': project_id, - 'network_uuid': network_uuid}}) + self.network_rpcapi.add_network_to_project(context, project_id, + network_uuid) @refresh_cache def get_instance_nw_info(self, context, instance): @@ -298,9 +241,7 @@ class API(base.Base): 'rxtx_factor': instance['instance_type']['rxtx_factor'], 'host': instance['host'], 'project_id': instance['project_id']} - nw_info = rpc.call(context, FLAGS.network_topic, - {'method': 'get_instance_nw_info', - 'args': args}) + nw_info = self.network_rpcapi.get_instance_nw_info(context, **args) return network_model.NetworkInfo.hydrate(nw_info) @@ -308,27 +249,21 @@ class API(base.Base): """validate the networks passed at the time of creating the server """ - args = {'networks': requested_networks} - return rpc.call(context, FLAGS.network_topic, - {'method': 'validate_networks', - 'args': args}) + return self.network_rpcapi.validate_networks(context, + requested_networks) def get_instance_uuids_by_ip_filter(self, context, filters): """Returns a list of dicts in the form of {'instance_uuid': uuid, 'ip': ip} that matched the ip_filter """ - args = {'filters': filters} - return rpc.call(context, FLAGS.network_topic, - {'method': 'get_instance_uuids_by_ip_filter', - 'args': args}) + return self.network_rpcapi.get_instance_uuids_by_ip_filter(context, + filters) def get_dns_domains(self, context): """Returns a list of available dns domains. These can be used to create DNS entries for floating ips. """ - return rpc.call(context, - FLAGS.network_topic, - {'method': 'get_dns_domains'}) + return self.network_rpcapi.get_dns_domains(context) def add_dns_entry(self, context, address, name, dns_type, domain): """Create specified DNS entry for address""" @@ -336,60 +271,43 @@ class API(base.Base): 'name': name, 'dns_type': dns_type, 'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'add_dns_entry', - 'args': args}) + return self.network_rpcapi.add_dns_entry(context, **args) def modify_dns_entry(self, context, name, address, domain): """Create specified DNS entry for address""" args = {'address': address, 'name': name, 'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'modify_dns_entry', - 'args': args}) + return self.network_rpcapi.modify_dns_entry(context, **args) def delete_dns_entry(self, context, name, domain): """Delete the specified dns entry.""" args = {'name': name, 'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'delete_dns_entry', - 'args': args}) + return self.network_rpcapi.delete_dns_entry(context, **args) def delete_dns_domain(self, context, domain): """Delete the specified dns domain.""" - args = {'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'delete_dns_domain', - 'args': args}) + return self.network_rpcapi.delete_dns_domain(context, domain=domain) def get_dns_entries_by_address(self, context, address, domain): """Get entries for address and domain""" args = {'address': address, 'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'get_dns_entries_by_address', - 'args': args}) + return self.network_rpcapi.get_dns_entries_by_address(context, **args) def get_dns_entries_by_name(self, context, name, domain): """Get entries for name and domain""" args = {'name': name, 'domain': domain} - return rpc.call(context, FLAGS.network_topic, - {'method': 'get_dns_entries_by_name', - 'args': args}) + return self.network_rpcapi.get_dns_entries_by_name(context, **args) def create_private_dns_domain(self, context, domain, availability_zone): """Create a private DNS domain with nova availability zone.""" args = {'domain': domain, 'av_zone': availability_zone} - return rpc.call(context, FLAGS.network_topic, - {'method': 'create_private_dns_domain', - 'args': args}) + return self.network_rpcapi.create_private_dns_domain(context, **args) def create_public_dns_domain(self, context, domain, project=None): - """Create a private DNS domain with optional nova project.""" + """Create a public DNS domain with optional nova project.""" args = {'domain': domain, 'project': project} - return rpc.call(context, FLAGS.network_topic, - {'method': 'create_public_dns_domain', - 'args': args}) + return self.network_rpcapi.create_public_dns_domain(context, **args) def setup_networks_on_host(self, context, instance, host=None, teardown=False): @@ -402,8 +320,4 @@ class API(base.Base): args = {'instance_id': instance['id'], 'host': host, 'teardown': teardown} - - # NOTE(tr3buchet): the call is just to wait for completion - rpc.call(context, FLAGS.network_topic, - {'method': 'setup_networks_on_host', - 'args': args}) + self.network_rpcapi.setup_networks_on_host(context, **args) diff --git a/nova/network/manager.py b/nova/network/manager.py index 02cdfdd3a..f8ef65d3a 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -61,6 +61,7 @@ from nova import ipv6 from nova import manager from nova.network import api as network_api from nova.network import model as network_model +from nova.network import rpcapi as network_rpcapi from nova.openstack.common import cfg from nova.openstack.common import excutils from nova.openstack.common import importutils @@ -191,22 +192,12 @@ class RPCAllocateFixedIP(object): host = network['host'] # NOTE(vish): if there is no network host, set one if host is None: - host = rpc.call(context, FLAGS.network_topic, - {'method': 'set_network_host', - 'args': {'network_ref': - jsonutils.to_primitive(network)}}) + host = self.network_rpcapi.set_network_host(context, network) if host != self.host: # need to call allocate_fixed_ip to correct network host - topic = rpc.queue_get_for(context, FLAGS.network_topic, host) - args = {} - args['instance_id'] = instance_id - args['network_id'] = network['id'] - args['address'] = address - args['vpn'] = vpn - - green_pool.spawn_n(rpc.call, context, topic, - {'method': '_rpc_allocate_fixed_ip', - 'args': args}) + green_pool.spawn_n(self.network_rpcapi._rpc_allocate_fixed_ip, + context, instance_id, network['id'], address, vpn, + host) else: # i am the correct host, run here self.allocate_fixed_ip(context, instance_id, network, @@ -235,12 +226,7 @@ class RPCAllocateFixedIP(object): host = network['host'] if host != self.host: # need to call deallocate_fixed_ip on correct network host - topic = rpc.queue_get_for(context, FLAGS.network_topic, host) - args = {'address': address, - 'host': host} - rpc.call(context, topic, - {'method': 'deallocate_fixed_ip', - 'args': args}) + self.network_rpcapi.deallocate_fixed_ip(context, address, host) else: # i am the correct host, run here super(RPCAllocateFixedIP, self).deallocate_fixed_ip(context, @@ -534,12 +520,8 @@ class FloatingIP(object): fixed_address, interface) else: # send to correct host - rpc.call(context, - rpc.queue_get_for(context, FLAGS.network_topic, host), - {'method': '_associate_floating_ip', - 'args': {'floating_address': floating_address, - 'fixed_address': fixed_address, - 'interface': interface}}) + self.network_rpcapi._associate_floating_ip(context, + floating_address, fixed_address, interface, host) return orig_instance_uuid @@ -607,11 +589,8 @@ class FloatingIP(object): self._disassociate_floating_ip(context, address, interface) else: # send to correct host - rpc.call(context, - rpc.queue_get_for(context, FLAGS.network_topic, host), - {'method': '_disassociate_floating_ip', - 'args': {'address': address, - 'interface': interface}}) + self.network_rpcapi._disassociate_floating_ip(context, address, + interface, host) def _disassociate_floating_ip(self, context, address, interface): """Performs db and driver calls to disassociate floating ip""" @@ -770,6 +749,8 @@ class NetworkManager(manager.SchedulerDependentManager): The one at a time part is to flatten the layout to help scale """ + RPC_API_VERSION = '1.0' + # If True, this manager requires VIF to create a bridge. SHOULD_CREATE_BRIDGE = False @@ -793,6 +774,7 @@ class NetworkManager(manager.SchedulerDependentManager): self.floating_dns_manager = importutils.import_object( FLAGS.floating_ip_dns_manager) self.network_api = network_api.API() + self.network_rpcapi = network_rpcapi.NetworkAPI() self.security_group_api = compute_api.SecurityGroupAPI() self.compute_api = compute_api.API( security_group_api=self.security_group_api) @@ -1657,12 +1639,9 @@ class NetworkManager(manager.SchedulerDependentManager): call_func(context, network) else: # i'm not the right host, run call on correct host - topic = rpc.queue_get_for(context, FLAGS.network_topic, host) - args = {'network_id': network['id'], 'teardown': teardown} - # NOTE(tr3buchet): the call is just to wait for completion - green_pool.spawn_n(rpc.call, context, topic, - {'method': 'rpc_setup_network_on_host', - 'args': args}) + green_pool.spawn_n( + self.network_rpcapi.rpc_setup_network_on_host, context, + network['id'], teardown, host) # wait for all of the setups (if any) to finish green_pool.waitall() diff --git a/nova/network/rpcapi.py b/nova/network/rpcapi.py new file mode 100644 index 000000000..43c17acb5 --- /dev/null +++ b/nova/network/rpcapi.py @@ -0,0 +1,274 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012, Red Hat, Inc. +# +# 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. + +""" +Client side of the network RPC API. +""" + +from nova import flags +from nova.openstack.common import jsonutils +from nova.openstack.common import rpc +from nova.openstack.common.rpc import proxy as rpc_proxy + + +FLAGS = flags.FLAGS + + +class NetworkAPI(rpc_proxy.RpcProxy): + '''Client side of the network rpc API. + + API version history: + + 1.0 - Initial version. + ''' + + # + # NOTE(russellb): This is the default minimum version that the server + # (manager) side must implement unless otherwise specified using a version + # argument to self.call()/cast()/etc. here. It should be left as X.0 where + # X is the current major API version (1.0, 2.0, ...). For more information + # about rpc API versioning, see the docs in + # openstack/common/rpc/dispatcher.py. + # + BASE_RPC_API_VERSION = '1.0' + + def __init__(self, topic=None): + topic = topic if topic else FLAGS.network_topic + super(NetworkAPI, self).__init__( + topic=topic, + default_version=self.BASE_RPC_API_VERSION) + + def get_all_networks(self, ctxt): + return self.call(ctxt, self.make_msg('get_all_networks')) + + def get_network(self, ctxt, network_uuid): + return self.call(ctxt, self.make_msg('get_network', + network_uuid=network_uuid)) + + # TODO(russellb): Convert this to named arguments. It's a pretty large + # list, so unwinding it all is probably best done in its own patch so it's + # easier to review. + def create_networks(self, ctxt, **kwargs): + return self.call(ctxt, self.make_msg('create_networks', **kwargs)) + + def delete_network(self, ctxt, uuid, fixed_range): + return self.call(ctxt, self.make_msg('delete_network', + uuid=uuid, fixed_range=fixed_range)) + + def disassociate_network(self, ctxt, network_uuid): + return self.call(ctxt, self.make_msg('disassociate_network', + network_uuid=network_uuid)) + + def get_fixed_ip(self, ctxt, id): + return self.call(ctxt, self.make_msg('get_fixed_ip', id=id)) + + def get_fixed_ip_by_address(self, ctxt, address): + return self.call(ctxt, self.make_msg('get_fixed_ip_by_address', + address=address)) + + def get_floating_ip(self, ctxt, id): + return self.call(ctxt, self.make_msg('get_floating_ip', id=id)) + + def get_floating_pools(self, ctxt): + return self.call(ctxt, self.make_msg('get_floating_pools')) + + def get_floating_ip_by_address(self, ctxt, address): + return self.call(ctxt, self.make_msg('get_floating_ip_by_address', + address=address)) + + def get_floating_ips_by_project(self, ctxt): + return self.call(ctxt, self.make_msg('get_floating_ips_by_project')) + + def get_floating_ips_by_fixed_address(self, ctxt, fixed_address): + return self.call(ctxt, self.make_msg( + 'get_floating_ips_by_fixed_address', + fixed_address=fixed_address)) + + def get_instance_id_by_floating_address(self, ctxt, address): + return self.call(ctxt, self.make_msg( + 'get_instance_id_by_floating_address', + address=address)) + + def get_vifs_by_instance(self, ctxt, instance_id): + # NOTE(vish): When the db calls are converted to store network + # data by instance_uuid, this should pass uuid instead. + return self.call(ctxt, self.make_msg('get_vifs_by_instance', + instance_id=instance_id)) + + def get_vif_by_mac_address(self, ctxt, mac_address): + return self.call(ctxt, self.make_msg('get_vif_by_mac_address', + mac_address=mac_address)) + + def allocate_floating_ip(self, ctxt, project_id, pool, auto_assigned): + return self.call(ctxt, self.make_msg('allocate_floating_ip', + project_id=project_id, pool=pool, auto_assigned=auto_assigned)) + + def deallocate_floating_ip(self, ctxt, address, affect_auto_assigned): + return self.call(ctxt, self.make_msg('deallocate_floating_ip', + address=address, affect_auto_assigned=affect_auto_assigned)) + + def associate_floating_ip(self, ctxt, floating_address, fixed_address, + affect_auto_assigned): + return self.call(ctxt, self.make_msg('associate_floating_ip', + floating_address=floating_address, fixed_address=fixed_address, + affect_auto_assigned=affect_auto_assigned)) + + def disassociate_floating_ip(self, ctxt, address, affect_auto_assigned): + return self.call(ctxt, self.make_msg('disassociate_floating_ip', + address=address, affect_auto_assigned=affect_auto_assigned)) + + def allocate_for_instance(self, ctxt, instance_id, instance_uuid, + project_id, host, rxtx_factor, vpn, + requested_networks): + return self.call(ctxt, self.make_msg('allocate_for_instance', + instance_id=instance_id, instance_uuid=instance_uuid, + project_id=project_id, host=host, rxtx_factor=rxtx_factor, + vpn=vpn, requested_networks=requested_networks)) + + def deallocate_for_instance(self, ctxt, instance_id, project_id, host): + return self.call(ctxt, self.make_msg('deallocate_for_instance', + instance_id=instance_id, project_id=project_id, host=host)) + + def add_fixed_ip_to_instance(self, ctxt, instance_id, host, network_id): + return self.call(ctxt, self.make_msg('add_fixed_ip_to_instance', + instance_id=instance_id, host=host, network_id=network_id)) + + def remove_fixed_ip_from_instance(self, ctxt, instance_id, host, address): + return self.call(ctxt, self.make_msg('remove_fixed_ip_from_instance', + instance_id=instance_id, host=host, address=address)) + + def add_network_to_project(self, ctxt, project_id, network_uuid): + return self.call(ctxt, self.make_msg('add_network_to_project', + project_id=project_id, network_uuid=network_uuid)) + + def get_instance_nw_info(self, ctxt, instance_id, instance_uuid, + rxtx_factor, host, project_id): + return self.call(ctxt, self.make_msg('get_instance_nw_info', + instance_id=instance_id, instance_uuid=instance_uuid, + rxtx_factor=rxtx_factor, host=host, project_id=project_id)) + + def validate_networks(self, ctxt, networks): + return self.call(ctxt, self.make_msg('validate_networks', + networks=networks)) + + def get_instance_uuids_by_ip_filter(self, ctxt, filters): + return self.call(ctxt, self.make_msg('get_instance_uuids_by_ip_filter', + filters=filters)) + + def get_dns_domains(self, ctxt): + return self.call(ctxt, self.make_msg('get_dns_domains')) + + def add_dns_entry(self, ctxt, address, name, dns_type, domain): + return self.call(ctxt, self.make_msg('add_dns_entry', address=address, + name=name, dns_type=dns_type, domain=domain)) + + def modify_dns_entry(self, ctxt, address, name, domain): + return self.call(ctxt, self.make_msg('modify_dns_entry', + address=address, name=name, domain=domain)) + + def delete_dns_entry(self, ctxt, name, domain): + return self.call(ctxt, self.make_msg('delete_dns_entry', + name=name, domain=domain)) + + def delete_dns_domain(self, ctxt, domain): + return self.call(ctxt, self.make_msg('delete_dns_domain', + domain=domain)) + + def get_dns_entries_by_address(self, ctxt, address, domain): + return self.call(ctxt, self.make_msg('get_dns_entries_by_address', + address=address, domain=domain)) + + def get_dns_entries_by_name(self, ctxt, name, domain): + return self.call(ctxt, self.make_msg('get_dns_entries_by_name', + name=name, domain=domain)) + + def create_private_dns_domain(self, ctxt, domain, av_zone): + return self.call(ctxt, self.make_msg('create_private_dns_domain', + domain=domain, av_zone=av_zone)) + + def create_public_dns_domain(self, ctxt, domain, project): + return self.call(ctxt, self.make_msg('create_public_dns_domain', + domain=domain, project=project)) + + def setup_networks_on_host(self, ctxt, instance_id, host, teardown): + # NOTE(tr3buchet): the call is just to wait for completion + return self.call(ctxt, self.make_msg('setup_networks_on_host', + instance_id=instance_id, host=host, teardown=teardown)) + + def lease_fixed_ip(self, ctxt, host, address): + self.cast(ctxt, self.make_msg('lease_fixed_ip', address=address), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + def release_fixed_ip(self, ctxt, host, address): + self.cast(ctxt, self.make_msg('release_fixed_ip', address=address), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + def set_network_host(self, ctxt, network_ref): + network_ref_p = jsonutils.to_primitive(network_ref) + return self.call(ctxt, self.make_msg('set_network_host', + network_ref=network_ref_p)) + + def rpc_setup_network_on_host(self, ctxt, network_id, teardown, host): + # NOTE(tr3buchet): the call is just to wait for completion + return self.call(ctxt, self.make_msg('rpc_setup_network_on_host', + network_id=network_id, teardown=teardown), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + # NOTE(russellb): Ideally this would not have a prefix of '_' since it is + # a part of the rpc API. However, this is how it was being called when the + # 1.0 API was being documented using this client proxy class. It should be + # changed if there was ever a 2.0. + def _rpc_allocate_fixed_ip(self, ctxt, instance_id, network_id, address, + vpn, host): + return self.call(ctxt, self.make_msg('_rpc_allocate_fixed_ip', + instance_id=instance_id, network_id=network_id, + address=address, vpn=vpn), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + def deallocate_fixed_ip(self, ctxt, address, host): + return self.call(ctxt, self.make_msg('deallocate_fixed_ip', + address=address, host=host), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + # NOTE(russellb): Ideally this would not have a prefix of '_' since it is + # a part of the rpc API. However, this is how it was being called when the + # 1.0 API was being documented using this client proxy class. It should be + # changed if there was ever a 2.0. + def _associate_floating_ip(self, ctxt, floating_address, fixed_address, + interface, host): + return self.call(ctxt, self.make_msg('_associate_floating_ip', + floating_address=floating_address, fixed_address=fixed_address, + interface=interface), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + # NOTE(russellb): Ideally this would not have a prefix of '_' since it is + # a part of the rpc API. However, this is how it was being called when the + # 1.0 API was being documented using this client proxy class. It should be + # changed if there was ever a 2.0. + def _disassociate_floating_ip(self, ctxt, address, interface, host): + return self.call(ctxt, self.make_msg('_disassociate_floating_ip', + address=address, interface=interface), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + def lease_fixed_ip(self, ctxt, address, host): + return self.cast(ctxt, self.make_msg('lease_fixed_ip', + address=address), + topic=rpc.queue_get_for(ctxt, self.topic, host)) + + def release_fixed_ip(self, ctxt, address, host): + return self.cast(ctxt, self.make_msg('release_fixed_ip', + address=address), + topic=rpc.queue_get_for(ctxt, self.topic, host)) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index a5081066e..6fc317775 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -2160,7 +2160,8 @@ class ComputeTestCase(BaseTestCase): rpc.call(c, 'network', {'method': 'setup_networks_on_host', 'args': {'instance_id': inst_id, 'host': self.compute.host, - 'teardown': False}}) + 'teardown': False}, + 'version': '1.0'}, None) rpcinst = jsonutils.to_primitive( db.instance_get_by_uuid(self.context, instance['uuid'])) rpc.call(c, topic, @@ -2255,7 +2256,8 @@ class ComputeTestCase(BaseTestCase): rpc.call(c, 'network', {'method': 'setup_networks_on_host', 'args': {'instance_id': inst_id, 'host': self.compute.host, - 'teardown': True}}) + 'teardown': True}, + 'version': '1.0'}, None) # start test self.mox.ReplayAll() diff --git a/nova/tests/network/test_api.py b/nova/tests/network/test_api.py index a29756caa..9bbd7ba92 100644 --- a/nova/tests/network/test_api.py +++ b/nova/tests/network/test_api.py @@ -35,7 +35,7 @@ class ApiTestCase(test.TestCase): new_instance = {'uuid': 'new-uuid'} - def fake_rpc_call(context, topic, msg): + def fake_rpc_call(context, topic, msg, timeout=None): return orig_instance_uuid self.stubs.Set(rpc, 'call', fake_rpc_call) diff --git a/nova/tests/network/test_rpcapi.py b/nova/tests/network/test_rpcapi.py new file mode 100644 index 000000000..a087ba97f --- /dev/null +++ b/nova/tests/network/test_rpcapi.py @@ -0,0 +1,260 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012, Red Hat, Inc. +# +# 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. + +""" +Unit Tests for nova.network.rpcapi +""" + +from nova import context +from nova import flags +from nova.network import rpcapi as network_rpcapi +from nova.openstack.common import rpc +from nova import test + + +FLAGS = flags.FLAGS + + +class NetworkRpcAPITestCase(test.TestCase): + def _test_network_api(self, method, rpc_method, **kwargs): + ctxt = context.RequestContext('fake_user', 'fake_project') + rpcapi = network_rpcapi.NetworkAPI() + expected_retval = 'foo' if method == 'call' else None + expected_version = kwargs.pop('version', rpcapi.BASE_RPC_API_VERSION) + expected_topic = FLAGS.network_topic + expected_msg = rpcapi.make_msg(method, **kwargs) + targeted_methods = [ + 'lease_fixed_ip', 'release_fixed_ip', 'rpc_setup_network_on_host', + '_rpc_allocate_fixed_ip', 'deallocate_fixed_ip', + '_associate_floating_ip', '_disassociate_floating_ip', + 'lease_fixed_ip', 'release_fixed_ip' + ] + if method in targeted_methods and 'host' in kwargs: + if method != 'deallocate_fixed_ip': + del expected_msg['args']['host'] + host = kwargs['host'] + expected_topic = rpc.queue_get_for(ctxt, FLAGS.network_topic, host) + expected_msg['version'] = expected_version + + self.fake_args = None + self.fake_kwargs = None + + def _fake_rpc_method(*args, **kwargs): + self.fake_args = args + self.fake_kwargs = kwargs + if expected_retval: + return expected_retval + + self.stubs.Set(rpc, rpc_method, _fake_rpc_method) + + retval = getattr(rpcapi, method)(ctxt, **kwargs) + + self.assertEqual(retval, expected_retval) + expected_args = [ctxt, expected_topic, expected_msg] + for arg, expected_arg in zip(self.fake_args, expected_args): + self.assertEqual(arg, expected_arg) + + def test_get_all_networks(self): + self._test_network_api('get_all_networks', rpc_method='call') + + def test_get_network(self): + self._test_network_api('get_network', rpc_method='call', + network_uuid='fake_uuid') + + def test_create_networks(self): + self._test_network_api('create_networks', rpc_method='call', + arg1='arg', arg2='arg') + + def test_delete_network(self): + self._test_network_api('delete_network', rpc_method='call', + uuid='fake_uuid', fixed_range='range') + + def test_disassociate_network(self): + self._test_network_api('disassociate_network', rpc_method='call', + network_uuid='fake_uuid') + + def test_get_fixed_ip(self): + self._test_network_api('get_fixed_ip', rpc_method='call', id='id') + + def test_get_fixed_ip_by_address(self): + self._test_network_api('get_fixed_ip_by_address', rpc_method='call', + address='a.b.c.d') + + def test_get_floating_ip(self): + self._test_network_api('get_floating_ip', rpc_method='call', id='id') + + def test_get_floating_pools(self): + self._test_network_api('get_floating_pools', rpc_method='call') + + def test_get_floating_ip_by_address(self): + self._test_network_api('get_floating_ip_by_address', rpc_method='call', + address='a.b.c.d') + + def test_get_floating_ips_by_project(self): + self._test_network_api('get_floating_ips_by_project', + rpc_method='call') + + def test_get_floating_ips_by_fixed_address(self): + self._test_network_api('get_floating_ips_by_fixed_address', + rpc_method='call', fixed_address='w.x.y.z') + + def test_get_instance_id_by_floating_address(self): + self._test_network_api('get_instance_id_by_floating_address', + rpc_method='call', address='w.x.y.z') + + def test_get_vifs_by_instance(self): + self._test_network_api('get_vifs_by_instance', + rpc_method='call', instance_id='fake_id') + + def test_get_vif_by_mac_address(self): + self._test_network_api('get_vif_by_mac_address', + rpc_method='call', mac_address='fake_mac_addr') + + def test_allocate_floating_ip(self): + self._test_network_api('allocate_floating_ip', rpc_method='call', + project_id='fake_id', pool='fake_pool', auto_assigned=False) + + def test_deallocate_floating_ip(self): + self._test_network_api('deallocate_floating_ip', rpc_method='call', + address='addr', affect_auto_assigned=True) + + def test_associate_floating_ip(self): + self._test_network_api('associate_floating_ip', rpc_method='call', + floating_address='blah', fixed_address='foo', + affect_auto_assigned=True) + + def test_disassociate_floating_ip(self): + self._test_network_api('disassociate_floating_ip', rpc_method='call', + address='addr', affect_auto_assigned=True) + + def test_allocate_for_instance(self): + self._test_network_api('allocate_for_instance', rpc_method='call', + instance_id='fake_id', instance_uuid='fake_uuid', + project_id='fake_id', host='fake_host', + rxtx_factor='fake_factor', vpn=False, requested_networks={}) + + def test_deallocate_for_instance(self): + self._test_network_api('deallocate_for_instance', rpc_method='call', + instance_id='fake_id', project_id='fake_id', host='fake_host') + + def test_add_fixed_ip_to_instance(self): + self._test_network_api('add_fixed_ip_to_instance', rpc_method='call', + instance_id='fake_id', host='fake_host', network_id='fake_id') + + def test_remove_fixed_ip_from_instance(self): + self._test_network_api('remove_fixed_ip_from_instance', + rpc_method='call', instance_id='fake_id', host='fake_host', + address='fake_address') + + def test_add_network_to_project(self): + self._test_network_api('add_network_to_project', rpc_method='call', + project_id='fake_id', network_uuid='fake_uuid') + + def test_get_instance_nw_info(self): + self._test_network_api('get_instance_nw_info', rpc_method='call', + instance_id='fake_id', instance_uuid='fake_uuid', + rxtx_factor='fake_factor', host='fake_host', + project_id='fake_id') + + def test_validate_networks(self): + self._test_network_api('validate_networks', rpc_method='call', + networks={}) + + def test_get_instance_uuids_by_ip_filter(self): + self._test_network_api('get_instance_uuids_by_ip_filter', + rpc_method='call', filters={}) + + def test_get_dns_domains(self): + self._test_network_api('get_dns_domains', rpc_method='call') + + def test_add_dns_entry(self): + self._test_network_api('add_dns_entry', rpc_method='call', + address='addr', name='name', dns_type='foo', domain='domain') + + def test_modify_dns_entry(self): + self._test_network_api('modify_dns_entry', rpc_method='call', + address='addr', name='name', domain='domain') + + def test_delete_dns_entry(self): + self._test_network_api('delete_dns_entry', rpc_method='call', + name='name', domain='domain') + + def test_delete_dns_domain(self): + self._test_network_api('delete_dns_domain', rpc_method='call', + domain='fake_domain') + + def test_get_dns_entries_by_address(self): + self._test_network_api('get_dns_entries_by_address', rpc_method='call', + address='fake_address', domain='fake_domain') + + def test_get_dns_entries_by_name(self): + self._test_network_api('get_dns_entries_by_name', rpc_method='call', + name='fake_name', domain='fake_domain') + + def test_create_private_dns_domain(self): + self._test_network_api('create_private_dns_domain', rpc_method='call', + domain='fake_domain', av_zone='fake_zone') + + def test_create_public_dns_domain(self): + self._test_network_api('create_public_dns_domain', rpc_method='call', + domain='fake_domain', project='fake_project') + + def test_setup_networks_on_host(self): + self._test_network_api('setup_networks_on_host', rpc_method='call', + instance_id='fake_id', host='fake_host', teardown=False) + + def test_lease_fixed_ip(self): + self._test_network_api('lease_fixed_ip', rpc_method='cast', + host='fake_host', address='fake_addr') + + def test_release_fixed_ip(self): + self._test_network_api('release_fixed_ip', rpc_method='cast', + host='fake_host', address='fake_addr') + + def test_set_network_host(self): + self._test_network_api('set_network_host', rpc_method='call', + network_ref={}) + + def test_rpc_setup_network_on_host(self): + self._test_network_api('rpc_setup_network_on_host', rpc_method='call', + network_id='fake_id', teardown=False, host='fake_host') + + def test_rpc_allocate_fixed_ip(self): + self._test_network_api('_rpc_allocate_fixed_ip', rpc_method='call', + instance_id='fake_id', network_id='fake_id', address='addr', + vpn=True, host='fake_host') + + def test_deallocate_fixed_ip(self): + self._test_network_api('deallocate_fixed_ip', rpc_method='call', + address='fake_addr', host='fake_host') + + def test__associate_floating_ip(self): + self._test_network_api('_associate_floating_ip', rpc_method='call', + floating_address='fake_addr', fixed_address='fixed_address', + interface='fake_interface', host='fake_host') + + def test__disassociate_floating_ip(self): + self._test_network_api('_disassociate_floating_ip', rpc_method='call', + address='fake_addr', interface='fake_interface', + host='fake_host') + + def test_lease_fixed_ip(self): + self._test_network_api('lease_fixed_ip', rpc_method='cast', + address='fake_addr', host='fake_host') + + def test_release_fixed_ip(self): + self._test_network_api('release_fixed_ip', rpc_method='cast', + address='fake_addr', host='fake_host') |
