2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-06-11 17:28:50 +00:00

Manipulate code to make it conform to pep8

This commit is contained in:
Jarrod Johnson
2014-02-06 13:13:16 -05:00
parent d2d7f04f49
commit 9aa73718b9
5 changed files with 103 additions and 90 deletions
+15 -12
View File
@@ -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:
+11 -16
View File
@@ -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:
# <responding to session open>: (the session seems to be opaque
# {"session":"h5lrOKViIeQGp1nXjKWpAQ","data":""}
# <responding to wait for data with data, specically a prompt that sets title>
# {"session":"blah","data":"\r\n\u001B]0;bob@thor:~\u0007[bob@thor ~]$ "}
# <responding to wait for data with data, specically a prompt
# that sets title>
# {"session":"blah","data":"\r\n\u001B]0;bob@thor:~\u0007$ "}
# <responding to wait with no data (seems to wait 46 seconds)
# {"session":"jSGBPmAxavsD/1acSl/uog","data":""}
# closed session returns HTTP 400 to a console answer
elif connection is not None: # This is a TLS or unix socket
conshandler = ConsoleSession(connection, releaseconnection)
ConsoleSession(connection, releaseconnection)
+40 -28
View File
@@ -6,6 +6,7 @@
import confluent.exceptions as exc
import json
class ConfluentMessage(object):
defaultvalue = ''
defaulttype = 'text'
@@ -48,26 +49,27 @@ class ConfluentMessage(object):
if isinstance(val, list):
snippet += key + ":"
for v in val:
snippet += \
'<input type="%s" name="%s" value="%s" title="%s">%s' % (
type, key, v, desc, note)
snippet += \
'<input type="%s" name="%s" value="" title="%s">%s' % (
type, key, desc, note)
snippet += '<input type="checkbox" name="restexplorerhonorkey" '
snippet += 'value="%s">' % (key)
snippet += ('<input type="{0}" name="{1}" value="{2}" '
' "title="{3}">{4}'
).format(type, key, v, desc, note)
snippet += (
'<input type="{0}" name="{1}" value="" title="{2}">{3}'
'<input type="checkbox" name="restexplorerhonorkey" '
'value="{1}">').format(type, key, desc, note)
return snippet
snippet += key + ":" + \
'<input type="%s" name="%s" value="%s" title="%s">%s' % (
type, key, value, desc, note)
snippet += '<input type="checkbox" name="restexplorerhonorkey" '
snippet += 'value="%s">' % (key)
snippet += (key + ":" +
'<input type="{0}" name="{1}" value="{2}" '
'title="{3}">{4}<input type="checkbox" '
'name="restexplorerhonorkey" value="{1}">'
).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 '<a href="%s" rel="%s">%s</a>' % (self.href, self.rel, self.href)
#return '<a href="%s" rel="%s">%s</a><input type="submit" name="restexprerorop" value="delete:%s"' % (self.href, self.rel, self.href, self.href)
return '<a href="{0}" rel="{1}">{0}</a>'.format(self.href, self.rel)
# return '<a href="%s" rel="%s">%s</a><input type="submit"
# name="restexprerorop" value="delete:%s"' % (self.href, self.rel,
# self.href, self.href)
class ChildCollection(LinkRelation):
@@ -119,16 +123,20 @@ class ChildCollection(LinkRelation):
def html(self):
if self.candelete:
return '<a href="%s" rel="%s">%s</a> . . . . . . . . . . . . . . . . . . <button type="submit" name="restexplorerop" value="delete" formaction="%s">delete</button>' % (self.href, self.rel, self.href, self.href)
return ('<a href="{0}" rel="{1}">{0}</a> . . . . . . . . . . . . '
'<button type="submit" name="restexplorerop" '
'value="delete" formaction="{0}">delete'
'</button>').format(self.href, self.rel)
else:
return '<a href="%s" rel="%s">%s</a>' % (self.href, self.rel, self.href)
return '<a href="{0}" rel="{0}">{0}</a>'.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:
+33 -28
View File
@@ -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. <nodeelement>/power/state maps to some plugin HardwareManager.get_power/set_power
# selected by hardwaremanagement.method
# e.g. <nodeelement>/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()
+4 -6
View File
@@ -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]