From e471cea178033523070301f9c890b19fbe63ab33 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 5 Jun 2014 22:04:15 -0400 Subject: [PATCH] Add support for network labels This patch adds the ability to specify a net-label instead of using a net-id (network UUID). Rather than use network UUID's in our nodepool.yaml config files it would be nice to use the more meaningful network labels instead. This should make the config file more readable across the various cloud providers and matches how we use image names (instead of image UUIDs) as well. The current implementation relies on the os-tenant-networks extension in Nova to provide the network label lookup. Given that nodepool is currently focused around using novaclient this made the most sense. We may at some point in the future want to use the Neutron API directly for this information or perhaps use a combination of both approaches to accommodate a variety of provider API deployment choices. Tested locally on my TripleO overcloud using two Neutron networks. Change-Id: I9bdd35adf2d85659cf1b992ccd2fcf98fb124528 --- doc/source/configuration.rst | 10 ++++++++++ nodepool/nodepool.py | 4 ++-- nodepool/provider_manager.py | 31 +++++++++++++++++++++++++++++-- tools/fake.yaml | 1 + 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst index 06263923e..710ece833 100644 --- a/doc/source/configuration.rst +++ b/doc/source/configuration.rst @@ -153,6 +153,9 @@ same name. Example:: boot-timeout: 120 launch-timeout: 900 template-hostname: '{image.name}-{timestamp}.template.openstack.org' + networks: + - net-id: 'some-uuid' + - net-label: 'some-network-name' images: - name: precise base-image: 'Precise' @@ -199,6 +202,13 @@ Both `boot-timeout` and `launch-timeout` keys are optional. The `boot-timeout` key defaults to 60 seconds and `launch-timeout` key will default to 3600 seconds. +The optional `networks` section may be used to specify custom +Neutron networks that get attached to each node. You can specify +Neutron networks using either the `net-id` or `net-label`. If +only the `net-label` is specified the network UUID is automatically +queried via the Nova os-tenant-networks API extension (this requires +that the cloud provider has deployed this extension). + The `availability-zones` key is optional. Without it nodepool will rely on nova to schedule an availability zone. If it is provided the value should be a list of availability zone names. Nodepool will select one diff --git a/nodepool/nodepool.py b/nodepool/nodepool.py index 1c6b32b5b..b7dd5b5ce 100644 --- a/nodepool/nodepool.py +++ b/nodepool/nodepool.py @@ -1014,7 +1014,7 @@ class NodePool(threading.Thread): p.boot_timeout = provider.get('boot-timeout', 60) p.launch_timeout = provider.get('launch-timeout', 3600) p.use_neutron = bool(provider.get('networks', ())) - p.nics = provider.get('networks') + p.networks = provider.get('networks') p.azs = provider.get('availability-zones') p.template_hostname = provider.get( 'template-hostname', @@ -1084,7 +1084,7 @@ class NodePool(threading.Thread): new_pm.boot_timeout != old_pm.provider.boot_timeout or new_pm.launch_timeout != old_pm.provider.launch_timeout or new_pm.use_neutron != old_pm.provider.use_neutron or - new_pm.nics != old_pm.provider.nics or + new_pm.networks != old_pm.provider.networks or new_pm.azs != old_pm.provider.azs): return False new_images = new_pm.images diff --git a/nodepool/provider_manager.py b/nodepool/provider_manager.py index 2f82f357b..76eff77d6 100644 --- a/nodepool/provider_manager.py +++ b/nodepool/provider_manager.py @@ -20,6 +20,8 @@ import logging import paramiko import novaclient import novaclient.client +import novaclient.extension +import novaclient.v1_1.contrib.tenant_networks import threading import time @@ -219,6 +221,12 @@ class DeleteImageTask(Task): client.images.delete(**self.args) +class FindNetworkTask(Task): + def main(self, client): + network = client.tenant_networks.find(**self.args) + return dict(id=str(network.id)) + + class ProviderManager(TaskManager): log = logging.getLogger("nodepool.ProviderManager") @@ -228,6 +236,7 @@ class ProviderManager(TaskManager): self.provider = provider self._client = self._getClient() self._images = {} + self._networks = {} self._cloud_metadata_read = False self.__flavors = {} self.__extensions = {} @@ -253,9 +262,11 @@ class ProviderManager(TaskManager): self._cloud_metadata_read = True def _getClient(self): + tenant_networks = novaclient.extension.Extension( + 'tenant_networks', novaclient.v1_1.contrib.tenant_networks) args = ['1.1', self.provider.username, self.provider.password, self.provider.project_id, self.provider.auth_url] - kwargs = {} + kwargs = {'extensions': [tenant_networks]} if self.provider.service_type: kwargs['service_type'] = self.provider.service_type if self.provider.service_name: @@ -295,6 +306,13 @@ class ProviderManager(TaskManager): self._images[name] = image return image + def findNetwork(self, label): + if label in self._networks: + return self._networks[label] + network = self.submitTask(FindNetworkTask(label=label)) + self._networks[label] = network + return network + def deleteImage(self, name): if name in self._images: del self._images[name] @@ -323,7 +341,16 @@ class ProviderManager(TaskManager): if az: create_args['availability_zone'] = az if self.provider.use_neutron: - create_args['nics'] = self.provider.nics + nics = [] + for network in self.provider.networks: + if 'net-id' in network: + nics.append({'net-id': network['net-id']}) + elif 'net-label' in network: + net_id = self.findNetwork(network['net-label'])['id'] + nics.append({'net-id': net_id}) + else: + raise Exception("Invalid 'networks' configuration.") + create_args['nics'] = nics return self.submitTask(CreateServerTask(**create_args)) diff --git a/tools/fake.yaml b/tools/fake.yaml index 318537c3a..96cf221a6 100644 --- a/tools/fake.yaml +++ b/tools/fake.yaml @@ -37,6 +37,7 @@ providers: pool: 'fake' networks: - net-id: 'some-uuid' + - net-label: 'some-label' images: - name: nodepool-fake base-image: 'Fake Precise'