def get_instance_state(self, instance_id): try: response = tornado_requests.request("GET", "http://%s:%s/v2/instances/%s"%(tenant_templ.cloudverifier_ip,tenant_templ.cloudverifier_port,instance_id),context=tenant_templ.context) except Exception as e: logger.error("Status command response: %s:%s Unexpected response from Cloud Verifier."%(tenant_templ.cloudverifier_ip,tenant_templ.cloudverifier_port)) logger.error(traceback.print_exc()) logger.error("Error: %s "%str(e)) raise e inst_response_body = response.json() if response.status_code != 200 and response.status_code != 404: logger.error("Status command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger,logging.ERROR,inst_response_body) return None if "results" not in inst_response_body: logger.critical("Error: unexpected http response body from Cloud Verifier: %s"%str(response.status_code)) return None # Node not added to CV (but still registered) if response.status_code == 404: return {"operational_state" : cloud_verifier_common.CloudInstance_Operational_State.REGISTERED} else: return inst_response_body["results"] return None
def getKeys(registrar_ip,registrar_port,instance_id): global context #make absolutely sure you don't ask for AIKs unauthenticated if context is None or context.verify_mode != ssl.CERT_REQUIRED: raise Exception("It is unsafe to use this interface to query AIKs with out server authenticated TLS") try: response = tornado_requests.request("GET", "http://%s:%s/v2/instances/%s"%(registrar_ip,registrar_port,instance_id), context=context) response_body = response.json() if response.status_code != 200: logger.critical("Error: unexpected http response code from Registrar Server: %s"%str(response.status_code)) common.log_http_response(logger,logging.CRITICAL,response_body) return None if "results" not in response_body: logger.critical("Error: unexpected http response body from Registrar Server: %s"%str(response.status_code)) return None if "aik" not in response_body["results"]: logger.critical("Error: did not receive aik from Registrar Server: %s"%str(response.status_code)) return None return response_body["results"] except Exception as e: logger.critical(traceback.format_exc()) logger.critical("An unexpected error occurred: " + str(e)) return None
def do_cvdelete(self): response = tornado_requests.request("DELETE","http://%s:%s/v2/instances/%s"%(self.cloudverifier_ip,self.cloudverifier_port,self.node_uuid),context=self.context) if response.status_code != 200: logger.error("Delete command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger,logging.ERROR,response.json()) else: logger.info("Node %s deleted from CV"%(self.node_uuid))
def do_cvdelete(self): response = tornado_requests.request( "DELETE", "http://%s:%s/agents/%s" % (self.cloudverifier_ip, self.cloudverifier_port, self.agent_uuid), context=self.context) if response.status_code == 202: deleted = False for _ in range(12): response = tornado_requests.request( "GET", "http://%s:%s/agents/%s" % (self.cloudverifier_ip, self.cloudverifier_port, self.agent_uuid), context=self.context) if response.status_code == 404: deleted = True break time.sleep(.4) if deleted: logger.info("CV completed deletion of agent %s" % (self.agent_uuid)) else: raise UserError( "Timed out waiting for delete of agent %s to complete at CV" % self.agent_uuid) elif response.status_code == 200: logger.info("Agent %s deleted from the CV" % (self.agent_uuid)) else: #raise UserError("Delete command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger, logging.ERROR, response.json())
def do_cv(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" b64_v = base64.b64encode(self.V) logger.debug("b64_v:" + b64_v) data = { 'v': b64_v, 'cloudnode_ip': self.cv_cloudnode_ip, 'cloudnode_port': self.cloudnode_port, 'tpm_policy': json.dumps(self.tpm_policy), 'vtpm_policy': json.dumps(self.vtpm_policy), 'ima_whitelist': json.dumps(self.ima_whitelist), 'metadata': json.dumps(self.metadata), 'revocation_key': self.revocation_key, } json_message = json.dumps(data) response = tornado_requests.request( "POST", "http://%s:%s/v2/instances/%s" % (self.cloudverifier_ip, self.cloudverifier_port, self.node_uuid), data=json_message, context=self.context) if response.status_code == 409: # this is a conflict, delete first then re-add logger.warning( "Node already existed at CV. Deleting and re-adding...") self.do_cvdelete() self.do_cv() elif response.status_code != 200: common.log_http_response(logger, logging.ERROR, response.json()) raise Exception( "POST command response: %d Unexpected response from Cloud Verifier: %s" % (response.status_code, response.body))
def do_cvstop(self): response = tornado_requests.request("PUT","http://%s:%s/agents/%s/stop"%(self.cloudverifier_ip,self.cloudverifier_port,self.agent_uuid),context=self.context,data=b'') if response.status_code != 200: raise UserError("Update command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger,logging.ERROR,response.json()) else: logger.info("Agent %s stopped"%(self.agent_uuid))
def do_cv(self): """initiaite v, agent_id and ip initiate the cloudinit sequence""" b64_v = base64.b64encode(self.V) logger.debug("b64_v:" + b64_v) data = { 'v': b64_v, 'cloudagent_ip': self.cv_cloudagent_ip, 'cloudagent_port': self.cloudagent_port, 'tpm_policy': json.dumps(self.tpm_policy), 'vtpm_policy':json.dumps(self.vtpm_policy), 'ima_whitelist':json.dumps(self.ima_whitelist), 'metadata':json.dumps(self.metadata), 'revocation_key':self.revocation_key, 'accept_tpm_hash_algs':self.accept_tpm_hash_algs, 'accept_tpm_encryption_algs':self.accept_tpm_encryption_algs, 'accept_tpm_signing_algs':self.accept_tpm_signing_algs, } json_message = json.dumps(data) response = tornado_requests.request("POST","http://%s:%s/agents/%s"%(self.cloudverifier_ip,self.cloudverifier_port,self.agent_uuid),data=json_message,context=self.context) if response.status_code == 409: # this is a conflict, need to update or delete it raise UserError("Agent %s already existed at CV. Please use delete or update."%self.agent_uuid) elif response.status_code != 200: common.log_http_response(logger,logging.ERROR,response.json()) raise UserError("POST command response: %d Unexpected response from Cloud Verifier: %s"%(response.status_code,response.body))
def doRegisterNode(registrar_ip,registrar_port,instance_id,pub_ek,ekcert,pub_aik): data = { 'ek': pub_ek, 'ekcert': ekcert, 'aik': pub_aik, } v_json_message = json.dumps(data) response = tornado_requests.request("POST", "http://%s:%s/v2/instances/%s"%(registrar_ip,registrar_port,instance_id), data=v_json_message, context=None) response_body = response.json() if response.status_code != 200: logger.error("Error: unexpected http response code from Registrar Server: " + str(response.status_code)) common.log_http_response(logger,logging.ERROR,response_body) return None logger.info("Node registration requested for %s"%instance_id) if "results" not in response_body: logger.critical("Error: unexpected http response body from Registrar Server: %s"%str(response.status_code)) return None if "blob" not in response_body["results"]: logger.critical("Error: did not receive blob from Registrar Server: %s"%str(response.status_code)) return None return response_body["results"]["blob"]
def do_cvreactivate(self): response = tornado_requests.request("PUT","http://%s:%s/v2/instances/%s/reactivate"%(self.cloudverifier_ip,self.cloudverifier_port,self.node_uuid),context=self.context,data=b'') if response.status_code != 200: logger.error("Update command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger,logging.ERROR,response.json()) else: logger.info("Node %s re-activated"%(self.node_uuid))
def doRegistrarDelete(registrar_ip,registrar_port, instance_id): global context response = tornado_requests.request("DELETE", "PUT", "http://%s:%s/v2/instances/%s"%(registrar_ip,registrar_port,instance_id), context=context) if response.status_code == 200: logger.debug("Registrar deleted.") else: logger.warn("Status command response: " + str(response.status_code) + " Unexpected response from Cloud Node.") common.log_http_response(logger,logging.WARNING,response.json())
def do_verify(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" challenge = tpm_initialize.random_password(20) numtries = 0 while True: try: response = tornado_requests.request( "GET", "http://%s:%s/v2/keys/verify/challenge/%s/" % (self.cloudnode_ip, self.cloudnode_port, challenge)) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( "Quitting after max number of retries to connect to %s" % (self.cloudnode_ip)) raise e retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudnode_ip, numtries, maxr, retry)) time.sleep(retry) continue else: raise e response_body = response.json() if response.status_code == 200: if "results" not in response_body or 'hmac' not in response_body[ 'results']: logger.critical( "Error: unexpected http response body from Cloud Node: %s" % str(response.status_code)) break mac = response_body['results']['hmac'] ex_mac = crypto.do_hmac(self.K, challenge) if mac == ex_mac: logger.info("Key derivation successful") else: logger.error("Key derivation failed") else: common.log_http_response(logger, logging.ERROR, response_body) retry = config.getfloat('tenant', 'retry_interval') logger.error( "Key derivation not yet complete...trying again in %s seconds...Ctrl-C to stop" % retry) time.sleep(retry) continue break
def do_cvstatus(self,listing=False): """initiaite v, agent_id and ip initiate the cloudinit sequence""" agent_uuid = "" if not listing: agent_uuid=self.agent_uuid response = tornado_requests.request("GET", "http://%s:%s/agents/%s"%(self.cloudverifier_ip,self.cloudverifier_port,agent_uuid),context=self.context) if response.status_code != 200: raise UserError("Status command response: %d Unexpected response from Cloud Verifier."%response.status_code) common.log_http_response(logger,logging.ERROR,response.json()) else: logger.info("Agent Status %d: %s"%(response.status_code,response.json()))
def doActivateVirtualNode(registrar_ip,registrar_port,instance_id,deepquote): data = { 'deepquote': deepquote, } v_json_message = json.dumps(data) response = tornado_requests.request("PUT", "http://%s:%s/v2/instances/%s/vactivate"%(registrar_ip,registrar_port,instance_id), data=v_json_message, context=None) if response.status_code == 200: logger.info("Registration activated for node %s."%instance_id) return True else: logger.error("Error: unexpected http response code from Registrar Server: " + str(response.status_code)) common.log_http_response(logger,logging.ERROR,response.json()) return False
def doActivateNode(registrar_ip,registrar_port,instance_id,key): data = { 'auth_tag': crypto.do_hmac(base64.b64decode(key),instance_id), } v_json_message = json.dumps(data) response = tornado_requests.request("PUT", "http://%s:%s/v2/instances/%s/activate"%(registrar_ip,registrar_port,instance_id), data=v_json_message, context=None) if response.status_code == 200: logger.info("Registration activated for node %s."%instance_id) return True else: logger.error("Error: unexpected http response code from Registrar Server: " + str(response.status_code)) common.log_http_response(logger,logging.ERROR,response.json()) return False
def get(self): """This method handles the GET requests to retrieve status on agents from the WebApp. Currently, only the web app is available for GETing, i.e. /agents. All other GET uri's will return errors. """ rest_params = common.get_restful_params(self.request.uri) if rest_params is None: common.echo_json_response( self, 405, "Not Implemented: Use /agents/ or /logs/ interface") return if "logs" in rest_params and rest_params["logs"] == "tenant": offset = 0 if "pos" in rest_params and rest_params[ "pos"] is not None and rest_params["pos"].isdigit(): offset = int(rest_params["pos"]) # intercept requests for logs with open(keylime_logging.LOGSTREAM, 'r') as f: logValue = f.readlines() common.echo_json_response(self, 200, "Success", {'log': logValue[offset:]}) return elif "agents" not in rest_params: # otherwise they must be looking for agent info common.echo_json_response(self, 400, "uri not supported") logger.warning('GET returning 400 response. uri not supported: ' + self.request.path) return agent_id = rest_params["agents"] if agent_id is not None: # Handle request for specific agent data separately agents = self.get_agent_state(agent_id) agents["id"] = agent_id common.echo_json_response(self, 200, "Success", agents) return # If no agent ID, get list of all agents from Registrar try: response = tornado_requests.request( "GET", "http://%s:%s/agents/" % (tenant_templ.registrar_ip, tenant_templ.registrar_port), context=tenant_templ.context) except Exception as e: logger.error( "Status command response: %s:%s Unexpected response from Registrar." % (tenant_templ.registrar_ip, tenant_templ.registrar_port)) logger.exception(e) common.echo_json_response(self, 500, "Unexpected response from Registrar", str(e)) return response_body = response.json() if response.status_code != 200: logger.error( "Status command response: %d Unexpected response from Registrar." % response.status_code) common.log_http_response(logger, logging.ERROR, response_body) return None if ("results" not in response_body) or ("uuids" not in response_body["results"]): logger.critical( "Error: unexpected http response body from Registrar: %s" % str(response.status_code)) return None agent_list = response_body["results"]["uuids"] # Loop through each agent and ask for status agents = {} for agent in agent_list: agents[agent] = self.get_agent_state(agent_id) # Pre-create sorted agents list sorted_by_state = {} states = cloud_verifier_common.CloudAgent_Operational_State.STR_MAPPINGS for state in states: sorted_by_state[state] = {} # Build sorted agents list for agent_id in agents: state = agents[agent_id]["operational_state"] sorted_by_state[state][agent_id] = agents[agent_id] print_order = [10, 9, 7, 3, 4, 5, 6, 2, 1, 8, 0] sorted_agents = [] for state in print_order: for agent_id in sorted_by_state[state]: sorted_agents.append(agent_id) common.echo_json_response(self, 200, "Success", {'uuids': sorted_agents})
def do_quote(self): """initiaite v, agent_id and ip initiate the cloudinit sequence""" self.nonce = TPM_Utilities.random_password(20) numtries = 0 response = None while True: # Get quote try: response = tornado_requests.request( "GET", "http://%s:%s/quotes/identity?nonce=%s" % (self.cloudagent_ip, self.cloudagent_port, self.nonce)) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: raise UserError( "Quitting after max number of retries to connect to %s" % (self.cloudagent_ip)) retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudagent_ip, numtries, maxr, retry)) time.sleep(retry) continue else: raise e break try: if response is not None and response.status_code != 200: raise UserError( "Status command response: %d Unexpected response from Cloud Agent." % response.status_code) response_body = response.json() if "results" not in response_body: raise UserError( "Error: unexpected http response body from Cloud Agent: %s" % str(response.status_code)) quote = response_body["results"]["quote"] logger.debug("agent_quote received quote:" + quote) public_key = response_body["results"]["pubkey"] logger.debug("agent_quote received public key:" + public_key) # Get tpm_version, hash_alg tpm_version = response_body["results"]["tpm_version"] logger.debug("agent_quote received tpm version:" + str(tpm_version)) # Ensure hash_alg is in accept_tpm_hash_algs list hash_alg = response_body["results"]["hash_alg"] logger.debug("agent_quote received hash algorithm:" + hash_alg) if not Hash_Algorithms.is_accepted( hash_alg, config.get('tenant', 'accept_tpm_hash_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted hash algorithm: %s" % hash_alg) # Ensure enc_alg is in accept_tpm_encryption_algs list enc_alg = response_body["results"]["enc_alg"] logger.debug("agent_quote received encryption algorithm:" + enc_alg) if not Encrypt_Algorithms.is_accepted( enc_alg, config.get('tenant', 'accept_tpm_encryption_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted encryption algorithm: %s" % enc_alg) # Ensure sign_alg is in accept_tpm_encryption_algs list sign_alg = response_body["results"]["sign_alg"] logger.debug("agent_quote received signing algorithm:" + sign_alg) if not Sign_Algorithms.is_accepted( sign_alg, config.get('tenant', 'accept_tpm_signing_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted signing algorithm: %s" % sign_alg) if not self.validate_tpm_quote(public_key, quote, tpm_version, hash_alg): raise UserError( "TPM Quote from cloud agent is invalid for nonce: %s" % self.nonce) logger.info("Quote from %s validated" % self.cloudagent_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: " + b64_encrypted_u) data = { 'encrypted_key': b64_encrypted_u, 'auth_tag': self.auth_tag } if self.payload is not None: data['payload'] = self.payload u_json_message = json.dumps(data) #post encrypted U back to CloudAgent response = tornado_requests.request( "POST", "http://%s:%s/keys/ukey" % (self.cloudagent_ip, self.cloudagent_port), data=u_json_message) if response.status_code != 200: common.log_http_response(logger, logging.ERROR, response_body) raise UserError( "Posting of Encrypted U to the Cloud Agent failed with response code %d" % response.status_code) except Exception as e: self.do_cvstop() raise e
def do_quote(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" self.nonce = tpm_initialize.random_password(20) numtries = 0 response = None while True: # Get quote try: response = tornado_requests.request( "GET", "http://%s:%s/v2/quotes/identity/nonce/%s/" % (self.cloudnode_ip, self.cloudnode_port, self.nonce)) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( "Quitting after max number of retries to connect to %s" % (self.cloudnode_ip)) raise e retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudnode_ip, numtries, maxr, retry)) time.sleep(retry) continue else: raise e break try: if response is not None and response.status_code != 200: raise Exception( "Status command response: %d Unexpected response from Cloud Node." % response.status_code) response_body = response.json() if "results" not in response_body: raise Exception( "Error: unexpected http response body from Cloud Node: %s" % str(response.status_code)) quote = response_body["results"]["quote"] logger.debug("cnquote received quote:" + quote) public_key = response_body["results"]["pubkey"] logger.debug("cnquote received public key:" + public_key) if not self.validate_tpm_quote(public_key, quote): raise Exception( "TPM Quote from cloud node is invalid for nonce: %s" % self.nonce) logger.info("Quote from %s validated" % self.cloudnode_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: " + b64_encrypted_u) data = { 'encrypted_key': b64_encrypted_u, 'auth_tag': self.auth_tag } if self.payload is not None: data['payload'] = self.payload u_json_message = json.dumps(data) #post encrypted U back to CloudNode response = tornado_requests.request( "POST", "http://%s:%s/v2/keys/ukey" % (self.cloudnode_ip, self.cloudnode_port), data=u_json_message) if response.status_code != 200: common.log_http_response(logger, logging.ERROR, response_body) raise Exception( "Posting of Encrypted U to the Cloud Node failed with response code %d" % response.status_code) except Exception as e: logger.error(e) self.do_cvstop()
def get(self): """This method handles the GET requests to retrieve status on instances for all nodes in a Web-based GUI. Currently, only the web app is available for GETing, i.e. /webapp. All other GET uri's will return errors. """ # Get list of instances from Registrar try: response = tornado_requests.request("GET", "http://%s:%s/v2/nodes/"%(tenant_templ.webapp_ip,tenant_templ.webapp_port),context=tenant_templ.context) except Exception as e: logger.error("Status command response: %s:%s Unexpected response from WebApp API."%(tenant_templ.webapp_ip,tenant_templ.webapp_port)) logger.error(traceback.print_exc()) logger.error("Error: %s "%str(e)) raise e response_body = response.json() if response.status_code != 200: logger.error("Status command response: %d Unexpected response from WebApp API."%response.status_code) common.log_http_response(logger,logging.ERROR,response_body) return None if ("results" not in response_body) or ("uuids" not in response_body["results"]): logger.critical("Error: unexpected http response body from WebApp API: %s"%str(response.status_code)) return None instance_list = response_body["results"]["uuids"] # Get default policies for TPM/vTPM from config as suggestions to user tpm_policy = json.dumps(json.loads(config.get('tenant', 'tpm_policy')), indent=2) vtpm_policy = json.dumps(json.loads(config.get('tenant', 'vtpm_policy')), indent=2) self.set_status(200) self.set_header('Content-Type', 'text/html') self.write( """ <!DOCTYPE html> <html> <head> <meta charset='UTF-8'> <title>Advanced Tenant Management System</title> <script type='text/javascript' src='/static/js/webapp.js'></script> <link href='/static/css/webapp.css' rel='stylesheet' type='text/css'/> </head> <body> <div id='modal_box' onclick="if (event.target == this) {toggleVisibility(this.id);resetAddNodeForm();return false;}"> """ ) self.write( """ <div id='modal_body'> <center> <h3>Add Node</h3> <h4 id='uuid_str'></h4> </center> <form id='add_node' name='add_node' onsubmit='submitAddNodeForm(this); return false;'> <div class="form_block"> <label for='node_ip'>Node IP: </label> <input type='text' id='node_ip' name='node_ip' value='127.0.0.1' required onfocus='this.select()'> <br> </div> <div id='imalist_toggle' onclick="toggleVisibility('imalist_block');" title='IMA Configuration'> IMA Configuration </div> <div id="imalist_block"> <div class="form_block"> <label for='w_list'>Whitelist: </label> <div id='w_list' name='w_list' class='file_drop'> <i>Drag payload here …</i> </div> <input type='hidden' name='w_list_data' id='w_list_data' value=''> <input type='hidden' name='w_list_name' id='w_list_name' value=''> <br> </div> <div class="form_block"> <label for='e_list'>Exclude: </label> <div id='e_list' name='e_list' class='file_drop'> <i>Drag payload here …</i> </div> <input type='hidden' name='e_list_data' id='e_list_data' value=''> <input type='hidden' name='e_list_name' id='e_list_name' value=''> <br> </div> </div> <br> <div id='policy_toggle' onclick="toggleVisibility('policy_block');" title='TPM & vTPM Policy Configuration'> TPM & vTPM Policy Configuration </div> <div id="policy_block"> <div class="form_block"> <label for='tpm_policy'>TPM Policy: </label><br> <textarea class='json_input' id='tpm_policy' name='tpm_policy'>{0}</textarea> <br> </div> <div class="form_block"> <label for='vtpm_policy'>vTPM Policy: </label><br> <textarea class='json_input' id='vtpm_policy' name='vtpm_policy'>{1}</textarea> <br> </div> </div> <br> """.format(tpm_policy, vtpm_policy) ) self.write( """ <div id="payload_block"> <div class="form_block"> <label for='ptype'>Payload type: </label> <label><input type='radio' name='ptype' value='{0}' checked="checked" onclick='toggleTabs(this.value)'> File </label> <label><input type='radio' name='ptype' value='{1}' onclick='toggleTabs(this.value)'> Keyfile </label> <label><input type='radio' name='ptype' value='{2}' onclick='toggleTabs(this.value)'> CA Dir </label> <br> </div> """.format(Node_Init_Types.FILE, Node_Init_Types.KEYFILE, Node_Init_Types.CA_DIR) ) self.write( """ <div id='keyfile_container' class="form_block" style="display:none;"> <label for='file'>Keyfile: </label> <div id='keyfile' name='keyfile' class='file_drop'> <i>Drag key file here …</i> </div> <input type='hidden' name='keyfile_data' id='keyfile_data' value=''> <input type='hidden' name='keyfile_name' id='keyfile_name' value=''> <br> </div> <div id='file_container' class="form_block"> <label for='file'>Payload: </label> <div id='file' name='file' class='file_drop'> <i>Drag payload here …</i> </div> <input type='hidden' name='file_data' id='file_data' value=''> <input type='hidden' name='file_name' id='file_name' value=''> <br> </div> <div id='ca_dir_container' style="display:none;"> <div class="form_block"> <label for='ca_dir'>CA Dir: </label> <input type='text' id='ca_dir' name='ca_dir' placeholder='e.g., default'> <br> </div> <div class="form_block"> <label for='ca_dir_pw'>CA Password: </label> <input type='password' id='ca_dir_pw' name='ca_dir_pw' placeholder='e.g., default'> <br> </div> <div class="form_block"> <label for='include_dir'>Include dir: </label> <div id='include_dir' name='include_dir' class='file_drop multi_file'> <i>Drag files here …</i> </div> <input type='hidden' name='include_dir_data' id='include_dir_data' value=''> <input type='hidden' name='include_dir_name' id='include_dir_name' value=''> <br> </div> </div> </div> <br> <input type='hidden' name='uuid' id='uuid' value=''> <center><button type="submit" value="Add Node">Add Node</button></center> <br> </form> </div> </div> <div id="header"> <div class="logo" title="Keylime"> </div> <div id="header_banner"> <h1>Keylime Advanced Tenant Management System</h1> </div> <div class="logo" style="float:right;" title="Keylime"> </div> <br style="clear:both;"> </div> <div id="instance_body"> <h2>Instances</h2> <div class='table_header'> <div class='table_control'> </div> <div class='table_col'>UUID</div> <div class='table_col'>address</div> <div class='table_col'>status</div> <br style='clear:both;' /> </div> <div id='node_container'> """ ) # Print out all instance node entries (if any) if len(instance_list) == 0: self.write( """ <div style="color:#888;margin-left:15px;padding:10px;"> <i>No nodes registered</i> </div> """ ) else: for instance_id in instance_list: self.write( """ <div id='{0}'> <div id='{0}-over' style='display:block;cursor:help;width:800px;'></div> <div id='{0}-det' style='display:none;'></div> </div> """.format(instance_id) ) self.write( """ </div> </div> </body> </html> """ )
def get(self): """This method handles the GET requests to retrieve status on instances from the WebApp. Currently, only the web app is available for GETing, i.e. /v2/nodes. All other GET uri's will return errors. """ rest_params = common.get_restful_params(self.request.path) if rest_params is None: common.echo_json_response(self, 405, "Not Implemented: Use /v2/nodes/ interface") return if "nodes" not in rest_params: common.echo_json_response(self, 400, "uri not supported") logger.warning('GET returning 400 response. uri not supported: ' + self.request.path) return instance_id = rest_params["nodes"] if instance_id is not None: instances = self.get_instance_state(instance_id) instances["id"] = instance_id common.echo_json_response(self, 200, "Success", instances) else: # Get list of instances from Registrar try: response = tornado_requests.request("GET", "http://%s:%s/v2/instances/"%(tenant_templ.registrar_ip,tenant_templ.registrar_port),context=tenant_templ.context) except Exception as e: logger.error("Status command response: %s:%s Unexpected response from Registrar."%(tenant_templ.registrar_ip,tenant_templ.registrar_port)) logger.error(traceback.print_exc()) logger.error("Error: %s "%str(e)) raise e response_body = response.json() if response.status_code != 200: logger.error("Status command response: %d Unexpected response from Registrar."%response.status_code) common.log_http_response(logger,logging.ERROR,response_body) return None if ("results" not in response_body) or ("uuids" not in response_body["results"]): logger.critical("Error: unexpected http response body from Registrar: %s"%str(response.status_code)) return None instance_list = response_body["results"]["uuids"] # Loop through each instance and ask for status instances = {} for instance in instance_list: instances[instance] = self.get_instance_state(instance_id) # Pre-create sorted instances list sorted_by_state = {} states = cloud_verifier_common.CloudInstance_Operational_State.STR_MAPPINGS for state in states: sorted_by_state[state] = {} # Build sorted instances list for instance_id in instances: state = instances[instance_id]["operational_state"] sorted_by_state[state][instance_id] = instances[instance_id] print_order = [9,7,3,4,5,6,2,1,8,0] sorted_instances = [] for state in print_order: for instance_id in sorted_by_state[state]: sorted_instances.append(instance_id) common.echo_json_response(self, 200, "Success", {'uuids':sorted_instances})