summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanwent <danwent@dan-xs3-cs>2011-07-20 09:26:01 -0700
committerdanwent <danwent@dan-xs3-cs>2011-07-20 09:26:01 -0700
commit8b244480bcd2ae9ac4769530d4444e983cc5d1aa (patch)
treea755e58263a6869d5c324c6230357853cd860a4f
parent43de3c5f6b5d65d981fbebf169c05d06faa6a09e (diff)
parent2bfa91575d36363b16c25c29623f7ac988e844bb (diff)
merge from lp:~midokura/nova/network-refactoring-l2
-rw-r--r--nova/compute/manager.py30
-rw-r--r--nova/network/manager.py4
-rw-r--r--nova/network/vmwareapi_net.py82
-rw-r--r--nova/virt/driver.py15
-rw-r--r--nova/virt/fake.py8
-rw-r--r--nova/virt/hyperv.py6
-rw-r--r--nova/virt/libvirt/connection.py27
-rw-r--r--nova/virt/libvirt/vif.py24
-rw-r--r--nova/virt/vif.py4
-rw-r--r--nova/virt/vmwareapi/vif.py93
-rw-r--r--nova/virt/vmwareapi/vmops.py29
-rw-r--r--nova/virt/vmwareapi_conn.py15
-rw-r--r--nova/virt/xenapi_conn.py6
13 files changed, 191 insertions, 152 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index eb52995be..cc5cf747c 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -299,7 +299,6 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info = self.network_api.allocate_for_instance(context,
instance, vpn=is_vpn)
LOG.debug(_("instance network_info: |%s|"), network_info)
- self.driver.setup_vif_network(context, instance['id'])
else:
# TODO(tr3buchet) not really sure how this should be handled.
# virt requires network_info to be passed in but stub_network
@@ -356,7 +355,7 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info = None
if not FLAGS.stub_network:
network_info = self.network_api.get_instance_nw_info(context,
- instance)
+ instance)
self.network_api.deallocate_for_instance(context, instance)
volumes = instance.get('volumes') or []
@@ -414,12 +413,12 @@ class ComputeManager(manager.SchedulerDependentManager):
self._update_state(context, instance_id, power_state.BUILDING)
network_info = self.network_api.get_instance_nw_info(context,
- instance_ref)
+ instance_ref)
self.driver.destroy(instance_ref, network_info)
image_ref = kwargs.get('image_ref')
instance_ref.image_ref = image_ref
instance_ref.injected_files = kwargs.get('injected_files', [])
- self.driver.spawn(instance_ref)
+ self.driver.spawn(instance_ref, network_info)
self._update_image_ref(context, instance_id, image_ref)
self._update_launched_at(context, instance_id)
@@ -452,7 +451,9 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_id,
power_state.NOSTATE,
'rebooting')
- self.driver.reboot(instance_ref)
+ network_info = self.network_api.get_instance_nw_info(context,
+ instance_ref)
+ self.driver.reboot(instance_ref, network_info)
self._update_state(context, instance_id)
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@@ -642,10 +643,11 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_id,
power_state.NOSTATE,
'rescuing')
- self.driver.setup_vif_network(context, instance_id)
+ network_info = self.network_api.get_instance_nw_info(context,
+ instance_ref)
_update_state = lambda result: self._update_state_callback(
self, context, instance_id, result)
- self.driver.rescue(instance_ref, _update_state)
+ self.driver.rescue(instance_ref, _update_state, network_info)
self._update_state(context, instance_id)
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@@ -661,7 +663,9 @@ class ComputeManager(manager.SchedulerDependentManager):
'unrescuing')
_update_state = lambda result: self._update_state_callback(
self, context, instance_id, result)
- self.driver.unrescue(instance_ref, _update_state)
+ network_info = self.network_api.get_instance_nw_info(context,
+ instance_ref)
+ self.driver.unrescue(instance_ref, _update_state, network_info)
self._update_state(context, instance_id)
@staticmethod
@@ -677,7 +681,7 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_ref = self.db.instance_get(context, instance_id)
network_info = self.network_api.get_instance_nw_info(context,
- instance_ref)
+ instance_ref)
self.driver.destroy(instance_ref, network_info)
usage_info = utils.usage_from_instance(instance_ref)
notifier.notify('compute.%s' % self.host,
@@ -698,7 +702,7 @@ class ComputeManager(manager.SchedulerDependentManager):
migration_ref = self.db.migration_get(context, migration_id)
network_info = self.network_api.get_instance_nw_info(context,
- instance_ref)
+ instance_ref)
self.driver.destroy(instance_ref, network_info)
topic = self.db.queue_get_for(context, FLAGS.compute_topic,
instance_ref['host'])
@@ -1203,16 +1207,18 @@ class ComputeManager(manager.SchedulerDependentManager):
#
# Retry operation is necessary because continuously request comes,
# concorrent request occurs to iptables, then it complains.
+ network_info = self.network_api.get_instance_nw_info(context,
+ instance_ref)
max_retry = FLAGS.live_migration_retry_count
for cnt in range(max_retry):
try:
- self.driver.setup_vif_network(context, instance_id)
+ self.driver.plug_vifs(instance_ref, network_info)
break
except exception.ProcessExecutionError:
if cnt == max_retry - 1:
raise
else:
- LOG.warn(_("setup_vif_network() failed %(cnt)d."
+ LOG.warn(_("plug_vifs() failed %(cnt)d."
"Retry up to %(max_retry)d for %(hostname)s.")
% locals())
time.sleep(1)
diff --git a/nova/network/manager.py b/nova/network/manager.py
index d5b8cf8dc..bf83bf4e6 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -444,7 +444,9 @@ class NetworkManager(manager.SchedulerDependentManager):
'id': network['id'],
'cidr': network['cidr'],
'cidr_v6': network['cidr_v6'],
- 'injected': network['injected']}
+ 'injected': network['injected'],
+ 'vlan': network['vlan'],
+ 'bridge_interface': network['bridge_interface']}
info = {
'label': network['label'],
'gateway': network['gateway'],
diff --git a/nova/network/vmwareapi_net.py b/nova/network/vmwareapi_net.py
deleted file mode 100644
index b32cf3303..000000000
--- a/nova/network/vmwareapi_net.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""Implements vlans for vmwareapi."""
-
-from nova import db
-from nova import exception
-from nova import flags
-from nova import log as logging
-from nova import utils
-from nova.virt.vmwareapi_conn import VMWareAPISession
-from nova.virt.vmwareapi import network_utils
-
-
-LOG = logging.getLogger("nova.network.vmwareapi_net")
-
-
-FLAGS = flags.FLAGS
-FLAGS['vlan_interface'].SetDefault('vmnic0')
-
-
-def ensure_vlan_bridge(vlan_num, bridge, bridge_interface, net_attrs=None):
- """Create a vlan and bridge unless they already exist."""
- # Open vmwareapi session
- host_ip = FLAGS.vmwareapi_host_ip
- host_username = FLAGS.vmwareapi_host_username
- host_password = FLAGS.vmwareapi_host_password
- if not host_ip or host_username is None or host_password is None:
- raise Exception(_('Must specify vmwareapi_host_ip, '
- 'vmwareapi_host_username '
- 'and vmwareapi_host_password to use '
- 'connection_type=vmwareapi'))
- session = VMWareAPISession(host_ip, host_username, host_password,
- FLAGS.vmwareapi_api_retry_count)
- vlan_interface = bridge_interface
- # Check if the vlan_interface physical network adapter exists on the host
- if not network_utils.check_if_vlan_interface_exists(session,
- vlan_interface):
- raise exception.NetworkAdapterNotFound(adapter=vlan_interface)
-
- # Get the vSwitch associated with the Physical Adapter
- vswitch_associated = network_utils.get_vswitch_for_vlan_interface(
- session, vlan_interface)
- if vswitch_associated is None:
- raise exception.SwicthNotFoundForNetworkAdapter(adapter=vlan_interface)
- # Check whether bridge already exists and retrieve the the ref of the
- # network whose name_label is "bridge"
- network_ref = network_utils.get_network_with_the_name(session, bridge)
- if network_ref is None:
- # Create a port group on the vSwitch associated with the vlan_interface
- # corresponding physical network adapter on the ESX host
- network_utils.create_port_group(session, bridge, vswitch_associated,
- vlan_num)
- else:
- # Get the vlan id and vswitch corresponding to the port group
- pg_vlanid, pg_vswitch = \
- network_utils.get_vlanid_and_vswitch_for_portgroup(session, bridge)
-
- # Check if the vswitch associated is proper
- if pg_vswitch != vswitch_associated:
- raise exception.InvalidVLANPortGroup(bridge=bridge,
- expected=vswitch_associated,
- actual=pg_vswitch)
-
- # Check if the vlan id is proper for the port group
- if pg_vlanid != vlan_num:
- raise exception.InvalidVLANTag(bridge=bridge, tag=vlan_num,
- pgroup=pg_vlanid)
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 178279d31..e8dcf138b 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -61,11 +61,11 @@ class ComputeDriver(object):
"""Return a list of InstanceInfo for all registered VMs"""
raise NotImplementedError()
- def spawn(self, instance, network_info=None, block_device_mapping=None):
+ def spawn(self, instance, network_info, block_device_mapping=None):
"""Launch a VM for the specified instance"""
raise NotImplementedError()
- def destroy(self, instance, cleanup=True):
+ def destroy(self, instance, network_info, cleanup=True):
"""Destroy (shutdown and delete) the specified instance.
The given parameter is an instance of nova.compute.service.Instance,
@@ -81,7 +81,7 @@ class ComputeDriver(object):
"""
raise NotImplementedError()
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot specified VM"""
raise NotImplementedError()
@@ -146,11 +146,11 @@ class ComputeDriver(object):
"""resume the specified instance"""
raise NotImplementedError()
- def rescue(self, instance, callback):
+ def rescue(self, instance, callback, network_info):
"""Rescue the specified instance"""
raise NotImplementedError()
- def unrescue(self, instance, callback):
+ def unrescue(self, instance, callback, network_info):
"""Unrescue the specified instance"""
raise NotImplementedError()
@@ -253,3 +253,8 @@ class ComputeDriver(object):
def set_host_enabled(self, host, enabled):
"""Sets the specified host's ability to accept new instances."""
raise NotImplementedError()
+
+ def plug_vifs(self, instance, network_info):
+ """Plugs in VIFs to networks."""
+ raise NotImplementedError()
+
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index ea0a59f21..c5e9d89e4 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -167,7 +167,7 @@ class FakeConnection(driver.ComputeDriver):
"""
pass
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""
Reboot the specified instance.
@@ -240,13 +240,13 @@ class FakeConnection(driver.ComputeDriver):
"""
pass
- def rescue(self, instance):
+ def rescue(self, instance, callback, network_info):
"""
Rescue the specified instance.
"""
pass
- def unrescue(self, instance):
+ def unrescue(self, instance, callback, network_info):
"""
Unrescue the specified instance.
"""
@@ -293,7 +293,7 @@ class FakeConnection(driver.ComputeDriver):
"""
pass
- def destroy(self, instance):
+ def destroy(self, instance, network_info):
key = instance.name
if key in self.instances:
del self.instances[key]
diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py
index 5c1dc772d..81c7dea58 100644
--- a/nova/virt/hyperv.py
+++ b/nova/virt/hyperv.py
@@ -139,7 +139,7 @@ class HyperVConnection(driver.ComputeDriver):
return instance_infos
- def spawn(self, instance, network_info=None, block_device_mapping=None):
+ def spawn(self, instance, network_info, block_device_mapping=None):
""" Create a new VM and start it."""
vm = self._lookup(instance.name)
if vm is not None:
@@ -368,14 +368,14 @@ class HyperVConnection(driver.ComputeDriver):
wmi_obj.Properties_.Item(prop).Value
return newinst
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot the specified instance."""
vm = self._lookup(instance.name)
if vm is None:
raise exception.InstanceNotFound(instance_id=instance.id)
self._set_vm_state(instance.name, 'Reboot')
- def destroy(self, instance):
+ def destroy(self, instance, network_info):
"""Destroy the VM. Also destroy the associated VHD disk files"""
LOG.debug(_("Got request to destroy vm %s"), instance.name)
vm = self._lookup(instance.name)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 1fa6e5c2f..3f6230e95 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -259,11 +259,10 @@ class LibvirtConnection(driver.ComputeDriver):
infos.append(info)
return infos
- def setup_vif_network(self, ctxt, instance_id):
- """Set up VIF networking on the host."""
- networks = db.network_get_all_by_instance(ctxt, instance_id)
- for network in networks:
- self.vif_driver.plug(network)
+ def plug_vifs(self, instance, network_info):
+ """Plugin VIFs into networks."""
+ for (network, mapping) in network_info:
+ self.vif_driver.plug(instance, network, mapping)
def destroy(self, instance, network_info, cleanup=True):
instance_name = instance['name']
@@ -478,7 +477,7 @@ class LibvirtConnection(driver.ComputeDriver):
shutil.rmtree(temp_dir)
@exception.wrap_exception()
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot a virtual machine, given an instance reference.
This method actually destroys and re-creates the domain to ensure the
@@ -493,7 +492,8 @@ class LibvirtConnection(driver.ComputeDriver):
# NOTE(itoumsn): self.shutdown() and wait instead of self.destroy() is
# better because we cannot ensure flushing dirty buffers
# in the guest OS. But, in case of KVM, shutdown() does not work...
- self.destroy(instance, False)
+ self.destroy(instance, network_info, cleanup=False)
+ self.plug_vifs(instance, network_info)
self.firewall_driver.setup_basic_filtering(instance)
self.firewall_driver.prepare_instance_filter(instance)
self._create_new_domain(xml)
@@ -543,7 +543,7 @@ class LibvirtConnection(driver.ComputeDriver):
dom.create()
@exception.wrap_exception()
- def rescue(self, instance):
+ def rescue(self, instance, callback, network_info):
"""Loads a VM using rescue images.
A rescue is normally performed when something goes wrong with the
@@ -552,7 +552,7 @@ class LibvirtConnection(driver.ComputeDriver):
data recovery.
"""
- self.destroy(instance, False)
+ self.destroy(instance, network_info, cleanup=False)
xml = self.to_xml(instance, rescue=True)
rescue_images = {'image_id': FLAGS.rescue_image_id,
@@ -581,14 +581,14 @@ class LibvirtConnection(driver.ComputeDriver):
return timer.start(interval=0.5, now=True)
@exception.wrap_exception()
- def unrescue(self, instance):
+ def unrescue(self, instance, network_info):
"""Reboot the VM which is being rescued back into primary images.
Because reboot destroys and re-creates instances, unresue should
simply call reboot.
"""
- self.reboot(instance)
+ self.reboot(instance, network_info)
@exception.wrap_exception()
def poll_rescued_instances(self, timeout):
@@ -597,7 +597,7 @@ class LibvirtConnection(driver.ComputeDriver):
# NOTE(ilyaalekseyev): Implementation like in multinics
# for xenapi(tr3buchet)
@exception.wrap_exception()
- def spawn(self, instance, network_info=None, block_device_mapping=None):
+ def spawn(self, instance, network_info, block_device_mapping=None):
xml = self.to_xml(instance, False, network_info=network_info,
block_device_mapping=block_device_mapping)
block_device_mapping = block_device_mapping or []
@@ -967,8 +967,7 @@ class LibvirtConnection(driver.ComputeDriver):
nics = []
for (network, mapping) in network_info:
- nics.append(self.vif_driver.get_configurations(instance, network,
- mapping))
+ nics.append(self.vif_driver.plug(instance, network, mapping))
# FIXME(vish): stick this in db
inst_type_id = instance['instance_type_id']
inst_type = instance_types.get_instance_type(inst_type_id)
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 2188251f0..1f8cebd08 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -31,19 +31,10 @@ flags.DEFINE_bool('allow_project_net_traffic',
flags.DEFINE_string('libvirt_ovs_integration_bridge', 'br-int',
'Name of Integration Bridge used by Open vSwitch')
-
-class LibvirtVIF(object):
- """VIF class for libvirt"""
-
- def get_configurations(self, instance, network, mapping):
- """Get a dictionary of VIF configuration for libvirt interfaces."""
- raise NotImplementedError()
-
-
-class LibvirtBridge(LibvirtVIF):
+class LibvirtBridge(object):
"""Linux bridge VIF for Libvirt."""
- def get_configurations(self, instance, network, mapping):
+ def get_configurations(self, network, mapping):
"""Get a dictionary of VIF configurations for bridge type."""
# Assume that the gateway also acts as the dhcp server.
dhcp_server = mapping['gateway']
@@ -82,10 +73,11 @@ class LibvirtBridge(LibvirtVIF):
class LibvirtBridgeDriver(VIFDriver, LibvirtBridge):
"""VIF driver for Linux bridge."""
- def plug(self, network):
+ def plug(self, instance, network, mapping):
"""Ensure that the bridge exists, and add VIF to it."""
linux_net.ensure_bridge(network['bridge'],
network['bridge_interface'])
+ return self.get_configurations(network, mapping)
def unplug(self, instance, network, mapping):
pass
@@ -94,10 +86,11 @@ class LibvirtBridgeDriver(VIFDriver, LibvirtBridge):
class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge):
"""VIF driver for Linux bridge with VLAN."""
- def plug(self, network):
+ def plug(self, instance, network, mapping):
"""Ensure that VLAN and bridge exist and add VIF to the bridge."""
linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'],
network['bridge_interface'])
+ return self.get_configurations(network, mapping)
def unplug(self, instance, network, mapping):
pass
@@ -106,7 +99,7 @@ class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge):
class LibvirtOpenVswitchDriver(VIFDriver):
"""VIF driver for Open vSwitch."""
- def get_configurations(self, instance, network, mapping):
+ def plug(self, instance, network, mapping):
vif_id = str(instance['id']) + "-" + str(network['id'])
dev = "tap-%s" % vif_id
utils.execute('sudo', 'ip', 'tuntap', 'add', dev, 'mode', 'tap')
@@ -124,9 +117,6 @@ class LibvirtOpenVswitchDriver(VIFDriver):
'mac_address': mapping['mac']}
return result
- def plug(self, network):
- pass
-
def unplug(self, instance, network, mapping):
vif_id = str(instance['id']) + "-" + str(network['id'])
dev = "tap-%s" % vif_id
diff --git a/nova/virt/vif.py b/nova/virt/vif.py
index bab1bdac9..b78689957 100644
--- a/nova/virt/vif.py
+++ b/nova/virt/vif.py
@@ -21,10 +21,10 @@
class VIFDriver(object):
"""Abstract class that defines generic interfaces for all VIF drivers."""
- def plug(self, network):
+ def plug(self, instance, network, mapping):
"""Plug VIF into network."""
raise NotImplementedError()
- def unplug(self, network):
+ def unplug(self, instance, network, mapping):
"""Unplug VIF from network."""
raise NotImplementedError()
diff --git a/nova/virt/vmwareapi/vif.py b/nova/virt/vmwareapi/vif.py
new file mode 100644
index 000000000..902699089
--- /dev/null
+++ b/nova/virt/vmwareapi/vif.py
@@ -0,0 +1,93 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""VIF drivers for VMWare."""
+
+from nova import db
+from nova import exception
+from nova import flags
+from nova import log as logging
+from nova import utils
+from nova.virt.vif import VIFDriver
+from nova.virt.vmwareapi_conn import VMWareAPISession
+from nova.virt.vmwareapi import network_utils
+
+
+LOG = logging.getLogger("nova.virt.vmwareapi.vif")
+
+FLAGS = flags.FLAGS
+
+
+class VMWareVlanBridgeDriver(VIFDriver):
+ """VIF driver for Linux VLAN bridge."""
+
+ def plug(self, instance, network, mapping):
+ """Create a vlan and bridge unless they already exist."""
+ vlan_num = network['vlan']
+ bridge = network['bridge']
+ bridge_interface = network['bridge_interface']
+
+ # Open vmwareapi session
+ host_ip = FLAGS.vmwareapi_host_ip
+ host_username = FLAGS.vmwareapi_host_username
+ host_password = FLAGS.vmwareapi_host_password
+ if not host_ip or host_username is None or host_password is None:
+ raise Exception(_('Must specify vmwareapi_host_ip, '
+ 'vmwareapi_host_username '
+ 'and vmwareapi_host_password to use '
+ 'connection_type=vmwareapi'))
+ session = VMWareAPISession(host_ip, host_username, host_password,
+ FLAGS.vmwareapi_api_retry_count)
+ vlan_interface = bridge_interface
+ # Check if the vlan_interface physical network adapter exists on the host
+ if not network_utils.check_if_vlan_interface_exists(session,
+ vlan_interface):
+ raise exception.NetworkAdapterNotFound(adapter=vlan_interface)
+
+ # Get the vSwitch associated with the Physical Adapter
+ vswitch_associated = network_utils.get_vswitch_for_vlan_interface(
+ session, vlan_interface)
+ if vswitch_associated is None:
+ raise exception.SwicthNotFoundForNetworkAdapter(adapter=vlan_interface)
+ # Check whether bridge already exists and retrieve the the ref of the
+ # network whose name_label is "bridge"
+ network_ref = network_utils.get_network_with_the_name(session, bridge)
+ if network_ref is None:
+ # Create a port group on the vSwitch associated with the vlan_interface
+ # corresponding physical network adapter on the ESX host
+ network_utils.create_port_group(session, bridge, vswitch_associated,
+ vlan_num)
+ else:
+ # Get the vlan id and vswitch corresponding to the port group
+ pg_vlanid, pg_vswitch = \
+ network_utils.get_vlanid_and_vswitch_for_portgroup(session, bridge)
+
+ # Check if the vswitch associated is proper
+ if pg_vswitch != vswitch_associated:
+ raise exception.InvalidVLANPortGroup(bridge=bridge,
+ expected=vswitch_associated,
+ actual=pg_vswitch)
+
+ # Check if the vlan id is proper for the port group
+ if pg_vlanid != vlan_num:
+ raise exception.InvalidVLANTag(bridge=bridge, tag=vlan_num,
+ pgroup=pg_vlanid)
+
+
+ def unplug(self, instance, network, mapping):
+ pass
+
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 94d9e6226..eded4391e 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -31,6 +31,7 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+from nova import utils
from nova.compute import power_state
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
@@ -38,6 +39,10 @@ from nova.virt.vmwareapi import vmware_images
from nova.virt.vmwareapi import network_utils
FLAGS = flags.FLAGS
+flags.DEFINE_string('vmware_vif_driver',
+ 'nova.virt.vmwareapi.vif.VMWareVlanBridgeDriver',
+ 'The VMWare VIF driver to configure the VIFs.')
+
LOG = logging.getLogger("nova.virt.vmwareapi.vmops")
VMWARE_POWER_STATES = {
@@ -52,6 +57,7 @@ class VMWareVMOps(object):
def __init__(self, session):
"""Initializer."""
self._session = session
+ self._vif_driver = utils.import_object(FLAGS.vmware_vif_driver)
def _wait_with_callback(self, instance_id, task, callback):
"""Waits for the task to finish and does a callback after."""
@@ -83,7 +89,7 @@ class VMWareVMOps(object):
LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
return lst_vm_names
- def spawn(self, instance):
+ def spawn(self, instance, network_info):
"""
Creates a VM instance.
@@ -117,6 +123,7 @@ class VMWareVMOps(object):
if network_ref is None:
raise exception.NetworkNotFoundForBridge(bridge=net_name)
+ self.plug_vifs(instance, network_info)
_check_if_network_bridge_exists()
def _get_datastore_ref():
@@ -472,11 +479,14 @@ class VMWareVMOps(object):
_clean_temp_data()
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot a VM instance."""
vm_ref = self._get_vm_ref_from_the_name(instance.name)
if vm_ref is None:
raise exception.InstanceNotFound(instance_id=instance.id)
+
+ self.plug_vifs(instance, network_info)
+
lst_properties = ["summary.guest.toolsStatus", "runtime.powerState",
"summary.guest.toolsRunningStatus"]
props = self._session._call_method(vim_util, "get_object_properties",
@@ -514,7 +524,7 @@ class VMWareVMOps(object):
self._session._wait_for_task(instance.id, reset_task)
LOG.debug(_("Did hard reboot of VM %s") % instance.name)
- def destroy(self, instance):
+ def destroy(self, instance, network_info):
"""
Destroy a VM instance. Steps followed are:
1. Power off the VM, if it is in poweredOn state.
@@ -560,6 +570,8 @@ class VMWareVMOps(object):
LOG.warn(_("In vmwareapi:vmops:destroy, got this exception"
" while un-registering the VM: %s") % str(excep))
+ self._unplug_vifs(instance, network_info)
+
# Delete the folder holding the VM related content on
# the datastore.
try:
@@ -784,3 +796,14 @@ class VMWareVMOps(object):
if vm.propSet[0].val == vm_name:
return vm.obj
return None
+
+ def plug_vifs(self, instance, network_info):
+ """Plug VIFs into networks."""
+ for (network, mapping) in network_info:
+ self._vif_driver.plug(instance, network, mapping)
+
+ def _unplug_vifs(self, instance, network_info):
+ """Unplug VIFs from networks."""
+ for (network, mapping) in network_info:
+ self._vif_driver.unplug(instance, network, mapping)
+
diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py
index d80e14931..2492c9951 100644
--- a/nova/virt/vmwareapi_conn.py
+++ b/nova/virt/vmwareapi_conn.py
@@ -124,21 +124,21 @@ class VMWareESXConnection(driver.ComputeDriver):
"""List VM instances."""
return self._vmops.list_instances()
- def spawn(self, instance, network_info=None, block_device_mapping=None):
+ def spawn(self, instance, network_info, block_device_mapping=None):
"""Create VM instance."""
- self._vmops.spawn(instance)
+ self._vmops.spawn(instance, network_info)
def snapshot(self, instance, name):
"""Create snapshot from a running VM instance."""
self._vmops.snapshot(instance, name)
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot VM instance."""
- self._vmops.reboot(instance)
+ self._vmops.reboot(instance, network_info)
- def destroy(self, instance):
+ def destroy(self, instance, network_info):
"""Destroy VM instance."""
- self._vmops.destroy(instance)
+ self._vmops.destroy(instance, network_info)
def pause(self, instance, callback):
"""Pause VM instance."""
@@ -194,6 +194,9 @@ class VMWareESXConnection(driver.ComputeDriver):
"""Sets the specified host's ability to accept new instances."""
pass
+ def plug_vifs(self, instance, network_info):
+ """Plugs in VIFs to networks."""
+ self._vmops.plug_vifs(instance, network_info)
class VMWareAPISession(object):
"""
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index ae39ecab4..10a532ea0 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -210,7 +210,7 @@ class XenAPIConnection(driver.ComputeDriver):
""" Create snapshot from a running VM instance """
self._vmops.snapshot(instance, image_id)
- def reboot(self, instance):
+ def reboot(self, instance, network_info):
"""Reboot VM instance"""
self._vmops.reboot(instance)
@@ -249,11 +249,11 @@ class XenAPIConnection(driver.ComputeDriver):
"""resume the specified instance"""
self._vmops.resume(instance, callback)
- def rescue(self, instance, callback):
+ def rescue(self, instance, callback, network_info):
"""Rescue the specified instance"""
self._vmops.rescue(instance, callback)
- def unrescue(self, instance, callback):
+ def unrescue(self, instance, callback, network_info):
"""Unrescue the specified instance"""
self._vmops.unrescue(instance, callback)