diff --git a/doc/config.rst b/doc/config.rst index df1e1d57..bb35c38d 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -73,7 +73,7 @@ Pool Manager Section nova_keyname = default nova_secgroup = default nova_image = 12345 - nova_image_size = 102 + nova_image_size = standard.medium api_server = 10.0.0.1:8889 10.0.0.2:8889 nodes = 10 check_interval = 5 @@ -230,12 +230,12 @@ Pool Manager Command Line Options .. option:: --nova_image - The image ID to use on new nodes spun up in the Nova API + The image ID or name to use on new nodes spun up in the Nova API .. option:: --nova_image_size - The flavor ID (image size ID) to use for new nodes spun up in the Nova - API + The flavor ID (image size ID) or name to use for new nodes spun up in + the Nova API .. option:: -p , --pid diff --git a/doc/pool_mgm/code.rst b/doc/pool_mgm/code.rst index 0aac8380..f27dc63e 100644 --- a/doc/pool_mgm/code.rst +++ b/doc/pool_mgm/code.rst @@ -69,8 +69,8 @@ Node Class :param region: The Nova region :param keyaname: The Nova key name for new nodes :param secgroup: The Nova security group for new nodes - :param image: The Nova image ID for new nodes - :param node_type: The flavor ID for new nodes + :param image: The Nova image ID or name for new nodes + :param node_type: The flavor ID or name for new nodes .. py:method:: build() diff --git a/etc/sample_libra.cfg b/etc/sample_libra.cfg index 2df4c89e..26513b42 100644 --- a/etc/sample_libra.cfg +++ b/etc/sample_libra.cfg @@ -46,7 +46,7 @@ nova_region = region nova_keyname = default nova_secgroup = default nova_image = 12345 -nova_image_size = 102 +nova_image_size = standard.medium api_server = 10.0.0.1:8889 10.0.0.2:8889 nodes = 10 check_interval = 5 diff --git a/libra/mgm/mgm.py b/libra/mgm/mgm.py index 0670d4b5..3bf9ef13 100644 --- a/libra/mgm/mgm.py +++ b/libra/mgm/mgm.py @@ -97,17 +97,23 @@ class Server(object): self.ct.start() def build_nodes(self, count, api): - nova = Node( - self.args.nova_user, - self.args.nova_pass, - self.args.nova_tenant, - self.args.nova_auth_url, - self.args.nova_region, - self.args.nova_keyname, - self.args.nova_secgroup, - self.args.nova_image, - self.args.nova_image_size - ) + try: + nova = Node( + self.args.nova_user, + self.args.nova_pass, + self.args.nova_tenant, + self.args.nova_auth_url, + self.args.nova_region, + self.args.nova_keyname, + self.args.nova_secgroup, + self.args.nova_image, + self.args.nova_image_size + ) + except Exception as exc: + self.logger.error('Error initialising Nova connection {exc}' + .format(exc=exc) + ) + return while count > 0: status, data = nova.build() if not status: @@ -200,12 +206,13 @@ def main(): ) options.parser.add_argument( '--nova_image', - help='the image ID to use for new nodes spun up in the Nova API' + help='the image ID or name to use for new nodes spun up in the' + ' Nova API' ) options.parser.add_argument( '--nova_image_size', - help='the image size ID (flavor ID) to use for new nodes spun up in' - ' the Nova API' + help='the image size ID (flavor ID) or name to use for new nodes spun' + ' up in the Nova API' ) args = options.run() diff --git a/libra/mgm/nova.py b/libra/mgm/nova.py index 770e5c8c..b70532d8 100644 --- a/libra/mgm/nova.py +++ b/libra/mgm/nova.py @@ -15,10 +15,15 @@ import uuid import time import sys +import urllib from novaclient import client +class NotFound(Exception): + pass + + class Node(object): def __init__(self, username, password, tenant, auth_url, region, keyname, secgroup, image, node_type): @@ -32,8 +37,15 @@ class Node(object): ) self.keyname = keyname self.secgroup = secgroup - self.image = image - self.node_type = node_type + if image.isdigit(): + self.image = image + else: + self.image = self._get_image(image) + + if node_type.isdigit(): + self.node_type = node_type + else: + self.node_type = self._get_flavor(node_type) def build(self): """ create a node, test it is running """ @@ -75,7 +87,7 @@ class Node(object): if resp['status'] != '204': return False, 'Error deleting node {nid} status {stat}'.format( - node=node_id, stat=status['status'] + node=node_id, stat=resp['status'] ) return True, '' @@ -108,3 +120,34 @@ class Node(object): resp, body = self.nova.delete(url) return resp + + def _get_image(self, image_name): + """ tries to find an image from the name """ + args = {'name': image_name} + url = "/images?{0}".format(urllib.urlencode(args)) + resp, body = self.nova.get(url) + if resp['status'] not in ['200', '203']: + msg = "Error {0} searching for image with name {1}".format( + resp['status'], image_name + ) + raise NotFound(msg) + if len(body['images']) != 1: + print body['images'] + msg = "Could not find image with name {0}".format(image_name) + raise NotFound(msg) + return body['images'][0]['id'] + + def _get_flavor(self, flavor_name): + """ tries to find a flavor from the name """ + url = "/flavors" + resp, body = self.nova.get(url) + if resp['status'] not in ['200', '203']: + msg = "Error {0} searching for flavor with name {1}".format( + resp['status'], flavor_name + ) + raise NotFound(msg) + for flavor in body['flavors']: + if flavor['name'] == flavor_name: + return flavor['id'] + msg = "Could not find flavor with name {0}".format(flavor_name) + raise NotFound(msg)