From ec9c06cf84fb9566035fc6f4cac5f2847de1c6d4 Mon Sep 17 00:00:00 2001 From: Sumit Naiksatam Date: Wed, 24 Aug 2011 03:15:54 -0700 Subject: [PATCH] Changes to incorporate reviwer's comments. Also changed client.py to handle extension URLs. --- quantum/client.py | 7 ++- quantum/plugins/cisco/nova/__init__.py | 18 ------- .../cisco/nova/quantum_aware_scheduler.py | 54 +++++++++++++------ quantum/plugins/cisco/nova/vifdirect.py | 54 ++++++++++++++----- 4 files changed, 83 insertions(+), 50 deletions(-) diff --git a/quantum/client.py b/quantum/client.py index 2e55dfb3ecd..74ac1958ba0 100644 --- a/quantum/client.py +++ b/quantum/client.py @@ -63,8 +63,6 @@ class Client(object): """A base client class - derived from Glance.BaseClient""" - action_prefix = '/v0.1/tenants/{tenant_id}' - # Action query strings networks_path = "/networks" network_path = "/networks/%s" @@ -74,7 +72,7 @@ class Client(object): def __init__(self, host="127.0.0.1", port=9696, use_ssl=False, tenant=None, format="xml", testingStub=None, key_file=None, cert_file=None, - logger=None): + logger=None, action_prefix="/v0.1/tenants/{tenant_id}"): """ Creates a new client to some service. @@ -97,6 +95,7 @@ class Client(object): self.key_file = key_file self.cert_file = cert_file self.logger = logger + self.action_prefix = action_prefix def get_connection_type(self): """ @@ -130,7 +129,7 @@ class Client(object): # Add format and tenant_id action += ".%s" % self.format - action = Client.action_prefix + action + action = self.action_prefix + action action = action.replace('{tenant_id}', self.tenant) if type(params) is dict: diff --git a/quantum/plugins/cisco/nova/__init__.py b/quantum/plugins/cisco/nova/__init__.py index db695fb0afb..e69de29bb2d 100644 --- a/quantum/plugins/cisco/nova/__init__.py +++ b/quantum/plugins/cisco/nova/__init__.py @@ -1,18 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# -# Copyright 2011 Cisco Systems, 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. -# -# @author: Sumit Naiksatam, Cisco Systems, Inc. -# diff --git a/quantum/plugins/cisco/nova/quantum_aware_scheduler.py b/quantum/plugins/cisco/nova/quantum_aware_scheduler.py index b5f21ac8205..4d30ccd4a1a 100644 --- a/quantum/plugins/cisco/nova/quantum_aware_scheduler.py +++ b/quantum/plugins/cisco/nova/quantum_aware_scheduler.py @@ -1,4 +1,3 @@ -""" # vim: tabstop=4 shiftwidth=4 softtabstop=4 # # Copyright 2011 Cisco Systems, Inc. All rights reserved. @@ -17,15 +16,15 @@ # # @author: Sumit Naiksatam, Cisco Systems, Inc. # -""" +from nova import exception as excp from nova import flags from nova import log as logging from nova.scheduler import driver from quantum.client import Client from quantum.common.wsgi import Serializer -LOG = logging.getLogger('nova.scheduler.quantum_aware_scheduler') +LOG = logging.getLogger('quantum.plugins.cisco.nova.quantum_aware_scheduler') FLAGS = flags.FLAGS flags.DEFINE_string('quantum_host', "127.0.0.1", @@ -36,7 +35,11 @@ flags.DEFINE_integer('quantum_port', 9696, HOST = FLAGS.quantum_host PORT = FLAGS.quantum_port USE_SSL = False +ACTION_PREFIX_EXT = '/v0.1' +ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \ + '/extensions/csco/tenants/{tenant_id}' TENANT_ID = 'nova' +CSCO_EXT_NAME = 'Cisco Nova Tenant' class QuantumScheduler(driver.Scheduler): @@ -44,26 +47,47 @@ class QuantumScheduler(driver.Scheduler): Quantum network service dependent scheduler Obtains the hostname from Quantum using an extension API """ + def __init__(self): + # 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") + request_url = "/extensions" + data = client.do_request('GET', request_url) + LOG.debug("Obtained supported extensions from Quantum: %s" % data) + for ext in data['extensions']: + name = ext['name'] + if name == CSCO_EXT_NAME: + 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, *args, **kwargs): """Gets the host name from the Quantum service""" - instance_id = _kwargs['instance_id'] + instance_id = kwargs['instance_id'] user_id = \ - _kwargs['request_spec']['instance_properties']['user_id'] + kwargs['request_spec']['instance_properties']['user_id'] project_id = \ - _kwargs['request_spec']['instance_properties']['project_id'] + kwargs['request_spec']['instance_properties']['project_id'] instance_data_dict = \ {'novatenant': \ - {'instance-id': instance_id, - 'instance-desc': \ - {'user_id': user_id, 'project_id': project_id}}} - client = Client(HOST, PORT, USE_SSL, format='json') - request_url = "/novatenants/" + project_id + "/get_host" - data = client.do_request(TENANT_ID, 'PUT', request_url, - body=instance_data_dict) - hostname = data["host_list"]["host_1"] + {'instance_id': instance_id, + 'instance_desc': \ + {'user_id': user_id, + 'project_id': project_id + }}} + client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID, + action_prefix=ACTION_PREFIX_CSCO) + request_url = "/novatenants/" + project_id + "/get_host" + 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" " for this request. Is the appropriate" diff --git a/quantum/plugins/cisco/nova/vifdirect.py b/quantum/plugins/cisco/nova/vifdirect.py index 1565bfe57e4..6581c32f3cd 100644 --- a/quantum/plugins/cisco/nova/vifdirect.py +++ b/quantum/plugins/cisco/nova/vifdirect.py @@ -1,4 +1,3 @@ -""" # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 Cisco Systems, Inc. All rights reserved. # @@ -16,19 +15,20 @@ # # @author: Sumit Naiksatam, Cisco Systems, Inc. # -""" + """VIF drivers for interface type direct.""" +from nova import exception as excp from nova import flags from nova import log as logging -from nova import utils from nova.network import linux_net from nova.virt.libvirt import netutils +from nova import utils from nova.virt.vif import VIFDriver from quantum.client import Client from quantum.common.wsgi import Serializer -LOG = logging.getLogger('nova.virt.libvirt.vif') +LOG = logging.getLogger('quantum.plugins.cisco.nova.vifdirect') FLAGS = flags.FLAGS flags.DEFINE_string('quantum_host', "127.0.0.1", @@ -40,10 +40,34 @@ HOST = FLAGS.quantum_host PORT = FLAGS.quantum_port USE_SSL = False TENANT_ID = 'nova' +ACTION_PREFIX_EXT = '/v0.1' +ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \ + '/extensions/csco/tenants/{tenant_id}' +TENANT_ID = 'nova' +CSCO_EXT_NAME = 'Cisco Nova Tenant' class Libvirt802dot1QbhDriver(VIFDriver): """VIF driver for Linux bridge.""" + def __init__(self): + # 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") + request_url = "/extensions" + data = client.do_request('GET', request_url) + LOG.debug("Obtained supported extensions from Quantum: %s" % data) + for ext in data['extensions']: + name = ext['name'] + if name == CSCO_EXT_NAME: + LOG.debug("Quantum plugin supports required \"%s\" extension" + "for the VIF driver." % name) + return + LOG.error("Quantum plugin does not support required \"%s\" extension" + " for the VIF driver. nova-compute will quit." \ + % CSCO_EXT_NAME) + raise excp.ServiceUnavailable() def _get_configurations(self, instance, network, mapping): """Gets the device name and the profile name from Quantum""" @@ -51,22 +75,26 @@ class Libvirt802dot1QbhDriver(VIFDriver): instance_id = instance['id'] user_id = instance['user_id'] project_id = instance['project_id'] + vif_id = mapping['vif_uuid'] instance_data_dict = \ {'novatenant': \ - {'instance-id': instance_id, - 'instance-desc': \ - {'user_id': user_id, 'project_id': project_id}}} + {'instance_id': instance_id, + 'instance_desc': \ + {'user_id': user_id, + 'project_id': project_id, + 'vif_id': vif_id + }}} - client = Client(HOST, PORT, USE_SSL, format='json') + client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID, + action_prefix=ACTION_PREFIX_CSCO) request_url = "/novatenants/" + project_id + "/get_instance_port" - data = client.do_request(TENANT_ID, 'PUT', request_url, - body=instance_data_dict) + data = client.do_request('PUT', request_url, body=instance_data_dict) + device = data['vif_desc']['device'] portprofile = data['vif_desc']['portprofile'] - - LOG.debug(_("Quantum returned device: %s\n") % device) - LOG.debug(_("Quantum returned portprofile: %s\n") % portprofile) + LOG.debug(_("Quantum provided the device: %s") % device) + LOG.debug(_("Quantum provided the portprofile: %s") % portprofile) mac_id = mapping['mac'].replace(':', '') result = {