From 9aa73718b97fafc4bd02d3382323f1fead22c0a7 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 6 Feb 2014 13:13:16 -0500 Subject: [PATCH] Manipulate code to make it conform to pep8 --- confluent/auth.py | 27 ++++++++------- confluent/consoleserver.py | 27 ++++++--------- confluent/messages.py | 68 ++++++++++++++++++++++---------------- confluent/pluginapi.py | 61 ++++++++++++++++++---------------- confluent/util.py | 10 +++--- 5 files changed, 103 insertions(+), 90 deletions(-) diff --git a/confluent/auth.py b/confluent/auth.py index e52f089a..035e23a4 100644 --- a/confluent/auth.py +++ b/confluent/auth.py @@ -1,6 +1,6 @@ # authentication and authorization routines for confluent # authentication scheme caches passphrase values to help HTTP Basic auth -# the PBKDF2 transform is skipped unless a user has been idle for sufficient +# the PBKDF2 transform is skipped unless a user has been idle for sufficient # time import confluent.config.configmanager as configmanager @@ -36,7 +36,7 @@ def _get_usertenant(name, tenant=False): administrator account a tenant gets. Otherwise, just assume a user in the default tenant """ - if not isinstance(tenant,bool): + if not isinstance(tenant, bool): # if not boolean, it must be explicit tenant user = name elif '/' in name: # tenant scoped name @@ -45,12 +45,13 @@ def _get_usertenant(name, tenant=False): # the account is the implicit tenant owner account user = name tenant = name - else: # assume it is a non-tenant user account + else: # assume it is a non-tenant user account user = name tenant = None yield user yield tenant + def authorize(name, element, tenant=False, access='rw'): #TODO: actually use the element to ascertain if this user is good enough """Determine whether the given authenticated name is authorized. @@ -70,7 +71,7 @@ def authorize(name, element, tenant=False, access='rw'): return None manager = configmanager.ConfigManager(tenant) userobj = manager.get_user(user) - if userobj: #returning + if userobj: # returning return (userobj, manager) return None @@ -89,9 +90,10 @@ def set_user_passphrase(name, passphrase, tenant=None): _passcache[(user, tenant)] = passphrase salt = os.urandom(8) crypted = kdf.PBKDF2(passphrase, salt, 32, 10000, - lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest()) + lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest() + ) cfm = configmanager.ConfigManager(tenant) - cfm.set_user(name, { 'cryptpass': (salt, crypted) }) + cfm.set_user(name, {'cryptpass': (salt, crypted)}) def check_user_passphrase(name, passphrase, element=None, tenant=False): @@ -116,14 +118,14 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False): # for that particular user. # similarly, guessing usernames is throttled to 20/sec user, tenant = _get_usertenant(name, tenant) - while (user,tenant) in _passchecking: + while (user, tenant) in _passchecking: # Want to serialize passphrase checking activity # by a user, which might be malicious # would normally make an event and wait # but here there's no need for that eventlet.sleep(0.5) - if (user,tenant) in _passcache: - if passphrase == _passcache[(user,tenant)]: + if (user, tenant) in _passcache: + if passphrase == _passcache[(user, tenant)]: return authorize(user, element, tenant) else: # In case of someone trying to guess, @@ -134,7 +136,7 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False): cfm = configmanager.ConfigManager(tenant) ucfg = cfm.get_user(user) if ucfg is None or 'cryptpass' not in ucfg: - eventlet.sleep(0.05) #stall even on test for existance of a username + eventlet.sleep(0.05) # stall even on test for existance of a username return None _passchecking[(user, tenant)] = True # TODO(jbjohnso): WORKERPOOL @@ -142,9 +144,10 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False): # throw it at the worker pool when implemented salt, crypt = ucfg['cryptpass'] crypted = kdf.PBKDF2(passphrase, salt, 32, 10000, - lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest()) + lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest() + ) del _passchecking[(user, tenant)] - eventlet.sleep(0.05) #either way, we want to stall so that client can't + eventlet.sleep(0.05) # either way, we want to stall so that client can't # determine failure because there is a delay, valid response will # delay as well if crypt == crypted: diff --git a/confluent/consoleserver.py b/confluent/consoleserver.py index e9c791bc..b152d73a 100644 --- a/confluent/consoleserver.py +++ b/confluent/consoleserver.py @@ -9,14 +9,13 @@ #there should be no more than one handler per node import confluent.interface.console as conapi import confluent.pluginapi as plugin -import confluent.util as util import eventlet import eventlet.green.threading as threading import random -import time _handled_consoles = {} + class _ConsoleHandler(object): def __init__(self, node, configmanager): self.rcpts = {} @@ -42,7 +41,6 @@ class _ConsoleHandler(object): self.rcpts[hdl] = callback return hdl - def flushbuffer(self): #TODO:log the old stuff if len(self.buffer) > 1024: @@ -108,6 +106,7 @@ class _ConsoleHandler(object): #level? self._console.write(data) + #this represents some api view of a console handler. This handles things like #holding the caller specific queue data, for example, when http api should be #sending data, but there is no outstanding POST request to hold it, @@ -131,7 +130,7 @@ class ConsoleSession(object): self.write = _handled_consoles[node].write if datacallback is None: self.reaper = eventlet.spawn_after(15, self.destroy) - self.databuffer = _handled_consoles[node].get_recent() + self.databuffer = _handled_consoles[node].get_recent() self.reghdl = _handled_consoles[node].register_rcpt(self.got_data) else: self.reghdl = _handled_consoles[node].register_rcpt(datacallback) @@ -161,13 +160,8 @@ class ConsoleSession(object): at least one case where we don't have that luxury """ self.reaper.cancel() - try: - if len(self.databuffer) == 0: - self._evt.wait(timeout) - except TypeError: - import traceback - traceback.print_exc() - return "" + if len(self.databuffer) == 0: + self._evt.wait(timeout) retval = self.databuffer self.databuffer = "" if self._evt is not None: @@ -185,8 +179,8 @@ def handle_request(request=None, connection=None, releaseconnection=False): :param connection: For socket style console, this is a read/write socket that the caller has released from it's control and console plugin will do all IO - :param releaseconnection: A function for console to call to indicate confluent - should resume control over the connection + :param releaseconnection: A function for console to call to indicate + confluent should resume control over the connection """ if request is not None: # This is indicative of http style @@ -209,10 +203,11 @@ def handle_request(request=None, connection=None, releaseconnection=False): # the responses: # : (the session seems to be opaque # {"session":"h5lrOKViIeQGp1nXjKWpAQ","data":""} - # - # {"session":"blah","data":"\r\n\u001B]0;bob@thor:~\u0007[bob@thor ~]$ "} + # + # {"session":"blah","data":"\r\n\u001B]0;bob@thor:~\u0007$ "} # %s' % ( - type, key, v, desc, note) - snippet += \ - '%s' % ( - type, key, desc, note) - snippet += '{4}' + ).format(type, key, v, desc, note) + snippet += ( + '{3}' + '').format(type, key, desc, note) return snippet - snippet += key + ":" + \ - '%s' % ( - type, key, value, desc, note) - snippet += '{4}' + ).format(type, key, value, desc, note) return snippet + class DeletedResource(ConfluentMessage): def __init__(self): self.kvpairs = {} + class ConfluentChoiceMessage(ConfluentMessage): def html(self): @@ -87,28 +89,30 @@ class ConfluentChoiceMessage(ConfluentMessage): snippet += 'value="%s">' % (key) return snippet + class LinkRelation(ConfluentMessage): def json_hal(self): """Provide json_hal style representation of the relation. This currently only makes sense for the socket api. """ - return {self.rel: '{ "href": "%s" }' % self.href } + return {self.rel: '{ "href": "%s" }' % self.href} def raw_rel(self): """Provide python structure of the relation. This currently is only sensible to consume from httpapi. """ - return { self.rel: { "href": self.href }} + return {self.rel: {"href": self.href}} def html(self): """Provide an html representation of the link relation. This is used by the API explorer aspect of httpapi""" - return '%s' % (self.href, self.rel, self.href) - #return '%s{0}'.format(self.href, self.rel) + # return '%s%s . . . . . . . . . . . . . . . . . . ' % (self.href, self.rel, self.href, self.href) + return ('{0} . . . . . . . . . . . . ' + '').format(self.href, self.rel) else: - return '%s' % (self.href, self.rel, self.href) + return '{0}'.format(self.href) + def get_input_message(path, operation, inputdata, nodes=None): if path[0] == 'power' and path[1] == 'state' and operation != 'retrieve': return InputPowerMessage(path, nodes, inputdata) elif path[0] == 'attributes' and operation != 'retrieve': return InputAttributes(path, nodes, inputdata) - elif path == [ 'boot', 'device' ] and operation != 'retrieve': + elif path == ['boot', 'device'] and operation != 'retrieve': return InputBootDevice(path, nodes, inputdata) elif inputdata: raise exc.InvalidArgumentException() @@ -181,7 +189,7 @@ class InputPowerMessage(ConfluentMessage): datum['powerstate'] not in self.valid_values): raise exc.InvalidArgumentException() self.powerbynode[key] = datum['powerstate'] - else: # we have a powerstate argument not by node + else: # we have a powerstate argument not by node datum = inputdata if ('powerstate' not in datum or datum['powerstate'] not in self.valid_values): @@ -204,13 +212,14 @@ class BootDevice(ConfluentChoiceMessage): def __init__(self, node, device): if device not in self.valid_values: - raise Exception("Invalid boot device argument passed in: %s" % device) + raise Exception("Invalid boot device argument passed in:" + device) self.kvpairs = { node: { - 'bootdevice': { 'value': device }, + 'bootdevice': {'value': device}, } } + class InputBootDevice(BootDevice): def __init__(self, path, nodes, inputdata): self.bootdevbynode = {} @@ -221,7 +230,7 @@ class InputBootDevice(BootDevice): if key not in inputdata: raise exc.InvalidArgumentException() datum = inputdata[key] - if ('powerstate' not in datoum or + if ('powerstate' not in datum or datum['powerstate'] not in self.valid_values): raise exc.InvalidArgumenTException() self.bootdevbynode[key] = datum['bootdevice'] @@ -248,16 +257,17 @@ class PowerState(ConfluentChoiceMessage): def __init__(self, node, state): self.kvpairs = { node: { - 'powerstate': { 'value': state }, + 'powerstate': {'value': state}, } } + class Attributes(ConfluentMessage): def __init__(self, node=None, kv=None, desc=None): self.desc = desc nkv = {} for key in kv.iterkeys(): - nkv[key] = { 'value': kv[key] } + nkv[key] = {'value': kv[key]} if node is None: self.kvpairs = nkv else: @@ -265,12 +275,14 @@ class Attributes(ConfluentMessage): node: nkv } + class ListAttributes(ConfluentMessage): def __init__(self, node, kv): self .kvpairs = { node: kv } + class CryptedAttributes(Attributes): defaulttype = 'password' @@ -279,7 +291,7 @@ class CryptedAttributes(Attributes): self.desc = desc nkv = {} for key in kv.iterkeys(): - nkv[key] = { 'note': 'Encrypted' } + nkv[key] = {'note': 'Encrypted'} if node is None: self.kvpairs = nkv else: diff --git a/confluent/pluginapi.py b/confluent/pluginapi.py index 9836392c..994a57f6 100644 --- a/confluent/pluginapi.py +++ b/confluent/pluginapi.py @@ -5,8 +5,8 @@ # have to specify a standard place for cfg selection of *which* plugin # as well a standard to map api requests to python funcitons -# e.g. /power/state maps to some plugin HardwareManager.get_power/set_power -# selected by hardwaremanagement.method +# e.g. /power/state maps to some plugin +# HardwareManager.get_power/set_power selected by hardwaremanagement.method # plugins can advertise a set of names if there is a desire for readable things # exceptions to handle os images # endpoints point to a class... usually, the class should have: @@ -25,16 +25,18 @@ import sys pluginmap = {} + def nested_lookup(nestdict, key): return reduce(dict.__getitem__, key, nestdict) + def load_plugins(): # To know our plugins directory, we get the parent path of 'bin' - path=os.path.dirname(os.path.realpath(__file__)) - plugintop = os.path.realpath(os.path.join(path,'..','plugins')) + path = os.path.dirname(os.path.realpath(__file__)) + plugintop = os.path.realpath(os.path.join(path, '..', 'plugins')) plugins = set() for plugindir in os.listdir(plugintop): - plugindir = os.path.join(plugintop,plugindir) + plugindir = os.path.join(plugintop, plugindir) if not os.path.isdir(plugindir): continue sys.path.append(plugindir) @@ -53,7 +55,8 @@ def load_plugins(): pluginmap[plugin] = tmpmod -rootcollections = [ 'node/', 'nodegroup/' ]; +rootcollections = ['node/', 'nodegroup/'] + class PluginRoute(object): def __init__(self, routedict): @@ -63,7 +66,7 @@ class PluginRoute(object): noderesources = { '_console': { 'session': PluginRoute({ - 'pluginattrs': ['console.method' ,'hardwaremanagement.method'], + 'pluginattrs': ['console.method', 'hardwaremanagement.method'], }), }, 'console': { @@ -83,22 +86,25 @@ noderesources = { }), }, 'attributes': { - 'all': PluginRoute({ 'handler': 'attributes' }), - 'current': PluginRoute({ 'handler': 'attributes' }), + 'all': PluginRoute({'handler': 'attributes'}), + 'current': PluginRoute({'handler': 'attributes'}), }, } + def stripnode(iterablersp, node): for i in iterablersp: i.strip_node(node) yield i + def iterate_collections(iterable): for coll in iterable: if coll[-1] != '/': coll = coll + '/' yield msg.ChildCollection(coll, candelete=True) + def iterate_resources(fancydict): for resource in fancydict.iterkeys(): if resource.startswith("_"): @@ -107,16 +113,18 @@ def iterate_resources(fancydict): resource += '/' yield msg.ChildCollection(resource) + def delete_node_collection(collectionpath, configmanager): - if len(collectionpath) == 2: #just node + if len(collectionpath) == 2: # just node node = collectionpath[-1] configmanager.del_nodes([node]) yield msg.DeletedResource() else: raise Exception("Not implemented") + def enumerate_node_collection(collectionpath, configmanager): - if collectionpath == [ 'node' ]: #it is simple '/node/', need a list of nodes + if collectionpath == ['node']: # it is just '/node/', need a list of nodes return iterate_collections(configmanager.get_nodes()) del collectionpath[0:2] collection = nested_lookup(noderesources, collectionpath) @@ -127,7 +135,7 @@ def create_node(inputdata, configmanager): try: nodename = inputdata['name'] del inputdata['name'] - attribmap = { nodename: inputdata } + attribmap = {nodename: inputdata} except KeyError: raise exc.InvalidArgumentException() configmanager.set_node_attributes(attribmap) @@ -151,11 +159,11 @@ def handle_path(path, operation, configmanager, inputdata=None): if pathcomponents[-1] == '': iscollection = True del pathcomponents[-1] - if not pathcomponents: #root collection list + if not pathcomponents: # root collection list return enumerate_collections(rootcollections) elif pathcomponents[0] == 'nodegroup': try: - group = pathcomponents[1] + pass # group = pathcomponents[1] except IndexError: return iterate_collections(configmanager.get_groups()) elif pathcomponents[0] in ('node', 'system', 'vm'): @@ -181,8 +189,9 @@ def handle_path(path, operation, configmanager, inputdata=None): plugroute = nested_lookup(noderesources, pathcomponents).routeinfo except KeyError: raise exc.NotFoundException("Invalid element requested") - inputdata = msg.get_input_message(pathcomponents, operation, inputdata, (node,)) - if 'handler' in plugroute: #fixed handler definition + inputdata = msg.get_input_message( + pathcomponents, operation, inputdata, (node,)) + if 'handler' in plugroute: # fixed handler definition passvalue = pluginmap[plugroute['handler']].__dict__[operation]( nodes=(node,), element=pathcomponents, configmanager=configmanager, @@ -190,17 +199,16 @@ def handle_path(path, operation, configmanager, inputdata=None): elif 'pluginattrs' in plugroute: nodeattr = configmanager.get_node_attributes( [node], plugroute['pluginattrs']) - foundplug = False + plugpath = None + if 'default' in plugroute: + plugpath = plugroute['default'] for attrname in plugroute['pluginattrs']: if attrname in nodeattr[node]: - foundplug = True - passvalue = pluginmap[nodeattr[node][attrname]['value']].__dict__[operation]( - nodes=(node,), element=pathcomponents, - configmanager=configmanager, - inputdata=inputdata) - if (not foundplug) and 'default' in plugroute: - passvalue = pluginmap[plugroute['default']].__dict__[operation]( - nodes=(node,), element=pathcomponents, configmanager=configmanager, + plugpath = nodeattr[node][attrname]['value'] + if plugpath is not None: + passvalue = pluginmap[plugpath].__dict__[operation]( + nodes=(node,), element=pathcomponents, + configmanager=configmanager, inputdata=inputdata) if isinstance(passvalue, console.Console): return passvalue @@ -208,6 +216,3 @@ def handle_path(path, operation, configmanager, inputdata=None): return stripnode(passvalue, node) else: raise exc.NotFoundException() - - - diff --git a/confluent/util.py b/confluent/util.py index 9bb2e1c4..b1d5313c 100644 --- a/confluent/util.py +++ b/confluent/util.py @@ -31,16 +31,14 @@ def securerandomnumber(min=0, max=4294967295): """ number = -1 while number < min or number > max: - number = struct.unpack("I",os.urandom(4))[0] + number = struct.unpack("I", os.urandom(4))[0] return number + def monotonic_time(): """Return a monotoc time value In scenarios like timeouts and such, monotonic timing is preferred. """ - if (os.name == "posix"): - return os.times()[4] - else: - return time.time() - #TODO: windows? + # for now, just support POSIX systems + return os.times()[4]