openstacksdk/shade/meta.py

201 lines
6.3 KiB
Python

# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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 a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import bunch
import six
from shade import exc
NON_CALLABLES = (six.string_types, bool, dict, int, list, type(None))
def find_nova_addresses(addresses, ext_tag=None, key_name=None, version=4):
ret = []
for (k, v) in iter(addresses.items()):
if key_name and k == key_name:
ret.extend([addrs['addr'] for addrs in v
if addrs['version'] == version])
else:
for interface_spec in v:
if ('OS-EXT-IPS:type' in interface_spec
and interface_spec['OS-EXT-IPS:type'] == ext_tag
and interface_spec['version'] == version):
ret.append(interface_spec['addr'])
return ret
def get_server_ip(server, **kwargs):
addrs = find_nova_addresses(server.addresses, **kwargs)
if not addrs:
return None
return addrs[0]
def get_server_private_ip(server):
return get_server_ip(server, ext_tag='fixed', key_name='private')
def get_server_public_ip(server):
return get_server_ip(server, ext_tag='floating', key_name='public')
def get_groups_from_server(cloud, server, server_vars):
groups = []
region = cloud.region_name
cloud_name = cloud.name
# Create a group for the cloud
groups.append(cloud_name)
# Create a group on region
groups.append(region)
# And one by cloud_region
groups.append("%s_%s" % (cloud_name, region))
# Check if group metadata key in servers' metadata
group = server.metadata.get('group')
if group:
groups.append(group)
for extra_group in server.metadata.get('groups', '').split(','):
if extra_group:
groups.append(extra_group)
groups.append('instance-%s' % server.id)
for key in ('flavor', 'image'):
if 'name' in server_vars[key]:
groups.append('%s-%s' % (key, server_vars[key]['name']))
for key, value in iter(server.metadata.items()):
groups.append('meta-%s_%s' % (key, value))
az = server_vars.get('az', None)
if az:
# Make groups for az, region_az and cloud_region_az
groups.append(az)
groups.append('%s_%s' % (region, az))
groups.append('%s_%s_%s' % (cloud.name, region, az))
return groups
def get_hostvars_from_server(cloud, server, mounts=None):
server_vars = server
server_vars.pop('links', None)
# Fist, add an IP address
server_vars['public_v4'] = get_server_public_ip(server)
server_vars['private_v4'] = get_server_private_ip(server)
if cloud.private:
interface_ip = server_vars['private_v4']
else:
interface_ip = server_vars['public_v4']
if interface_ip:
server_vars['interface_ip'] = interface_ip
server_vars['region'] = cloud.region_name
server_vars['cloud'] = cloud.name
flavor_id = server.flavor['id']
flavor_name = cloud.get_flavor_name(flavor_id)
if flavor_name:
server_vars['flavor']['name'] = flavor_name
server_vars['flavor'].pop('links', None)
# OpenStack can return image as a string when you've booted from volume
if str(server.image) == server.image:
image_id = server.image
server_vars['image'] = dict(id=image_id)
else:
image_id = server.image.get('id', None)
if image_id:
image_name = cloud.get_image_name(image_id)
if image_name:
server_vars['image']['name'] = image_name
server_vars['image'].pop('links', None)
volumes = []
try:
for volume in cloud.get_volumes(server):
# Make things easier to consume elsewhere
volume['device'] = volume['attachments'][0]['device']
volumes.append(volume)
except exc.OpenStackCloudException:
pass
server_vars['volumes'] = volumes
if mounts:
for mount in mounts:
for vol in server_vars['volumes']:
if vol['display_name'] == mount['display_name']:
if 'mount' in mount:
vol['mount'] = mount['mount']
az = server_vars.get('OS-EXT-AZ:availability_zone', None)
if az:
server_vars['az'] = az
return server_vars
def obj_to_dict(obj):
""" Turn an object with attributes into a dict suitable for serializing.
Some of the things that are returned in OpenStack are objects with
attributes. That's awesome - except when you want to expose them as JSON
structures. We use this as the basis of get_hostvars_from_server above so
that we can just have a plain dict of all of the values that exist in the
nova metadata for a server.
"""
instance = bunch.Bunch()
for key in dir(obj):
value = getattr(obj, key)
if isinstance(value, NON_CALLABLES) and not key.startswith('_'):
instance[key] = value
return instance
def obj_list_to_dict(list):
"""Enumerate through lists of objects and return lists of dictonaries.
Some of the objects returned in OpenStack are actually lists of objects,
and in order to expose the data structures as JSON, we need to facilitate
the conversion to lists of dictonaries.
"""
new_list = []
for obj in list:
new_list.append(obj_to_dict(obj))
return new_list
def warlock_to_dict(obj):
# glanceclient v2 uses warlock to construct its objects. Warlock does
# deep black magic to attribute look up to support validation things that
# means we cannot use normal obj_to_dict
obj_dict = bunch.Bunch()
for (key, value) in obj.items():
if isinstance(value, NON_CALLABLES) and not key.startswith('_'):
obj_dict[key] = value
return obj_dict
def warlock_list_to_dict(list):
new_list = []
for obj in list:
new_list.append(warlock_to_dict(obj))
return new_list