def process_request(connection, request, cfm, authdata, authname, skipauth): if isinstance(request, tlvdata.ClientFile): cfm.add_client_file(request) return if not isinstance(request, dict): raise exc.InvalidArgumentException operation = request['operation'] path = request['path'] params = request.get('parameters', {}) hdlr = None auditmsg = { 'operation': operation, 'target': path, } if not skipauth: authdata = auth.authorize(authdata[2], path, authdata[3], operation) if not authdata: auditmsg['allowed'] = False auditlog.log(auditmsg) raise exc.ForbiddenRequest() auditmsg['user'] = authdata[2] if authdata[3] is not None: auditmsg['tenant'] = authdata[3] auditmsg['allowed'] = True if _should_authlog(path, operation): tlvdata.unicode_dictvalues(auditmsg) auditlog.log(auditmsg) try: if operation == 'start': return start_term(authname, cfm, connection, params, path, authdata, skipauth) elif operation == 'shutdown' and skipauth: configmanager.ConfigManager.shutdown() else: hdlr = pluginapi.handle_path(path, operation, cfm, params) except exc.NotFoundException as e: send_data(connection, { "errorcode": 404, "error": "Target not found - " + str(e) }) send_data(connection, {"_requestdone": 1}) except exc.InvalidArgumentException as e: send_data(connection, { "errorcode": 400, "error": "Bad Request - " + str(e) }) send_data(connection, {"_requestdone": 1}) send_response(hdlr, connection) return
def update(nodes, element, configmanager, inputdata): emebs = configmanager.get_node_attributes( nodes, (u'enclosure.manager', u'enclosure.bay')) for node in nodes: try: em = emebs[node]['enclosure.manager']['value'] eb = emebs[node]['enclosure.bay']['value'] except KeyError: yield msg.ConfluentNodeError( node, 'Reseat is only supported on servers in an enclosure, and ' 'with enclosure.manager and enclosure.bay defined') continue try: for rsp in core.handle_path( '/nodes/{0}/_enclosure/reseat_bay'.format(em), 'update', configmanager, inputdata={'reseat': int(eb)}): yield rsp except pygexc.UnsupportedFunctionality as uf: yield msg.ConfluentNodeError(node, str(uf))
def update(nodes, element, configmanager, inputdata): emebs = configmanager.get_node_attributes( nodes, (u'enclosure.manager', u'enclosure.bay')) for node in nodes: try: em = emebs[node]['enclosure.manager']['value'] eb = emebs[node]['enclosure.bay']['value'] except KeyError: em = node eb = -1 try: for rsp in core.handle_path( '/nodes/{0}/_enclosure/reseat_bay'.format(em), 'update', configmanager, inputdata={'reseat': int(eb)}): yield rsp except pygexc.UnsupportedFunctionality as uf: yield msg.ConfluentNodeError(node, str(uf)) except exc.TargetEndpointUnreachable as uf: yield msg.ConfluentNodeError(node, str(uf))
def process_request(connection, request, cfm, authdata, authname, skipauth): if not isinstance(request, dict): raise exc.InvalidArgumentException operation = request['operation'] path = request['path'] params = request.get('parameters', {}) hdlr = None if not skipauth: authdata = auth.authorize(authdata[2], path, authdata[3], operation) auditmsg = { 'operation': operation, 'target': path, } if authdata is None: auditmsg['allowed'] = False auditlog.log(auditmsg) raise exc.ForbiddenRequest() auditmsg['user'] = authdata[2] if authdata[3] is not None: auditmsg['tenant'] = authdata[3] auditmsg['allowed'] = True auditlog.log(auditmsg) try: if operation == 'start': return start_term(authname, cfm, connection, params, path) elif operation == 'shutdown': configmanager.ConfigManager.shutdown() else: hdlr = pluginapi.handle_path(path, operation, cfm, params) except exc.NotFoundException as e: send_data(connection, {"errorcode": 404, "error": "Target not found - " + str(e)}) send_data(connection, {"_requestdone": 1}) except exc.InvalidArgumentException as e: send_data(connection, {"errorcode": 400, "error": "Bad Request - " + str(e)}) send_data(connection, {"_requestdone": 1}) send_response(hdlr, connection) return
def resourcehandler_backend(env, start_response): """Function to handle new wsgi requests """ mimetype, extension = _pick_mimetype(env) headers = [('Content-Type', mimetype), ('Cache-Control', 'no-store'), ('Pragma', 'no-cache'), ('X-Content-Type-Options', 'nosniff'), ('Content-Security-Policy', "default-src 'self'"), ('X-XSS-Protection', '1; mode=block'), ('X-Frame-Options', 'deny'), ('Strict-Transport-Security', 'max-age=86400'), ('X-Permitted-Cross-Domain-Policies', 'none')] reqbody = None reqtype = None if 'CONTENT_LENGTH' in env and int(env['CONTENT_LENGTH']) > 0: reqbody = env['wsgi.input'].read(int(env['CONTENT_LENGTH'])) reqtype = env['CONTENT_TYPE'] operation = opmap[env['REQUEST_METHOD']] querydict = _get_query_dict(env, reqbody, reqtype) if 'restexplorerop' in querydict: operation = querydict['restexplorerop'] del querydict['restexplorerop'] authorized = _authorize_request(env, operation) if 'logout' in authorized: start_response('200 Successful logout', headers) yield ('{"result": "200 - Successful logout"}') return if 'HTTP_SUPPRESSAUTHHEADER' in env or 'HTTP_CONFLUENTAUTHTOKEN' in env: badauth = [('Content-type', 'text/plain')] else: badauth = [('Content-type', 'text/plain'), ('WWW-Authenticate', 'Basic realm="confluent"')] if authorized['code'] == 401: start_response('401 Authentication Required', badauth) yield 'authentication required' return if authorized['code'] == 403: start_response('403 Forbidden', badauth) yield 'authorization failed' return if authorized['code'] != 200: raise Exception("Unrecognized code from auth engine") headers.extend(("Set-Cookie", m.OutputString()) for m in authorized['cookie'].values()) cfgmgr = authorized['cfgmgr'] if (operation == 'create') and env['PATH_INFO'] == '/sessions/current/async': pagecontent = "" try: for rsp in _assemble_json( confluent.asynchttp.handle_async( env, querydict, httpsessions[authorized['sessionid']]['inflight'])): pagecontent += rsp start_response("200 OK", headers) yield pagecontent return except exc.ConfluentException as e: if e.apierrorcode == 500: # raise generics to trigger the tracelog raise start_response('{0} {1}'.format(e.apierrorcode, e.apierrorstr), headers) yield e.get_error_body() elif (env['PATH_INFO'].endswith('/forward/web') and env['PATH_INFO'].startswith('/nodes/')): prefix, _, _ = env['PATH_INFO'].partition('/forward/web') _, _, nodename = prefix.rpartition('/') hm = cfgmgr.get_node_attributes(nodename, 'hardwaremanagement.manager') targip = hm.get(nodename, {}).get('hardwaremanagement.manager', {}).get('value', None) if not targip: start_response('404 Not Found', headers) yield 'No hardwaremanagemnet.manager defined for node' return funport = forwarder.get_port(targip, env['HTTP_X_FORWARDED_FOR'], authorized['sessionid']) host = env['HTTP_X_FORWARDED_HOST'] url = 'https://{0}:{1}/'.format(host, funport) start_response('302', [('Location', url)]) yield 'Our princess is in another castle!' return elif (operation == 'create' and ('/console/session' in env['PATH_INFO'] or '/shell/sessions/' in env['PATH_INFO'])): #hard bake JSON into this path, do not support other incarnations if '/console/session' in env['PATH_INFO']: prefix, _, _ = env['PATH_INFO'].partition('/console/session') shellsession = False elif '/shell/sessions/' in env['PATH_INFO']: prefix, _, _ = env['PATH_INFO'].partition('/shell/sessions') shellsession = True _, _, nodename = prefix.rpartition('/') if 'session' not in querydict.keys() or not querydict['session']: auditmsg = { 'operation': 'start', 'target': env['PATH_INFO'], 'user': authorized['username'], } if 'tenant' in authorized: auditmsg['tenant'] = authorized['tenant'] auditlog.log(auditmsg) # Request for new session skipreplay = False if 'skipreplay' in querydict and querydict['skipreplay']: skipreplay = True datacallback = None async = None if 'HTTP_CONFLUENTASYNCID' in env: async = confluent.asynchttp.get_async(env, querydict) termrel = async .set_term_relation(env) datacallback = termrel.got_data try: if shellsession: consession = shellserver.ShellSession( node=nodename, configmanager=cfgmgr, username=authorized['username'], skipreplay=skipreplay, datacallback=datacallback) else: consession = consoleserver.ConsoleSession( node=nodename, configmanager=cfgmgr, username=authorized['username'], skipreplay=skipreplay, datacallback=datacallback) except exc.NotFoundException: start_response("404 Not found", headers) yield "404 - Request Path not recognized" return if not consession: start_response("500 Internal Server Error", headers) return sessid = _assign_consessionid(consession) if async: async .add_console_session(sessid) start_response('200 OK', headers) yield '{"session":"%s","data":""}' % sessid return elif 'bytes' in querydict.keys(): # not keycodes... myinput = querydict['bytes'] sessid = querydict['session'] if sessid not in consolesessions: start_response('400 Expired Session', headers) return consolesessions[sessid]['expiry'] = time.time() + 90 consolesessions[sessid]['session'].write(myinput) start_response('200 OK', headers) yield json.dumps({'session': querydict['session']}) return # client has requests to send or receive, not both... elif 'closesession' in querydict: consolesessions[querydict['session']]['session'].destroy() del consolesessions[querydict['session']] start_response('200 OK', headers) yield '{"sessionclosed": true}' return elif 'action' in querydict: if querydict['action'] == 'break': consolesessions[querydict['session']]['session'].send_break() elif querydict['action'] == 'reopen': consolesessions[querydict['session']]['session'].reopen() else: start_response('400 Bad Request') yield 'Unrecognized action ' + querydict['action'] return start_response('200 OK', headers) yield json.dumps({'session': querydict['session']}) else: # no keys, but a session, means it's hooking to receive data sessid = querydict['session'] if sessid not in consolesessions: start_response('400 Expired Session', headers) yield '' return consolesessions[sessid]['expiry'] = time.time() + 90 # add our thread to the 'inflight' to have a hook to terminate # a long polling request loggedout = None mythreadid = greenlet.getcurrent() httpsessions[authorized['sessionid']]['inflight'].add(mythreadid) try: outdata = consolesessions[sessid]['session'].get_next_output( timeout=25) except greenlet.GreenletExit as ge: loggedout = ge httpsessions[authorized['sessionid']]['inflight'].discard( mythreadid) if sessid not in consolesessions: start_response('400 Expired Session', headers) yield '' return if loggedout is not None: consolesessions[sessid]['session'].destroy() start_response('401 Logged out', headers) yield '{"loggedout": 1}' return bufferage = False if 'stampsent' not in consolesessions[sessid]: consolesessions[sessid]['stampsent'] = True bufferage = consolesessions[sessid]['session'].get_buffer_age() if isinstance(outdata, dict): rspdata = outdata rspdata['session'] = querydict['session'] else: rspdata = {'session': querydict['session'], 'data': outdata} if bufferage is not False: rspdata['bufferage'] = bufferage try: rsp = json.dumps(rspdata) except UnicodeDecodeError: try: rsp = json.dumps(rspdata, encoding='cp437') except UnicodeDecodeError: rsp = json.dumps({ 'session': querydict['session'], 'data': 'DECODEERROR' }) start_response('200 OK', headers) yield rsp return else: # normal request url = env['PATH_INFO'] url = url.replace('.json', '') url = url.replace('.html', '') if url == '/sessions/current/info': start_response('200 OK', headers) sessinfo = {'username': authorized['username']} if 'authtoken' in authorized: sessinfo['authtoken'] = authorized['authtoken'] yield json.dumps(sessinfo) return resource = '.' + url[url.rindex('/'):] lquerydict = copy.deepcopy(querydict) try: hdlr = pluginapi.handle_path(url, operation, cfgmgr, querydict) if 'HTTP_CONFLUENTASYNCID' in env: confluent.asynchttp.run_handler(hdlr, env) start_response('202 Accepted', headers) yield 'Request queued' return pagecontent = "" if mimetype == 'text/html': for datum in _assemble_html(hdlr, resource, lquerydict, url, extension): pagecontent += datum else: for datum in _assemble_json(hdlr, resource, url, extension): pagecontent += datum start_response('200 OK', headers) yield pagecontent except exc.ConfluentException as e: if ((not isinstance(e, exc.LockedCredentials)) and e.apierrorcode == 500): # raise generics to trigger the tracelog raise start_response('{0} {1}'.format(e.apierrorcode, e.apierrorstr), headers) yield e.get_error_body()
def _connect_backend(self): if self._console: self._console.close() self._console = None self.connectstate = 'connecting' self._send_rcpts({'connectstate': self.connectstate}) if self.reconnect: self.reconnect.cancel() self.reconnect = None try: self._console = plugin.handle_path( self._plugin_path.format(self.node), "create", self.cfgmgr) except exc.NotImplementedException: self._console = None except: _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) if not isinstance(self._console, conapi.Console): self.connectstate = 'unconnected' self.error = 'misconfigured' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) return self.send_break = self._console.send_break if self._attribwatcher: self.cfgmgr.remove_watcher(self._attribwatcher) self._attribwatcher = None if hasattr(self._console, "configattributes"): attribstowatch = self._console.configattributes | self._genwatchattribs else: attribstowatch = self._genwatchattribs if self._genwatchattribs: self._attribwatcher = self.cfgmgr.watch_attributes( (self.node,), attribstowatch, self._attribschanged) try: self._console.connect(self.get_console_output) except exc.TargetEndpointBadCredentials: self.error = 'badcredentials' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except exc.TargetEndpointUnreachable: self.error = 'unreachable' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except Exception: _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) self.error = 'unknown' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return self._got_connected()
def _connect_backend(self): if self._console: self._console.close() self._console = None self.connectstate = 'connecting' self._send_rcpts({'connectstate': self.connectstate}) if self.reconnect: self.reconnect.cancel() self.reconnect = None try: self._console = plugin.handle_path( self._plugin_path.format(self.node), "create", self.cfgmgr) except: _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) if not isinstance(self._console, conapi.Console): self.connectstate = 'unconnected' self.error = 'misconfigured' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) return self.send_break = self._console.send_break if self._attribwatcher: self.cfgmgr.remove_watcher(self._attribwatcher) self._attribwatcher = None if hasattr(self._console, "configattributes"): attribstowatch = self._console.configattributes | self._genwatchattribs else: attribstowatch = self._genwatchattribs if self._genwatchattribs: self._attribwatcher = self.cfgmgr.watch_attributes( (self.node,), attribstowatch, self._attribschanged) try: self._console.connect(self.get_console_output) except exc.TargetEndpointBadCredentials: self.error = 'badcredentials' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except exc.TargetEndpointUnreachable: self.error = 'unreachable' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except Exception: _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) self.error = 'unknown' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = 120 + (120 * random.random()) if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return self._got_connected()
def resourcehandler_backend(env, start_response): """Function to handle new wsgi requests """ mimetype, extension = _pick_mimetype(env) headers = [('Content-Type', mimetype), ('Cache-Control', 'no-store'), ('Pragma', 'no-cache'), ('X-Content-Type-Options', 'nosniff'), ('Content-Security-Policy', "default-src 'self'"), ('X-XSS-Protection', '1'), ('X-Frame-Options', 'deny'), ('Strict-Transport-Security', 'max-age=86400'), ('X-Permitted-Cross-Domain-Policies', 'none')] reqbody = None reqtype = None if 'CONTENT_LENGTH' in env and int(env['CONTENT_LENGTH']) > 0: reqbody = env['wsgi.input'].read(int(env['CONTENT_LENGTH'])) reqtype = env['CONTENT_TYPE'] operation = opmap[env['REQUEST_METHOD']] querydict = _get_query_dict(env, reqbody, reqtype) if 'restexplorerop' in querydict: operation = querydict['restexplorerop'] del querydict['restexplorerop'] authorized = _authorize_request(env, operation) if 'logout' in authorized: start_response('200 Successful logout', headers) yield('{"result": "200 - Successful logout"}') return if 'HTTP_SUPPRESSAUTHHEADER' in env or 'HTTP_CONFLUENTAUTHTOKEN' in env: badauth = [('Content-type', 'text/plain')] else: badauth = [('Content-type', 'text/plain'), ('WWW-Authenticate', 'Basic realm="confluent"')] if authorized['code'] == 401: start_response('401 Authentication Required', badauth) yield 'authentication required' return if authorized['code'] == 403: start_response('403 Forbidden', badauth) yield 'authorization failed' return if authorized['code'] != 200: raise Exception("Unrecognized code from auth engine") headers.extend( ("Set-Cookie", m.OutputString()) for m in authorized['cookie'].values()) cfgmgr = authorized['cfgmgr'] if (operation == 'create') and env['PATH_INFO'] == '/sessions/current/async': pagecontent = "" try: for rsp in _assemble_json( confluent.asynchttp.handle_async( env, querydict, httpsessions[authorized['sessionid']]['inflight'])): pagecontent += rsp start_response("200 OK", headers) yield pagecontent return except exc.ConfluentException as e: if e.apierrorcode == 500: # raise generics to trigger the tracelog raise start_response('{0} {1}'.format(e.apierrorcode, e.apierrorstr), headers) yield e.get_error_body() elif (operation == 'create' and ('/console/session' in env['PATH_INFO'] or '/shell/sessions/' in env['PATH_INFO'])): #hard bake JSON into this path, do not support other incarnations if '/console/session' in env['PATH_INFO']: prefix, _, _ = env['PATH_INFO'].partition('/console/session') shellsession = False elif '/shell/sessions/' in env['PATH_INFO']: prefix, _, _ = env['PATH_INFO'].partition('/shell/sessions') shellsession = True _, _, nodename = prefix.rpartition('/') if 'session' not in querydict.keys() or not querydict['session']: auditmsg = { 'operation': 'start', 'target': env['PATH_INFO'], 'user': authorized['username'], } if 'tenant' in authorized: auditmsg['tenant'] = authorized['tenant'] auditlog.log(auditmsg) # Request for new session skipreplay = False if 'skipreplay' in querydict and querydict['skipreplay']: skipreplay = True datacallback = None async = None if 'HTTP_CONFLUENTASYNCID' in env: async = confluent.asynchttp.get_async(env, querydict) termrel = async.set_term_relation(env) datacallback = termrel.got_data try: if shellsession: consession = shellserver.ShellSession( node=nodename, configmanager=cfgmgr, username=authorized['username'], skipreplay=skipreplay, datacallback=datacallback ) else: consession = consoleserver.ConsoleSession( node=nodename, configmanager=cfgmgr, username=authorized['username'], skipreplay=skipreplay, datacallback=datacallback ) except exc.NotFoundException: start_response("404 Not found", headers) yield "404 - Request Path not recognized" return if not consession: start_response("500 Internal Server Error", headers) return sessid = _assign_consessionid(consession) if async: async.add_console_session(sessid) start_response('200 OK', headers) yield '{"session":"%s","data":""}' % sessid return elif 'bytes' in querydict.keys(): # not keycodes... myinput = querydict['bytes'] sessid = querydict['session'] if sessid not in consolesessions: start_response('400 Expired Session', headers) return consolesessions[sessid]['expiry'] = time.time() + 90 consolesessions[sessid]['session'].write(myinput) start_response('200 OK', headers) yield json.dumps({'session': querydict['session']}) return # client has requests to send or receive, not both... elif 'closesession' in querydict: consolesessions[querydict['session']]['session'].destroy() del consolesessions[querydict['session']] start_response('200 OK', headers) yield '{"sessionclosed": true}' return elif 'action' in querydict: if querydict['action'] == 'break': consolesessions[querydict['session']]['session'].send_break() elif querydict['action'] == 'reopen': consolesessions[querydict['session']]['session'].reopen() else: start_response('400 Bad Request') yield 'Unrecognized action ' + querydict['action'] return start_response('200 OK', headers) yield json.dumps({'session': querydict['session']}) else: # no keys, but a session, means it's hooking to receive data sessid = querydict['session'] if sessid not in consolesessions: start_response('400 Expired Session', headers) yield '' return consolesessions[sessid]['expiry'] = time.time() + 90 # add our thread to the 'inflight' to have a hook to terminate # a long polling request loggedout = None mythreadid = greenlet.getcurrent() httpsessions[authorized['sessionid']]['inflight'].add(mythreadid) try: outdata = consolesessions[sessid]['session'].get_next_output( timeout=25) except greenlet.GreenletExit as ge: loggedout = ge httpsessions[authorized['sessionid']]['inflight'].discard( mythreadid) if sessid not in consolesessions: start_response('400 Expired Session', headers) yield '' return if loggedout is not None: consolesessions[sessid]['session'].destroy() start_response('401 Logged out', headers) yield '{"loggedout": 1}' return bufferage = False if 'stampsent' not in consolesessions[sessid]: consolesessions[sessid]['stampsent'] = True bufferage = consolesessions[sessid]['session'].get_buffer_age() if isinstance(outdata, dict): rspdata = outdata rspdata['session'] = querydict['session'] else: rspdata = {'session': querydict['session'], 'data': outdata} if bufferage is not False: rspdata['bufferage'] = bufferage try: rsp = json.dumps(rspdata) except UnicodeDecodeError: try: rsp = json.dumps(rspdata, encoding='cp437') except UnicodeDecodeError: rsp = json.dumps({'session': querydict['session'], 'data': 'DECODEERROR'}) start_response('200 OK', headers) yield rsp return else: # normal request url = env['PATH_INFO'] url = url.replace('.json', '') url = url.replace('.html', '') if url == '/sessions/current/info': start_response('200 OK', headers) sessinfo = {'username': authorized['username']} if 'authtoken' in authorized: sessinfo['authtoken'] = authorized['authtoken'] yield json.dumps(sessinfo) return resource = '.' + url[url.rindex('/'):] lquerydict = copy.deepcopy(querydict) try: hdlr = pluginapi.handle_path(url, operation, cfgmgr, querydict) if 'HTTP_CONFLUENTASYNCID' in env: confluent.asynchttp.run_handler(hdlr, env) start_response('202 Accepted', headers) yield 'Request queued' return pagecontent = "" if mimetype == 'text/html': for datum in _assemble_html(hdlr, resource, lquerydict, url, extension): pagecontent += datum else: for datum in _assemble_json(hdlr, resource, url, extension): pagecontent += datum start_response('200 OK', headers) yield pagecontent except exc.ConfluentException as e: if ((not isinstance(e, exc.LockedCredentials)) and e.apierrorcode == 500): # raise generics to trigger the tracelog raise start_response('{0} {1}'.format(e.apierrorcode, e.apierrorstr), headers) yield e.get_error_body()
def process_request(connection, request, cfm, authdata, authname, skipauth): if not isinstance(request, dict): raise ValueError operation = request['operation'] path = request['path'] params = request.get('parameters', None) hdlr = None if not skipauth: authdata = auth.authorize(authdata[2], path, authdata[3], operation) auditmsg = { 'operation': operation, 'user': authdata[2], 'target': path, } if authdata[3] is not None: auditmsg['tenant'] = authdata[3] if authdata is None: auditmsg['allowed'] = False auditlog.log(auditmsg) raise exc.ForbiddenRequest() auditmsg['allowed'] = True auditlog.log(auditmsg) try: if operation == 'start': elems = path.split('/') if elems[3] != "console": raise exc.InvalidArgumentException() node = elems[2] ccons = ClientConsole(connection) skipreplay = False if params and 'skipreplay' in params and params['skipreplay']: skipreplay = True consession = consoleserver.ConsoleSession( node=node, configmanager=cfm, username=authname, datacallback=ccons.sendall, skipreplay=skipreplay) if consession is None: raise Exception("TODO") send_data(connection, {'started': 1}) ccons.startsending() bufferage = consession.get_buffer_age() if bufferage is not False: send_data(connection, {'bufferage': bufferage}) while consession is not None: data = tlvdata.recv(connection) if type(data) == dict: if data['operation'] == 'stop': consession.destroy() return elif data['operation'] == 'break': consession.send_break() continue elif data['operation'] == 'reopen': consession.reopen() continue else: raise Exception("TODO") if not data: consession.destroy() return consession.write(data) elif operation == 'shutdown': configmanager.ConfigManager.shutdown() else: hdlr = pluginapi.handle_path(path, operation, cfm, params) except exc.NotFoundException as e: send_data(connection, {"errorcode": 404, "error": "Target not found - " + str(e)}) send_data(connection, {"_requestdone": 1}) except exc.InvalidArgumentException as e: send_data(connection, {"errorcode": 400, "error": "Bad Request - " + str(e)}) send_data(connection, {"_requestdone": 1}) send_response(hdlr, connection) return
def _connect_backend(self): if self._console: self._console.close() self._console = None self.connectstate = 'connecting' self._send_rcpts({'connectstate': self.connectstate}) if self.reconnect: self.reconnect.cancel() self.reconnect = None try: self._console = list(plugin.handle_path( self._plugin_path.format(self.node), "create", self.cfgmgr))[0] except (exc.NotImplementedException, exc.NotFoundException): self._console = None except: if _tracelog: _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) else: print(traceback.format_exc()) if not isinstance(self._console, conapi.Console): self.clearbuffer() self.connectstate = 'unconnected' self.error = 'misconfigured' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) self.feedbuffer( '\x1bc\x1b[2J\x1b[1;1H[The console.method attribute for this node is ' 'not configured,\r\nset it to a valid value for console ' 'function]') self._send_rcpts( '\x1bc\x1b[2J\x1b[1;1H[The console.method attribute for this node is ' 'not configured,\r\nset it to a valid value for console ' 'function]') self.clearerror = True return if self.clearerror: self.clearerror = False self.clearbuffer() self._send_rcpts(b'\x1bc\x1b[2J\x1b[1;1H') self.send_break = self._console.send_break self.resize = self._console.resize if self._attribwatcher: self.cfgmgr.remove_watcher(self._attribwatcher) self._attribwatcher = None if hasattr(self._console, "configattributes"): attribstowatch = self._console.configattributes | self._genwatchattribs else: attribstowatch = self._genwatchattribs if self._genwatchattribs: self._attribwatcher = self.cfgmgr.watch_attributes( (self.node,), attribstowatch, self._attribschanged) try: self.resize(width=self.initsize[0], height=self.initsize[1]) self._console.connect(self.get_console_output) except exc.TargetEndpointBadCredentials: self.clearbuffer() self.error = 'badcredentials' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = self._get_retry_time() if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except exc.TargetEndpointUnreachable: self.clearbuffer() self.error = 'unreachable' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = self._get_retry_time() if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return except Exception: self.clearbuffer() _tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event, event=log.Events.stacktrace) self.error = 'unknown' self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate, 'error': self.error}) retrytime = self._get_retry_time() if not self.reconnect: self.reconnect = eventlet.spawn_after(retrytime, self._connect) return self._got_connected()