PEP8 cleanup in nova/api. There should be no functional changes here, just style changes to get violations down.
This commit is contained in:
@@ -36,7 +36,8 @@ flags.DEFINE_string('osapi_subdomain', 'api',
|
|||||||
flags.DEFINE_string('ec2api_subdomain', 'ec2',
|
flags.DEFINE_string('ec2api_subdomain', 'ec2',
|
||||||
'subdomain running the EC2 API')
|
'subdomain running the EC2 API')
|
||||||
flags.DEFINE_string('FAKE_subdomain', None,
|
flags.DEFINE_string('FAKE_subdomain', None,
|
||||||
'set to api or ec2 to fake the subdomain of the host for testing')
|
'set to api or ec2 to fake the subdomain of the host '
|
||||||
|
'for testing')
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ class API(wsgi.Router):
|
|||||||
"""Routes top-level requests to the appropriate controller."""
|
"""Routes top-level requests to the appropriate controller."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
osapidomain = {'sub_domain': [FLAGS.osapi_subdomain]}
|
osapidomain = {'sub_domain': [FLAGS.osapi_subdomain]}
|
||||||
ec2domain = {'sub_domain': [FLAGS.ec2api_subdomain]}
|
ec2domain = {'sub_domain': [FLAGS.ec2api_subdomain]}
|
||||||
# If someone wants to pretend they're hitting the OSAPI subdomain
|
# If someone wants to pretend they're hitting the OSAPI subdomain
|
||||||
# on their local box, they can set FAKE_subdomain to 'api', which
|
# on their local box, they can set FAKE_subdomain to 'api', which
|
||||||
@@ -107,5 +108,3 @@ class API(wsgi.Router):
|
|||||||
'2009-04-04',
|
'2009-04-04',
|
||||||
]
|
]
|
||||||
return ''.join('%s\n' % v for v in versions)
|
return ''.join('%s\n' % v for v in versions)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -62,7 +62,8 @@ class Authenticate(wsgi.Middleware):
|
|||||||
|
|
||||||
# Make a copy of args for authentication and signature verification.
|
# Make a copy of args for authentication and signature verification.
|
||||||
auth_params = dict(req.params)
|
auth_params = dict(req.params)
|
||||||
auth_params.pop('Signature') # not part of authentication args
|
# Not part of authentication args
|
||||||
|
auth_params.pop('Signature')
|
||||||
|
|
||||||
# Authenticate the request.
|
# Authenticate the request.
|
||||||
try:
|
try:
|
||||||
@@ -109,9 +110,11 @@ class Router(wsgi.Middleware):
|
|||||||
'SignatureVersion', 'Version', 'Timestamp']
|
'SignatureVersion', 'Version', 'Timestamp']
|
||||||
args = dict(req.params)
|
args = dict(req.params)
|
||||||
try:
|
try:
|
||||||
action = req.params['Action'] # raise KeyError if omitted
|
# Raise KeyError if omitted
|
||||||
|
action = req.params['Action']
|
||||||
for non_arg in non_args:
|
for non_arg in non_args:
|
||||||
args.pop(non_arg) # remove, but raise KeyError if omitted
|
# Remove, but raise KeyError if omitted
|
||||||
|
args.pop(non_arg)
|
||||||
except:
|
except:
|
||||||
raise webob.exc.HTTPBadRequest()
|
raise webob.exc.HTTPBadRequest()
|
||||||
|
|
||||||
@@ -184,7 +187,8 @@ class Authorizer(wsgi.Middleware):
|
|||||||
context = req.environ['ec2.context']
|
context = req.environ['ec2.context']
|
||||||
controller_name = req.environ['ec2.controller'].__class__.__name__
|
controller_name = req.environ['ec2.controller'].__class__.__name__
|
||||||
action = req.environ['ec2.action']
|
action = req.environ['ec2.action']
|
||||||
allowed_roles = self.action_roles[controller_name].get(action, ['none'])
|
allowed_roles = self.action_roles[controller_name].get(action,
|
||||||
|
['none'])
|
||||||
if self._matches_any_role(context, allowed_roles):
|
if self._matches_any_role(context, allowed_roles):
|
||||||
return self.application
|
return self.application
|
||||||
else:
|
else:
|
||||||
@@ -242,4 +246,3 @@ class Executor(wsgi.Application):
|
|||||||
'<Message>%s</Message></Error></Errors>'
|
'<Message>%s</Message></Error></Errors>'
|
||||||
'<RequestID>?</RequestID></Response>') % (code, message)
|
'<RequestID>?</RequestID></Response>') % (code, message)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ class AdminController(object):
|
|||||||
def describe_users(self, _context, **_kwargs):
|
def describe_users(self, _context, **_kwargs):
|
||||||
"""Returns all users - should be changed to deal with a list."""
|
"""Returns all users - should be changed to deal with a list."""
|
||||||
return {'userSet':
|
return {'userSet':
|
||||||
[user_dict(u) for u in manager.AuthManager().get_users()] }
|
[user_dict(u) for u in manager.AuthManager().get_users()]}
|
||||||
|
|
||||||
def register_user(self, _context, name, **_kwargs):
|
def register_user(self, _context, name, **_kwargs):
|
||||||
"""Creates a new user, and returns generated credentials."""
|
"""Creates a new user, and returns generated credentials."""
|
||||||
@@ -91,7 +91,7 @@ class AdminController(object):
|
|||||||
def describe_roles(self, context, project_roles=True, **kwargs):
|
def describe_roles(self, context, project_roles=True, **kwargs):
|
||||||
"""Returns a list of allowed roles."""
|
"""Returns a list of allowed roles."""
|
||||||
roles = manager.AuthManager().get_roles(project_roles)
|
roles = manager.AuthManager().get_roles(project_roles)
|
||||||
return { 'roles': [{'role': r} for r in roles]}
|
return {'roles': [{'role': r} for r in roles]}
|
||||||
|
|
||||||
def describe_user_roles(self, context, user, project=None, **kwargs):
|
def describe_user_roles(self, context, user, project=None, **kwargs):
|
||||||
"""Returns a list of roles for the given user.
|
"""Returns a list of roles for the given user.
|
||||||
@@ -99,7 +99,7 @@ class AdminController(object):
|
|||||||
Specifying project will return only project specific roles.
|
Specifying project will return only project specific roles.
|
||||||
"""
|
"""
|
||||||
roles = manager.AuthManager().get_user_roles(user, project=project)
|
roles = manager.AuthManager().get_user_roles(user, project=project)
|
||||||
return { 'roles': [{'role': r} for r in roles]}
|
return {'roles': [{'role': r} for r in roles]}
|
||||||
|
|
||||||
def modify_user_role(self, context, user, role, project=None,
|
def modify_user_role(self, context, user, role, project=None,
|
||||||
operation='add', **kwargs):
|
operation='add', **kwargs):
|
||||||
@@ -155,9 +155,10 @@ class AdminController(object):
|
|||||||
'members': [{'member': m} for m in project.member_ids]}
|
'members': [{'member': m} for m in project.member_ids]}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def modify_project_member(self, context, user, project, operation, **kwargs):
|
def modify_project_member(self, context, user, project, operation,
|
||||||
|
**kwargs):
|
||||||
"""Add or remove a user from a project."""
|
"""Add or remove a user from a project."""
|
||||||
if operation =='add':
|
if operation == 'add':
|
||||||
manager.AuthManager().add_to_project(user, project)
|
manager.AuthManager().add_to_project(user, project)
|
||||||
elif operation == 'remove':
|
elif operation == 'remove':
|
||||||
manager.AuthManager().remove_from_project(user, project)
|
manager.AuthManager().remove_from_project(user, project)
|
||||||
|
@@ -44,6 +44,7 @@ def _underscore_to_xmlcase(str):
|
|||||||
res = _underscore_to_camelcase(str)
|
res = _underscore_to_camelcase(str)
|
||||||
return res[:1].lower() + res[1:]
|
return res[:1].lower() + res[1:]
|
||||||
|
|
||||||
|
|
||||||
def _try_convert(value):
|
def _try_convert(value):
|
||||||
"""Return a non-string if possible"""
|
"""Return a non-string if possible"""
|
||||||
if value == 'None':
|
if value == 'None':
|
||||||
@@ -59,12 +60,12 @@ def _try_convert(value):
|
|||||||
return value
|
return value
|
||||||
if valueneg[0] == '0':
|
if valueneg[0] == '0':
|
||||||
if valueneg[1] in 'xX':
|
if valueneg[1] in 'xX':
|
||||||
return int(value,16)
|
return int(value, 16)
|
||||||
elif valueneg[1] in 'bB':
|
elif valueneg[1] in 'bB':
|
||||||
return int(value,2)
|
return int(value, 2)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return int(value,8)
|
return int(value, 8)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
@@ -80,6 +81,7 @@ def _try_convert(value):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class APIRequest(object):
|
class APIRequest(object):
|
||||||
def __init__(self, controller, action):
|
def __init__(self, controller, action):
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
@@ -48,6 +48,7 @@ flags.DECLARE('storage_availability_zone', 'nova.volume.manager')
|
|||||||
|
|
||||||
InvalidInputException = exception.InvalidInputException
|
InvalidInputException = exception.InvalidInputException
|
||||||
|
|
||||||
|
|
||||||
class QuotaError(exception.ApiError):
|
class QuotaError(exception.ApiError):
|
||||||
"""Quota Exceeeded"""
|
"""Quota Exceeeded"""
|
||||||
pass
|
pass
|
||||||
@@ -137,8 +138,8 @@ class CloudController(object):
|
|||||||
for node in nodes:
|
for node in nodes:
|
||||||
rpc.cast(context,
|
rpc.cast(context,
|
||||||
'%s.%s' % (FLAGS.compute_topic, node),
|
'%s.%s' % (FLAGS.compute_topic, node),
|
||||||
{ "method": "refresh_security_group",
|
{"method": "refresh_security_group",
|
||||||
"args": {"security_group_id": security_group.id}})
|
"args": {"security_group_id": security_group.id}})
|
||||||
|
|
||||||
def get_metadata(self, address):
|
def get_metadata(self, address):
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
@@ -147,48 +148,42 @@ class CloudController(object):
|
|||||||
return None
|
return None
|
||||||
mpi = self._get_mpi_data(ctxt, instance_ref['project_id'])
|
mpi = self._get_mpi_data(ctxt, instance_ref['project_id'])
|
||||||
if instance_ref['key_name']:
|
if instance_ref['key_name']:
|
||||||
keys = {
|
keys = {'0': {'_name': instance_ref['key_name'],
|
||||||
'0': {
|
'openssh-key': instance_ref['key_data']}}
|
||||||
'_name': instance_ref['key_name'],
|
|
||||||
'openssh-key': instance_ref['key_data']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else:
|
else:
|
||||||
keys = ''
|
keys = ''
|
||||||
hostname = instance_ref['hostname']
|
hostname = instance_ref['hostname']
|
||||||
floating_ip = db.instance_get_floating_address(ctxt,
|
floating_ip = db.instance_get_floating_address(ctxt,
|
||||||
instance_ref['id'])
|
instance_ref['id'])
|
||||||
|
ec2_id = internal_id_to_ec2_id(instance_ref['internal_id'])
|
||||||
data = {
|
data = {
|
||||||
'user-data': base64.b64decode(instance_ref['user_data']),
|
'user-data': base64.b64decode(instance_ref['user_data']),
|
||||||
'meta-data': {
|
'meta-data': {
|
||||||
'ami-id': instance_ref['image_id'],
|
'ami-id': instance_ref['image_id'],
|
||||||
'ami-launch-index': instance_ref['launch_index'],
|
'ami-launch-index': instance_ref['launch_index'],
|
||||||
'ami-manifest-path': 'FIXME',
|
'ami-manifest-path': 'FIXME',
|
||||||
'block-device-mapping': { # TODO(vish): replace with real data
|
'block-device-mapping': {
|
||||||
|
# TODO(vish): replace with real data
|
||||||
'ami': 'sda1',
|
'ami': 'sda1',
|
||||||
'ephemeral0': 'sda2',
|
'ephemeral0': 'sda2',
|
||||||
'root': '/dev/sda1',
|
'root': '/dev/sda1',
|
||||||
'swap': 'sda3'
|
'swap': 'sda3'},
|
||||||
},
|
|
||||||
'hostname': hostname,
|
'hostname': hostname,
|
||||||
'instance-action': 'none',
|
'instance-action': 'none',
|
||||||
'instance-id': internal_id_to_ec2_id(instance_ref['internal_id']),
|
'instance-id': ec2_id,
|
||||||
'instance-type': instance_ref['instance_type'],
|
'instance-type': instance_ref['instance_type'],
|
||||||
'local-hostname': hostname,
|
'local-hostname': hostname,
|
||||||
'local-ipv4': address,
|
'local-ipv4': address,
|
||||||
'kernel-id': instance_ref['kernel_id'],
|
'kernel-id': instance_ref['kernel_id'],
|
||||||
'placement': {
|
# TODO(vish): real zone
|
||||||
'availability-zone': 'nova' # TODO(vish): real zone
|
'placement': {'availability-zone': 'nova'},
|
||||||
},
|
|
||||||
'public-hostname': hostname,
|
'public-hostname': hostname,
|
||||||
'public-ipv4': floating_ip or '',
|
'public-ipv4': floating_ip or '',
|
||||||
'public-keys': keys,
|
'public-keys': keys,
|
||||||
'ramdisk-id': instance_ref['ramdisk_id'],
|
'ramdisk-id': instance_ref['ramdisk_id'],
|
||||||
'reservation-id': instance_ref['reservation_id'],
|
'reservation-id': instance_ref['reservation_id'],
|
||||||
'security-groups': '',
|
'security-groups': '',
|
||||||
'mpi': mpi
|
'mpi': mpi}}
|
||||||
}
|
|
||||||
}
|
|
||||||
if False: # TODO(vish): store ancestor ids
|
if False: # TODO(vish): store ancestor ids
|
||||||
data['ancestor-ami-ids'] = []
|
data['ancestor-ami-ids'] = []
|
||||||
if False: # TODO(vish): store product codes
|
if False: # TODO(vish): store product codes
|
||||||
@@ -211,7 +206,7 @@ class CloudController(object):
|
|||||||
'regionEndpoint': FLAGS.ec2_url}]
|
'regionEndpoint': FLAGS.ec2_url}]
|
||||||
if region_name:
|
if region_name:
|
||||||
regions = [r for r in regions if r['regionName'] in region_name]
|
regions = [r for r in regions if r['regionName'] in region_name]
|
||||||
return {'regionInfo': regions }
|
return {'regionInfo': regions}
|
||||||
|
|
||||||
def describe_snapshots(self,
|
def describe_snapshots(self,
|
||||||
context,
|
context,
|
||||||
@@ -237,7 +232,8 @@ class CloudController(object):
|
|||||||
for key_pair in key_pairs:
|
for key_pair in key_pairs:
|
||||||
# filter out the vpn keys
|
# filter out the vpn keys
|
||||||
suffix = FLAGS.vpn_key_suffix
|
suffix = FLAGS.vpn_key_suffix
|
||||||
if context.user.is_admin() or not key_pair['name'].endswith(suffix):
|
if context.user.is_admin() or \
|
||||||
|
not key_pair['name'].endswith(suffix):
|
||||||
result.append({
|
result.append({
|
||||||
'keyName': key_pair['name'],
|
'keyName': key_pair['name'],
|
||||||
'keyFingerprint': key_pair['fingerprint'],
|
'keyFingerprint': key_pair['fingerprint'],
|
||||||
@@ -271,7 +267,7 @@ class CloudController(object):
|
|||||||
if not group_name is None:
|
if not group_name is None:
|
||||||
groups = [g for g in groups if g.name in group_name]
|
groups = [g for g in groups if g.name in group_name]
|
||||||
|
|
||||||
return {'securityGroupInfo': groups }
|
return {'securityGroupInfo': groups}
|
||||||
|
|
||||||
def _format_security_group(self, context, group):
|
def _format_security_group(self, context, group):
|
||||||
g = {}
|
g = {}
|
||||||
@@ -295,13 +291,10 @@ class CloudController(object):
|
|||||||
g['ipPermissions'] += [r]
|
g['ipPermissions'] += [r]
|
||||||
return g
|
return g
|
||||||
|
|
||||||
|
def _revoke_rule_args_to_dict(self, context, to_port=None, from_port=None,
|
||||||
def _authorize_revoke_rule_args_to_dict(self, context,
|
ip_protocol=None, cidr_ip=None, user_id=None,
|
||||||
to_port=None, from_port=None,
|
source_security_group_name=None,
|
||||||
ip_protocol=None, cidr_ip=None,
|
source_security_group_owner_id=None):
|
||||||
user_id=None,
|
|
||||||
source_security_group_name=None,
|
|
||||||
source_security_group_owner_id=None):
|
|
||||||
|
|
||||||
values = {}
|
values = {}
|
||||||
|
|
||||||
@@ -322,16 +315,16 @@ class CloudController(object):
|
|||||||
values['cidr'] = '0.0.0.0/0'
|
values['cidr'] = '0.0.0.0/0'
|
||||||
|
|
||||||
if ip_protocol and from_port and to_port:
|
if ip_protocol and from_port and to_port:
|
||||||
from_port = int(from_port)
|
from_port = int(from_port)
|
||||||
to_port = int(to_port)
|
to_port = int(to_port)
|
||||||
ip_protocol = str(ip_protocol)
|
ip_protocol = str(ip_protocol)
|
||||||
|
|
||||||
if ip_protocol.upper() not in ['TCP','UDP','ICMP']:
|
if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
|
||||||
raise InvalidInputException('%s is not a valid ipProtocol' %
|
raise InvalidInputException('%s is not a valid ipProtocol' %
|
||||||
(ip_protocol,))
|
(ip_protocol,))
|
||||||
if ((min(from_port, to_port) < -1) or
|
if ((min(from_port, to_port) < -1) or
|
||||||
(max(from_port, to_port) > 65535)):
|
(max(from_port, to_port) > 65535)):
|
||||||
raise InvalidInputException('Invalid port range')
|
raise InvalidInputException('Invalid port range')
|
||||||
|
|
||||||
values['protocol'] = ip_protocol
|
values['protocol'] = ip_protocol
|
||||||
values['from_port'] = from_port
|
values['from_port'] = from_port
|
||||||
@@ -343,7 +336,6 @@ class CloudController(object):
|
|||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _security_group_rule_exists(self, security_group, values):
|
def _security_group_rule_exists(self, security_group, values):
|
||||||
"""Indicates whether the specified rule values are already
|
"""Indicates whether the specified rule values are already
|
||||||
defined in the given security group.
|
defined in the given security group.
|
||||||
@@ -362,20 +354,19 @@ class CloudController(object):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def revoke_security_group_ingress(self, context, group_name, **kwargs):
|
def revoke_security_group_ingress(self, context, group_name, **kwargs):
|
||||||
self._ensure_default_security_group(context)
|
self._ensure_default_security_group(context)
|
||||||
security_group = db.security_group_get_by_name(context,
|
security_group = db.security_group_get_by_name(context,
|
||||||
context.project_id,
|
context.project_id,
|
||||||
group_name)
|
group_name)
|
||||||
|
|
||||||
criteria = self._authorize_revoke_rule_args_to_dict(context, **kwargs)
|
criteria = self._revoke_rule_args_to_dict(context, **kwargs)
|
||||||
if criteria == None:
|
if criteria == None:
|
||||||
raise exception.ApiError("No rule for the specified parameters.")
|
raise exception.ApiError("No rule for the specified parameters.")
|
||||||
|
|
||||||
for rule in security_group.rules:
|
for rule in security_group.rules:
|
||||||
match = True
|
match = True
|
||||||
for (k,v) in criteria.iteritems():
|
for (k, v) in criteria.iteritems():
|
||||||
if getattr(rule, k, False) != v:
|
if getattr(rule, k, False) != v:
|
||||||
match = False
|
match = False
|
||||||
if match:
|
if match:
|
||||||
@@ -394,7 +385,7 @@ class CloudController(object):
|
|||||||
context.project_id,
|
context.project_id,
|
||||||
group_name)
|
group_name)
|
||||||
|
|
||||||
values = self._authorize_revoke_rule_args_to_dict(context, **kwargs)
|
values = self._revoke_rule_args_to_dict(context, **kwargs)
|
||||||
values['parent_group_id'] = security_group.id
|
values['parent_group_id'] = security_group.id
|
||||||
|
|
||||||
if self._security_group_rule_exists(security_group, values):
|
if self._security_group_rule_exists(security_group, values):
|
||||||
@@ -407,7 +398,6 @@ class CloudController(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _get_source_project_id(self, context, source_security_group_owner_id):
|
def _get_source_project_id(self, context, source_security_group_owner_id):
|
||||||
if source_security_group_owner_id:
|
if source_security_group_owner_id:
|
||||||
# Parse user:project for source group.
|
# Parse user:project for source group.
|
||||||
@@ -425,13 +415,12 @@ class CloudController(object):
|
|||||||
|
|
||||||
return source_project_id
|
return source_project_id
|
||||||
|
|
||||||
|
|
||||||
def create_security_group(self, context, group_name, group_description):
|
def create_security_group(self, context, group_name, group_description):
|
||||||
self._ensure_default_security_group(context)
|
self._ensure_default_security_group(context)
|
||||||
if db.security_group_exists(context, context.project_id, group_name):
|
if db.security_group_exists(context, context.project_id, group_name):
|
||||||
raise exception.ApiError('group %s already exists' % group_name)
|
raise exception.ApiError('group %s already exists' % group_name)
|
||||||
|
|
||||||
group = {'user_id' : context.user.id,
|
group = {'user_id': context.user.id,
|
||||||
'project_id': context.project_id,
|
'project_id': context.project_id,
|
||||||
'name': group_name,
|
'name': group_name,
|
||||||
'description': group_description}
|
'description': group_description}
|
||||||
@@ -440,7 +429,6 @@ class CloudController(object):
|
|||||||
return {'securityGroupSet': [self._format_security_group(context,
|
return {'securityGroupSet': [self._format_security_group(context,
|
||||||
group_ref)]}
|
group_ref)]}
|
||||||
|
|
||||||
|
|
||||||
def delete_security_group(self, context, group_name, **kwargs):
|
def delete_security_group(self, context, group_name, **kwargs):
|
||||||
security_group = db.security_group_get_by_name(context,
|
security_group = db.security_group_get_by_name(context,
|
||||||
context.project_id,
|
context.project_id,
|
||||||
@@ -448,7 +436,6 @@ class CloudController(object):
|
|||||||
db.security_group_destroy(context, security_group.id)
|
db.security_group_destroy(context, security_group.id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def get_console_output(self, context, instance_id, **kwargs):
|
def get_console_output(self, context, instance_id, **kwargs):
|
||||||
# instance_id is passed in as a list of instances
|
# instance_id is passed in as a list of instances
|
||||||
ec2_id = instance_id[0]
|
ec2_id = instance_id[0]
|
||||||
@@ -457,13 +444,13 @@ class CloudController(object):
|
|||||||
output = rpc.call(context,
|
output = rpc.call(context,
|
||||||
'%s.%s' % (FLAGS.compute_topic,
|
'%s.%s' % (FLAGS.compute_topic,
|
||||||
instance_ref['host']),
|
instance_ref['host']),
|
||||||
{"method" : "get_console_output",
|
{"method": "get_console_output",
|
||||||
"args" : {"instance_id": instance_ref['id']}})
|
"args": {"instance_id": instance_ref['id']}})
|
||||||
|
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
return { "InstanceId" : ec2_id,
|
return {"InstanceId": ec2_id,
|
||||||
"Timestamp" : now,
|
"Timestamp": now,
|
||||||
"output" : base64.b64encode(output) }
|
"output": base64.b64encode(output)}
|
||||||
|
|
||||||
def describe_volumes(self, context, **kwargs):
|
def describe_volumes(self, context, **kwargs):
|
||||||
if context.user.is_admin():
|
if context.user.is_admin():
|
||||||
@@ -530,7 +517,6 @@ class CloudController(object):
|
|||||||
|
|
||||||
return {'volumeSet': [self._format_volume(context, volume_ref)]}
|
return {'volumeSet': [self._format_volume(context, volume_ref)]}
|
||||||
|
|
||||||
|
|
||||||
def attach_volume(self, context, volume_id, instance_id, device, **kwargs):
|
def attach_volume(self, context, volume_id, instance_id, device, **kwargs):
|
||||||
volume_ref = db.volume_get_by_ec2_id(context, volume_id)
|
volume_ref = db.volume_get_by_ec2_id(context, volume_id)
|
||||||
# TODO(vish): abstract status checking?
|
# TODO(vish): abstract status checking?
|
||||||
@@ -633,8 +619,7 @@ class CloudController(object):
|
|||||||
i['imageId'] = instance['image_id']
|
i['imageId'] = instance['image_id']
|
||||||
i['instanceState'] = {
|
i['instanceState'] = {
|
||||||
'code': instance['state'],
|
'code': instance['state'],
|
||||||
'name': instance['state_description']
|
'name': instance['state_description']}
|
||||||
}
|
|
||||||
fixed_addr = None
|
fixed_addr = None
|
||||||
floating_addr = None
|
floating_addr = None
|
||||||
if instance['fixed_ip']:
|
if instance['fixed_ip']:
|
||||||
@@ -656,7 +641,7 @@ class CloudController(object):
|
|||||||
i['amiLaunchIndex'] = instance['launch_index']
|
i['amiLaunchIndex'] = instance['launch_index']
|
||||||
i['displayName'] = instance['display_name']
|
i['displayName'] = instance['display_name']
|
||||||
i['displayDescription'] = instance['display_description']
|
i['displayDescription'] = instance['display_description']
|
||||||
if not reservations.has_key(instance['reservation_id']):
|
if instance['reservation_id'] not in reservations:
|
||||||
r = {}
|
r = {}
|
||||||
r['reservationId'] = instance['reservation_id']
|
r['reservationId'] = instance['reservation_id']
|
||||||
r['ownerId'] = instance['project_id']
|
r['ownerId'] = instance['project_id']
|
||||||
@@ -757,10 +742,10 @@ class CloudController(object):
|
|||||||
context.project_id,
|
context.project_id,
|
||||||
'default')
|
'default')
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
values = { 'name' : 'default',
|
values = {'name': 'default',
|
||||||
'description' : 'default',
|
'description': 'default',
|
||||||
'user_id' : context.user.id,
|
'user_id': context.user.id,
|
||||||
'project_id' : context.project_id }
|
'project_id': context.project_id}
|
||||||
group = db.security_group_create(context, values)
|
group = db.security_group_create(context, values)
|
||||||
|
|
||||||
def run_instances(self, context, **kwargs):
|
def run_instances(self, context, **kwargs):
|
||||||
@@ -804,7 +789,7 @@ class CloudController(object):
|
|||||||
logging.debug("Going to run %s instances...", num_instances)
|
logging.debug("Going to run %s instances...", num_instances)
|
||||||
launch_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
|
launch_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
|
||||||
key_data = None
|
key_data = None
|
||||||
if kwargs.has_key('key_name'):
|
if 'key_name' in kwargs:
|
||||||
key_pair_ref = db.key_pair_get(context,
|
key_pair_ref = db.key_pair_get(context,
|
||||||
context.user.id,
|
context.user.id,
|
||||||
kwargs['key_name'])
|
kwargs['key_name'])
|
||||||
@@ -883,7 +868,6 @@ class CloudController(object):
|
|||||||
(context.project.name, context.user.name, inst_id))
|
(context.project.name, context.user.name, inst_id))
|
||||||
return self._format_run_instances(context, reservation_id)
|
return self._format_run_instances(context, reservation_id)
|
||||||
|
|
||||||
|
|
||||||
def terminate_instances(self, context, instance_id, **kwargs):
|
def terminate_instances(self, context, instance_id, **kwargs):
|
||||||
"""Terminate each instance in instance_id, which is a list of ec2 ids.
|
"""Terminate each instance in instance_id, which is a list of ec2 ids.
|
||||||
|
|
||||||
@@ -991,7 +975,7 @@ class CloudController(object):
|
|||||||
|
|
||||||
def register_image(self, context, image_location=None, **kwargs):
|
def register_image(self, context, image_location=None, **kwargs):
|
||||||
# FIXME: should the objectstore be doing these authorization checks?
|
# FIXME: should the objectstore be doing these authorization checks?
|
||||||
if image_location is None and kwargs.has_key('name'):
|
if image_location is None and 'name' in kwargs:
|
||||||
image_location = kwargs['name']
|
image_location = kwargs['name']
|
||||||
image_id = images.register(context, image_location)
|
image_id = images.register(context, image_location)
|
||||||
logging.debug("Registered %s as %s" % (image_location, image_id))
|
logging.debug("Registered %s as %s" % (image_location, image_id))
|
||||||
@@ -1009,7 +993,8 @@ class CloudController(object):
|
|||||||
result['launchPermission'].append({'group': 'all'})
|
result['launchPermission'].append({'group': 'all'})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def modify_image_attribute(self, context, image_id, attribute, operation_type, **kwargs):
|
def modify_image_attribute(self, context, image_id, attribute,
|
||||||
|
operation_type, **kwargs):
|
||||||
# TODO(devcamcar): Support users and groups other than 'all'.
|
# TODO(devcamcar): Support users and groups other than 'all'.
|
||||||
if attribute != 'launchPermission':
|
if attribute != 'launchPermission':
|
||||||
raise exception.ApiError('attribute not supported: %s' % attribute)
|
raise exception.ApiError('attribute not supported: %s' % attribute)
|
||||||
|
@@ -43,6 +43,7 @@ def modify(context, image_id, operation):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def update(context, image_id, attributes):
|
def update(context, image_id, attributes):
|
||||||
"""update an image's attributes / info.json"""
|
"""update an image's attributes / info.json"""
|
||||||
attributes.update({"image_id": image_id})
|
attributes.update({"image_id": image_id})
|
||||||
@@ -52,6 +53,7 @@ def update(context, image_id, attributes):
|
|||||||
query_args=qs(attributes))
|
query_args=qs(attributes))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def register(context, image_location):
|
def register(context, image_location):
|
||||||
""" rpc call to register a new image based from a manifest """
|
""" rpc call to register a new image based from a manifest """
|
||||||
|
|
||||||
@@ -64,13 +66,14 @@ def register(context, image_location):
|
|||||||
|
|
||||||
return image_id
|
return image_id
|
||||||
|
|
||||||
|
|
||||||
def list(context, filter_list=[]):
|
def list(context, filter_list=[]):
|
||||||
""" return a list of all images that a user can see
|
""" return a list of all images that a user can see
|
||||||
|
|
||||||
optionally filtered by a list of image_id """
|
optionally filtered by a list of image_id """
|
||||||
|
|
||||||
if FLAGS.connection_type == 'fake':
|
if FLAGS.connection_type == 'fake':
|
||||||
return [{ 'imageId' : 'bar'}]
|
return [{'imageId': 'bar'}]
|
||||||
|
|
||||||
# FIXME: send along the list of only_images to check for
|
# FIXME: send along the list of only_images to check for
|
||||||
response = conn(context).make_request(
|
response = conn(context).make_request(
|
||||||
@@ -82,6 +85,7 @@ def list(context, filter_list=[]):
|
|||||||
return [i for i in result if i['imageId'] in filter_list]
|
return [i for i in result if i['imageId'] in filter_list]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get(context, image_id):
|
def get(context, image_id):
|
||||||
"""return a image object if the context has permissions"""
|
"""return a image object if the context has permissions"""
|
||||||
result = list(context, [image_id])
|
result = list(context, [image_id])
|
||||||
|
@@ -27,7 +27,6 @@ from nova.api.ec2 import cloud
|
|||||||
|
|
||||||
|
|
||||||
class MetadataRequestHandler(object):
|
class MetadataRequestHandler(object):
|
||||||
|
|
||||||
"""Serve metadata from the EC2 API."""
|
"""Serve metadata from the EC2 API."""
|
||||||
|
|
||||||
def print_data(self, data):
|
def print_data(self, data):
|
||||||
@@ -43,7 +42,8 @@ class MetadataRequestHandler(object):
|
|||||||
else:
|
else:
|
||||||
output += '/'
|
output += '/'
|
||||||
output += '\n'
|
output += '\n'
|
||||||
return output[:-1] # cut off last \n
|
# Cut off last \n
|
||||||
|
return output[:-1]
|
||||||
elif isinstance(data, list):
|
elif isinstance(data, list):
|
||||||
return '\n'.join(data)
|
return '\n'.join(data)
|
||||||
else:
|
else:
|
||||||
@@ -65,7 +65,8 @@ class MetadataRequestHandler(object):
|
|||||||
cc = cloud.CloudController()
|
cc = cloud.CloudController()
|
||||||
meta_data = cc.get_metadata(req.remote_addr)
|
meta_data = cc.get_metadata(req.remote_addr)
|
||||||
if meta_data is None:
|
if meta_data is None:
|
||||||
logging.error('Failed to get metadata for ip: %s' % req.remote_addr)
|
logging.error('Failed to get metadata for ip: %s' %
|
||||||
|
req.remote_addr)
|
||||||
raise webob.exc.HTTPNotFound()
|
raise webob.exc.HTTPNotFound()
|
||||||
data = self.lookup(req.path_info, meta_data)
|
data = self.lookup(req.path_info, meta_data)
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@@ -46,6 +46,7 @@ flags.DEFINE_string('nova_api_auth',
|
|||||||
'nova.api.openstack.auth.BasicApiAuthManager',
|
'nova.api.openstack.auth.BasicApiAuthManager',
|
||||||
'The auth mechanism to use for the OpenStack API implemenation')
|
'The auth mechanism to use for the OpenStack API implemenation')
|
||||||
|
|
||||||
|
|
||||||
class API(wsgi.Middleware):
|
class API(wsgi.Middleware):
|
||||||
"""WSGI entry point for all OpenStack API requests."""
|
"""WSGI entry point for all OpenStack API requests."""
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ class API(wsgi.Middleware):
|
|||||||
app = AuthMiddleware(RateLimitingMiddleware(APIRouter()))
|
app = AuthMiddleware(RateLimitingMiddleware(APIRouter()))
|
||||||
super(API, self).__init__(app)
|
super(API, self).__init__(app)
|
||||||
|
|
||||||
|
|
||||||
class AuthMiddleware(wsgi.Middleware):
|
class AuthMiddleware(wsgi.Middleware):
|
||||||
"""Authorize the openstack API request or return an HTTP Forbidden."""
|
"""Authorize the openstack API request or return an HTTP Forbidden."""
|
||||||
|
|
||||||
@@ -62,7 +64,7 @@ class AuthMiddleware(wsgi.Middleware):
|
|||||||
|
|
||||||
@webob.dec.wsgify
|
@webob.dec.wsgify
|
||||||
def __call__(self, req):
|
def __call__(self, req):
|
||||||
if not req.headers.has_key("X-Auth-Token"):
|
if 'X-Auth-Token' not in req.headers:
|
||||||
return self.auth_driver.authenticate(req)
|
return self.auth_driver.authenticate(req)
|
||||||
|
|
||||||
user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"])
|
user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"])
|
||||||
@@ -70,11 +72,12 @@ class AuthMiddleware(wsgi.Middleware):
|
|||||||
if not user:
|
if not user:
|
||||||
return faults.Fault(webob.exc.HTTPUnauthorized())
|
return faults.Fault(webob.exc.HTTPUnauthorized())
|
||||||
|
|
||||||
if not req.environ.has_key('nova.context'):
|
if 'nova.context' not in req.environ:
|
||||||
req.environ['nova.context'] = {}
|
req.environ['nova.context'] = {}
|
||||||
req.environ['nova.context']['user'] = user
|
req.environ['nova.context']['user'] = user
|
||||||
return self.application
|
return self.application
|
||||||
|
|
||||||
|
|
||||||
class RateLimitingMiddleware(wsgi.Middleware):
|
class RateLimitingMiddleware(wsgi.Middleware):
|
||||||
"""Rate limit incoming requests according to the OpenStack rate limits."""
|
"""Rate limit incoming requests according to the OpenStack rate limits."""
|
||||||
|
|
||||||
@@ -108,7 +111,8 @@ class RateLimitingMiddleware(wsgi.Middleware):
|
|||||||
"""
|
"""
|
||||||
user_id = req.environ['nova.context']['user']['id']
|
user_id = req.environ['nova.context']['user']['id']
|
||||||
action_name = self.get_action_name(req)
|
action_name = self.get_action_name(req)
|
||||||
if not action_name: # not rate limited
|
if not action_name:
|
||||||
|
# Not rate limited
|
||||||
return self.application
|
return self.application
|
||||||
delay = self.get_delay(action_name, user_id)
|
delay = self.get_delay(action_name, user_id)
|
||||||
if delay:
|
if delay:
|
||||||
@@ -152,13 +156,13 @@ class APIRouter(wsgi.Router):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
mapper = routes.Mapper()
|
mapper = routes.Mapper()
|
||||||
mapper.resource("server", "servers", controller=servers.Controller(),
|
mapper.resource("server", "servers", controller=servers.Controller(),
|
||||||
collection={ 'detail': 'GET'},
|
collection={'detail': 'GET'},
|
||||||
member={'action':'POST'})
|
member={'action': 'POST'})
|
||||||
|
|
||||||
mapper.resource("backup_schedule", "backup_schedules",
|
mapper.resource("backup_schedule", "backup_schedules",
|
||||||
controller=backup_schedules.Controller(),
|
controller=backup_schedules.Controller(),
|
||||||
parent_resource=dict(member_name='server',
|
parent_resource=dict(member_name='server',
|
||||||
collection_name = 'servers'))
|
collection_name='servers'))
|
||||||
|
|
||||||
mapper.resource("image", "images", controller=images.Controller(),
|
mapper.resource("image", "images", controller=images.Controller(),
|
||||||
collection={'detail': 'GET'})
|
collection={'detail': 'GET'})
|
||||||
@@ -187,4 +191,3 @@ def limited(items, req):
|
|||||||
limit = min(1000, limit)
|
limit = min(1000, limit)
|
||||||
range_end = offset + limit
|
range_end = offset + limit
|
||||||
return items[offset:range_end]
|
return items[offset:range_end]
|
||||||
|
|
||||||
|
@@ -15,9 +15,11 @@ from nova.api.openstack import faults
|
|||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
|
|
||||||
class Context(object):
|
class Context(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BasicApiAuthManager(object):
|
class BasicApiAuthManager(object):
|
||||||
""" Implements a somewhat rudimentary version of OpenStack Auth"""
|
""" Implements a somewhat rudimentary version of OpenStack Auth"""
|
||||||
|
|
||||||
@@ -98,4 +100,3 @@ class BasicApiAuthManager(object):
|
|||||||
|
|
||||||
def _get_server_mgmt_url(self):
|
def _get_server_mgmt_url(self):
|
||||||
return 'https://%s/v1.0/' % self.host
|
return 'https://%s/v1.0/' % self.host
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ from nova import wsgi
|
|||||||
from nova.api.openstack import faults
|
from nova.api.openstack import faults
|
||||||
import nova.image.service
|
import nova.image.service
|
||||||
|
|
||||||
|
|
||||||
class Controller(wsgi.Controller):
|
class Controller(wsgi.Controller):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
@@ -22,16 +22,14 @@ from nova.compute import instance_types
|
|||||||
from nova import wsgi
|
from nova import wsgi
|
||||||
import nova.api.openstack
|
import nova.api.openstack
|
||||||
|
|
||||||
|
|
||||||
class Controller(wsgi.Controller):
|
class Controller(wsgi.Controller):
|
||||||
"""Flavor controller for the OpenStack API."""
|
"""Flavor controller for the OpenStack API."""
|
||||||
|
|
||||||
_serialization_metadata = {
|
_serialization_metadata = {
|
||||||
'application/xml': {
|
'application/xml': {
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"flavor": [ "id", "name", "ram", "disk" ]
|
"flavor": ["id", "name", "ram", "disk"]}}}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
"""Return all flavors in brief."""
|
"""Return all flavors in brief."""
|
||||||
|
@@ -27,16 +27,14 @@ from nova.api.openstack import faults
|
|||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
|
|
||||||
class Controller(wsgi.Controller):
|
class Controller(wsgi.Controller):
|
||||||
|
|
||||||
_serialization_metadata = {
|
_serialization_metadata = {
|
||||||
'application/xml': {
|
'application/xml': {
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"image": [ "id", "name", "updated", "created", "status",
|
"image": ["id", "name", "updated", "created", "status",
|
||||||
"serverId", "progress" ]
|
"serverId", "progress"]}}}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._service = utils.import_object(FLAGS.image_service)
|
self._service = utils.import_object(FLAGS.image_service)
|
||||||
|
@@ -13,6 +13,7 @@ PER_MINUTE = 60
|
|||||||
PER_HOUR = 60 * 60
|
PER_HOUR = 60 * 60
|
||||||
PER_DAY = 60 * 60 * 24
|
PER_DAY = 60 * 60 * 24
|
||||||
|
|
||||||
|
|
||||||
class Limiter(object):
|
class Limiter(object):
|
||||||
|
|
||||||
"""Class providing rate limiting of arbitrary actions."""
|
"""Class providing rate limiting of arbitrary actions."""
|
||||||
@@ -101,7 +102,8 @@ class WSGIApp(object):
|
|||||||
return webob.exc.HTTPForbidden(
|
return webob.exc.HTTPForbidden(
|
||||||
headers={'X-Wait-Seconds': "%.2f" % delay})
|
headers={'X-Wait-Seconds': "%.2f" % delay})
|
||||||
else:
|
else:
|
||||||
return '' # 200 OK
|
# 200 OK
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class WSGIAppProxy(object):
|
class WSGIAppProxy(object):
|
||||||
@@ -118,5 +120,6 @@ class WSGIAppProxy(object):
|
|||||||
conn.request('POST', '/limiter/%s/%s' % (username, action))
|
conn.request('POST', '/limiter/%s/%s' % (username, action))
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
if resp.status == 200:
|
if resp.status == 200:
|
||||||
return None # no delay
|
# No delay
|
||||||
|
return None
|
||||||
return float(resp.getheader('X-Wait-Seconds'))
|
return float(resp.getheader('X-Wait-Seconds'))
|
||||||
|
@@ -34,30 +34,32 @@ import nova.image.service
|
|||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
|
|
||||||
def _filter_params(inst_dict):
|
def _filter_params(inst_dict):
|
||||||
""" Extracts all updatable parameters for a server update request """
|
""" Extracts all updatable parameters for a server update request """
|
||||||
keys = dict(name='name', admin_pass='adminPass')
|
keys = dict(name='name', admin_pass='adminPass')
|
||||||
new_attrs = {}
|
new_attrs = {}
|
||||||
for k, v in keys.items():
|
for k, v in keys.items():
|
||||||
if inst_dict.has_key(v):
|
if v in inst_dict:
|
||||||
new_attrs[k] = inst_dict[v]
|
new_attrs[k] = inst_dict[v]
|
||||||
return new_attrs
|
return new_attrs
|
||||||
|
|
||||||
|
|
||||||
def _entity_list(entities):
|
def _entity_list(entities):
|
||||||
""" Coerces a list of servers into proper dictionary format """
|
""" Coerces a list of servers into proper dictionary format """
|
||||||
return dict(servers=entities)
|
return dict(servers=entities)
|
||||||
|
|
||||||
|
|
||||||
def _entity_detail(inst):
|
def _entity_detail(inst):
|
||||||
""" Maps everything to Rackspace-like attributes for return"""
|
""" Maps everything to Rackspace-like attributes for return"""
|
||||||
power_mapping = {
|
power_mapping = {
|
||||||
power_state.NOSTATE: 'build',
|
power_state.NOSTATE: 'build',
|
||||||
power_state.RUNNING: 'active',
|
power_state.RUNNING: 'active',
|
||||||
power_state.BLOCKED: 'active',
|
power_state.BLOCKED: 'active',
|
||||||
power_state.PAUSED: 'suspended',
|
power_state.PAUSED: 'suspended',
|
||||||
power_state.SHUTDOWN: 'active',
|
power_state.SHUTDOWN: 'active',
|
||||||
power_state.SHUTOFF: 'active',
|
power_state.SHUTOFF: 'active',
|
||||||
power_state.CRASHED: 'error'
|
power_state.CRASHED: 'error'}
|
||||||
}
|
|
||||||
inst_dict = {}
|
inst_dict = {}
|
||||||
|
|
||||||
mapped_keys = dict(status='state', imageId='image_id',
|
mapped_keys = dict(status='state', imageId='image_id',
|
||||||
@@ -73,21 +75,20 @@ def _entity_detail(inst):
|
|||||||
|
|
||||||
return dict(server=inst_dict)
|
return dict(server=inst_dict)
|
||||||
|
|
||||||
|
|
||||||
def _entity_inst(inst):
|
def _entity_inst(inst):
|
||||||
""" Filters all model attributes save for id and name """
|
""" Filters all model attributes save for id and name """
|
||||||
return dict(server=dict(id=inst['id'], name=inst['server_name']))
|
return dict(server=dict(id=inst['id'], name=inst['server_name']))
|
||||||
|
|
||||||
|
|
||||||
class Controller(wsgi.Controller):
|
class Controller(wsgi.Controller):
|
||||||
""" The Server API controller for the OpenStack API """
|
""" The Server API controller for the OpenStack API """
|
||||||
|
|
||||||
_serialization_metadata = {
|
_serialization_metadata = {
|
||||||
'application/xml': {
|
'application/xml': {
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"server": [ "id", "imageId", "name", "flavorId", "hostId",
|
"server": ["id", "imageId", "name", "flavorId", "hostId",
|
||||||
"status", "progress", "progress" ]
|
"status", "progress", "progress"]}}}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, db_driver=None):
|
def __init__(self, db_driver=None):
|
||||||
if not db_driver:
|
if not db_driver:
|
||||||
@@ -209,7 +210,7 @@ class Controller(wsgi.Controller):
|
|||||||
image = img_service.show(image_id)
|
image = img_service.show(image_id)
|
||||||
|
|
||||||
if not image:
|
if not image:
|
||||||
raise Exception, "Image not found"
|
raise Exception("Image not found")
|
||||||
|
|
||||||
inst['server_name'] = env['server']['name']
|
inst['server_name'] = env['server']['name']
|
||||||
inst['image_id'] = image_id
|
inst['image_id'] = image_id
|
||||||
|
@@ -17,4 +17,6 @@
|
|||||||
|
|
||||||
from nova import wsgi
|
from nova import wsgi
|
||||||
|
|
||||||
class Controller(wsgi.Controller): pass
|
|
||||||
|
class Controller(wsgi.Controller):
|
||||||
|
pass
|
||||||
|
Reference in New Issue
Block a user