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. Palo adapters) installed.
* UCSM 2.0 (Capitola) Build 230 or above. * UCSM 2.0 (Capitola) Build 230 or above.
* OpenStack Diablo D3 or later (should have VIF-driver support) * OpenStack Diablo D3 or later (should have VIF-driver support)
* RHEL 6.1 (as of this writing, UCS only officially supports RHEL, but * OS supported:
it should be noted that Ubuntu support is planned in coming releases as well) ** RHEL 6.1 or above
** Ubuntu 11.10 or above
** Package: python-configobj-4.6.0-3.el6.noarch (or newer) ** Package: python-configobj-4.6.0-3.el6.noarch (or newer)
** Package: python-routes-1.12.3-2.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 version and packages to enable Nexus support:
* NX-OS 5.2.1 (Delhi) Build 69 or above. * NX-OS 5.2.1 (Delhi) Build 69 or above.
* paramiko library - SSHv2 protocol library for python * 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 * ncclient v0.3.1 - Python library for NETCONF clients
** You need a version of ncclient modifed by Cisco Systems. ** You need a version of ncclient modifed by Cisco Systems.
To get it, from your shell prompt do: 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: ** For more information of ncclient, see:
http://schmizz.net/ncclient/ 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: Module Structure:
----------------- -----------------
* quantum/plugins/cisco/ - Contains the L2-Network Plugin Framework * quantum/plugins/cisco/ - Contains the L2-Network Plugin Framework
@ -93,15 +74,17 @@ Module Structure:
/nexus - Nexus-specific modules /nexus - Nexus-specific modules
/segmentation - Implementation of segmentation manager, /segmentation - Implementation of segmentation manager,
e.g. VLAN Manager e.g. VLAN Manager
/services - Set of orchestration libraries to insert
In-path Networking Services
/tests - Tests specific to this plugin /tests - Tests specific to this plugin
/ucs - UCS-specific modules /ucs - UCS-specific modules
Plugin Installation Instructions 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: to the L2Network-plugin:
provider = quantum.plugins.cisco.l2network_plugin.L2Network 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 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: 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. This needs to be done for each nova compute node.
5. If you want to turn on support for Cisco Nexus switches: 5. If you want to turn on support for Cisco Nexus switches:
5a. Uncomment the nexus_plugin property in 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 nexus_plugin=quantum.plugins.cisco.nexus.cisco_nexus_plugin.NexusPlugin
5b. Enter the relevant configuration in the 5b. Enter the relevant configuration in the
quantum/plugins/cisco/conf/nexus.ini file. Example: etc/quantum/plugins/cisco/nexus.ini file. Example:
[SWITCH] [SWITCH]
# Change the following to reflect the IP address of the Nexus 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 (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: 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: with request body:
@ -269,7 +252,7 @@ and value should be used.
The corresponding CLI for this operation is as follows: 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.) (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 CLI module for the core APIs to ensure consistency when using either). This
command line client can be invoked as follows: 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 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 Created a new Virtual Network with ID: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant demo for Tenant demo
2. Listing the networks 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 Virtual Networks for Tenant demo
Network ID: 0e85e924-6ef6-40c1-9f7a-3520ac6888b3 Network ID: 0e85e924-6ef6-40c1-9f7a-3520ac6888b3
Network ID: c4a2bea7-a528-4caf-b16e-80397cd1663a 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 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'}]} 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 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 Ports on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant: demo for Tenant: demo
Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
@ -315,7 +298,7 @@ for Tenant: demo
5. Show the details of a port 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 Logical Port ID: 118ac473-294d-480e-8f6d-425acbbe81ae
administrative State: ACTIVE administrative State: ACTIVE
interface: <none> interface: <none>
@ -335,7 +318,7 @@ for Tenant: demo
will be established only after the plug/attach operation is performed (as will be established only after the plug/attach operation is performed (as
described in the next step). 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 Logical Port ID: 118ac473-294d-480e-8f6d-425acbbe81ae
administrative State: ACTIVE administrative State: ACTIVE
interface: b73e3585-d074-4379-8dde-931c0fc4db0e(detached) 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 Use the interface information obtained in step 6 to plug the interface into
the network. 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 Plugged interface b73e3585-d074-4379-8dde-931c0fc4db0e
into Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae into Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
@ -356,7 +339,7 @@ for Tenant: demo
8. Unplug an interface and port from the network 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 Unplugged interface from Logical Port: 118ac473-294d-480e-8f6d-425acbbe81ae
on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a on Virtual Network: c4a2bea7-a528-4caf-b16e-80397cd1663a
for Tenant: demo for Tenant: demo

View File

@ -17,33 +17,48 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc. # @author: Sumit Naiksatam, Cisco Systems, Inc.
# #
"""
Quantum Port Aware Scheduler Implementation
"""
from nova import exception as excp from nova import exception as excp
from nova import flags from nova import flags
from nova import log as logging from nova import log as logging
from nova.openstack.common import cfg
from nova.scheduler import driver from nova.scheduler import driver
from nova.scheduler import chance
from quantum.client import Client 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 = flags.FLAGS
flags.DEFINE_string('quantum_host', "127.0.0.1", FLAGS.register_opts(quantum_opts)
'IP address of the quantum network service.')
flags.DEFINE_integer('quantum_port', 9696,
'Listening port for Quantum network service')
HOST = FLAGS.quantum_host HOST = FLAGS.quantum_connection_host
PORT = FLAGS.quantum_port PORT = FLAGS.quantum_connection_port
USE_SSL = False USE_SSL = False
ACTION_PREFIX_EXT = '/v1.0' VERSION = '1.0'
ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \ URI_PREFIX_CSCO = '/extensions/csco/tenants/{tenant_id}'
'/extensions/csco/tenants/{tenant_id}'
TENANT_ID = 'nova' TENANT_ID = 'nova'
CSCO_EXT_NAME = 'Cisco Nova Tenant' CSCO_EXT_NAME = 'Cisco Nova Tenant'
ACTION = '/schedule_host' ACTION = '/schedule_host'
class QuantumPortAwareScheduler(driver.Scheduler): class QuantumPortAwareScheduler(chance.ChanceScheduler):
""" """
Quantum network service dependent scheduler Quantum network service dependent scheduler
Obtains the hostname from Quantum using an extension API 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 # We have to send a dummy tenant name here since the client
# needs some tenant name, but the tenant name will not be used # needs some tenant name, but the tenant name will not be used
# since the extensions URL does not require it # since the extensions URL does not require it
client = Client(HOST, PORT, USE_SSL, format='json', LOG.debug("Initializing Cisco Quantum Port-aware Scheduler...")
action_prefix=ACTION_PREFIX_EXT, tenant="dummy") client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
uri_prefix="", tenant="dummy", logger=LOG)
request_url = "/extensions" request_url = "/extensions"
data = client.do_request('GET', request_url) data = client.do_request('GET', request_url)
LOG.debug("Obtained supported extensions from Quantum: %s" % data) 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" LOG.debug("Quantum plugin supports required \"%s\" extension"
"for the scheduler." % name) "for the scheduler." % name)
return return
LOG.error("Quantum plugin does not support required \"%s\" extension" LOG.error("Quantum plugin does not support required \"%s\" extension"
" for the scheduler. Scheduler will quit." % CSCO_EXT_NAME) " for the scheduler. Scheduler will quit." % CSCO_EXT_NAME)
raise excp.ServiceUnavailable() 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""" """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 = \ user_id = \
kwargs['request_spec']['instance_properties']['user_id'] request_spec['instance_properties']['user_id']
project_id = \ project_id = \
kwargs['request_spec']['instance_properties']['project_id'] request_spec['instance_properties']['project_id']
instance_data_dict = \ instance_data_dict = \
{'novatenant': \ {'novatenant': \
@ -82,14 +100,15 @@ class QuantumPortAwareScheduler(driver.Scheduler):
{'user_id': user_id, {'user_id': user_id,
'project_id': project_id}}} 'project_id': project_id}}}
client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID, client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION,
action_prefix=ACTION_PREFIX_CSCO) uri_prefix=URI_PREFIX_CSCO, tenant=TENANT_ID,
logger=LOG)
request_url = "/novatenants/" + project_id + ACTION request_url = "/novatenants/" + project_id + ACTION
data = client.do_request('PUT', request_url, body=instance_data_dict) data = client.do_request('PUT', request_url, body=instance_data_dict)
hostname = data["host_list"]["host_1"] hostname = data["host_list"]["host_1"]
if not hostname: 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" " for this request. Is the appropriate"
" service running?")) " service running?"))

View File

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