diff options
| author | Eric Day <eday@oddments.org> | 2010-10-22 21:58:59 +0000 |
|---|---|---|
| committer | Tarmac <> | 2010-10-22 21:58:59 +0000 |
| commit | e8ffba4d2384b91b154ef1f73df9afd49077386d (patch) | |
| tree | 35bdf833d47eb09f3ffcd421da9cdadf0064127e | |
| parent | 685e2a1b4b359c1f7e8ec72817c2c420f2b26a18 (diff) | |
| parent | 777b14c27ba9bd5ee298f62323b2170023e44ca6 (diff) | |
| download | nova-e8ffba4d2384b91b154ef1f73df9afd49077386d.tar.gz nova-e8ffba4d2384b91b154ef1f73df9afd49077386d.tar.xz nova-e8ffba4d2384b91b154ef1f73df9afd49077386d.zip | |
Another pep8 cleanup branch for nova/api, should be merged after lp:~eday/nova/pep8-fixes.
46 files changed, 368 insertions, 340 deletions
diff --git a/bin/nova-api b/bin/nova-api index a5027700b..20f1bd74f 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -39,6 +39,7 @@ from nova import server FLAGS = flags.FLAGS flags.DEFINE_integer('api_port', 8773, 'API port') + def main(_args): from nova import api from nova import wsgi diff --git a/bin/nova-manage b/bin/nova-manage index 219f32250..08b3da123 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -22,8 +22,8 @@ # Copyright (c) 2005, the Lawrence Journal-World # All rights reserved. # -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. @@ -32,20 +32,21 @@ # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # -# 3. Neither the name of Django nor the names of its contributors may be used -# to endorse or promote products derived from this software without +# 3. Neither the name of Django nor the names of its contributors may be +# used to endorse or promote products derived from this software without # specific prior written permission. # -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ @@ -181,8 +182,8 @@ class ShellCommands(object): if shell == 'ipython': try: import IPython - # Explicitly pass an empty list as arguments, because otherwise IPython - # would use sys.argv from this script. + # Explicitly pass an empty list as arguments, because + # otherwise IPython would use sys.argv from this script. shell = IPython.Shell.IPShell(argv=[]) shell.mainloop() except ImportError: @@ -190,13 +191,14 @@ class ShellCommands(object): if shell == 'python': import code - try: # Try activating rlcompleter, because it's handy. + try: + # Try activating rlcompleter, because it's handy. import readline except ImportError: pass else: - # We don't have to wrap the following import in a 'try', because - # we already know 'readline' was imported successfully. + # We don't have to wrap the following import in a 'try', + # because we already know 'readline' was imported successfully. import rlcompleter readline.parse_and_bind("tab:complete") code.interact() @@ -242,7 +244,6 @@ class UserCommands(object): print 'export EC2_ACCESS_KEY=%s' % user.access print 'export EC2_SECRET_KEY=%s' % user.secret - def __init__(self): self.manager = manager.AuthManager() @@ -291,6 +292,7 @@ class UserCommands(object): is_admin = False self.manager.modify_user(name, access_key, secret_key, is_admin) + class ProjectCommands(object): """Class for managing projects.""" @@ -380,7 +382,6 @@ class FloatingIpCommands(object): db.floating_ip_destroy(context.get_admin_context(), str(address)) - def list(self, host=None): """Lists all floating ips (optionally by host) arguments: [host]""" @@ -397,6 +398,7 @@ class FloatingIpCommands(object): floating_ip['address'], instance) + class NetworkCommands(object): """Class for managing networks.""" @@ -429,8 +431,7 @@ CATEGORIES = [ ('shell', ShellCommands), ('vpn', VpnCommands), ('floating', FloatingIpCommands), - ('network', NetworkCommands) -] + ('network', NetworkCommands)] def lazy_match(name, key_value_tuples): diff --git a/bzrplugins/novalog/__init__.py b/bzrplugins/novalog/__init__.py index e16b2e00f..9817dc886 100644 --- a/bzrplugins/novalog/__init__.py +++ b/bzrplugins/novalog/__init__.py @@ -17,13 +17,14 @@ import bzrlib.log from bzrlib.osutils import format_date -# -# This is mostly stolen from bzrlib.log.GnuChangelogLogFormatter -# The difference is that it logs the author rather than the committer -# which for Nova always is Tarmac. -# + class NovaLogFormat(bzrlib.log.GnuChangelogLogFormatter): + """This is mostly stolen from bzrlib.log.GnuChangelogLogFormatter + The difference is that it logs the author rather than the committer + which for Nova always is Tarmac.""" + preferred_levels = 1 + def log_revision(self, revision): """Log a revision, either merged or not.""" to_file = self.to_file @@ -38,13 +39,14 @@ class NovaLogFormat(bzrlib.log.GnuChangelogLogFormatter): to_file.write('%s %s\n\n' % (date_str, ", ".join(authors))) if revision.delta is not None and revision.delta.has_changed(): - for c in revision.delta.added + revision.delta.removed + revision.delta.modified: + for c in revision.delta.added + revision.delta.removed + \ + revision.delta.modified: path, = c[:1] to_file.write('\t* %s:\n' % (path,)) for c in revision.delta.renamed: - oldpath,newpath = c[:2] + oldpath, newpath = c[:2] # For renamed files, show both the old and the new path - to_file.write('\t* %s:\n\t* %s:\n' % (oldpath,newpath)) + to_file.write('\t* %s:\n\t* %s:\n' % (oldpath, newpath)) to_file.write('\n') if not revision.rev.message: @@ -56,4 +58,3 @@ class NovaLogFormat(bzrlib.log.GnuChangelogLogFormatter): to_file.write('\n') bzrlib.log.register_formatter('novalog', NovaLogFormat) - diff --git a/nova/adminclient.py b/nova/adminclient.py index fc9fcfde0..b7a3d2c32 100644 --- a/nova/adminclient.py +++ b/nova/adminclient.py @@ -25,10 +25,10 @@ import httplib from boto.ec2.regioninfo import RegionInfo -DEFAULT_CLC_URL='http://127.0.0.1:8773' -DEFAULT_REGION='nova' -DEFAULT_ACCESS_KEY='admin' -DEFAULT_SECRET_KEY='admin' +DEFAULT_CLC_URL = 'http://127.0.0.1:8773' +DEFAULT_REGION = 'nova' +DEFAULT_ACCESS_KEY = 'admin' +DEFAULT_SECRET_KEY = 'admin' class UserInfo(object): @@ -199,9 +199,7 @@ class NovaAdminClient(object): def connection_for(self, username, project, clc_url=None, region=None, **kwargs): - """ - Returns a boto ec2 connection for the given username. - """ + """Returns a boto ec2 connection for the given username.""" if not clc_url: clc_url = self.clc_url if not region: @@ -220,36 +218,37 @@ class NovaAdminClient(object): **kwargs) def split_clc_url(self, clc_url): - """ - Splits a cloud controller endpoint url. - """ + """Splits a cloud controller endpoint url.""" parts = httplib.urlsplit(clc_url) is_secure = parts.scheme == 'https' ip, port = parts.netloc.split(':') return {'ip': ip, 'port': int(port), 'is_secure': is_secure} def get_users(self): - """ grabs the list of all users """ + """Grabs the list of all users.""" return self.apiconn.get_list('DescribeUsers', {}, [('item', UserInfo)]) def get_user(self, name): - """ grab a single user by name """ - user = self.apiconn.get_object('DescribeUser', {'Name': name}, UserInfo) - + """Grab a single user by name.""" + user = self.apiconn.get_object('DescribeUser', {'Name': name}, + UserInfo) if user.username != None: return user def has_user(self, username): - """ determine if user exists """ + """Determine if user exists.""" return self.get_user(username) != None def create_user(self, username): - """ creates a new user, returning the userinfo object with access/secret """ - return self.apiconn.get_object('RegisterUser', {'Name': username}, UserInfo) + """Creates a new user, returning the userinfo object with + access/secret.""" + return self.apiconn.get_object('RegisterUser', {'Name': username}, + UserInfo) def delete_user(self, username): - """ deletes a user """ - return self.apiconn.get_object('DeregisterUser', {'Name': username}, UserInfo) + """Deletes a user.""" + return self.apiconn.get_object('DeregisterUser', {'Name': username}, + UserInfo) def get_roles(self, project_roles=True): """Returns a list of available roles.""" @@ -258,11 +257,10 @@ class NovaAdminClient(object): [('item', UserRole)]) def get_user_roles(self, user, project=None): - """Returns a list of roles for the given user. - Omitting project will return any global roles that the user has. - Specifying project will return only project specific roles. - """ - params = {'User':user} + """Returns a list of roles for the given user. Omitting project will + return any global roles that the user has. Specifying project will + return only project specific roles.""" + params = {'User': user} if project: params['Project'] = project return self.apiconn.get_list('DescribeUserRoles', @@ -270,24 +268,19 @@ class NovaAdminClient(object): [('item', UserRole)]) def add_user_role(self, user, role, project=None): - """ - Add a role to a user either globally or for a specific project. - """ + """Add a role to a user either globally or for a specific project.""" return self.modify_user_role(user, role, project=project, operation='add') def remove_user_role(self, user, role, project=None): - """ - Remove a role from a user either globally or for a specific project. - """ + """Remove a role from a user either globally or for a specific + project.""" return self.modify_user_role(user, role, project=project, operation='remove') def modify_user_role(self, user, role, project=None, operation='add', **kwargs): - """ - Add or remove a role for a user and project. - """ + """Add or remove a role for a user and project.""" params = {'User': user, 'Role': role, 'Project': project, @@ -295,9 +288,7 @@ class NovaAdminClient(object): return self.apiconn.get_status('ModifyUserRole', params) def get_projects(self, user=None): - """ - Returns a list of all projects. - """ + """Returns a list of all projects.""" if user: params = {'User': user} else: @@ -307,9 +298,7 @@ class NovaAdminClient(object): [('item', ProjectInfo)]) def get_project(self, name): - """ - Returns a single project with the specified name. - """ + """Returns a single project with the specified name.""" project = self.apiconn.get_object('DescribeProject', {'Name': name}, ProjectInfo) @@ -319,9 +308,7 @@ class NovaAdminClient(object): def create_project(self, projectname, manager_user, description=None, member_users=None): - """ - Creates a new project. - """ + """Creates a new project.""" params = {'Name': projectname, 'ManagerUser': manager_user, 'Description': description, @@ -329,50 +316,38 @@ class NovaAdminClient(object): return self.apiconn.get_object('RegisterProject', params, ProjectInfo) def delete_project(self, projectname): - """ - Permanently deletes the specified project. - """ + """Permanently deletes the specified project.""" return self.apiconn.get_object('DeregisterProject', {'Name': projectname}, ProjectInfo) def get_project_members(self, name): - """ - Returns a list of members of a project. - """ + """Returns a list of members of a project.""" return self.apiconn.get_list('DescribeProjectMembers', {'Name': name}, [('item', ProjectMember)]) def add_project_member(self, user, project): - """ - Adds a user to a project. - """ + """Adds a user to a project.""" return self.modify_project_member(user, project, operation='add') def remove_project_member(self, user, project): - """ - Removes a user from a project. - """ + """Removes a user from a project.""" return self.modify_project_member(user, project, operation='remove') def modify_project_member(self, user, project, operation='add'): - """ - Adds or removes a user from a project. - """ + """Adds or removes a user from a project.""" params = {'User': user, 'Project': project, 'Operation': operation} return self.apiconn.get_status('ModifyProjectMember', params) def get_zip(self, user, project): - """ - Returns the content of a zip file containing novarc and access credentials. - """ + """Returns the content of a zip file containing novarc and access + credentials.""" params = {'Name': user, 'Project': project} zip = self.apiconn.get_object('GenerateX509ForUser', params, UserInfo) return zip.file def get_hosts(self): return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)]) - diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 8ec7094d7..8a1d9fe32 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -31,12 +31,13 @@ from nova.api import openstack from nova.api.ec2 import metadatarequesthandler -flags.DEFINE_string('osapi_subdomain', 'api', +flags.DEFINE_string('osapi_subdomain', 'api', 'subdomain running the OpenStack API') -flags.DEFINE_string('ec2api_subdomain', 'ec2', +flags.DEFINE_string('ec2api_subdomain', 'ec2', 'subdomain running the EC2 API') -flags.DEFINE_string('FAKE_subdomain', None, - 'set to api or ec2 to fake the subdomain of the host for testing') +flags.DEFINE_string('FAKE_subdomain', None, + 'set to api or ec2 to fake the subdomain of the host ' + 'for testing') FLAGS = flags.FLAGS @@ -44,7 +45,7 @@ class API(wsgi.Router): """Routes top-level requests to the appropriate controller.""" def __init__(self): - osapidomain = {'sub_domain': [FLAGS.osapi_subdomain]} + osapidomain = {'sub_domain': [FLAGS.osapi_subdomain]} ec2domain = {'sub_domain': [FLAGS.ec2api_subdomain]} # If someone wants to pretend they're hitting the OSAPI subdomain # on their local box, they can set FAKE_subdomain to 'api', which @@ -55,7 +56,7 @@ class API(wsgi.Router): ec2domain = {} mapper = routes.Mapper() mapper.sub_domains = True - mapper.connect("/", controller=self.osapi_versions, + mapper.connect("/", controller=self.osapi_versions, conditions=osapidomain) mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(), conditions=osapidomain) @@ -107,5 +108,3 @@ class API(wsgi.Router): '2009-04-04', ] return ''.join('%s\n' % v for v in versions) - - diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 5735eb956..0df4d3710 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -62,7 +62,8 @@ class Authenticate(wsgi.Middleware): # Make a copy of args for authentication and signature verification. 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. try: @@ -109,9 +110,11 @@ class Router(wsgi.Middleware): 'SignatureVersion', 'Version', 'Timestamp'] args = dict(req.params) try: - action = req.params['Action'] # raise KeyError if omitted + # Raise KeyError if omitted + action = req.params['Action'] 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: raise webob.exc.HTTPBadRequest() @@ -184,7 +187,8 @@ class Authorizer(wsgi.Middleware): context = req.environ['ec2.context'] controller_name = req.environ['ec2.controller'].__class__.__name__ 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): return self.application else: @@ -242,4 +246,3 @@ class Executor(wsgi.Application): '<Message>%s</Message></Error></Errors>' '<RequestID>?</RequestID></Response>') % (code, message) return resp - diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 36feae451..1c6ab688d 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -73,7 +73,7 @@ class AdminController(object): def describe_users(self, _context, **_kwargs): """Returns all users - should be changed to deal with a list.""" 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): """Creates a new user, and returns generated credentials.""" @@ -91,7 +91,7 @@ class AdminController(object): def describe_roles(self, context, project_roles=True, **kwargs): """Returns a list of allowed 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): """Returns a list of roles for the given user. @@ -99,7 +99,7 @@ class AdminController(object): Specifying project will return only project specific roles. """ 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, operation='add', **kwargs): @@ -155,9 +155,10 @@ class AdminController(object): 'members': [{'member': m} for m in project.member_ids]} 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.""" - if operation =='add': + if operation == 'add': manager.AuthManager().add_to_project(user, project) elif operation == 'remove': manager.AuthManager().remove_from_project(user, project) diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py index 3c8651582..5758781b6 100644 --- a/nova/api/ec2/apirequest.py +++ b/nova/api/ec2/apirequest.py @@ -44,6 +44,7 @@ def _underscore_to_xmlcase(str): res = _underscore_to_camelcase(str) return res[:1].lower() + res[1:] + def _try_convert(value): """Return a non-string if possible""" if value == 'None': @@ -59,12 +60,12 @@ def _try_convert(value): return value if valueneg[0] == '0': if valueneg[1] in 'xX': - return int(value,16) + return int(value, 16) elif valueneg[1] in 'bB': - return int(value,2) + return int(value, 2) else: try: - return int(value,8) + return int(value, 8) except ValueError: pass try: @@ -80,6 +81,7 @@ def _try_convert(value): except ValueError: return value + class APIRequest(object): def __init__(self, controller, action): self.controller = controller diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 6d4f58499..784697b01 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -48,6 +48,7 @@ flags.DECLARE('storage_availability_zone', 'nova.volume.manager') InvalidInputException = exception.InvalidInputException + class QuotaError(exception.ApiError): """Quota Exceeeded""" pass @@ -137,8 +138,8 @@ class CloudController(object): for node in nodes: rpc.cast(context, '%s.%s' % (FLAGS.compute_topic, node), - { "method": "refresh_security_group", - "args": {"security_group_id": security_group.id}}) + {"method": "refresh_security_group", + "args": {"security_group_id": security_group.id}}) def get_metadata(self, address): ctxt = context.get_admin_context() @@ -147,48 +148,42 @@ class CloudController(object): return None mpi = self._get_mpi_data(ctxt, instance_ref['project_id']) if instance_ref['key_name']: - keys = { - '0': { - '_name': instance_ref['key_name'], - 'openssh-key': instance_ref['key_data'] - } - } + keys = {'0': {'_name': instance_ref['key_name'], + 'openssh-key': instance_ref['key_data']}} else: keys = '' hostname = instance_ref['hostname'] floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) + ec2_id = internal_id_to_ec2_id(instance_ref['internal_id']) data = { 'user-data': base64.b64decode(instance_ref['user_data']), 'meta-data': { 'ami-id': instance_ref['image_id'], 'ami-launch-index': instance_ref['launch_index'], 'ami-manifest-path': 'FIXME', - 'block-device-mapping': { # TODO(vish): replace with real data + 'block-device-mapping': { + # TODO(vish): replace with real data 'ami': 'sda1', 'ephemeral0': 'sda2', 'root': '/dev/sda1', - 'swap': 'sda3' - }, + 'swap': 'sda3'}, 'hostname': hostname, 'instance-action': 'none', - 'instance-id': internal_id_to_ec2_id(instance_ref['internal_id']), + 'instance-id': ec2_id, 'instance-type': instance_ref['instance_type'], 'local-hostname': hostname, 'local-ipv4': address, 'kernel-id': instance_ref['kernel_id'], - 'placement': { - 'availability-zone': 'nova' # TODO(vish): real zone - }, + # TODO(vish): real zone + 'placement': {'availability-zone': 'nova'}, 'public-hostname': hostname, 'public-ipv4': floating_ip or '', 'public-keys': keys, 'ramdisk-id': instance_ref['ramdisk_id'], 'reservation-id': instance_ref['reservation_id'], 'security-groups': '', - 'mpi': mpi - } - } + 'mpi': mpi}} if False: # TODO(vish): store ancestor ids data['ancestor-ami-ids'] = [] if False: # TODO(vish): store product codes @@ -211,7 +206,7 @@ class CloudController(object): 'regionEndpoint': FLAGS.ec2_url}] if region_name: regions = [r for r in regions if r['regionName'] in region_name] - return {'regionInfo': regions } + return {'regionInfo': regions} def describe_snapshots(self, context, @@ -237,7 +232,8 @@ class CloudController(object): for key_pair in key_pairs: # filter out the vpn keys 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({ 'keyName': key_pair['name'], 'keyFingerprint': key_pair['fingerprint'], @@ -271,7 +267,7 @@ class CloudController(object): if not group_name is None: 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): g = {} @@ -295,13 +291,10 @@ class CloudController(object): g['ipPermissions'] += [r] return g - - def _authorize_revoke_rule_args_to_dict(self, context, - to_port=None, from_port=None, - ip_protocol=None, cidr_ip=None, - user_id=None, - source_security_group_name=None, - source_security_group_owner_id=None): + def _revoke_rule_args_to_dict(self, context, to_port=None, from_port=None, + ip_protocol=None, cidr_ip=None, user_id=None, + source_security_group_name=None, + source_security_group_owner_id=None): values = {} @@ -322,16 +315,16 @@ class CloudController(object): values['cidr'] = '0.0.0.0/0' if ip_protocol and from_port and to_port: - from_port = int(from_port) - to_port = int(to_port) + from_port = int(from_port) + to_port = int(to_port) ip_protocol = str(ip_protocol) - if ip_protocol.upper() not in ['TCP','UDP','ICMP']: - raise InvalidInputException('%s is not a valid ipProtocol' % - (ip_protocol,)) + if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: + raise InvalidInputException('%s is not a valid ipProtocol' % + (ip_protocol,)) if ((min(from_port, to_port) < -1) or (max(from_port, to_port) > 65535)): - raise InvalidInputException('Invalid port range') + raise InvalidInputException('Invalid port range') values['protocol'] = ip_protocol values['from_port'] = from_port @@ -343,7 +336,6 @@ class CloudController(object): return values - def _security_group_rule_exists(self, security_group, values): """Indicates whether the specified rule values are already defined in the given security group. @@ -362,20 +354,19 @@ class CloudController(object): return True return False - def revoke_security_group_ingress(self, context, group_name, **kwargs): self._ensure_default_security_group(context) security_group = db.security_group_get_by_name(context, context.project_id, group_name) - criteria = self._authorize_revoke_rule_args_to_dict(context, **kwargs) + criteria = self._revoke_rule_args_to_dict(context, **kwargs) if criteria == None: raise exception.ApiError("No rule for the specified parameters.") for rule in security_group.rules: match = True - for (k,v) in criteria.iteritems(): + for (k, v) in criteria.iteritems(): if getattr(rule, k, False) != v: match = False if match: @@ -394,7 +385,7 @@ class CloudController(object): context.project_id, 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 if self._security_group_rule_exists(security_group, values): @@ -407,7 +398,6 @@ class CloudController(object): return True - def _get_source_project_id(self, context, source_security_group_owner_id): if source_security_group_owner_id: # Parse user:project for source group. @@ -425,13 +415,12 @@ class CloudController(object): return source_project_id - def create_security_group(self, context, group_name, group_description): self._ensure_default_security_group(context) if db.security_group_exists(context, context.project_id, 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, 'name': group_name, 'description': group_description} @@ -440,7 +429,6 @@ class CloudController(object): return {'securityGroupSet': [self._format_security_group(context, group_ref)]} - def delete_security_group(self, context, group_name, **kwargs): security_group = db.security_group_get_by_name(context, context.project_id, @@ -448,7 +436,6 @@ class CloudController(object): db.security_group_destroy(context, security_group.id) return True - def get_console_output(self, context, instance_id, **kwargs): # instance_id is passed in as a list of instances ec2_id = instance_id[0] @@ -457,13 +444,13 @@ class CloudController(object): output = rpc.call(context, '%s.%s' % (FLAGS.compute_topic, instance_ref['host']), - {"method" : "get_console_output", - "args" : {"instance_id": instance_ref['id']}}) + {"method": "get_console_output", + "args": {"instance_id": instance_ref['id']}}) now = datetime.datetime.utcnow() - return { "InstanceId" : ec2_id, - "Timestamp" : now, - "output" : base64.b64encode(output) } + return {"InstanceId": ec2_id, + "Timestamp": now, + "output": base64.b64encode(output)} def describe_volumes(self, context, **kwargs): if context.user.is_admin(): @@ -530,7 +517,6 @@ class CloudController(object): return {'volumeSet': [self._format_volume(context, volume_ref)]} - def attach_volume(self, context, volume_id, instance_id, device, **kwargs): volume_ref = db.volume_get_by_ec2_id(context, volume_id) # TODO(vish): abstract status checking? @@ -633,8 +619,7 @@ class CloudController(object): i['imageId'] = instance['image_id'] i['instanceState'] = { 'code': instance['state'], - 'name': instance['state_description'] - } + 'name': instance['state_description']} fixed_addr = None floating_addr = None if instance['fixed_ip']: @@ -656,7 +641,7 @@ class CloudController(object): i['amiLaunchIndex'] = instance['launch_index'] i['displayName'] = instance['display_name'] i['displayDescription'] = instance['display_description'] - if not reservations.has_key(instance['reservation_id']): + if instance['reservation_id'] not in reservations: r = {} r['reservationId'] = instance['reservation_id'] r['ownerId'] = instance['project_id'] @@ -757,10 +742,10 @@ class CloudController(object): context.project_id, 'default') except exception.NotFound: - values = { 'name' : 'default', - 'description' : 'default', - 'user_id' : context.user.id, - 'project_id' : context.project_id } + values = {'name': 'default', + 'description': 'default', + 'user_id': context.user.id, + 'project_id': context.project_id} group = db.security_group_create(context, values) def run_instances(self, context, **kwargs): @@ -804,7 +789,7 @@ class CloudController(object): logging.debug("Going to run %s instances...", num_instances) launch_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) key_data = None - if kwargs.has_key('key_name'): + if 'key_name' in kwargs: key_pair_ref = db.key_pair_get(context, context.user.id, kwargs['key_name']) @@ -883,7 +868,6 @@ class CloudController(object): (context.project.name, context.user.name, inst_id)) return self._format_run_instances(context, reservation_id) - def terminate_instances(self, context, instance_id, **kwargs): """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): # 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_id = images.register(context, image_location) logging.debug("Registered %s as %s" % (image_location, image_id)) @@ -1009,7 +993,8 @@ class CloudController(object): result['launchPermission'].append({'group': 'all'}) 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'. if attribute != 'launchPermission': raise exception.ApiError('attribute not supported: %s' % attribute) diff --git a/nova/api/ec2/images.py b/nova/api/ec2/images.py index f0a43dad6..60f9008e9 100644 --- a/nova/api/ec2/images.py +++ b/nova/api/ec2/images.py @@ -43,6 +43,7 @@ def modify(context, image_id, operation): return True + def update(context, image_id, attributes): """update an image's attributes / info.json""" attributes.update({"image_id": image_id}) @@ -52,6 +53,7 @@ def update(context, image_id, attributes): query_args=qs(attributes)) return True + def register(context, image_location): """ rpc call to register a new image based from a manifest """ @@ -64,13 +66,14 @@ def register(context, image_location): return image_id + def list(context, filter_list=[]): """ return a list of all images that a user can see optionally filtered by a list of image_id """ if FLAGS.connection_type == 'fake': - return [{ 'imageId' : 'bar'}] + return [{'imageId': 'bar'}] # FIXME: send along the list of only_images to check for 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 result + def get(context, image_id): """return a image object if the context has permissions""" result = list(context, [image_id]) diff --git a/nova/api/ec2/metadatarequesthandler.py b/nova/api/ec2/metadatarequesthandler.py index 08a8040ca..2f4f414cc 100644 --- a/nova/api/ec2/metadatarequesthandler.py +++ b/nova/api/ec2/metadatarequesthandler.py @@ -27,7 +27,6 @@ from nova.api.ec2 import cloud class MetadataRequestHandler(object): - """Serve metadata from the EC2 API.""" def print_data(self, data): @@ -43,7 +42,8 @@ class MetadataRequestHandler(object): else: output += '/' output += '\n' - return output[:-1] # cut off last \n + # Cut off last \n + return output[:-1] elif isinstance(data, list): return '\n'.join(data) else: @@ -65,7 +65,8 @@ class MetadataRequestHandler(object): cc = cloud.CloudController() meta_data = cc.get_metadata(req.remote_addr) 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() data = self.lookup(req.path_info, meta_data) if data is None: diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 5706dbc09..bb86f08dd 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -43,9 +43,10 @@ from nova.auth import manager FLAGS = flags.FLAGS 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') + class API(wsgi.Middleware): """WSGI entry point for all OpenStack API requests.""" @@ -53,6 +54,7 @@ class API(wsgi.Middleware): app = AuthMiddleware(RateLimitingMiddleware(APIRouter())) super(API, self).__init__(app) + class AuthMiddleware(wsgi.Middleware): """Authorize the openstack API request or return an HTTP Forbidden.""" @@ -62,7 +64,7 @@ class AuthMiddleware(wsgi.Middleware): @webob.dec.wsgify 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) user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"]) @@ -70,11 +72,12 @@ class AuthMiddleware(wsgi.Middleware): if not user: 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']['user'] = user return self.application + class RateLimitingMiddleware(wsgi.Middleware): """Rate limit incoming requests according to the OpenStack rate limits.""" @@ -87,7 +90,7 @@ class RateLimitingMiddleware(wsgi.Middleware): """ super(RateLimitingMiddleware, self).__init__(application) if not service_host: - #TODO(gundlach): These limits were based on limitations of Cloud + #TODO(gundlach): These limits were based on limitations of Cloud #Servers. We should revisit them in Nova. self.limiter = ratelimiting.Limiter(limits={ 'DELETE': (100, ratelimiting.PER_MINUTE), @@ -102,13 +105,14 @@ class RateLimitingMiddleware(wsgi.Middleware): @webob.dec.wsgify def __call__(self, req): """Rate limit the request. - - If the request should be rate limited, return a 413 status with a + + If the request should be rate limited, return a 413 status with a Retry-After header giving the time when the request would succeed. """ user_id = req.environ['nova.context']['user']['id'] action_name = self.get_action_name(req) - if not action_name: # not rate limited + if not action_name: + # Not rate limited return self.application delay = self.get_delay(action_name, user_id) if delay: @@ -152,13 +156,13 @@ class APIRouter(wsgi.Router): def __init__(self): mapper = routes.Mapper() mapper.resource("server", "servers", controller=servers.Controller(), - collection={ 'detail': 'GET'}, - member={'action':'POST'}) + collection={'detail': 'GET'}, + member={'action': 'POST'}) - mapper.resource("backup_schedule", "backup_schedules", + mapper.resource("backup_schedule", "backup_schedules", controller=backup_schedules.Controller(), - parent_resource=dict(member_name='server', - collection_name = 'servers')) + parent_resource=dict(member_name='server', + collection_name='servers')) mapper.resource("image", "images", controller=images.Controller(), collection={'detail': 'GET'}) @@ -172,7 +176,7 @@ class APIRouter(wsgi.Router): def limited(items, req): """Return a slice of items according to requested offset and limit. - + items - a sliceable req - wobob.Request possibly containing offset and limit GET variables. offset is where to start in the list, and limit is the maximum number @@ -187,4 +191,3 @@ def limited(items, req): limit = min(1000, limit) range_end = offset + limit return items[offset:range_end] - diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 7aba55728..ff428ff70 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -15,9 +15,11 @@ from nova.api.openstack import faults FLAGS = flags.FLAGS + class Context(object): pass + class BasicApiAuthManager(object): """ Implements a somewhat rudimentary version of OpenStack Auth""" @@ -61,7 +63,7 @@ class BasicApiAuthManager(object): def authorize_token(self, token_hash): """ retrieves user information from the datastore given a token - + If the token has expired, returns None If the token is not found, returns None Otherwise returns dict(id=(the authorized user's id)) @@ -69,7 +71,7 @@ class BasicApiAuthManager(object): This method will also remove the token if the timestamp is older than 2 days ago. """ - token = self.db.auth_get_token(self.context, token_hash) + token = self.db.auth_get_token(self.context, token_hash) if token: delta = datetime.datetime.now() - token.created_at if delta.days >= 2: @@ -94,8 +96,7 @@ class BasicApiAuthManager(object): token_dict['user_id'] = user.id token = self.db.auth_create_token(self.context, token_dict) return token, user - return None, None + return None, None def _get_server_mgmt_url(self): return 'https://%s/v1.0/' % self.host - diff --git a/nova/api/openstack/backup_schedules.py b/nova/api/openstack/backup_schedules.py index db240c65a..3ed691d7b 100644 --- a/nova/api/openstack/backup_schedules.py +++ b/nova/api/openstack/backup_schedules.py @@ -22,6 +22,7 @@ from nova import wsgi from nova.api.openstack import faults import nova.image.service + class Controller(wsgi.Controller): def __init__(self): pass diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py index 32e5c866f..e69e51439 100644 --- a/nova/api/openstack/faults.py +++ b/nova/api/openstack/faults.py @@ -55,7 +55,7 @@ class Fault(webob.exc.HTTPException): if code == 413: retry = self.wrapped_exc.headers['Retry-After'] fault_data[fault_name]['retryAfter'] = retry - # 'code' is an attribute on the fault tag itself + # 'code' is an attribute on the fault tag itself metadata = {'application/xml': {'attributes': {fault_name: 'code'}}} serializer = wsgi.Serializer(req.environ, metadata) self.wrapped_exc.body = serializer.to_content_type(fault_data) diff --git a/nova/api/openstack/flavors.py b/nova/api/openstack/flavors.py index 793984a5d..f23f74fd1 100644 --- a/nova/api/openstack/flavors.py +++ b/nova/api/openstack/flavors.py @@ -22,16 +22,14 @@ from nova.compute import instance_types from nova import wsgi import nova.api.openstack + class Controller(wsgi.Controller): """Flavor controller for the OpenStack API.""" _serialization_metadata = { 'application/xml': { "attributes": { - "flavor": [ "id", "name", "ram", "disk" ] - } - } - } + "flavor": ["id", "name", "ram", "disk"]}}} def index(self, req): """Return all flavors in brief.""" diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 5ccf659f7..5bc915e63 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -27,16 +27,14 @@ from nova.api.openstack import faults FLAGS = flags.FLAGS + class Controller(wsgi.Controller): _serialization_metadata = { 'application/xml': { "attributes": { - "image": [ "id", "name", "updated", "created", "status", - "serverId", "progress" ] - } - } - } + "image": ["id", "name", "updated", "created", "status", + "serverId", "progress"]}}} def __init__(self): self._service = utils.import_object(FLAGS.image_service) @@ -72,6 +70,6 @@ class Controller(wsgi.Controller): raise faults.Fault(exc.HTTPNotFound()) def update(self, req, id): - # Users may not modify public images, and that's all that + # Users may not modify public images, and that's all that # we support for now. raise faults.Fault(exc.HTTPNotFound()) diff --git a/nova/api/openstack/ratelimiting/__init__.py b/nova/api/openstack/ratelimiting/__init__.py index f843bac0f..9e028ecf5 100644 --- a/nova/api/openstack/ratelimiting/__init__.py +++ b/nova/api/openstack/ratelimiting/__init__.py @@ -13,6 +13,7 @@ PER_MINUTE = 60 PER_HOUR = 60 * 60 PER_DAY = 60 * 60 * 24 + class Limiter(object): """Class providing rate limiting of arbitrary actions.""" @@ -101,7 +102,8 @@ class WSGIApp(object): return webob.exc.HTTPForbidden( headers={'X-Wait-Seconds': "%.2f" % delay}) else: - return '' # 200 OK + # 200 OK + return '' class WSGIAppProxy(object): @@ -109,7 +111,7 @@ class WSGIAppProxy(object): """Limiter lookalike that proxies to a ratelimiting.WSGIApp.""" def __init__(self, service_host): - """Creates a proxy pointing to a ratelimiting.WSGIApp at the given + """Creates a proxy pointing to a ratelimiting.WSGIApp at the given host.""" self.service_host = service_host @@ -118,5 +120,6 @@ class WSGIAppProxy(object): conn.request('POST', '/limiter/%s/%s' % (username, action)) resp = conn.getresponse() if resp.status == 200: - return None # no delay + # No delay + return None return float(resp.getheader('X-Wait-Seconds')) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index a73591ccc..ef773c3be 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -34,30 +34,32 @@ import nova.image.service FLAGS = flags.FLAGS + def _filter_params(inst_dict): """ Extracts all updatable parameters for a server update request """ keys = dict(name='name', admin_pass='adminPass') new_attrs = {} for k, v in keys.items(): - if inst_dict.has_key(v): + if v in inst_dict: new_attrs[k] = inst_dict[v] return new_attrs + def _entity_list(entities): """ Coerces a list of servers into proper dictionary format """ return dict(servers=entities) + def _entity_detail(inst): """ Maps everything to Rackspace-like attributes for return""" power_mapping = { - power_state.NOSTATE: 'build', - power_state.RUNNING: 'active', - power_state.BLOCKED: 'active', - power_state.PAUSED: 'suspended', + power_state.NOSTATE: 'build', + power_state.RUNNING: 'active', + power_state.BLOCKED: 'active', + power_state.PAUSED: 'suspended', power_state.SHUTDOWN: 'active', - power_state.SHUTOFF: 'active', - power_state.CRASHED: 'error' - } + power_state.SHUTOFF: 'active', + power_state.CRASHED: 'error'} inst_dict = {} mapped_keys = dict(status='state', imageId='image_id', @@ -73,21 +75,20 @@ def _entity_detail(inst): return dict(server=inst_dict) + def _entity_inst(inst): """ Filters all model attributes save for id and name """ return dict(server=dict(id=inst['id'], name=inst['server_name'])) + class Controller(wsgi.Controller): """ The Server API controller for the OpenStack API """ _serialization_metadata = { 'application/xml': { "attributes": { - "server": [ "id", "imageId", "name", "flavorId", "hostId", - "status", "progress", "progress" ] - } - } - } + "server": ["id", "imageId", "name", "flavorId", "hostId", + "status", "progress", "progress"]}}} def __init__(self, db_driver=None): if not db_driver: @@ -209,7 +210,7 @@ class Controller(wsgi.Controller): image = img_service.show(image_id) if not image: - raise Exception, "Image not found" + raise Exception("Image not found") inst['server_name'] = env['server']['name'] inst['image_id'] = image_id diff --git a/nova/api/openstack/sharedipgroups.py b/nova/api/openstack/sharedipgroups.py index 4d2d0ede1..e805ca9f7 100644 --- a/nova/api/openstack/sharedipgroups.py +++ b/nova/api/openstack/sharedipgroups.py @@ -17,4 +17,6 @@ from nova import wsgi -class Controller(wsgi.Controller): pass + +class Controller(wsgi.Controller): + pass diff --git a/nova/context.py b/nova/context.py index f5d3fed08..f2669c9f1 100644 --- a/nova/context.py +++ b/nova/context.py @@ -26,7 +26,9 @@ import random from nova import exception from nova import utils + class RequestContext(object): + def __init__(self, user, project, is_admin=None, read_deleted=False, remote_address=None, timestamp=None, request_id=None): if hasattr(user, 'id'): @@ -56,10 +58,8 @@ class RequestContext(object): timestamp = utils.parse_isotime(timestamp) self.timestamp = timestamp if not request_id: - request_id = ''.join( - [random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-') - for x in xrange(20)] - ) + chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-' + request_id = ''.join([random.choice(chars) for x in xrange(20)]) self.request_id = request_id @property @@ -81,7 +81,8 @@ class RequestContext(object): from nova.auth import manager if not self._project: try: - self._project = manager.AuthManager().get_project(self.project_id) + auth_manager = manager.AuthManager() + self._project = auth_manager.get_project(self.project_id) except exception.NotFound: pass return self._project diff --git a/nova/crypto.py b/nova/crypto.py index 1c6fe57ad..16b4f5e1f 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -39,9 +39,12 @@ from nova import flags FLAGS = flags.FLAGS flags.DEFINE_string('ca_file', 'cacert.pem', 'Filename of root CA') -flags.DEFINE_string('keys_path', utils.abspath('../keys'), 'Where we keep our keys') -flags.DEFINE_string('ca_path', utils.abspath('../CA'), 'Where we keep our root CA') -flags.DEFINE_boolean('use_intermediate_ca', False, 'Should we use intermediate CAs for each project?') +flags.DEFINE_string('keys_path', utils.abspath('../keys'), + 'Where we keep our keys') +flags.DEFINE_string('ca_path', utils.abspath('../CA'), + 'Where we keep our root CA') +flags.DEFINE_boolean('use_intermediate_ca', False, + 'Should we use intermediate CAs for each project?') def ca_path(project_id): @@ -55,11 +58,11 @@ def fetch_ca(project_id=None, chain=True): project_id = None buffer = "" if project_id: - with open(ca_path(project_id),"r") as cafile: + with open(ca_path(project_id), "r") as cafile: buffer += cafile.read() if not chain: return buffer - with open(ca_path(None),"r") as cafile: + with open(ca_path(None), "r") as cafile: buffer += cafile.read() return buffer @@ -88,17 +91,18 @@ def generate_key_pair(bits=1024): def ssl_pub_to_ssh_pub(ssl_public_key, name='root', suffix='nova'): - rsa_key = M2Crypto.RSA.load_pub_key_bio(M2Crypto.BIO.MemoryBuffer(ssl_public_key)) + pub_key_buffer = M2Crypto.BIO.MemoryBuffer(ssl_public_key) + rsa_key = M2Crypto.RSA.load_pub_key_bio(pub_key_buffer) e, n = rsa_key.pub() key_type = 'ssh-rsa' key_data = struct.pack('>I', len(key_type)) key_data += key_type - key_data += '%s%s' % (e,n) + key_data += '%s%s' % (e, n) b64_blob = base64.b64encode(key_data) - return '%s %s %s@%s\n' %(key_type, b64_blob, name, suffix) + return '%s %s %s@%s\n' % (key_type, b64_blob, name, suffix) def generate_x509_cert(subject, bits=1024): @@ -106,8 +110,11 @@ def generate_x509_cert(subject, bits=1024): keyfile = os.path.abspath(os.path.join(tmpdir, 'temp.key')) csrfile = os.path.join(tmpdir, 'temp.csr') logging.debug("openssl genrsa -out %s %s" % (keyfile, bits)) - utils.runthis("Generating private key: %s", "openssl genrsa -out %s %s" % (keyfile, bits)) - utils.runthis("Generating CSR: %s", "openssl req -new -key %s -out %s -batch -subj %s" % (keyfile, csrfile, subject)) + utils.runthis("Generating private key: %s", + "openssl genrsa -out %s %s" % (keyfile, bits)) + utils.runthis("Generating CSR: %s", + "openssl req -new -key %s -out %s -batch -subj %s" % + (keyfile, csrfile, subject)) private_key = open(keyfile).read() csr = open(csrfile).read() shutil.rmtree(tmpdir) @@ -123,7 +130,8 @@ def sign_csr(csr_text, intermediate=None): if not os.path.exists(user_ca): start = os.getcwd() os.chdir(FLAGS.ca_path) - utils.runthis("Generating intermediate CA: %s", "sh geninter.sh %s" % (intermediate)) + utils.runthis("Generating intermediate CA: %s", + "sh geninter.sh %s" % (intermediate)) os.chdir(start) return _sign_csr(csr_text, user_ca) @@ -137,7 +145,10 @@ def _sign_csr(csr_text, ca_folder): start = os.getcwd() # Change working dir to CA os.chdir(ca_folder) - utils.runthis("Signing cert: %s", "openssl ca -batch -out %s/outbound.crt -config ./openssl.cnf -infiles %s/inbound.csr" % (tmpfolder, tmpfolder)) + utils.runthis("Signing cert: %s", + "openssl ca -batch -out %s/outbound.crt " + "-config ./openssl.cnf -infiles %s/inbound.csr" % + (tmpfolder, tmpfolder)) os.chdir(start) with open("%s/outbound.crt" % (tmpfolder), "r") as crtfile: return crtfile.read() @@ -148,10 +159,11 @@ def mkreq(bits, subject="foo", ca=0): req = M2Crypto.X509.Request() rsa = M2Crypto.RSA.gen_key(bits, 65537, callback=lambda: None) pk.assign_rsa(rsa) - rsa = None # should not be freed here + # Should not be freed here + rsa = None req.set_pubkey(pk) req.set_subject(subject) - req.sign(pk,'sha512') + req.sign(pk, 'sha512') assert req.verify(pk) pk2 = req.get_pubkey() assert req.verify(pk2) @@ -165,7 +177,8 @@ def mkcacert(subject='nova', years=1): cert = M2Crypto.X509.X509() cert.set_serial_number(1) cert.set_version(2) - cert.set_subject(sub) # FIXME subject is not set in mkreq yet + # FIXME subject is not set in mkreq yet + cert.set_subject(sub) t = long(time.time()) + time.timezone now = M2Crypto.ASN1.ASN1_UTCTIME() now.set_time(t) @@ -189,7 +202,6 @@ def mkcacert(subject='nova', years=1): return cert, pk, pkey - # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ # # Permission is hereby granted, free of charge, to any person obtaining a @@ -212,6 +224,7 @@ def mkcacert(subject='nova', years=1): # IN THE SOFTWARE. # http://code.google.com/p/boto + def compute_md5(fp): """ @type fp: file diff --git a/nova/exception.py b/nova/exception.py index f157fab2d..6d6c37338 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -47,7 +47,7 @@ class ApiError(Error): def __init__(self, message='Unknown', code='Unknown'): self.message = message self.code = code - super(ApiError, self).__init__('%s: %s'% (code, message)) + super(ApiError, self).__init__('%s: %s' % (code, message)) class NotFound(Error): @@ -69,6 +69,7 @@ class NotEmpty(Error): class Invalid(Error): pass + class InvalidInputException(Error): pass @@ -86,5 +87,3 @@ def wrap_exception(f): raise _wrap.func_name = f.func_name return _wrap - - diff --git a/nova/fakerabbit.py b/nova/fakerabbit.py index df5e61e6e..c64617931 100644 --- a/nova/fakerabbit.py +++ b/nova/fakerabbit.py @@ -130,7 +130,6 @@ class Backend(object): self._exchanges[exchange].publish( message, routing_key=routing_key) - __instance = None def __init__(self, *args, **kwargs): diff --git a/nova/flags.py b/nova/flags.py index 3b473488f..f3b0384ad 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -180,7 +180,8 @@ DEFINE_string('connection_type', 'libvirt', 'libvirt, xenapi or fake') DEFINE_integer('s3_port', 3333, 's3 port') DEFINE_string('s3_host', '127.0.0.1', 's3 host') DEFINE_string('compute_topic', 'compute', 'the topic compute nodes listen on') -DEFINE_string('scheduler_topic', 'scheduler', 'the topic scheduler nodes listen on') +DEFINE_string('scheduler_topic', 'scheduler', + 'the topic scheduler nodes listen on') DEFINE_string('volume_topic', 'volume', 'the topic volume nodes listen on') DEFINE_string('network_topic', 'network', 'the topic network nodes listen on') diff --git a/nova/manager.py b/nova/manager.py index 56ba7d3f6..4244b2db4 100644 --- a/nova/manager.py +++ b/nova/manager.py @@ -45,8 +45,6 @@ class Manager(object): yield def init_host(self): - """Do any initialization that needs to be run if this is a standalone service. - - Child classes should override this method. - """ - pass + """Do any initialization that needs to be run if this is a standalone + service. Child classes should override this method.""" + pass diff --git a/nova/process.py b/nova/process.py index 13cb90e82..b33df048b 100644 --- a/nova/process.py +++ b/nova/process.py @@ -36,6 +36,7 @@ FLAGS = flags.FLAGS flags.DEFINE_integer('process_pool_size', 4, 'Number of processes to use in the process pool') + # This is based on _BackRelay from twister.internal.utils, but modified to # capture both stdout and stderr, without odd stderr handling, and also to # handle stdin @@ -55,8 +56,8 @@ class BackRelayWithInput(protocol.ProcessProtocol): will be called back when the process ends. This C{Deferred} is also associated with the L{_ProcessExecutionError} which C{deferred} fires with earlier in this case so that users can determine when the process - has actually ended, in addition to knowing when bytes have been received - via stderr. + has actually ended, in addition to knowing when bytes have been + received via stderr. """ def __init__(self, deferred, cmd, started_deferred=None, @@ -93,7 +94,7 @@ class BackRelayWithInput(protocol.ProcessProtocol): if self.deferred is not None: stdout, stderr = self.stdout.getvalue(), self.stderr.getvalue() exit_code = reason.value.exitCode - if self.check_exit_code and exit_code <> 0: + if self.check_exit_code and exit_code != 0: self.deferred.errback(self._build_execution_error(exit_code)) else: try: @@ -101,14 +102,15 @@ class BackRelayWithInput(protocol.ProcessProtocol): reason.trap(error.ProcessDone) self.deferred.callback((stdout, stderr)) except: - # NOTE(justinsb): This logic is a little suspicious to me... - # If the callback throws an exception, then errback will be - # called also. However, this is what the unit tests test for... - self.deferred.errback(self._build_execution_error(exit_code)) + # NOTE(justinsb): This logic is a little suspicious to me. + # If the callback throws an exception, then errback will + # be called also. However, this is what the unit tests + # test for. + exec_error = self._build_execution_error(exit_code) + self.deferred.errback(exec_error) elif self.on_process_ended is not None: self.on_process_ended.errback(reason) - def connectionMade(self): if self.started_deferred: self.started_deferred.callback(self) @@ -116,6 +118,7 @@ class BackRelayWithInput(protocol.ProcessProtocol): self.transport.write(str(self.process_input)) self.transport.closeStdin() + def get_process_output(executable, args=None, env=None, path=None, process_reactor=None, check_exit_code=True, process_input=None, started_deferred=None, @@ -142,7 +145,7 @@ def get_process_output(executable, args=None, env=None, path=None, if not args is None: args = [str(x) for x in args] process_reactor.spawnProcess(process_handler, executable, - (executable,)+tuple(args), env, path) + (executable,) + tuple(args), env, path) return deferred @@ -193,9 +196,11 @@ class ProcessPool(object): class SharedPool(object): _instance = None + def __init__(self): if SharedPool._instance is None: self.__class__._instance = ProcessPool() + def __getattr__(self, key): return getattr(self._instance, key) diff --git a/nova/quota.py b/nova/quota.py index 045051207..01dd0ecd4 100644 --- a/nova/quota.py +++ b/nova/quota.py @@ -37,6 +37,7 @@ flags.DEFINE_integer('quota_gigabytes', 1000, flags.DEFINE_integer('quota_floating_ips', 10, 'number of floating ips allowed per project') + def get_quota(context, project_id): rval = {'instances': FLAGS.quota_instances, 'cores': FLAGS.quota_cores, @@ -52,6 +53,7 @@ def get_quota(context, project_id): pass return rval + def allowed_instances(context, num_instances, instance_type): """Check quota and return min(num_instances, allowed_instances)""" project_id = context.project_id @@ -92,4 +94,3 @@ def allowed_floating_ips(context, num_floating_ips): quota = get_quota(context, project_id) allowed_floating_ips = quota['floating_ips'] - used_floating_ips return min(num_floating_ips, allowed_floating_ips) - diff --git a/nova/rpc.py b/nova/rpc.py index 965934205..895820cd0 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -268,6 +268,7 @@ def _unpack_context(msg): LOG.debug('unpacked context: %s', context_dict) return context.RequestContext.from_dict(context_dict) + def _pack_context(msg, context): """Pack context into msg. @@ -280,6 +281,7 @@ def _pack_context(msg, context): for (key, value) in context.to_dict().iteritems()]) msg.update(context) + def call(context, topic, msg): """Sends a message on a topic and wait for a response""" LOG.debug("Making asynchronous call...") diff --git a/nova/server.py b/nova/server.py index c58a15041..cb424caa1 100644 --- a/nova/server.py +++ b/nova/server.py @@ -54,11 +54,11 @@ def stop(pidfile): """ # Get the pid from the pidfile try: - pid = int(open(pidfile,'r').read().strip()) + pid = int(open(pidfile, 'r').read().strip()) except IOError: message = "pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % pidfile) - return # not an error in a restart + return # Try killing the daemon process try: @@ -143,6 +143,5 @@ def daemonize(args, name, main): stderr=stderr, uid=FLAGS.uid, gid=FLAGS.gid, - files_preserve=files_to_keep - ): + files_preserve=files_to_keep): main(args) diff --git a/nova/test.py b/nova/test.py index 8e89eb43e..8ef7eca1a 100644 --- a/nova/test.py +++ b/nova/test.py @@ -58,7 +58,7 @@ def skip_if_fake(func): class TrialTestCase(unittest.TestCase): """Test case base class for all unit tests""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): """Run before each test method to initialize test environment""" super(TrialTestCase, self).setUp() # NOTE(vish): We need a better method for creating fixtures for tests @@ -82,8 +82,9 @@ class TrialTestCase(unittest.TestCase): self._monkey_patch_attach() self._original_flags = FLAGS.FlagValuesDict() - def tearDown(self): # pylint: disable-msg=C0103 - """Runs after each test method to finalize/tear down test environment""" + def tearDown(self): + """Runs after each test method to finalize/tear down test + environment.""" try: self.mox.UnsetStubs() self.stubs.UnsetAll() @@ -91,7 +92,8 @@ class TrialTestCase(unittest.TestCase): self.mox.VerifyAll() # NOTE(vish): Clean up any ips associated during the test. ctxt = context.get_admin_context() - db.fixed_ip_disassociate_all_by_timeout(ctxt, FLAGS.host, self.start) + db.fixed_ip_disassociate_all_by_timeout(ctxt, FLAGS.host, + self.start) db.network_disassociate_all(ctxt) rpc.Consumer.attach_to_twisted = self.originalAttach for x in self.injected: @@ -149,6 +151,7 @@ class TrialTestCase(unittest.TestCase): def _monkey_patch_attach(self): self.originalAttach = rpc.Consumer.attach_to_twisted + def _wrapped(innerSelf): rv = self.originalAttach(innerSelf) self.injected.append(rv) @@ -164,7 +167,7 @@ class BaseTestCase(TrialTestCase): DEPRECATED: This is being removed once Tornado is gone, use TrialTestCase. """ - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): """Run before each test method to initialize test environment""" super(BaseTestCase, self).setUp() # TODO(termie): we could possibly keep a more global registry of @@ -179,7 +182,9 @@ class BaseTestCase(TrialTestCase): """ Push the ioloop along to wait for our test to complete. """ self._waiting = self.ioloop.add_timeout(time.time() + timeout, self._timeout) + def _wait(): + """Wrapped wait function. Called on timeout.""" if self._timed_out: self.fail('test timed out') @@ -198,7 +203,7 @@ class BaseTestCase(TrialTestCase): if self._waiting: try: self.ioloop.remove_timeout(self._waiting) - except Exception: # pylint: disable-msg=W0703 + except Exception: # pylint: disable-msg=W0703 # TODO(jaypipes): This produces a pylint warning. Should # we really be catching Exception and then passing here? pass @@ -219,9 +224,11 @@ class BaseTestCase(TrialTestCase): Example (callback chain, ugly): - d = self.compute.terminate_instance(instance_id) # a Deferred instance + # A deferred instance + d = self.compute.terminate_instance(instance_id) def _describe(_): - d_desc = self.compute.describe_instances() # another Deferred instance + # Another deferred instance + d_desc = self.compute.describe_instances() return d_desc def _checkDescribe(rv): self.assertEqual(rv, []) diff --git a/nova/tests/api/__init__.py b/nova/tests/api/__init__.py index f051e2390..a0681f414 100644 --- a/nova/tests/api/__init__.py +++ b/nova/tests/api/__init__.py @@ -32,10 +32,10 @@ from nova.tests.api.fakes import APIStub class Test(unittest.TestCase): - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): self.stubs = stubout.StubOutForTesting() - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): self.stubs.UnsetAll() def _request(self, url, subdomain, **kwargs): diff --git a/nova/tests/api_unittest.py b/nova/tests/api_unittest.py index 3f60f38f2..55a7ff32f 100644 --- a/nova/tests/api_unittest.py +++ b/nova/tests/api_unittest.py @@ -101,7 +101,7 @@ class XmlConversionTestCase(test.BaseTestCase): class ApiEc2TestCase(test.BaseTestCase): """Unit test for the cloud controller on an EC2 API""" - def setUp(self): # pylint: disable-msg=C0103,C0111 + def setUp(self): super(ApiEc2TestCase, self).setUp() self.manager = manager.AuthManager() diff --git a/nova/tests/compute_unittest.py b/nova/tests/compute_unittest.py index 01e1bcd30..01b5651df 100644 --- a/nova/tests/compute_unittest.py +++ b/nova/tests/compute_unittest.py @@ -37,7 +37,7 @@ FLAGS = flags.FLAGS class ComputeTestCase(test.TrialTestCase): """Test case for compute""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): logging.getLogger().setLevel(logging.DEBUG) super(ComputeTestCase, self).setUp() self.flags(connection_type='fake', @@ -48,7 +48,7 @@ class ComputeTestCase(test.TrialTestCase): self.project = self.manager.create_project('fake', 'fake', 'fake') self.context = context.get_admin_context() - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) super(ComputeTestCase, self).tearDown() diff --git a/nova/tests/network_unittest.py b/nova/tests/network_unittest.py index e8dd2624f..44cf47407 100644 --- a/nova/tests/network_unittest.py +++ b/nova/tests/network_unittest.py @@ -35,7 +35,7 @@ FLAGS = flags.FLAGS class NetworkTestCase(test.TrialTestCase): """Test cases for network code""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): super(NetworkTestCase, self).setUp() # NOTE(vish): if you change these flags, make sure to change the # flags in the corresponding section in nova-dhcpbridge @@ -65,7 +65,7 @@ class NetworkTestCase(test.TrialTestCase): instance_ref = self._create_instance(1) self.instance2_id = instance_ref['id'] - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): super(NetworkTestCase, self).tearDown() # TODO(termie): this should really be instantiating clean datastores # in between runs, one failure kills all the tests diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py index f096ac6fe..d1604c4e5 100644 --- a/nova/tests/objectstore_unittest.py +++ b/nova/tests/objectstore_unittest.py @@ -57,7 +57,7 @@ os.makedirs(os.path.join(OSS_TEMPDIR, 'buckets')) class ObjectStoreTestCase(test.TrialTestCase): """Test objectstore API directly.""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): """Setup users and projects.""" super(ObjectStoreTestCase, self).setUp() self.flags(buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), @@ -73,7 +73,7 @@ class ObjectStoreTestCase(test.TrialTestCase): self.auth_manager.create_project('proj2', 'user2', 'a proj', ['user2']) self.context = context.RequestContext('user1', 'proj1') - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): """Tear down users and projects.""" self.auth_manager.delete_project('proj1') self.auth_manager.delete_project('proj2') @@ -194,7 +194,7 @@ class TestSite(server.Site): class S3APITestCase(test.TrialTestCase): """Test objectstore through S3 API.""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): """Setup users, projects, and start a test server.""" super(S3APITestCase, self).setUp() @@ -309,7 +309,7 @@ class S3APITestCase(test.TrialTestCase): deferred.addCallback(self._ensure_no_buckets) return deferred - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): """Tear down auth and test server.""" self.auth_manager.delete_user('admin') self.auth_manager.delete_project('admin') diff --git a/nova/tests/quota_unittest.py b/nova/tests/quota_unittest.py index 72e44bf52..92f3be508 100644 --- a/nova/tests/quota_unittest.py +++ b/nova/tests/quota_unittest.py @@ -33,7 +33,7 @@ FLAGS = flags.FLAGS class QuotaTestCase(test.TrialTestCase): - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): logging.getLogger().setLevel(logging.DEBUG) super(QuotaTestCase, self).setUp() self.flags(connection_type='fake', @@ -51,7 +51,7 @@ class QuotaTestCase(test.TrialTestCase): self.context = context.RequestContext(project=self.project, user=self.user) - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): manager.AuthManager().delete_project(self.project) manager.AuthManager().delete_user(self.user) super(QuotaTestCase, self).tearDown() diff --git a/nova/tests/rpc_unittest.py b/nova/tests/rpc_unittest.py index 5d2bb1046..c380393a0 100644 --- a/nova/tests/rpc_unittest.py +++ b/nova/tests/rpc_unittest.py @@ -33,7 +33,7 @@ FLAGS = flags.FLAGS class RpcTestCase(test.TrialTestCase): """Test cases for rpc""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): super(RpcTestCase, self).setUp() self.conn = rpc.Connection.instance() self.receiver = TestReceiver() diff --git a/nova/tests/scheduler_unittest.py b/nova/tests/scheduler_unittest.py index 379f8cdc8..166a32702 100644 --- a/nova/tests/scheduler_unittest.py +++ b/nova/tests/scheduler_unittest.py @@ -44,7 +44,7 @@ class TestDriver(driver.Scheduler): class SchedulerTestCase(test.TrialTestCase): """Test case for scheduler""" - def setUp(self): # pylint: disable=C0103 + def setUp(self): super(SchedulerTestCase, self).setUp() self.flags(scheduler_driver='nova.tests.scheduler_unittest.TestDriver') @@ -73,7 +73,7 @@ class SchedulerTestCase(test.TrialTestCase): class SimpleDriverTestCase(test.TrialTestCase): """Test case for simple driver""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): super(SimpleDriverTestCase, self).setUp() self.flags(connection_type='fake', max_cores=4, @@ -87,7 +87,7 @@ class SimpleDriverTestCase(test.TrialTestCase): self.project = self.manager.create_project('fake', 'fake', 'fake') self.context = context.get_admin_context() - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) diff --git a/nova/tests/service_unittest.py b/nova/tests/service_unittest.py index 8533fab0a..6df108a98 100644 --- a/nova/tests/service_unittest.py +++ b/nova/tests/service_unittest.py @@ -78,7 +78,7 @@ class ServiceManagerTestCase(test.BaseTestCase): class ServiceTestCase(test.BaseTestCase): """Test cases for Services""" - def setUp(self): # pylint: disable=C0103 + def setUp(self): super(ServiceTestCase, self).setUp() self.mox.StubOutWithMock(service, 'db') self.context = context.get_admin_context() diff --git a/nova/tests/volume_unittest.py b/nova/tests/volume_unittest.py index 8e2fa11c1..20bae8a7f 100644 --- a/nova/tests/volume_unittest.py +++ b/nova/tests/volume_unittest.py @@ -34,7 +34,7 @@ FLAGS = flags.FLAGS class VolumeTestCase(test.TrialTestCase): """Test Case for volumes""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): logging.getLogger().setLevel(logging.DEBUG) super(VolumeTestCase, self).setUp() self.compute = utils.import_object(FLAGS.compute_manager) diff --git a/nova/twistd.py b/nova/twistd.py index df75b603e..3ec0ff61e 100644 --- a/nova/twistd.py +++ b/nova/twistd.py @@ -53,6 +53,7 @@ class TwistdServerOptions(ServerOptions): class FlagParser(object): # this is a required attribute for gflags syntactic_help = '' + def __init__(self, parser): self.parser = parser @@ -63,6 +64,7 @@ class FlagParser(object): def WrapTwistedOptions(wrapped): class TwistedOptionsToFlags(wrapped): subCommands = None + def __init__(self): # NOTE(termie): _data exists because Twisted stuff expects # to be able to set arbitrary things that are @@ -80,7 +82,8 @@ def WrapTwistedOptions(wrapped): def _absorbFlags(self): twistd_flags = [] - reflect.accumulateClassList(self.__class__, 'optFlags', twistd_flags) + reflect.accumulateClassList(self.__class__, 'optFlags', + twistd_flags) for flag in twistd_flags: key = flag[0].replace('-', '_') if hasattr(FLAGS, key): @@ -89,7 +92,8 @@ def WrapTwistedOptions(wrapped): def _absorbParameters(self): twistd_params = [] - reflect.accumulateClassList(self.__class__, 'optParameters', twistd_params) + reflect.accumulateClassList(self.__class__, 'optParameters', + twistd_params) for param in twistd_params: key = param[0].replace('-', '_') if hasattr(FLAGS, key): @@ -103,13 +107,14 @@ def WrapTwistedOptions(wrapped): def _absorbHandlers(self): twistd_handlers = {} - reflect.addMethodNamesToDict(self.__class__, twistd_handlers, "opt_") + reflect.addMethodNamesToDict(self.__class__, twistd_handlers, + "opt_") # NOTE(termie): Much of the following is derived/copied from # twisted.python.usage with the express purpose of # providing compatibility for name in twistd_handlers.keys(): - method = getattr(self, 'opt_'+name) + method = getattr(self, 'opt_' + name) takesArg = not usage.flagFunction(method, name) doc = getattr(method, '__doc__', None) @@ -125,7 +130,6 @@ def WrapTwistedOptions(wrapped): flags.DEFINE_string(name, None, doc) self._paramHandlers[name] = method - def _doHandlers(self): for flag, handler in self._flagHandlers.iteritems(): if self[flag]: @@ -195,7 +199,7 @@ def stop(pidfile): """ # Get the pid from the pidfile try: - pf = file(pidfile,'r') + pf = file(pidfile, 'r') pid = int(pf.read().strip()) pf.close() except IOError: @@ -204,7 +208,8 @@ def stop(pidfile): if not pid: message = "pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % pidfile) - return # not an error in a restart + # Not an error in a restart + return # Try killing the daemon process try: diff --git a/nova/utils.py b/nova/utils.py index 10b27ffec..7683fc9f4 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -39,6 +39,7 @@ from nova.exception import ProcessExecutionError FLAGS = flags.FLAGS TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" + def import_class(import_str): """Returns a class from a string including module and class""" mod_str, _sep, class_str = import_str.rpartition('.') @@ -48,6 +49,7 @@ def import_class(import_str): except (ImportError, ValueError, AttributeError): raise exception.NotFound('Class %s cannot be found' % class_str) + def import_object(import_str): """Returns an object including a module or module and class""" try: @@ -57,6 +59,7 @@ def import_object(import_str): cls = import_class(import_str) return cls() + def fetchfile(url, target): logging.debug("Fetching %s" % url) # c = pycurl.Curl() @@ -68,6 +71,7 @@ def fetchfile(url, target): # fp.close() execute("curl --fail %s -o %s" % (url, target)) + def execute(cmd, process_input=None, addl_env=None, check_exit_code=True): logging.debug("Running cmd: %s", cmd) env = os.environ.copy() @@ -83,7 +87,7 @@ def execute(cmd, process_input=None, addl_env=None, check_exit_code=True): obj.stdin.close() if obj.returncode: logging.debug("Result was %s" % (obj.returncode)) - if check_exit_code and obj.returncode <> 0: + if check_exit_code and obj.returncode != 0: (stdout, stderr) = result raise ProcessExecutionError(exit_code=obj.returncode, stdout=stdout, @@ -106,7 +110,8 @@ def default_flagfile(filename='nova.conf'): script_dir = os.path.dirname(inspect.stack()[-1][1]) filename = os.path.abspath(os.path.join(script_dir, filename)) if os.path.exists(filename): - sys.argv = sys.argv[:1] + ['--flagfile=%s' % filename] + sys.argv[1:] + flagfile = ['--flagfile=%s' % filename] + sys.argv = sys.argv[:1] + flagfile + sys.argv[1:] def debug(arg): @@ -114,11 +119,11 @@ def debug(arg): return arg -def runthis(prompt, cmd, check_exit_code = True): +def runthis(prompt, cmd, check_exit_code=True): logging.debug("Running %s" % (cmd)) exit_code = subprocess.call(cmd.split(" ")) logging.debug(prompt % (exit_code)) - if check_exit_code and exit_code <> 0: + if check_exit_code and exit_code != 0: raise ProcessExecutionError(exit_code=exit_code, stdout=None, stderr=None, @@ -128,7 +133,7 @@ def runthis(prompt, cmd, check_exit_code = True): def generate_uid(topic, size=8): if topic == "i": # Instances have integer internal ids. - return random.randint(0, 2**32-1) + return random.randint(0, 2 ** 32 - 1) else: characters = '01234567890abcdefghijklmnopqrstuvwxyz' choices = [random.choice(characters) for x in xrange(size)] @@ -136,9 +141,10 @@ def generate_uid(topic, size=8): def generate_mac(): - mac = [0x02, 0x16, 0x3e, random.randint(0x00, 0x7f), - random.randint(0x00, 0xff), random.randint(0x00, 0xff) - ] + mac = [0x02, 0x16, 0x3e, + random.randint(0x00, 0x7f), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff)] return ':'.join(map(lambda x: "%02x" % x, mac)) @@ -201,6 +207,7 @@ class LazyPluggable(object): backend = self.__get_backend() return getattr(backend, key) + def deferredToThread(f): def g(*args, **kwargs): return deferToThread(f, *args, **kwargs) diff --git a/nova/validate.py b/nova/validate.py index 21f4ed286..7ea27daa6 100644 --- a/nova/validate.py +++ b/nova/validate.py @@ -16,18 +16,20 @@ # License for the specific language governing permissions and limitations # under the License. -""" - Decorators for argument validation, courtesy of - http://rmi.net/~lutz/rangetest.html -""" +"""Decorators for argument validation, courtesy of +http://rmi.net/~lutz/rangetest.html""" -def rangetest(**argchecks): # validate ranges for both+defaults - def onDecorator(func): # onCall remembers func and argchecks + +def rangetest(**argchecks): + """Validate ranges for both + defaults""" + + def onDecorator(func): + """onCall remembers func and argchecks""" import sys code = func.__code__ if sys.version_info[0] == 3 else func.func_code - allargs = code.co_varnames[:code.co_argcount] + allargs = code.co_varnames[:code.co_argcount] funcname = func.__name__ - + def onCall(*pargs, **kargs): # all pargs match first N args by position # the rest must be in kargs or omitted defaults @@ -38,7 +40,8 @@ def rangetest(**argchecks): # validate ranges for both+defaults # for all args to be checked if argname in kargs: # was passed by name - if float(kargs[argname]) < low or float(kargs[argname]) > high: + if float(kargs[argname]) < low or \ + float(kargs[argname]) > high: errmsg = '{0} argument "{1}" not in {2}..{3}' errmsg = errmsg.format(funcname, argname, low, high) raise TypeError(errmsg) @@ -46,9 +49,12 @@ def rangetest(**argchecks): # validate ranges for both+defaults elif argname in positionals: # was passed by position position = positionals.index(argname) - if float(pargs[position]) < low or float(pargs[position]) > high: - errmsg = '{0} argument "{1}" with value of {4} not in {2}..{3}' - errmsg = errmsg.format(funcname, argname, low, high, pargs[position]) + if float(pargs[position]) < low or \ + float(pargs[position]) > high: + errmsg = '{0} argument "{1}" with value of {4} ' \ + 'not in {2}..{3}' + errmsg = errmsg.format(funcname, argname, low, high, + pargs[position]) raise TypeError(errmsg) else: pass @@ -62,9 +68,9 @@ def typetest(**argchecks): def onDecorator(func): import sys code = func.__code__ if sys.version_info[0] == 3 else func.func_code - allargs = code.co_varnames[:code.co_argcount] + allargs = code.co_varnames[:code.co_argcount] funcname = func.__name__ - + def onCall(*pargs, **kargs): positionals = list(allargs)[:len(pargs)] for (argname, typeof) in argchecks.items(): @@ -76,12 +82,13 @@ def typetest(**argchecks): elif argname in positionals: position = positionals.index(argname) if not isinstance(pargs[position], typeof): - errmsg = '{0} argument "{1}" with value of {2} not of type {3}' - errmsg = errmsg.format(funcname, argname, pargs[position], typeof) + errmsg = '{0} argument "{1}" with value of {2} ' \ + 'not of type {3}' + errmsg = errmsg.format(funcname, argname, + pargs[position], typeof) raise TypeError(errmsg) else: pass return func(*pargs, **kargs) return onCall return onDecorator - diff --git a/nova/wsgi.py b/nova/wsgi.py index b91d91121..eb305a3d3 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -94,11 +94,11 @@ class Middleware(Application): behavior. """ - def __init__(self, application): # pylint: disable-msg=W0231 + def __init__(self, application): # pylint: disable-msg=W0231 self.application = application @webob.dec.wsgify - def __call__(self, req): # pylint: disable-msg=W0221 + def __call__(self, req): # pylint: disable-msg=W0221 """Override to implement middleware behavior.""" return self.application @@ -216,7 +216,7 @@ class Controller(object): arg_dict['req'] = req result = method(**arg_dict) if type(result) is dict: - return self._serialize(result, req) + return self._serialize(result, req) else: return result @@ -240,6 +240,7 @@ class Controller(object): serializer = Serializer(request.environ, _metadata) return serializer.deserialize(data) + class Serializer(object): """ Serializes and deserializes dictionaries to certain MIME types. @@ -263,12 +264,13 @@ class Serializer(object): elif 'application/xml' in req.accept: self.handler = self._to_xml else: - self.handler = self._to_json # default + # This is the default + self.handler = self._to_json def to_content_type(self, data): """ Serialize a dictionary into a string. - + The format of the string will be decided based on the Content Type requested in self.environ: by Accept: header, or by URL suffix. """ @@ -277,7 +279,7 @@ class Serializer(object): def deserialize(self, datastring): """ Deserialize a string to a dictionary. - + The string must be in the format of a supported MIME type. """ datastring = datastring.strip() @@ -298,7 +300,7 @@ class Serializer(object): def _from_xml_node(self, node, listnames): """ Convert a minidom node to a simple Python type. - + listnames is a collection of names of XML nodes whose subnodes should be considered list items. """ @@ -312,7 +314,8 @@ class Serializer(object): result[attr] = node.attributes[attr].nodeValue for child in node.childNodes: if child.nodeType != node.TEXT_NODE: - result[child.nodeName] = self._from_xml_node(child, listnames) + result[child.nodeName] = self._from_xml_node(child, + listnames) return result def _to_json(self, data): @@ -347,7 +350,8 @@ class Serializer(object): else: node = self._to_xml_node(doc, metadata, k, v) result.appendChild(node) - else: # atom + else: + # Type is atom node = doc.createTextNode(str(data)) result.appendChild(node) return result @@ -13,7 +13,7 @@ argument-rgx=[a-z_][a-z0-9_]{1,30}$ # Method names should be at least 3 characters long # and be lowecased with underscores -method-rgx=[a-z_][a-z0-9_]{2,50}$ +method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|tearDown)$ # Module names matching nova-* are ok (files in bin/) module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(nova-[a-z0-9_-]+))$ |
