mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-26 11:30:23 +00:00
Enable support for IPMI user management
Provide a framework for management of users on managed endpoints, and implement for IPMI plugin. From Juliana Motira
This commit is contained in:
parent
49bff93eed
commit
14a9220acb
@ -83,7 +83,7 @@ def load_plugins():
|
||||
if plugtype == '.sh':
|
||||
pluginmap[plugin] = shellmodule.Plugin(
|
||||
os.path.join(plugindir, plugin + '.sh'))
|
||||
elif "__init__" not in plugin:
|
||||
elif "__init__" not in plugin:
|
||||
plugins.add(plugin)
|
||||
for plugin in plugins:
|
||||
tmpmod = __import__(plugin)
|
||||
@ -126,7 +126,11 @@ noderesources = {
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
}
|
||||
},
|
||||
'users': PluginCollection({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
}
|
||||
},
|
||||
'_console': {
|
||||
|
@ -103,9 +103,36 @@ def node_creation_resources():
|
||||
desc=attribs.node[attr]['description']).html() + '<br>\n'
|
||||
|
||||
|
||||
def user_creation_resources():
|
||||
credential = {
|
||||
'uid': {
|
||||
'description': (''),
|
||||
},
|
||||
'username': {
|
||||
'description': (''),
|
||||
},
|
||||
'password': {
|
||||
'description': (''),
|
||||
},
|
||||
'privilege_level': {
|
||||
'description': (''),
|
||||
},
|
||||
}
|
||||
for attr in sorted(credential.iterkeys()):
|
||||
if attr == "password":
|
||||
yield confluent.messages.CryptedAttributes(
|
||||
kv={attr: None},
|
||||
desc=credential[attr]['description']).html() + '<br>\n'
|
||||
else:
|
||||
yield confluent.messages.Attributes(
|
||||
kv={attr: None},
|
||||
desc=credential[attr]['description']).html() + '<br>\n'
|
||||
|
||||
|
||||
create_resource_functions = {
|
||||
'/nodes/': node_creation_resources,
|
||||
'/groups/': group_creation_resources,
|
||||
'nodes': node_creation_resources,
|
||||
'groups': group_creation_resources,
|
||||
'users': user_creation_resources,
|
||||
}
|
||||
|
||||
|
||||
@ -444,11 +471,15 @@ def _assemble_html(responses, resource, querydict, url, extension):
|
||||
if iscollection:
|
||||
# localpath = url[:-2] (why was this here??)
|
||||
try:
|
||||
if url == '/users/':
|
||||
return
|
||||
firstpass = True
|
||||
for y in create_resource_functions[url]():
|
||||
module = url.split('/')
|
||||
if not module:
|
||||
return
|
||||
for y in create_resource_functions[module[-2]]():
|
||||
if firstpass:
|
||||
yield "<hr>Define new resource in %s:<BR>" % \
|
||||
url.split("/")[-2]
|
||||
yield "<hr>Define new resource in %s:<BR>" % module[-2]
|
||||
firstpass = False
|
||||
yield y
|
||||
yield ('<input value="create" name="restexplorerop" type="submit">'
|
||||
|
@ -107,7 +107,10 @@ class ConfluentMessage(object):
|
||||
for key in pairs.iterkeys():
|
||||
val = pairs[key]
|
||||
value = self.defaultvalue
|
||||
valtype = self.defaulttype
|
||||
if isinstance(val, dict) and 'type' in val:
|
||||
valtype = val['type']
|
||||
else:
|
||||
valtype = self.defaulttype
|
||||
notes = []
|
||||
|
||||
if isinstance(val, list):
|
||||
@ -322,6 +325,9 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False):
|
||||
return InputIdentifyMessage(path, nodes, inputdata)
|
||||
elif path == ['events', 'hardware', 'decode']:
|
||||
return InputAlertData(path, inputdata, nodes)
|
||||
elif (path[:3] == ['configuration', 'management_controller', 'users'] and
|
||||
operation != 'retrieve'):
|
||||
return InputCredential(path, inputdata, nodes)
|
||||
elif inputdata:
|
||||
raise exc.InvalidArgumentException()
|
||||
|
||||
@ -405,6 +411,61 @@ class InputAttributes(ConfluentMessage):
|
||||
return nodeattr
|
||||
|
||||
|
||||
class InputCredential(ConfluentMessage):
|
||||
valid_privilege_levels = set([
|
||||
'callback',
|
||||
'user',
|
||||
'operator',
|
||||
'administrator',
|
||||
'proprietary',
|
||||
'no_access',
|
||||
])
|
||||
|
||||
def __init__(self, path, inputdata, nodes=None):
|
||||
self.credentials = {}
|
||||
nestedmode = False
|
||||
if not inputdata:
|
||||
raise exc.InvalidArgumentException('no request data provided')
|
||||
|
||||
if len(path) == 4:
|
||||
inputdata['uid'] = path[-1]
|
||||
|
||||
if ('uid' not in inputdata or 'privilege_level' not in inputdata
|
||||
or 'username' not in inputdata or 'password' not in inputdata):
|
||||
raise exc.InvalidArgumentException('missing arguments')
|
||||
|
||||
if not inputdata['uid'].isdigit():
|
||||
raise exc.InvalidArgumentException('uid must be a number')
|
||||
else:
|
||||
inputdata['uid'] = int(inputdata['uid'])
|
||||
if inputdata['privilege_level'] not in self.valid_privilege_levels:
|
||||
raise exc.InvalidArgumentException('privilege_level is not one of '
|
||||
+ ','.join(self.valid_privilege_levels))
|
||||
|
||||
if nodes is None:
|
||||
raise exc.InvalidArgumentException(
|
||||
'This only supports per-node input')
|
||||
for node in nodes:
|
||||
self.credentials[node] = inputdata
|
||||
|
||||
def get_attributes(self, node):
|
||||
if node not in self.credentials:
|
||||
return {}
|
||||
credential = self.credentials[node]
|
||||
for attr in credentials:
|
||||
if type(credentials[attr]) in (str, unicode):
|
||||
try:
|
||||
# as above, use format() to see if string follows
|
||||
# expression, store value back in case of escapes
|
||||
tv = credential[attr].format()
|
||||
credential[attr] = tv
|
||||
except (KeyError, IndexError):
|
||||
# an expression string will error if format() done
|
||||
# use that as cue to put it into config as an expr
|
||||
credential[attr] = {'expression': credential[attr]}
|
||||
return credential
|
||||
|
||||
|
||||
class ConfluentInputMessage(ConfluentMessage):
|
||||
keyname = 'state'
|
||||
|
||||
@ -480,7 +541,7 @@ class BootDevice(ConfluentChoiceMessage):
|
||||
valid_paramset = {
|
||||
'bootmode': valid_bootmodes,
|
||||
}
|
||||
|
||||
|
||||
|
||||
def __init__(self, node, device, bootmode='unspecified'):
|
||||
if device not in self.valid_values:
|
||||
@ -601,6 +662,21 @@ class EventCollection(ConfluentMessage):
|
||||
self.kvpairs = {name: {'events': eventdata}}
|
||||
|
||||
|
||||
class User(ConfluentMessage):
|
||||
def __init__(self, uid, username, privilege_level, name=None):
|
||||
self.desc = 'foo'
|
||||
self.stripped = False
|
||||
self.notnode = name is None
|
||||
kvpairs = {'username': {'value': username},
|
||||
'password': {'value': '', 'type': 'password'},
|
||||
'privilege_level': {'value': privilege_level}
|
||||
}
|
||||
if self.notnode:
|
||||
self.kvpairs = kvpairs
|
||||
else:
|
||||
self.kvpairs = {name: kvpairs}
|
||||
|
||||
|
||||
class AlertDestination(ConfluentMessage):
|
||||
def __init__(self, ip, acknowledge=False, retries=0, name=None):
|
||||
self.desc = 'foo'
|
||||
|
@ -371,6 +371,8 @@ class IpmiHandler(object):
|
||||
def handle_configuration(self):
|
||||
if self.element[1:3] == ['management_controller', 'alerts' ]:
|
||||
return self.handle_alerts()
|
||||
elif self.element[1:3] == ['management_controller', 'users' ]:
|
||||
return self.handle_users()
|
||||
raise Exception('Not implemented')
|
||||
|
||||
def decode_alert(self):
|
||||
@ -421,6 +423,39 @@ class IpmiHandler(object):
|
||||
return
|
||||
raise Exception('Not implemented')
|
||||
|
||||
def handle_users(self):
|
||||
if len(self.element) == 3:
|
||||
if self.op == 'update':
|
||||
user = self.inputdata.credentials[self.node]
|
||||
self.ipmicmd.create_user(uid=user['uid'], name=user['username'],
|
||||
password=user['password'], channel=1,
|
||||
callback=True,link_auth=True, ipmi_msg=True,
|
||||
privilege_level=user['privilege_level'])
|
||||
# A list of users
|
||||
for user in self.ipmicmd.get_users(channel=1):
|
||||
self.output.put(msg.ChildCollection(user))
|
||||
return
|
||||
elif len(self.element) == 4:
|
||||
user = int(self.element[-1])
|
||||
if self.op == 'read':
|
||||
data = self.ipmicmd.get_user(uid=user, channel=1)
|
||||
self.output.put(msg.User(
|
||||
uid=data['uid'],
|
||||
username=data['name'],
|
||||
privilege_level=data['access']['privilege_level'],
|
||||
name=self.node))
|
||||
return
|
||||
elif self.op == 'update':
|
||||
user = self.inputdata.credentials[self.node]
|
||||
self.ipmicmd.create_user(uid=user['uid'], name=user['username'],
|
||||
password=user['password'], channel=1,
|
||||
callback=True,link_auth=True, ipmi_msg=True,
|
||||
privilege_level=user['privilege_level'])
|
||||
return
|
||||
elif self.op == 'delete':
|
||||
self.ipmicmd.user_delete(uid=user, channel=1)
|
||||
return
|
||||
|
||||
def do_eventlog(self):
|
||||
eventout = []
|
||||
for event in self.ipmicmd.get_event_log():
|
||||
|
Loading…
Reference in New Issue
Block a user