2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-22 09:32:21 +00:00

Have rest explorer actually mostly work as expected

This commit is contained in:
Jarrod Johnson 2013-11-07 14:39:34 -05:00
parent 836ea16603
commit 215acdf4a7
5 changed files with 87 additions and 36 deletions

View File

@ -257,6 +257,9 @@ def _assemble_html(responses, resource, querydict):
yield '<input type="hidden" name="restexplorerop" value="update">'
yield '<input type="hidden" name="restexplorerhonorkey" value="">'
yield '<a rel="self" href="%s">%s</a><br>' % (resource, resource)
print 'got a %s' % resource
if resource in ('/', './'):
pass
if resource[-1] == '/':
yield '<a rel="collection" href="../">../</a><br>'
else:

View File

@ -76,9 +76,9 @@ class ChildCollection(LinkRelation):
self.href = collname
def get_input_message(path, operation, inputdata, nodes=None):
if 'power/state' in path and operation != 'retrieve':
if path[0] == 'power' and path[1] == 'state' and operation != 'retrieve':
return InputPowerMessage(path, nodes, inputdata)
elif path.startswith('attributes/') and operation != 'retrieve':
elif path[0] == 'attributes' and operation != 'retrieve':
return InputAttributes(path, nodes, inputdata)
elif inputdata:
raise exc.InvalidArgumentException()

View File

@ -25,6 +25,8 @@ 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'
@ -62,7 +64,40 @@ nodecollections = {
rootcollections = {
'node/': nodecollections
}
# _ elements are for internal use (e.g. special console scheme)
class PluginRoute(object):
def __init__(self, routedict):
self.routeinfo = routedict
# _ prefix indicates internal use (e.g. special console scheme) and should not
# be enumerated in any collection
noderesources = {
'_console': {
'session': PluginRoute({
'pluginattrs': ['console.method' ,'hardwaremanagement.method'],
}),
},
'console': {
#this is a dummy value, http or socket must handle special
'session': PluginRoute({}),
},
'power': {
'state': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
},
'boot': {
'device': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
},
'attributes': {
'all': PluginRoute({ 'handler': 'attributes' }),
'current': PluginRoute({ 'handler': 'attributes' }),
},
}
nodeelements = {
'_console/session': {
'pluginattrs': ['console.method' ,'hardwaremanagement.method'],
@ -97,21 +132,21 @@ def iterate_collections(iterable):
coll = coll + '/'
yield msg.ChildCollection(coll)
def enumerate_collection(collection, configmanager):
if collection.startswith("/"):
collection = collection[1:]
if collection == 'node/':
def iterate_resources(fancydict):
for resource in fancydict.iterkeys():
if resource.startswith("_"):
continue
if not isinstance(fancydict[resource], PluginRoute): # a resource
resource += '/'
yield msg.ChildCollection(resource)
def enumerate_node_collection(collectionpath, configmanager):
print repr(collectionpath)
if collectionpath == [ 'node' ]: #it is simple '/node/', need a list of nodes
return iterate_collections(configmanager.get_nodes())
elif collection.startswith('node/'):
nodecoll = collection.replace('node/','')
print nodecoll
if '/' not in nodecoll[:-1]: # it is supposed to be a node
node = nodecoll[:-1]
if not configmanager.is_node(node):
raise exc.NotFoundException("Invalid node requested")
return iterate_collections(nodecollections.iterkeys())
else:
raise exc.NotFoundException("Invalid path")
del collectionpath[0:2]
collection = nested_lookup(noderesources, collectionpath)
return iterate_resources(collection)
def enumerate_collections(collections):
@ -125,23 +160,36 @@ def handle_path(path, operation, configmanager, inputdata=None):
An exception is made for console/session, which should return
a class with connect(), read(), write(bytes), and close()
'''
if path == '/':
iscollection = False
pathcomponents = path.split('/')
del pathcomponents[0] # discard the value from leading /
print repr(pathcomponents)
if pathcomponents[-1] == '':
iscollection = True
del pathcomponents[-1]
if not pathcomponents: #root collection list
return enumerate_collections(rootcollections)
elif path[-1] == '/':
return enumerate_collection(path, configmanager)
elif (path.startswith("/node/") or path.startswith("/system/") or
# single node requests
path.startswith("/vm/")):
nodeidx = path.find("/",1) + 1
node = path[nodeidx:]
node, _, element = node.partition("/")
if element not in nodeelements:
elif pathcomponents[0] in ('node', 'system', 'vm'):
#single node request of some sort
try:
node = pathcomponents[1]
except IndexError: # doesn't actually have a long enough path
return iterate_collections(configmanager.get_nodes())
if iscollection:
print "oh hi there..."
print repr(pathcomponents[2:])
return enumerate_node_collection(pathcomponents, configmanager)
print repr(pathcomponents)
del pathcomponents[0:2]
print repr(pathcomponents)
try:
plugroute = nested_lookup(noderesources, pathcomponents).routeinfo
except KeyError:
raise exc.NotFoundException("Invalid element requested")
inputdata = msg.get_input_message(element, operation, inputdata, (node,))
plugroute = nodeelements[element]
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=element,
nodes=(node,), element=pathcomponents,
configmanager=configmanager,
inputdata=inputdata)
elif 'pluginattrs' in plugroute:
@ -150,12 +198,12 @@ def handle_path(path, operation, configmanager, inputdata=None):
for attrname in plugroute['pluginattrs']:
if attrname in nodeattr[node]:
passvalue = pluginmap[nodeattr[node][attrname]['value']].__dict__[operation](
nodes=(node,), element=element,
nodes=(node,), element=pathcomponents,
configmanager=configmanager,
inputdata=inputdata)
if 'default' in plugroute:
passvalue = pluginmap[plugroute['default']].__dict__[operation](
nodes=(node,), element=element, configmanager=configmanager,
nodes=(node,), element=pathcomponents, configmanager=configmanager,
inputdata=inputdata)
if isinstance(passvalue, console.Console):
return passvalue

View File

@ -3,7 +3,7 @@ import confluent.config.attributes as allattributes
def retrieve(nodes, element, configmanager, inputdata):
attributes = configmanager.get_node_attributes(nodes)
if element.endswith('/all'):
if element[-1] == 'all':
for node in nodes:
for attribute in sorted(allattributes.node.iterkeys()):
if attribute in attributes[node]: #have a setting for it
@ -16,7 +16,7 @@ def retrieve(nodes, element, configmanager, inputdata):
else:
yield msg.Attributes(node,
{attribute: val['value']})
elif element.endswith('/current'):
elif element[-1] == 'current':
for node in attributes.iterkeys():
for attribute in sorted(attributes[node].iterkeys()):
currattr = attributes[node][attribute]

View File

@ -251,7 +251,7 @@ class IpmiHandler(object):
def handle_request(self):
while not self.loggedin:
wait_on_ipmi()
if self.element == 'power/state':
if self.element == [ 'power', 'state' ]:
if 'read' == self.op:
power = self.call_ipmicmd(self.ipmicmd.get_power)
return msg.PowerState(node=self.node,
@ -266,7 +266,7 @@ class IpmiHandler(object):
def create(nodes, element, configmanager, inputdata):
if element == '_console/session':
if element == [ '_console', 'session' ]:
if len(nodes) > 1:
raise Exception("_console/session does not support multiple nodes")
return IpmiConsole(nodes[0], configmanager)