VIF driver and scheduler for UCS plugin are broken since the flag
configuration mechanism in nova is changed. Fixing that and also
fixing some property names, along changes to how the quantum client
code is invoked.

Change-Id: I757cc149f08673ce24d35ee0bfffae8e5b1a4afc
This commit is contained in:
Sumit Naiksatam 2012-03-15 16:43:19 -07:00
parent 98419e1fa4
commit 8009f0fc27
3 changed files with 499 additions and 489 deletions

View File

@ -41,8 +41,9 @@ If you plan to just leverage the plugin framework, you do not need these.)
Palo adapters) installed.
* UCSM 2.0 (Capitola) Build 230 or above.
* OpenStack Diablo D3 or later (should have VIF-driver support)
* RHEL 6.1 (as of this writing, UCS only officially supports RHEL, but
it should be noted that Ubuntu support is planned in coming releases as well)
* OS supported:
** RHEL 6.1 or above
** Ubuntu 11.10 or above
** Package: python-configobj-4.6.0-3.el6.noarch (or newer)
** Package: python-routes-1.12.3-2.el6.noarch (or newer)
@ -50,7 +51,6 @@ If you are using a Nexus switch in your topology, you'll need the following
NX-OS version and packages to enable Nexus support:
* NX-OS 5.2.1 (Delhi) Build 69 or above.
* paramiko library - SSHv2 protocol library for python
** To install on RHEL 6.1, run: yum install python-paramiko
* ncclient v0.3.1 - Python library for NETCONF clients
** You need a version of ncclient modifed by Cisco Systems.
To get it, from your shell prompt do:
@ -61,25 +61,6 @@ NX-OS version and packages to enable Nexus support:
** For more information of ncclient, see:
http://schmizz.net/ncclient/
To verify the version of any package you have installed on your system,
run "rpm -qav | grep <package name>", where <package name> is the
package you want to query (for example: python-routes).
Note that you can get access to recent versions of the packages above
and other OpenStack software packages by adding a new repository to
your yum configuration. To do so, edit or create
/etc/yum.repos.d/openstack.repo and add the following:
[openstack-deps]
name=OpenStack Nova Compute Dependencies
baseurl=http://yum.griddynamics.net/yum/cactus/deps
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-OPENSTACK
Then run "yum install python-routes".
Module Structure:
-----------------
* quantum/plugins/cisco/ - Contains the L2-Network Plugin Framework
@ -93,15 +74,17 @@ Module Structure:
/nexus - Nexus-specific modules
/segmentation - Implementation of segmentation manager,
e.g. VLAN Manager
/services - Set of orchestration libraries to insert
In-path Networking Services
/tests - Tests specific to this plugin
/ucs - UCS-specific modules
Plugin Installation Instructions
----------------------------------
1. Make a backup copy of quantum/quantum/plugins.ini.
1. Make a backup copy of quantum/etc/plugins.ini.
2. Edit quantum/quantum/plugins.ini and edit the "provider" entry to point
2. Edit quantum/etc/plugins.ini and edit the "provider" entry to point
to the L2Network-plugin:
provider = quantum.plugins.cisco.l2network_plugin.L2Network
@ -130,18 +113,18 @@ provider = quantum.plugins.cisco.l2network_plugin.L2Network
4. To support the above configuration, you will need some Quantum modules. It's easiest
to copy the entire quantum directory from your quantum installation into:
/usr/lib/python2.6/site-packages/
/usr/lib/python2.7/site-packages/
This needs to be done for each nova compute node.
5. If you want to turn on support for Cisco Nexus switches:
5a. Uncomment the nexus_plugin property in
quantum/plugins/cisco/conf/plugins.ini to read:
etc/quantum/plugins/cisco/cisco_plugins.ini to read:
nexus_plugin=quantum.plugins.cisco.nexus.cisco_nexus_plugin.NexusPlugin
5b. Enter the relevant configuration in the
quantum/plugins/cisco/conf/nexus.ini file. Example:
etc/quantum/plugins/cisco/nexus.ini file. Example:
[SWITCH]
# Change the following to reflect the IP address of the Nexus switch.
@ -252,7 +235,7 @@ networks. That implies -
(2) Before each VM is instantiated, you should create Quantum ports on each of those
networks. These ports need to be created using the following rest call:
POST /v1.0/extensions/csco/tenants/{tenant_id}/multiport/
POST /1.0/extensions/csco/tenants/{tenant_id}/multiport/
with request body:
@ -269,7 +252,7 @@ and value should be used.
The corresponding CLI for this operation is as follows:
PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py create_multiport <tenant_id> <net_id1,net_id2,...>
PYTHONPATH=. python quantum/plugins/cisco/client/cli.py create_multiport <tenant_id> <net_id1,net_id2,...>
(Note that you should not be using the create port core API in the above case.)
@ -282,18 +265,18 @@ to switch between different CLI modules (it internally invokes the Quantum
CLI module for the core APIs to ensure consistency when using either). This
command line client can be invoked as follows:
PYTHONPATH=.:tools python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py
PYTHONPATH=.:tools python quantum/plugins/cisco/client/cli.py
1. Creating the network
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py create_net -H 10.10.2.6 demo net1
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py create_net -H 10.10.2.6 demo net1
Created a new Virtual Network with ID: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant demo
2. Listing the networks
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py list_nets -H 10.10.2.6 demo
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py list_nets -H 10.10.2.6 demo
Virtual Networks for Tenant demo
Network ID: 0e85e924-6ef6-40c1-9f7a-3520ac6888b3
Network ID: c4a2bea7-a528-4caf-b16e-80397cd1663a
@ -301,13 +284,13 @@ Virtual Networks for Tenant demo
3. Creating one port on each of the networks
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py create_multiport -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a,0e85e924-6ef6-40c1-9f7a-3520ac6888b3
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py create_multiport -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a,0e85e924-6ef6-40c1-9f7a-3520ac6888b3
Created ports: {u'ports': [{u'id': u'118ac473-294d-480e-8f6d-425acbbe81ae'}, {u'id': u'996e84b8-2ed3-40cf-be75-de17ff1214c4'}]}
4. List all the ports on a network
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py list_ports -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py list_ports -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a
Ports on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant: demo
Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
@ -315,7 +298,7 @@ for Tenant: demo
5. Show the details of a port
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py show_port -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py show_port -H 10.10.2.6 demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
Logical Port ID: 118ac473-294d-480e-8f6d-425acbbe81ae
administrative State: ACTIVE
interface: <none>
@ -335,7 +318,7 @@ for Tenant: demo
will be established only after the plug/attach operation is performed (as
described in the next step).
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py show_port demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py show_port demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
Logical Port ID: 118ac473-294d-480e-8f6d-425acbbe81ae
administrative State: ACTIVE
interface: b73e3585-d074-4379-8dde-931c0fc4db0e(detached)
@ -347,7 +330,7 @@ for Tenant: demo
Use the interface information obtained in step 6 to plug the interface into
the network.
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py plug_iface demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae b73e3585-d074-4379-8dde-931c0fc4db0e
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py plug_iface demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae b73e3585-d074-4379-8dde-931c0fc4db0e
Plugged interface b73e3585-d074-4379-8dde-931c0fc4db0e
into Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
@ -356,7 +339,7 @@ for Tenant: demo
8. Unplug an interface and port from the network
# PYTHONPATH=. python plugins/cisco-plugin/lib/quantum/plugins/cisco/client/cli.py unplug_iface demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
# PYTHONPATH=. python quantum/plugins/cisco/client/cli.py unplug_iface demo c4a2bea7-a528-4caf-b16e-80397cd1663a 118ac473-294d-480e-8f6d-425acbbe81ae
Unplugged interface from Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant: demo

