diff --git a/confluent_server/confluent/auth.py b/confluent_server/confluent/auth.py index 709ac3ca..452cdc40 100644 --- a/confluent_server/confluent/auth.py +++ b/confluent_server/confluent/auth.py @@ -116,7 +116,7 @@ def authorize(name, element, tenant=False, operation='create', user, tenant = _get_usertenant(name, tenant) if tenant is not None and not configmanager.is_tenant(tenant): return None - manager = configmanager.ConfigManager(tenant) + manager = configmanager.ConfigManager(tenant, username=user) if skipuserobj: return None, manager, user, tenant, skipuserobj userobj = manager.get_user(user) @@ -178,7 +178,7 @@ def check_user_passphrase(name, passphrase, element=None, tenant=False): # invalidate cache and force the slower check del _passcache[(user, tenant)] return None - cfm = configmanager.ConfigManager(tenant) + cfm = configmanager.ConfigManager(tenant, username=user) ucfg = cfm.get_user(user) if ucfg is None or 'cryptpass' not in ucfg: eventlet.sleep(0.05) # stall even on test for existence of a username diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 71462573..d241df9d 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -429,9 +429,10 @@ class ConfigManager(object): _nodecollwatchers = {} _notifierids = {} - def __init__(self, tenant, decrypt=False): + def __init__(self, tenant, decrypt=False, username=None): global _cfgstore self.decrypt = decrypt + self.current_user = username if tenant is None: self.tenant = None if 'main' not in _cfgstore: diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index dac3c29e..5bd29bbd 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -70,6 +70,7 @@ def nested_lookup(nestdict, key): def load_plugins(): # To know our plugins directory, we get the parent path of 'bin' + _init_core() path = os.path.dirname(os.path.realpath(__file__)) plugintop = os.path.realpath(os.path.join(path, 'plugins')) plugins = set() @@ -109,157 +110,163 @@ class PluginCollection(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 = { - 'attributes': { - 'all': PluginRoute({'handler': 'attributes'}), - 'current': PluginRoute({'handler': 'attributes'}), - }, - 'boot': { - 'nextdevice': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - 'configuration': { - 'management_controller': { - 'alerts': { - 'destinations': PluginCollection({ +def _init_core(): + global noderesources + global nodegroupresources + import confluent.shellserver as shellserver + # _ prefix indicates internal use (e.g. special console scheme) and should not + # be enumerated in any collection + noderesources = { + 'attributes': { + 'all': PluginRoute({'handler': 'attributes'}), + 'current': PluginRoute({'handler': 'attributes'}), + }, + 'boot': { + 'nextdevice': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, + 'configuration': { + 'management_controller': { + 'alerts': { + 'destinations': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, + 'users': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'net_interfaces': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'reset': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'identifier': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'domain_name': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'ntp': { + 'enabled': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'servers': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, + } + }, + '_console': { + 'session': PluginRoute({ + 'pluginattrs': ['console.method'], + }), + }, + '_shell': { + 'session': PluginRoute({ + # For now, not configurable, wait until there's demand + 'handler': 'ssh', + }), + }, + 'shell': { + # another special case similar to console + 'sessions': PluginCollection({ + 'handler': shellserver, + }), + }, + 'console': { + # this is a dummy value, http or socket must handle special + 'session': None, + 'license': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, + 'events': { + 'hardware': { + 'log': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'decode': PluginRoute({ 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), }, - 'users': PluginCollection({ + }, + 'health': { + 'hardware': PluginRoute({ 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), - 'net_interfaces': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'reset': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'identifier': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'domain_name': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'ntp': { - 'enabled': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'servers': PluginCollection({ + }, + 'identify': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'inventory': { + 'hardware': { + 'all': PluginCollection({ 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), }, - } - }, - '_console': { - 'session': PluginRoute({ - 'pluginattrs': ['console.method'], - }), - }, - '_shell': { - 'session': PluginRoute({ - # For now, not configurable, wait until there's demand - 'handler': 'ssh', - }) - }, - 'shell': { - # another special case similar to console - 'sessions': {}, - }, - 'console': { - # this is a dummy value, http or socket must handle special - 'session': None, - 'license': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - 'events': { - 'hardware': { - 'log': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'decode': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - }, - 'health': { - 'hardware': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - 'identify': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'inventory': { - 'hardware': { - 'all': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - 'firmware': { - 'all': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - }, - 'power': { - 'state': PluginRoute({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - }, - 'sensors': { - 'hardware': { - 'all': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'temperature': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'power': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'fans': PluginCollection({ - 'pluginattrs': ['hardwaremanagement.method'], - 'default': 'ipmi', - }), - 'leds': PluginCollection({ + 'firmware': { + 'all': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, + }, + 'power': { + 'state': PluginRoute({ 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), }, + 'sensors': { + 'hardware': { + 'all': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'temperature': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'power': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'fans': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + 'leds': PluginCollection({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, - }, -} + }, + } -nodegroupresources = { - 'attributes': { - 'all': PluginRoute({'handler': 'attributes'}), - 'current': PluginRoute({'handler': 'attributes'}), - }, -} + nodegroupresources = { + 'attributes': { + 'all': PluginRoute({'handler': 'attributes'}), + 'current': PluginRoute({'handler': 'attributes'}), + }, + } def create_user(inputdata, configmanager): @@ -525,7 +532,10 @@ def handle_node_request(configmanager, inputdata, operation, inputdata = msg.get_input_message( pathcomponents, operation, inputdata, nodes, isnoderange) if 'handler' in plugroute: # fixed handler definition, easy enough - hfunc = getattr(pluginmap[plugroute['handler']], operation) + if isinstance(plugroute['handler'], str): + hfunc = getattr(pluginmap[plugroute['handler']], operation) + else: + hfunc = getattr(plugroute['handler'], operation) passvalue = hfunc( nodes=nodes, element=pathcomponents, configmanager=configmanager, diff --git a/confluent_server/confluent/shellserver.py b/confluent_server/confluent/shellserver.py index 6ba2cfd5..1a8aaeb5 100644 --- a/confluent_server/confluent/shellserver.py +++ b/confluent_server/confluent/shellserver.py @@ -20,8 +20,8 @@ import confluent.consoleserver as consoleserver -import uuid - +import confluent.exceptions as exc +import confluent.messages as msg activesessions = {} @@ -99,3 +99,14 @@ class ShellSession(consoleserver.ConsoleSession): activesessions[(tenant, self.node)][self.sessionid] = _ShellHandler(self.node, self.configmanager) self.conshdl = activesessions[(self.configmanager.tenant, self.node)][self.sessionid] +def create(nodes, element, configmanager, inputdata): + # For creating a resource, it really has to be handled + # in httpapi/sockapi specially, like a console. + raise exc.InvalidArgumentException('Special client code required') + +def retrieve(nodes, element, configmanager, inputdata): + tenant = configmanager.tenant + user = configmanager.current_user + if (tenant, nodes[0]) in activesessions: + for sessionid in activesessions[(tenant, nodes[0])]: + yield msg.ChildCollection(sessionid) diff --git a/confluent_server/confluent/sockapi.py b/confluent_server/confluent/sockapi.py index 4c819b66..38bf589c 100644 --- a/confluent_server/confluent/sockapi.py +++ b/confluent_server/confluent/sockapi.py @@ -89,7 +89,7 @@ def sessionhdl(connection, authname, skipauth=False): cfm = None if skipauth: authenticated = True - cfm = configmanager.ConfigManager(tenant=None) + cfm = configmanager.ConfigManager(tenant=None, username=authname) elif authname: authdata = auth.authorize(authname, element=None) if authdata is not None: