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/virt/driver.py | 8 ++++++++ nova/virt/fake.py | 14 ++++++++++++++ nova/virt/libvirt/driver.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index ba0dfbafe..994f85ec1 100755 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -302,6 +302,14 @@ class ComputeDriver(object): """Detach the disk attached to the instance.""" raise NotImplementedError() + def attach_interface(self, instance, image_meta, network_info): + """Attach an interface to the instance.""" + raise NotImplementedError() + + def detach_interface(self, instance, network_info): + """Detach an interface from the instance.""" + raise NotImplementedError() + def migrate_disk_and_power_off(self, context, instance, dest, instance_type, network_info, block_device_info=None): diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 30a5fc758..5545dcf96 100755 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -102,6 +102,7 @@ class FakeDriver(driver.ComputeDriver): 'hypervisor_hostname': 'fake-mini', } self._mounts = {} + self._interfaces = {} def init_host(self, host): return @@ -222,6 +223,19 @@ class FakeDriver(driver.ComputeDriver): pass return True + def attach_interface(self, instance, image_meta, network_info): + for (network, mapping) in network_info: + if mapping['vif_uuid'] in self._interfaces: + raise exception.InterfaceAttachFailed('duplicate') + self._interfaces[mapping['vif_uuid']] = mapping + + def detach_interface(self, instance, network_info): + for (network, mapping) in network_info: + try: + del self._interfaces[mapping['vif_uuid']] + except KeyError: + raise exception.InterfaceDetachFailed('not attached') + def get_info(self, instance): if instance['name'] not in self.instances: raise exception.InstanceNotFound(instance_id=instance['name']) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 386fe836c..24de509e2 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -767,6 +767,50 @@ class LibvirtDriver(driver.ComputeDriver): connection_info, disk_dev) + @exception.wrap_exception() + def attach_interface(self, instance, image_meta, network_info): + virt_dom = self._lookup_by_name(instance['name']) + for (network, mapping) in network_info: + self.vif_driver.plug(instance, (network, mapping)) + self.firewall_driver.setup_basic_filtering(instance, + [(network, mapping)]) + cfg = self.vif_driver.get_config(instance, network, mapping, + image_meta) + try: + flags = libvirt.VIR_DOMAIN_AFFECT_CONFIG + state = LIBVIRT_POWER_STATE[virt_dom.info()[0]] + if state == power_state.RUNNING: + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE + virt_dom.attachDeviceFlags(cfg.to_xml(), flags) + except libvirt.libvirtError as ex: + LOG.error(_('attaching network adapter failed.'), + instance=instance) + self.vif_driver.unplug(instance, (network, mapping)) + raise exception.InterfaceAttachFailed(instance) + + @exception.wrap_exception() + def detach_interface(self, instance, network_info): + virt_dom = self._lookup_by_name(instance['name']) + for (network, mapping) in network_info: + cfg = self.vif_driver.get_config(instance, network, mapping, None) + try: + self.vif_driver.unplug(instance, (network, mapping)) + flags = libvirt.VIR_DOMAIN_AFFECT_CONFIG + state = LIBVIRT_POWER_STATE[virt_dom.info()[0]] + if state == power_state.RUNNING: + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE + virt_dom.detachDeviceFlags(cfg.to_xml(), flags) + except libvirt.libvirtError as ex: + error_code = ex.get_error_code() + if error_code == libvirt.VIR_ERR_NO_DOMAIN: + LOG.warn(_("During detach_interface, " + "instance disappeared."), + instance=instance) + else: + LOG.error(_('detaching network adapter failed.'), + instance=instance) + raise exception.InterfaceDetachFailed(instance) + def snapshot(self, context, instance, image_href, update_task_state): """Create snapshot from a running VM instance. -- cgit