View File

@ -17,33 +17,48 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
"""
Quantum Port Aware Scheduler Implementation
"""
from nova import exception as excp
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova.scheduler import driver
from nova.scheduler import chance
from quantum.client import Client
from quantum.common.wsgi import Serializer
LOG = logging.getLogger('quantum.plugins.cisco.nova.quantum_aware_scheduler')
LOG = logging.getLogger(__name__)
quantum_opts = [
cfg.StrOpt('quantum_connection_host',
default='127.0.0.1',
help='HOST for connecting to quantum'),
cfg.StrOpt('quantum_connection_port',
default='9696',
help='PORT for connecting to quantum'),
cfg.StrOpt('quantum_default_tenant_id',
default="default",
help='Default tenant id when creating quantum networks'),
]
FLAGS = flags.FLAGS
flags.DEFINE_string('quantum_host', "127.0.0.1",
'IP address of the quantum network service.')
flags.DEFINE_integer('quantum_port', 9696,
'Listening port for Quantum network service')
FLAGS.register_opts(quantum_opts)
HOST = FLAGS.quantum_host
PORT = FLAGS.quantum_port
HOST = FLAGS.quantum_connection_host
PORT = FLAGS.quantum_connection_port
USE_SSL = False
ACTION_PREFIX_EXT = '/v1.0'
ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \
'/extensions/csco/tenants/{tenant_id}'
VERSION = '1.0'
URI_PREFIX_CSCO = '/extensions/csco/tenants/{tenant_id}'
TENANT_ID = 'nova'
CSCO_EXT_NAME = 'Cisco Nova Tenant'
ACTION = '/schedule_host'
class QuantumPortAwareScheduler(driver.Scheduler):
class QuantumPortAwareScheduler(chance.ChanceScheduler):
"""
Quantum network service dependent scheduler
Obtains the hostname from Quantum using an extension API
@ -52,8 +67,9 @@ class QuantumPortAwareScheduler(driver.Scheduler):
# We have to send a dummy tenant name here since the client
# needs some tenant name, but the tenant name will not be used
# since the extensions URL does not require it
client = Client(HOST, PORT, USE_SSL, format='json',
action_prefix=ACTION_PREFIX_EXT, tenant="dummy")
LOG.debug("Initializing Cisco Quantum Port-aware Scheduler...")
client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
uri_prefix="", tenant="dummy", logger=LOG)
request_url = "/extensions"
data = client.do_request('GET', request_url)
LOG.debug("Obtained supported extensions from Quantum: %s" % data)
@ -63,17 +79,19 @@ class QuantumPortAwareScheduler(driver.Scheduler):
LOG.debug("Quantum plugin supports required \"%s\" extension"
"for the scheduler." % name)
return
LOG.error("Quantum plugin does not support required \"%s\" extension"
" for the scheduler. Scheduler will quit." % CSCO_EXT_NAME)
raise excp.ServiceUnavailable()
def schedule(self, context, topic, *args, **kwargs):
def _schedule(self, context, topic, request_spec, **kwargs):
"""Gets the host name from the Quantum service"""
instance_id = kwargs['instance_id']
LOG.debug("Cisco Quantum Port-aware Scheduler is scheduling...")
instance_id = request_spec['instance_properties']['uuid']
user_id = \
kwargs['request_spec']['instance_properties']['user_id']
request_spec['instance_properties']['user_id']
project_id = \
kwargs['request_spec']['instance_properties']['project_id']
request_spec['instance_properties']['project_id']
instance_data_dict = \
{'novatenant': \
@ -82,14 +100,15 @@ class QuantumPortAwareScheduler(driver.Scheduler):
{'user_id': user_id,
'project_id': project_id}}}
client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID,
action_prefix=ACTION_PREFIX_CSCO)
client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
uri_prefix=URI_PREFIX_CSCO, tenant=TENANT_ID,
logger=LOG)
request_url = "/novatenants/" + project_id + ACTION
data = client.do_request('PUT', request_url, body=instance_data_dict)
hostname = data["host_list"]["host_1"]
if not hostname:
raise driver.NoValidHost(_("Scheduler was unable to locate a host"
raise excp.NoValidHost(_("Scheduler was unable to locate a host"
" for this request. Is the appropriate"
" service running?"))

View File

@ -18,31 +18,37 @@
"""VIF drivers for interface type direct."""
from nova import exception as excp
from nova import flags
from nova import log as logging
from nova.network import linux_net
from nova.virt.libvirt import netutils
from nova import utils
from nova.openstack.common import cfg
from nova.virt.vif import VIFDriver
from quantum.client import Client
from quantum.common.wsgi import Serializer
LOG = logging.getLogger('quantum.plugins.cisco.nova.vifdirect')
LOG = logging.getLogger(__name__)
quantum_opts = [
cfg.StrOpt('quantum_connection_host',
default='127.0.0.1',
help='HOST for connecting to quantum'),
cfg.StrOpt('quantum_connection_port',
default='9696',
help='PORT for connecting to quantum'),
cfg.StrOpt('quantum_default_tenant_id',
default="default",
help='Default tenant id when creating quantum networks'),
]
FLAGS = flags.FLAGS
flags.DEFINE_string('quantum_host', "127.0.0.1",
'IP address of the quantum network service.')
flags.DEFINE_integer('quantum_port', 9696,
'Listening port for Quantum network service')
FLAGS.register_opts(quantum_opts)
HOST = FLAGS.quantum_host
PORT = FLAGS.quantum_port
HOST = FLAGS.quantum_connection_host
PORT = FLAGS.quantum_connection_port
USE_SSL = False
TENANT_ID = 'nova'
ACTION_PREFIX_EXT = '/v1.0'
ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \
'/extensions/csco/tenants/{tenant_id}'
VERSION = '1.0'
URI_PREFIX_CSCO = '/extensions/csco/tenants/{tenant_id}'
TENANT_ID = 'nova'
CSCO_EXT_NAME = 'Cisco Nova Tenant'
ASSOCIATE_ACTION = '/associate_port'
@ -55,8 +61,9 @@ class Libvirt802dot1QbhDriver(VIFDriver):
# We have to send a dummy tenant name here since the client
# needs some tenant name, but the tenant name will not be used
# since the extensions URL does not require it
client = Client(HOST, PORT, USE_SSL, format='json',
action_prefix=ACTION_PREFIX_EXT, tenant="dummy")
LOG.debug("Initializing Cisco Quantum VIF driver...")
client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
uri_prefix="", tenant="dummy", logger=LOG)
request_url = "/extensions"
data = client.do_request('GET', request_url)
LOG.debug("Obtained supported extensions from Quantum: %s" % data)
@ -73,8 +80,8 @@ class Libvirt802dot1QbhDriver(VIFDriver):
def _update_configurations(self, instance, network, mapping, action):
"""Gets the device name and the profile name from Quantum"""
instance_id = instance['id']
LOG.debug("Cisco Quantum VIF driver performing: %s" % (action))
instance_id = instance['uuid']
user_id = instance['user_id']
project_id = instance['project_id']
vif_id = mapping['vif_uuid']
@ -87,8 +94,9 @@ class Libvirt802dot1QbhDriver(VIFDriver):
'project_id': project_id,
'vif_id': vif_id}}}
client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID,
action_prefix=ACTION_PREFIX_CSCO)
client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
uri_prefix=URI_PREFIX_CSCO, tenant=TENANT_ID,
logger=LOG)
request_url = "/novatenants/" + project_id + action
data = client.do_request('PUT', request_url, body=instance_data_dict)