diff --git a/bin/nova-api b/bin/nova-api index a5027700bc5f..20f1bd74f723 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 219f32250d32..08b3da1231a6 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 e16b2e00f8be..9817dc8868d6 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 fc9fcfde0683..b7a3d2c32431 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/context.py b/nova/context.py index f5d3fed08cf4..f2669c9f1785 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 1c6fe57adfef..16b4f5e1f26a 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 f157fab2dd69..6d6c3733802c 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 df5e61e6e963..c64617931cc7 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 3b473488fad4..f3b0384ad8c2 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 56ba7d3f6578..4244b2db4e82 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 13cb90e82909..b33df048bfc1 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 045051207c8b..01dd0ecd4547 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 965934205259..895820cd0097 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 c58a15041524..cb424caa19b9 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 8e89eb43ee41..8ef7eca1aedb 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 f051e2390813..a0681f4149f7 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 3f60f38f26a6..55a7ff32f7d8 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 01e1bcd3085e..01b5651df1bf 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 e8dd2624f0ca..44cf474077e4 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 f096ac6fec1c..d1604c4e5080 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 72e44bf526a6..92f3be508c20 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 5d2bb10463b2..c380393a0ed9 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 379f8cdc8f28..166a32702c68 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 8533fab0a8ca..6df108a985c2 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 8e2fa11c14bb..20bae8a7ff30 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 df75b603eb28..3ec0ff61e46b 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 10b27ffecbfa..7683fc9f458a 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 21f4ed286bd5..7ea27daa6ef7 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 b91d911213f1..eb305a3d326d 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 diff --git a/pylintrc b/pylintrc index 024802835199..f07b1498093b 100644 --- a/pylintrc +++ b/pylintrc @@ -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_-]+))$