From 4ebc80e9d00923810cb461e8a529f5a5dcc5d1c6 Mon Sep 17 00:00:00 2001 From: German Eichberger Date: Thu, 15 Jan 2015 13:58:44 -0800 Subject: [PATCH] Patches nova client to work with HP Cloud - nova v2 only - network instead of interfaces Change-Id: Ibe7059013fd67be81b5aa183457d66a69ecc0ab8 --- etc/octavia.conf | 2 +- octavia/common/config.py | 2 +- octavia/compute/drivers/nova_driver.py | 36 +++++++++------ octavia/tests/unit/compute/__init__.py | 0 .../tests/unit/compute/drivers/__init__.py | 0 .../drivers/test_nova_driver.py | 44 ++++++++----------- 6 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 octavia/tests/unit/compute/__init__.py create mode 100644 octavia/tests/unit/compute/drivers/__init__.py rename octavia/tests/unit/{amphorae => compute}/drivers/test_nova_driver.py (78%) diff --git a/etc/octavia.conf b/etc/octavia.conf index 8683970a75..457539f4fe 100644 --- a/etc/octavia.conf +++ b/etc/octavia.conf @@ -39,4 +39,4 @@ [networking] # Network to communicate with amphora -# lb_network_id = +# lb_network_name = diff --git a/octavia/common/config.py b/octavia/common/config.py index 294bda1ef7..376a186e34 100644 --- a/octavia/common/config.py +++ b/octavia/common/config.py @@ -83,7 +83,7 @@ keystone_authtoken_opts = [ ] networking_opts = [ - cfg.StrOpt('lb_network_id', help=_('ID of amphora internal network')), + cfg.StrOpt('lb_network_name', help=_('Name of amphora internal network')), ] core_cli_opts = [] diff --git a/octavia/compute/drivers/nova_driver.py b/octavia/compute/drivers/nova_driver.py index d3475f0312..11e15e42a7 100644 --- a/octavia/compute/drivers/nova_driver.py +++ b/octavia/compute/drivers/nova_driver.py @@ -1,4 +1,4 @@ -# Copyright 2014 Rackspace +# Copyright 2014 Rackspace # # 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 @@ -35,10 +35,10 @@ CONF.import_group('networking', 'octavia.common.config') class VirtualMachineManager(compute_base.ComputeBase): '''Compute implementation of virtual machines via nova.''' - def __init__(self): + def __init__(self, region=None): super(VirtualMachineManager, self).__init__() # Must initialize nova api - self._nova_client = NovaKeystoneAuth.get_nova_client() + self._nova_client = NovaKeystoneAuth.get_nova_client(region) self.manager = self._nova_client.servers def get_logger(self): @@ -59,11 +59,15 @@ class VirtualMachineManager(compute_base.ComputeBase): :returns: UUID of amphora ''' try: + nics = [] + for net_id in network_ids: + nics.append({"net-id": net_id}) + amphora = self.manager.create( name=name, image=image_id, flavor=amphora_flavor, key_name=key_name, security_groups=sec_groups, - nics=network_ids) - return amphora.get('id') + nics=nics) + return amphora.id except Exception: LOG.exception(_LE("Error building nova virtual machine.")) raise exceptions.ComputeBuildException() @@ -86,7 +90,8 @@ class VirtualMachineManager(compute_base.ComputeBase): :returns: constant of amphora status ''' try: - if self.get_amphora(amphora_id=amphora_id): + amphora = self.get_amphora(amphora_id=amphora_id) + if amphora and amphora.status == 'ACTIVE': return constants.AMPHORA_UP except Exception: LOG.exception(_LE("Error retrieving nova virtual machine status.")) @@ -116,12 +121,14 @@ class VirtualMachineManager(compute_base.ComputeBase): # Extract information from nova response to populate desired amphora # fields lb_network_ip = None - for interface in nova_response.get('interface_list'): - if interface.get('net_id') is CONF.networking.lb_network_id: - lb_network_ip = interface.get('fixed_ips')[0].get('ip_address') + + for network_name in nova_response.addresses: + if network_name == CONF.networking.lb_network_name: + lb_network_ip = ( + nova_response.addresses[network_name][0]['addr']) response = models.Amphora( - compute_id=nova_response.get('id'), - status=nova_response.get('status'), + compute_id=nova_response.id, + status=nova_response.status, lb_network_ip=lb_network_ip ) return response @@ -151,20 +158,21 @@ class NovaKeystoneAuth(object): except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Error creating Keystone session.")) - LOG.info() return cls._keystone_session @classmethod - def get_nova_client(cls): + def get_nova_client(cls, region): """Create nova client object. + :param region: The region of the service :return: a Nova Client object. :raises Exception: if the client cannot be created """ if not cls._nova_client: try: cls._nova_client = nova_client.Client( - constants.NOVA_3, session=cls._get_keystone_session() + constants.NOVA_2, session=cls._get_keystone_session(), + region_name=region ) except Exception: with excutils.save_and_reraise_exception(): diff --git a/octavia/tests/unit/compute/__init__.py b/octavia/tests/unit/compute/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/octavia/tests/unit/compute/drivers/__init__.py b/octavia/tests/unit/compute/drivers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/octavia/tests/unit/amphorae/drivers/test_nova_driver.py b/octavia/tests/unit/compute/drivers/test_nova_driver.py similarity index 78% rename from octavia/tests/unit/amphorae/drivers/test_nova_driver.py rename to octavia/tests/unit/compute/drivers/test_nova_driver.py index 4b842de75d..79554e07d5 100644 --- a/octavia/tests/unit/amphorae/drivers/test_nova_driver.py +++ b/octavia/tests/unit/compute/drivers/test_nova_driver.py @@ -31,42 +31,35 @@ CONF.import_group('networking', 'octavia.common.config') class TestNovaClient(base.TestCase): def setUp(self): - net_id = uuidutils.generate_uuid() - CONF.set_override(group='networking', name='lb_network_id', - override=net_id) + net_name = uuidutils.generate_uuid() + CONF.set_override(group='networking', name='lb_network_name', + override=net_name) self.amphora = models.Amphora( compute_id=uuidutils.generate_uuid(), - status='ONLINE', + status='ACTIVE', lb_network_ip='10.0.0.1' ) - self.nova_response = {'id': self.amphora.compute_id, - 'type': constants.AMPHORA_VM, - 'image': uuidutils.generate_uuid(), - 'flavor': 1, - 'keys': [uuidutils.generate_uuid()], - 'security_groups': ['admin'], - 'nics': [uuidutils.generate_uuid()], - 'status': 'ONLINE', - 'interface_list': [{ - "fixed_ips": [ - {'ip_address': '10.0.0.1', - 'subnet_id': uuidutils.generate_uuid()} - ], - 'net_id': net_id}]} + + self.nova_response = mock.Mock() + self.nova_response.id = self.amphora.compute_id + self.nova_response.status = 'ACTIVE' + self.nova_response.addresses = {net_name: [{'addr': '10.0.0.1'}]} + self.manager = nova_common.VirtualMachineManager() self.manager.manager = mock.MagicMock() self.manager.manager.get.return_value = self.nova_response self.manager.manager.create.return_value = self.nova_response + super(TestNovaClient, self).setUp() def test_build(self): amphora_id = self.manager.build(amphora_flavor=1, image_id=1, key_name=1, sec_groups=1, - network_ids=1) + network_ids=[1]) self.assertEqual(self.amphora.compute_id, amphora_id) self.manager.manager.create.assert_called_with( name="amphora_name", image=1, flavor=1, key_name=1, - security_groups=1, nics=1 + security_groups=1, nics=[{'net-id': 1}] ) def test_bad_build(self): @@ -76,7 +69,7 @@ class TestNovaClient(base.TestCase): def test_delete(self): amphora_id = self.manager.build(amphora_flavor=1, image_id=1, key_name=1, sec_groups=1, - network_ids=1) + network_ids=[1]) self.manager.delete(amphora_id) self.manager.manager.delete.assert_called_with(server=amphora_id) @@ -84,7 +77,7 @@ class TestNovaClient(base.TestCase): self.manager.manager.delete.side_effect = Exception amphora_id = self.manager.build(amphora_flavor=1, image_id=1, key_name=1, sec_groups=1, - network_ids=1) + network_ids=[1]) self.assertRaises(exceptions.ComputeDeleteException, self.manager.delete, amphora_id) @@ -150,12 +143,12 @@ class TestNovaAuth(base.TestCase): nova_common.NovaKeystoneAuth._keystone_session = ( mock.MagicMock() ) - bc1 = nova_common.NovaKeystoneAuth.get_nova_client() + bc1 = nova_common.NovaKeystoneAuth.get_nova_client(region=None) # Our returned client should also be the saved client self.assertIsInstance( nova_common.NovaKeystoneAuth._nova_client, - novaclient.v3.client.Client + novaclient.v1_1.client.Client ) self.assertIs( nova_common.NovaKeystoneAuth._nova_client, @@ -163,5 +156,6 @@ class TestNovaAuth(base.TestCase): ) # Getting the session again should return the same object - bc2 = nova_common.NovaKeystoneAuth.get_nova_client() + bc2 = nova_common.NovaKeystoneAuth.get_nova_client( + region="test-region") self.assertIs(bc1, bc2) \ No newline at end of file