add metadata to nova_client results
Fixes bug 1190547 Change-Id: I90861038f0623e6183dfd43899669aba88b47796
This commit is contained in:
parent
69cb42933d
commit
298e2f7e7b
@ -37,16 +37,12 @@ INSTANCE_PROPERTIES = [
|
||||
# Type properties
|
||||
'architecture',
|
||||
# Location properties
|
||||
'availability_zone',
|
||||
'kernel_id',
|
||||
'os_type',
|
||||
'ramdisk_id',
|
||||
# Capacity properties
|
||||
'disk_gb',
|
||||
'ephemeral_gb',
|
||||
'memory_mb',
|
||||
'root_gb',
|
||||
'vcpus']
|
||||
'root_gb']
|
||||
|
||||
|
||||
def add_reserved_user_metadata(instance, metadata):
|
||||
@ -71,9 +67,14 @@ def get_metadata_from_object(instance):
|
||||
"""Return a metadata dictionary for the instance.
|
||||
"""
|
||||
metadata = {
|
||||
'availability_zone': getattr(instance,
|
||||
'OS-EXT-AZ:availability_zone', u''),
|
||||
'display_name': instance.name,
|
||||
'name': getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', u''),
|
||||
'instance_type': (instance.flavor['id'] if instance.flavor else None),
|
||||
'disk_gb': (instance.flavor['disk'] if instance.flavor else None),
|
||||
'memory_mb': (instance.flavor['ram'] if instance.flavor else None),
|
||||
'vcpus': (instance.flavor['vcpus'] if instance.flavor else None),
|
||||
'host': instance.hostId,
|
||||
# Image properties
|
||||
'image_ref': (instance.image['id'] if instance.image else None),
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import functools
|
||||
|
||||
import novaclient
|
||||
from novaclient.v1_1 import client as nova_client
|
||||
from oslo.config import cfg
|
||||
|
||||
@ -52,21 +53,44 @@ class Client(object):
|
||||
auth_url=cfg.CONF.service_credentials.os_auth_url,
|
||||
no_cache=True)
|
||||
|
||||
def _with_flavor(self, instances):
|
||||
flavors = dict((f.id, f) for f in self.nova_client.flavors.list())
|
||||
def _with_flavor_and_image(self, instances):
|
||||
flavor_attrs = ['name', 'vcpus', 'ram', 'disk']
|
||||
for instance in instances:
|
||||
fid = instance.flavor['id']
|
||||
try:
|
||||
instance.flavor['name'] = flavors[fid].name
|
||||
except KeyError:
|
||||
instance.flavor['name'] = 'unknown-id-%s' % fid
|
||||
flavor = self.nova_client.flavors.get(fid)
|
||||
except novaclient.exceptions.NotFound:
|
||||
flavor = None
|
||||
|
||||
for attr in flavor_attrs:
|
||||
try:
|
||||
instance.flavor[attr] = getattr(flavor, attr)
|
||||
except (KeyError, AttributeError):
|
||||
if attr == 'name':
|
||||
instance.flavor['name'] = 'unknown-id-%s' % fid
|
||||
|
||||
iid = instance.image['id']
|
||||
try:
|
||||
image = self.nova_client.images.get(iid)
|
||||
except novaclient.exceptions.NotFound:
|
||||
image = None
|
||||
|
||||
try:
|
||||
image_meta = getattr(image, 'metadata')
|
||||
except (KeyError, AttributeError):
|
||||
instance.image['name'] = 'unknown-id-%s' % iid
|
||||
else:
|
||||
instance.image['name'] = getattr(image, 'name')
|
||||
instance.kernel_id = image_meta['kernel_id']
|
||||
instance.ramdisk_id = image_meta['ramdisk_id']
|
||||
|
||||
return instances
|
||||
|
||||
@logged
|
||||
def instance_get_all_by_host(self, hostname):
|
||||
"""Returns list of instances on particular host."""
|
||||
search_opts = {'host': hostname, 'all_tenants': True}
|
||||
return self._with_flavor(self.nova_client.servers.list(
|
||||
return self._with_flavor_and_image(self.nova_client.servers.list(
|
||||
detailed=True,
|
||||
search_opts=search_opts))
|
||||
|
||||
|
@ -52,56 +52,57 @@ class TestLocationMetadata(base.TestCase):
|
||||
self.INSTANCE_PROPERTIES = {'name': 'display name',
|
||||
'OS-EXT-SRV-ATTR:instance_name':
|
||||
'instance-000001',
|
||||
'availability_zone': None,
|
||||
'OS-EXT-AZ:availability_zone':
|
||||
'foo-zone',
|
||||
'reservation_id': 'reservation id',
|
||||
'architecture': 'x86_64',
|
||||
'availability_zone': 'zone1',
|
||||
'kernel_id': 'kernel id',
|
||||
'os_type': 'linux',
|
||||
'ramdisk_id': 'ramdisk id',
|
||||
'disk_gb': 10,
|
||||
'ephemeral_gb': 7,
|
||||
'memory_mb': 2048,
|
||||
'root_gb': 3,
|
||||
'vcpus': 1,
|
||||
'image': {'id': 1,
|
||||
'links': [{"rel": "bookmark",
|
||||
'href': 2}]},
|
||||
'flavor': {'id': 1},
|
||||
'hostId': '1234-5678',
|
||||
'flavor': {'id': 1,
|
||||
'disk': 0,
|
||||
'ram': 512,
|
||||
'vcpus': 2},
|
||||
'metadata': {'metering.autoscale.group':
|
||||
'X' * 512,
|
||||
'metering.ephemeral_gb': 42}}
|
||||
|
||||
self.instance = FauxInstance(**self.INSTANCE_PROPERTIES)
|
||||
self.instance.host = 'made-up-hostname'
|
||||
m = mock.MagicMock()
|
||||
m.flavorid = 1
|
||||
self.instance.instance_type = m
|
||||
|
||||
def test_metadata(self):
|
||||
md = instance.get_metadata_from_object(self.instance)
|
||||
iprops = self.INSTANCE_PROPERTIES
|
||||
for name in md.keys():
|
||||
actual = md[name]
|
||||
print 'checking', name, actual
|
||||
if name == 'name':
|
||||
assert actual == iprops['OS-EXT-SRV-ATTR:instance_name']
|
||||
elif name == 'host':
|
||||
assert actual == iprops['hostId']
|
||||
elif name == 'display_name':
|
||||
assert actual == iprops['name']
|
||||
elif name == 'instance_type':
|
||||
assert actual == iprops['flavor']['id']
|
||||
elif name == 'image_ref':
|
||||
assert actual == iprops['image']['id']
|
||||
elif name == 'image_ref_url':
|
||||
assert actual == iprops['image']['links'][0]['href']
|
||||
elif name == 'user_metadata':
|
||||
expected = iprops['metadata']['metering.autoscale.group'][:256]
|
||||
self.assertEqual(actual['autoscale_group'], expected)
|
||||
self.assertEqual(len(actual), 1)
|
||||
else:
|
||||
assert actual == iprops[name]
|
||||
self.assertEqual(md['availability_zone'],
|
||||
iprops['OS-EXT-AZ:availability_zone'])
|
||||
self.assertEqual(md['name'], iprops['OS-EXT-SRV-ATTR:instance_name'])
|
||||
self.assertEqual(md['disk_gb'], iprops['flavor']['disk'])
|
||||
self.assertEqual(md['display_name'], iprops['name'])
|
||||
self.assertEqual(md['instance_type'], iprops['flavor']['id'])
|
||||
self.assertEqual(md['image_ref'], iprops['image']['id'])
|
||||
self.assertEqual(md['image_ref_url'],
|
||||
iprops['image']['links'][0]['href'])
|
||||
self.assertEqual(md['memory_mb'], iprops['flavor']['ram'])
|
||||
self.assertEqual(md['vcpus'], iprops['flavor']['vcpus'])
|
||||
self.assertEqual(md['host'], iprops['hostId'])
|
||||
|
||||
self.assertEqual(md['reservation_id'], iprops['reservation_id'])
|
||||
self.assertEqual(md['kernel_id'], iprops['kernel_id'])
|
||||
self.assertEqual(md['ramdisk_id'], iprops['ramdisk_id'])
|
||||
self.assertEqual(md['architecture'], iprops['architecture'])
|
||||
self.assertEqual(md['os_type'], iprops['os_type'])
|
||||
self.assertEqual(md['ephemeral_gb'], iprops['ephemeral_gb'])
|
||||
self.assertEqual(md['root_gb'], iprops['root_gb'])
|
||||
user_metadata = md['user_metadata']
|
||||
expected = iprops['metadata']['metering.autoscale.group'][:256]
|
||||
self.assertEqual(user_metadata['autoscale_group'], expected)
|
||||
self.assertEqual(len(user_metadata), 1)
|
||||
|
||||
def test_metadata_empty_image(self):
|
||||
self.INSTANCE_PROPERTIES['image'] = ''
|
||||
|
@ -41,7 +41,8 @@ class TestPollsterBase(test_base.TestCase):
|
||||
setattr(self.instance, 'OS-EXT-SRV-ATTR:instance_name',
|
||||
self.instance.name)
|
||||
self.instance.id = 1
|
||||
self.instance.flavor = {'name': 'm1.small', 'id': 2}
|
||||
self.instance.flavor = {'name': 'm1.small', 'id': 2, 'vcpus': 1,
|
||||
'ram': 512, 'disk': 0}
|
||||
|
||||
|
||||
class TestInstancePollster(TestPollsterBase):
|
||||
|
@ -29,6 +29,35 @@ class TestNovaClient(base.TestCase):
|
||||
super(TestNovaClient, self).setUp()
|
||||
self.nv = nova_client.Client()
|
||||
|
||||
@staticmethod
|
||||
def fake_flavors_get(*args, **kwargs):
|
||||
a = mock.MagicMock()
|
||||
a.id = args[0]
|
||||
if a.id == 1:
|
||||
a.name = 'm1.tiny'
|
||||
elif a.id == 2:
|
||||
a.name = 'm1.large'
|
||||
else:
|
||||
return None
|
||||
return a
|
||||
|
||||
@staticmethod
|
||||
def fake_images_get(*args, **kwargs):
|
||||
a = mock.MagicMock()
|
||||
a.id = args[0]
|
||||
if a.id == 1:
|
||||
a.name = 'ubuntu-12.04-x86'
|
||||
a.metadata = {'kernel_id': 11,
|
||||
'ramdisk_id': 21}
|
||||
elif a.id == 2:
|
||||
a.name = 'centos-5.4-x64'
|
||||
a.metadata = {'kernel_id': 12,
|
||||
'ramdisk_id': 22}
|
||||
else:
|
||||
return None
|
||||
|
||||
return a
|
||||
|
||||
@staticmethod
|
||||
def fake_flavors_list():
|
||||
a = mock.MagicMock()
|
||||
@ -44,31 +73,60 @@ class TestNovaClient(base.TestCase):
|
||||
a = mock.MagicMock()
|
||||
a.id = 42
|
||||
a.flavor = {'id': 1}
|
||||
a.image = {'id': 1}
|
||||
return [a]
|
||||
|
||||
def test_instance_get_all_by_host(self):
|
||||
self.stubs.Set(self.nv.nova_client.flavors, 'list',
|
||||
self.fake_flavors_list)
|
||||
self.stubs.Set(self.nv.nova_client.flavors, 'get',
|
||||
self.fake_flavors_get)
|
||||
self.stubs.Set(self.nv.nova_client.servers, 'list',
|
||||
self.fake_servers_list)
|
||||
self.stubs.Set(self.nv.nova_client.images, 'get',
|
||||
self.fake_images_get)
|
||||
|
||||
instances = self.nv.instance_get_all_by_host('foobar')
|
||||
self.assertEqual(len(instances), 1)
|
||||
self.assertEqual(instances[0].flavor['name'], 'm1.tiny')
|
||||
self.assertEqual(instances[0].image['name'], 'ubuntu-12.04-x86')
|
||||
self.assertEqual(instances[0].kernel_id, 11)
|
||||
self.assertEqual(instances[0].ramdisk_id, 21)
|
||||
|
||||
@staticmethod
|
||||
def fake_servers_list_unknown_flavor(*args, **kwargs):
|
||||
a = mock.MagicMock()
|
||||
a.id = 42
|
||||
a.flavor = {'id': 666}
|
||||
a.image = {'id': 1}
|
||||
return [a]
|
||||
|
||||
def test_instance_get_all_by_host_unknown_flavor(self):
|
||||
self.stubs.Set(self.nv.nova_client.flavors, 'list',
|
||||
self.fake_flavors_list)
|
||||
self.stubs.Set(self.nv.nova_client.flavors, 'get',
|
||||
self.fake_flavors_get)
|
||||
self.stubs.Set(self.nv.nova_client.servers, 'list',
|
||||
self.fake_servers_list_unknown_flavor)
|
||||
self.stubs.Set(self.nv.nova_client.images, 'get',
|
||||
self.fake_images_get)
|
||||
|
||||
instances = self.nv.instance_get_all_by_host('foobar')
|
||||
self.assertEqual(len(instances), 1)
|
||||
self.assertEqual(instances[0].flavor['name'], 'unknown-id-666')
|
||||
|
||||
@staticmethod
|
||||
def fake_servers_list_unknown_image(*args, **kwargs):
|
||||
a = mock.MagicMock()
|
||||
a.id = 42
|
||||
a.flavor = {'id': 1}
|
||||
a.image = {'id': 666}
|
||||
return [a]
|
||||
|
||||
def test_instance_get_all_by_host_unknown_image(self):
|
||||
self.stubs.Set(self.nv.nova_client.flavors, 'get',
|
||||
self.fake_flavors_get)
|
||||
self.stubs.Set(self.nv.nova_client.servers, 'list',
|
||||
self.fake_servers_list_unknown_image)
|
||||
self.stubs.Set(self.nv.nova_client.images, 'get',
|
||||
self.fake_images_get)
|
||||
|
||||
instances = self.nv.instance_get_all_by_host('foobar')
|
||||
self.assertEqual(len(instances), 1)
|
||||
self.assertEqual(instances[0].image['name'], 'unknown-id-666')
|
||||
|
Loading…
Reference in New Issue
Block a user