Files
deb-nova/nova/api/ec2/ec2utils.py
Jason Kölker c9ca372b0b Standardize logging delaration and use
* Make modules use getLogger(__name__) and log to the result

Change-Id: Ib6d69b4be140ec89affc86ed11e65e422d551df1
2012-02-14 13:02:43 -06:00

227 lines
6.9 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# 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 re
from nova import exception
from nova import flags
from nova import log as logging
from nova import network
from nova.network import model as network_model
FLAGS = flags.FLAGS
LOG = logging.getLogger(__name__)
def image_type(image_type):
"""Converts to a three letter image type.
aki, kernel => aki
ari, ramdisk => ari
anything else => ami
"""
if image_type == 'kernel':
return 'aki'
if image_type == 'ramdisk':
return 'ari'
if image_type not in ['aki', 'ari']:
return 'ami'
return image_type
def ec2_id_to_id(ec2_id):
"""Convert an ec2 ID (i-[base 16 number]) to an instance id (int)"""
try:
return int(ec2_id.split('-')[-1], 16)
except ValueError:
raise exception.InvalidEc2Id(ec2_id=ec2_id)
def image_ec2_id(image_id, image_type='ami'):
"""Returns image ec2_id using id and three letter type."""
template = image_type + '-%08x'
try:
return id_to_ec2_id(image_id, template=template)
except ValueError:
#TODO(wwolf): once we have ec2_id -> glance_id mapping
# in place, this wont be necessary
return "ami-00000000"
def get_ip_info_for_instance_from_nw_info(nw_info):
ip_info = dict(fixed_ips=[], fixed_ip6s=[], floating_ips=[])
for vif in nw_info:
vif_fixed_ips = vif.fixed_ips()
fixed_ips = [ip['address']
for ip in vif_fixed_ips if ip['version'] == 4]
fixed_ip6s = [ip['address']
for ip in vif_fixed_ips if ip['version'] == 6]
floating_ips = [ip['address']
for ip in vif.floating_ips()]
ip_info['fixed_ips'].extend(fixed_ips)
ip_info['fixed_ip6s'].extend(fixed_ip6s)
ip_info['floating_ips'].extend(floating_ips)
return ip_info
def get_ip_info_for_instance_from_cache(instance):
if (not instance.get('info_cache') or
not instance['info_cache'].get('network_info')):
# NOTE(jkoelker) Raising ValueError so that we trigger the
# fallback lookup
raise ValueError
cached_info = instance['info_cache']['network_info']
nw_info = network_model.NetworkInfo.hydrate(cached_info)
return get_ip_info_for_instance_from_nw_info(nw_info)
def get_ip_info_for_instance(context, instance):
"""Return a list of all fixed IPs for an instance"""
try:
return get_ip_info_for_instance_from_cache(instance)
except (ValueError, KeyError, AttributeError):
# NOTE(jkoelker) If the json load (ValueError) or the
# sqlalchemy FK (KeyError, AttributeError)
# fail fall back to calling out to he
# network api
network_api = network.API()
nw_info = network_api.get_instance_nw_info(context, instance)
return get_ip_info_for_instance_from_nw_info(nw_info)
def get_availability_zone_by_host(services, host):
if len(services) > 0:
return services[0]['availability_zone']
return 'unknown zone'
def id_to_ec2_id(instance_id, template='i-%08x'):
"""Convert an instance ID (int) to an ec2 ID (i-[base 16 number])"""
return template % int(instance_id)
def id_to_ec2_snap_id(instance_id):
"""Convert an snapshot ID (int) to an ec2 snapshot ID
(snap-[base 16 number])"""
return id_to_ec2_id(instance_id, 'snap-%08x')
def id_to_ec2_vol_id(instance_id):
"""Convert an volume ID (int) to an ec2 volume ID (vol-[base 16 number])"""
return id_to_ec2_id(instance_id, 'vol-%08x')
_c2u = re.compile('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
def camelcase_to_underscore(str):
return _c2u.sub(r'_\1', str).lower().strip('_')
def _try_convert(value):
"""Return a non-string from a string or unicode, if possible.
============= =====================================================
When value is returns
============= =====================================================
zero-length ''
'None' None
'True' True case insensitive
'False' False case insensitive
'0', '-0' 0
0xN, -0xN int from hex (positive) (N is any number)
0bN, -0bN int from binary (positive) (N is any number)
* try conversion to int, float, complex, fallback value
"""
if len(value) == 0:
return ''
if value == 'None':
return None
lowered_value = value.lower()
if lowered_value == 'true':
return True
if lowered_value == 'false':
return False
valueneg = value[1:] if value[0] == '-' else value
if valueneg == '0':
return 0
if valueneg == '':
return value
if valueneg[0] == '0':
if valueneg[1] in 'xX':
return int(value, 16)
elif valueneg[1] in 'bB':
return int(value, 2)
else:
try:
return int(value, 8)
except ValueError:
pass
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
try:
return complex(value)
except ValueError:
return value
def dict_from_dotted_str(items):
"""parse multi dot-separated argument into dict.
EBS boot uses multi dot-separated arguments like
BlockDeviceMapping.1.DeviceName=snap-id
Convert the above into
{'block_device_mapping': {'1': {'device_name': snap-id}}}
"""
args = {}
for key, value in items:
parts = key.split(".")
key = str(camelcase_to_underscore(parts[0]))
if isinstance(value, str) or isinstance(value, unicode):
# NOTE(vish): Automatically convert strings back
# into their respective values
value = _try_convert(value)
if len(parts) > 1:
d = args.get(key, {})
args[key] = d
for k in parts[1:-1]:
k = camelcase_to_underscore(k)
v = d.get(k, {})
d[k] = v
d = v
d[camelcase_to_underscore(parts[-1])] = value
else:
args[key] = value
return args