nova/nova/virt/xenapi/vif.py

164 lines
6.4 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
# Copyright (C) 2011 Nicira, Inc
# All Rights Reserved.
#
# 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 XenAPI."""
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova.virt.vif import VIFDriver
from nova.virt.xenapi.network_utils import NetworkHelper
from nova.virt.xenapi.vm_utils import VMHelper
xenapi_ovs_integration_bridge_opt = \
cfg.StrOpt('xenapi_ovs_integration_bridge',
default='xapi1',
help='Name of Integration Bridge used by Open vSwitch')
FLAGS = flags.FLAGS
FLAGS.add_option(xenapi_ovs_integration_bridge_opt)
LOG = logging.getLogger("nova.virt.xenapi.vif")
class XenVIFDriver(VIFDriver):
def __init__(self, xenapi_session):
self._session = xenapi_session
class XenAPIBridgeDriver(XenVIFDriver):
"""VIF Driver for XenAPI that uses XenAPI to create Networks."""
def plug(self, instance, network, mapping, vm_ref=None, device=None):
if not vm_ref:
vm_ref = VMHelper.lookup(self._session, instance.name)
if not device:
device = 0
if mapping.get('should_create_vlan'):
network_ref = self._ensure_vlan_bridge(network)
else:
network_ref = NetworkHelper.find_network_with_bridge(
self._session, network['bridge'])
vif_rec = {}
vif_rec['device'] = str(device)
vif_rec['network'] = network_ref
vif_rec['VM'] = vm_ref
vif_rec['MAC'] = mapping['mac']
vif_rec['MTU'] = '1500'
vif_rec['other_config'] = {}
if "rxtx_cap" in mapping:
vif_rec['qos_algorithm_type'] = "ratelimit"
vif_rec['qos_algorithm_params'] = \
{"kbps": str(mapping['rxtx_cap'] * 1024)}
else:
vif_rec['qos_algorithm_type'] = ""
vif_rec['qos_algorithm_params'] = {}
return vif_rec
def _ensure_vlan_bridge(self, network):
"""Ensure that a VLAN bridge exists"""
vlan_num = network['vlan']
bridge = network['bridge']
bridge_interface = FLAGS.vlan_interface or network['bridge_interface']
# Check whether bridge already exists
# Retrieve network whose name_label is "bridge"
network_ref = NetworkHelper.find_network_with_name_label(
self._session, bridge)
if network_ref is None:
# If bridge does not exists
# 1 - create network
description = 'network for nova bridge %s' % bridge
network_rec = {'name_label': bridge,
'name_description': description,
'other_config': {}}
network_ref = self._session.call_xenapi('network.create',
network_rec)
# 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
# quotes inside single quotes as xapi filter only support
# tokens in double quotes
expr = 'field "device" = "%s" and \
field "VLAN" = "-1"' % bridge_interface
pifs = self._session.call_xenapi('PIF.get_all_records_where',
expr)
pif_ref = None
# Multiple PIF are ok: we are dealing with a pool
if len(pifs) == 0:
raise Exception(_('Found no PIF for device %s') % \
bridge_interface)
for pif_ref in pifs.keys():
self._session.call_xenapi('VLAN.create',
pif_ref,
str(vlan_num),
network_ref)
else:
# Check VLAN tag is appropriate
network_rec = self._session.call_xenapi('network.get_record',
network_ref)
# Retrieve PIFs from network
for pif_ref in network_rec['PIFs']:
# Retrieve VLAN from PIF
pif_rec = self._session.call_xenapi('PIF.get_record',
pif_ref)
pif_vlan = int(pif_rec['VLAN'])
# Raise an exception if VLAN != vlan_num
if pif_vlan != vlan_num:
raise Exception(_(
"PIF %(pif_rec['uuid'])s for network "
"%(bridge)s has VLAN id %(pif_vlan)d. "
"Expected %(vlan_num)d") % locals())
return network_ref
def unplug(self, instance, network, mapping):
pass
class XenAPIOpenVswitchDriver(XenVIFDriver):
"""VIF driver for Open vSwitch with XenAPI."""
def plug(self, instance, network, mapping, vm_ref=None, device=None):
if not vm_ref:
vm_ref = VMHelper.lookup(self._session, instance.name)
if not device:
device = 0
# with OVS model, always plug into an OVS integration bridge
# that is already created
network_ref = NetworkHelper.find_network_with_bridge(self._session,
FLAGS.xenapi_ovs_integration_bridge)
vif_rec = {}
vif_rec['device'] = str(device)
vif_rec['network'] = network_ref
vif_rec['VM'] = vm_ref
vif_rec['MAC'] = mapping['mac']
vif_rec['MTU'] = '1500'
vif_rec['qos_algorithm_type'] = ""
vif_rec['qos_algorithm_params'] = {}
# OVS on the hypervisor monitors this key and uses it to
# set the iface-id attribute
vif_rec['other_config'] = \
{"nicira-iface-id": mapping['vif_uuid']}
return vif_rec
def unplug(self, instance, network, mapping):
pass