Patches nova client to work with HP Cloud

- nova v2 only
- network instead of interfaces

Change-Id: Ibe7059013fd67be81b5aa183457d66a69ecc0ab8
This commit is contained in:
German Eichberger 2015-01-15 13:58:44 -08:00
parent 88cdb78acc
commit 4ebc80e9d0
6 changed files with 43 additions and 41 deletions

View File

@ -39,4 +39,4 @@
[networking] [networking]
# Network to communicate with amphora # Network to communicate with amphora
# lb_network_id = # lb_network_name =

View File

@ -83,7 +83,7 @@ keystone_authtoken_opts = [
] ]
networking_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 = [] core_cli_opts = []

View File

@ -1,4 +1,4 @@
# Copyright 2014 Rackspace # Copyright 2014 Rackspace
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # 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 # 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): class VirtualMachineManager(compute_base.ComputeBase):
'''Compute implementation of virtual machines via nova.''' '''Compute implementation of virtual machines via nova.'''
def __init__(self): def __init__(self, region=None):
super(VirtualMachineManager, self).__init__() super(VirtualMachineManager, self).__init__()
# Must initialize nova api # 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 self.manager = self._nova_client.servers
def get_logger(self): def get_logger(self):
@ -59,11 +59,15 @@ class VirtualMachineManager(compute_base.ComputeBase):
:returns: UUID of amphora :returns: UUID of amphora
''' '''
try: try:
nics = []
for net_id in network_ids:
nics.append({"net-id": net_id})
amphora = self.manager.create( amphora = self.manager.create(
name=name, image=image_id, flavor=amphora_flavor, name=name, image=image_id, flavor=amphora_flavor,
key_name=key_name, security_groups=sec_groups, key_name=key_name, security_groups=sec_groups,
nics=network_ids) nics=nics)
return amphora.get('id') return amphora.id
except Exception: except Exception:
LOG.exception(_LE("Error building nova virtual machine.")) LOG.exception(_LE("Error building nova virtual machine."))
raise exceptions.ComputeBuildException() raise exceptions.ComputeBuildException()
@ -86,7 +90,8 @@ class VirtualMachineManager(compute_base.ComputeBase):
:returns: constant of amphora status :returns: constant of amphora status
''' '''
try: 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 return constants.AMPHORA_UP
except Exception: except Exception:
LOG.exception(_LE("Error retrieving nova virtual machine status.")) 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 # Extract information from nova response to populate desired amphora
# fields # fields
lb_network_ip = None lb_network_ip = None
for interface in nova_response.get('interface_list'):
if interface.get('net_id') is CONF.networking.lb_network_id: for network_name in nova_response.addresses:
lb_network_ip = interface.get('fixed_ips')[0].get('ip_address') if network_name == CONF.networking.lb_network_name:
lb_network_ip = (
nova_response.addresses[network_name][0]['addr'])
response = models.Amphora( response = models.Amphora(
compute_id=nova_response.get('id'), compute_id=nova_response.id,
status=nova_response.get('status'), status=nova_response.status,
lb_network_ip=lb_network_ip lb_network_ip=lb_network_ip
) )
return response return response
@ -151,20 +158,21 @@ class NovaKeystoneAuth(object):
except Exception: except Exception:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.exception(_LE("Error creating Keystone session.")) LOG.exception(_LE("Error creating Keystone session."))
LOG.info()
return cls._keystone_session return cls._keystone_session
@classmethod @classmethod
def get_nova_client(cls): def get_nova_client(cls, region):
"""Create nova client object. """Create nova client object.
:param region: The region of the service
:return: a Nova Client object. :return: a Nova Client object.
:raises Exception: if the client cannot be created :raises Exception: if the client cannot be created
""" """
if not cls._nova_client: if not cls._nova_client:
try: try:
cls._nova_client = nova_client.Client( 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: except Exception:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():

View File

View File

@ -31,42 +31,35 @@ CONF.import_group('networking', 'octavia.common.config')
class TestNovaClient(base.TestCase): class TestNovaClient(base.TestCase):
def setUp(self): def setUp(self):
net_id = uuidutils.generate_uuid() net_name = uuidutils.generate_uuid()
CONF.set_override(group='networking', name='lb_network_id', CONF.set_override(group='networking', name='lb_network_name',
override=net_id) override=net_name)
self.amphora = models.Amphora( self.amphora = models.Amphora(
compute_id=uuidutils.generate_uuid(), compute_id=uuidutils.generate_uuid(),
status='ONLINE', status='ACTIVE',
lb_network_ip='10.0.0.1' lb_network_ip='10.0.0.1'
) )
self.nova_response = {'id': self.amphora.compute_id,
'type': constants.AMPHORA_VM, self.nova_response = mock.Mock()
'image': uuidutils.generate_uuid(), self.nova_response.id = self.amphora.compute_id
'flavor': 1, self.nova_response.status = 'ACTIVE'
'keys': [uuidutils.generate_uuid()], self.nova_response.addresses = {net_name: [{'addr': '10.0.0.1'}]}
'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.manager = nova_common.VirtualMachineManager() self.manager = nova_common.VirtualMachineManager()
self.manager.manager = mock.MagicMock() self.manager.manager = mock.MagicMock()
self.manager.manager.get.return_value = self.nova_response self.manager.manager.get.return_value = self.nova_response
self.manager.manager.create.return_value = self.nova_response self.manager.manager.create.return_value = self.nova_response
super(TestNovaClient, self).setUp() super(TestNovaClient, self).setUp()
def test_build(self): def test_build(self):
amphora_id = self.manager.build(amphora_flavor=1, image_id=1, amphora_id = self.manager.build(amphora_flavor=1, image_id=1,
key_name=1, sec_groups=1, key_name=1, sec_groups=1,
network_ids=1) network_ids=[1])
self.assertEqual(self.amphora.compute_id, amphora_id) self.assertEqual(self.amphora.compute_id, amphora_id)
self.manager.manager.create.assert_called_with( self.manager.manager.create.assert_called_with(
name="amphora_name", image=1, flavor=1, key_name=1, 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): def test_bad_build(self):
@ -76,7 +69,7 @@ class TestNovaClient(base.TestCase):
def test_delete(self): def test_delete(self):
amphora_id = self.manager.build(amphora_flavor=1, image_id=1, amphora_id = self.manager.build(amphora_flavor=1, image_id=1,
key_name=1, sec_groups=1, key_name=1, sec_groups=1,
network_ids=1) network_ids=[1])
self.manager.delete(amphora_id) self.manager.delete(amphora_id)
self.manager.manager.delete.assert_called_with(server=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 self.manager.manager.delete.side_effect = Exception
amphora_id = self.manager.build(amphora_flavor=1, image_id=1, amphora_id = self.manager.build(amphora_flavor=1, image_id=1,
key_name=1, sec_groups=1, key_name=1, sec_groups=1,
network_ids=1) network_ids=[1])
self.assertRaises(exceptions.ComputeDeleteException, self.assertRaises(exceptions.ComputeDeleteException,
self.manager.delete, amphora_id) self.manager.delete, amphora_id)
@ -150,12 +143,12 @@ class TestNovaAuth(base.TestCase):
nova_common.NovaKeystoneAuth._keystone_session = ( nova_common.NovaKeystoneAuth._keystone_session = (
mock.MagicMock() 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 # Our returned client should also be the saved client
self.assertIsInstance( self.assertIsInstance(
nova_common.NovaKeystoneAuth._nova_client, nova_common.NovaKeystoneAuth._nova_client,
novaclient.v3.client.Client novaclient.v1_1.client.Client
) )
self.assertIs( self.assertIs(
nova_common.NovaKeystoneAuth._nova_client, nova_common.NovaKeystoneAuth._nova_client,
@ -163,5 +156,6 @@ class TestNovaAuth(base.TestCase):
) )
# Getting the session again should return the same object # 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) self.assertIs(bc1, bc2)