From a9add7d35e27b90f0c420d2b24b1af88b978fd7b Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Tue, 12 Feb 2013 15:45:24 -0500 Subject: Add support for network adapter hotplug. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch makes it possible to add/del instance interface other than booting time. Implement bp:network-adapter-hotplug Originally from change Ibee003a9ec6cc9b3fd275417caccd0c67f6c871f Co-authored-by: Yaguang Tang Co-authored-by: Édouard Thuleau Change-Id: I4f8f677af58afcb928379e5cf859388d1da45d51 --- nova/compute/api.py | 14 ++++++++++++++ nova/compute/manager.py | 35 ++++++++++++++++++++++++++++++++++- nova/compute/rpcapi.py | 17 +++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index f83243e8b..d7e85d035 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2284,6 +2284,20 @@ class API(base.Base): raise exception.VolumeUnattached(volume_id=volume_id) self._detach_volume(context, instance, volume_id) + @wrap_check_policy + def attach_interface(self, context, instance, network_id, port_id, + requested_ip): + """Use hotplug to add an network adapter to an instance.""" + return self.compute_rpcapi.attach_interface(context, + instance=instance, network_id=network_id, port_id=port_id, + requested_ip=requested_ip) + + @wrap_check_policy + def detach_interface(self, context, instance, port_id): + """Detach an network adapter from an instance.""" + self.compute_rpcapi.detach_interface(context, instance=instance, + port_id=port_id) + @wrap_check_policy def get_instance_metadata(self, context, instance): """Get all metadata associated with an instance.""" diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9d4fc0a46..92cf3cb00 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -315,7 +315,7 @@ class ComputeVirtAPI(virtapi.VirtAPI): class ComputeManager(manager.SchedulerDependentManager): """Manages the running instances from creation to destruction.""" - RPC_API_VERSION = '2.24' + RPC_API_VERSION = '2.25' def __init__(self, compute_driver=None, *args, **kwargs): """Load configuration options and connect to the hypervisor.""" @@ -2691,6 +2691,39 @@ class ComputeManager(manager.SchedulerDependentManager): except exception.NotFound: pass + def attach_interface(self, context, instance, network_id, port_id, + requested_ip=None): + """Use hotplug to add an network adapter to an instance.""" + network_info = self.network_api.allocate_port_for_instance( + context, instance, port_id, network_id, requested_ip, + self.conductor_api) + image_meta = _get_image_meta(context, instance['image_ref']) + legacy_net_info = self._legacy_nw_info(network_info) + for (network, mapping) in legacy_net_info: + if mapping['vif_uuid'] == port_id: + self.driver.attach_interface(instance, image_meta, + [(network, mapping)]) + return (network, mapping) + + def detach_interface(self, context, instance, port_id): + """Detach an network adapter from an instance.""" + network_info = self.network_api.get_instance_nw_info( + context.elevated(), instance, conductor_api=self.conductor_api) + legacy_nwinfo = self._legacy_nw_info(network_info) + condemned = None + for (network, mapping) in legacy_nwinfo: + if mapping['vif_uuid'] == port_id: + condemned = (network, mapping) + break + if condemned is None: + raise exception.PortNotFound(_("Port %(port_id)s is not " + "attached") % locals()) + + self.network_api.deallocate_port_for_instance(context, instance, + port_id, + self.conductor_api) + self.driver.detach_interface(instance, [condemned]) + def _get_compute_info(self, context, host): compute_node_ref = self.conductor_api.service_get_by_compute_host( context, host) diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index 525d1adc7..0b45b1f63 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -159,6 +159,7 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): rebuild_instance() 2.23 - Remove network_info from reboot_instance 2.24 - Added get_spice_console method + 2.25 - Add attach_interface() and detach_interface() ''' # @@ -200,6 +201,15 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): instance=instance_p, network_id=network_id), topic=_compute_topic(self.topic, ctxt, None, instance)) + def attach_interface(self, ctxt, instance, network_id, port_id, + requested_ip): + instance_p = jsonutils.to_primitive(instance) + return self.call(ctxt, self.make_msg('attach_interface', + instance=instance_p, network_id=network_id, + port_id=port_id, requested_ip=requested_ip), + topic=_compute_topic(self.topic, ctxt, None, instance), + version='2.25') + def attach_volume(self, ctxt, instance, volume_id, mountpoint): instance_p = jsonutils.to_primitive(instance) self.cast(ctxt, self.make_msg('attach_volume', @@ -243,6 +253,13 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): topic=_compute_topic(self.topic, ctxt, host, instance), version='2.7') + def detach_interface(self, ctxt, instance, port_id): + instance_p = jsonutils.to_primitive(instance) + self.cast(ctxt, self.make_msg('detach_interface', + instance=instance_p, port_id=port_id), + topic=_compute_topic(self.topic, ctxt, None, instance), + version='2.25') + def detach_volume(self, ctxt, instance, volume_id): instance_p = jsonutils.to_primitive(instance) self.cast(ctxt, self.make_msg('detach_volume', -- cgit