+ cherrypy.log("NodeList: " + str(NodeList))
+
+ # if NodeList empty
+ if not NodeList:
+ cherrypy.log("*** NodeList - Empty ***")
+ else:
+ HaveNodeList = True
+
+ # ##############################################################################
+ # #### Host file processing ###########################
+ # #### 1. Use file delivered with playbook ###########################
+ # #### 2. If HostNames + NodeList generate and use ###########################
+ # ##############################################################################
+
+ # Verify inventory directory exists
+ path = PlaybookDir + "/inventory/"
+ if not os.path.isdir(path):
+ cherrypy.log("Inventory directory %s does not exist - create it" % path)
+ try:
+ os.mkdir(path)
+ except OSError:
+ cherrypy.log("Creation of the directory %s failed" % path)
+ else:
+ cherrypy.log("Successfully created the directory %s " % path)
+
+ # location of host file - Default
+ HostFile = PlaybookDir + "/inventory/" + VNF_instance + "hosts"
+ cherrypy.log("HostFile: " + HostFile)
+
+ # if NodeList and InventoryNames need to build host file
+ if HaveInventoryNames & HaveNodeList:
+ cherrypy.log("Build host file from NodeList")
+ ret = buildHostsSysCall(input_json, PlaybookDir, inventory_names)
+ if ret < 0:
+ cherrypy.log("Returning Error: Not running Playbook")
+ return {"StatusCode": 105,
+ "StatusMessage": "NodeList: Missing vnfc-type field"}
+
+ # Having been built now copy new file to correct file
+ shutil.copy(PlaybookDir + "/host_file.txt", HostFile)
+ cherrypy.log("Copying Generated host file to: " + HostFile)
+
+ if 'Timeout' in input_json:
+ timeout = int(input_json['Timeout'])
+ cherrypy.log("Timeout from API: " + str(timeout))
+ else:
+ timeout = timeout_seconds
+ cherrypy.log("Timeout not passed from API using default: " + str(timeout))
+
+ EnvParam = input_json.get('EnvParameters', {})
+ LocalParam = input_json.get('LocalParameters', {})
+ FileParam = input_json.get('FileParameters', {})
+ callback_flag = input_json.get('CallBack', None)
+
+ # if AnsibleServer is not set to 'na' don't send AnsibleServer in PENDING response.
+ TestRecord[Id] = {
+ 'PlaybookName': PlaybookName,
+ 'Version': version,
+ 'NodeList': NodeList,
+ 'HostGroupList': hostgrouplist,
+ 'HostNameList': hostnamelist,
+ 'Time': time_now,
+ 'Duration': timeout,
+ 'Timeout': timeout,
+ 'EnvParameters': EnvParam,
+ 'LocalParameters': LocalParam,
+ 'FileParameters': FileParam,
+ 'CallBack': callback_flag,
+ 'Result': {
+ "StatusCode": 100,
+ "StatusMessage": 'PENDING',
+ "ExpectedDuration": str(timeout) + "sec"
+ },
+ 'Log': '',
+ 'Output': {},
+ 'Path': PlaybookDir,
+ 'Mandatory': None
+ }
+ if AnsibleServer != 'na':
+ TestRecord[Id]['Result']["AnsibleServer"] = str(AnsibleServer),
+
+ cherrypy.log("Test_Record: " + str(TestRecord[Id]))
+
+ # Write files
+ if TestRecord[Id]['FileParameters']:
+ for key in TestRecord[Id]['FileParameters']:
+ filename = key
+ filecontent = TestRecord[Id]['FileParameters'][key]
+ f = open(PlaybookDir + "/" + filename, "w")
+ f.write(filecontent)
+ f.close()
+
+ # Process playbook
+ if os.path.exists(ANSIBLE_PATH + '/' + PlaybookName):
+ AnsiblePlaybookFail = False
+
+ if AnsiblePlaybookFail:
+ # if os.path.exists(PlaybookDir):
+ # shutil.rmtree (PlaybookDir)
+ cherrypy.log("AnsiblePlaybookFail")
+ del TestRecord[Id]
+ return {"StatusCode": 101, "StatusMessage": "PLAYBOOK NOT FOUND"}
+ else:
+ # Test EnvParameters
+ playbook_path = PlaybookDir
+
+ # Store local vars
+ store_local_vars(playbook_path, Id)
+
+ # write some info out to files before running
+ if AUTH:
+ f = open(playbook_path + "/User.txt", "a")
+ f.write(cherrypy.request.login)
+ f.close()
+
+ f = open(playbook_path + "/PlaybookName.txt", "a")
+ f.write(PlaybookName)
+ f.close()
+
+ f = open(playbook_path + "/PlaybookExDir.txt", "a")
+ f.write(PlaybookDir + "/" + PlayBookFunction)
+ f.close()
+
+ f = open(playbook_path + "/JsonRequest.txt", "w")
+ f.write(json.dumps(input_json, indent=4, sort_keys=True))
+ f.close()
+
+ # Check that HostFile exists
+ if not os.path.isfile(HostFile):
+ cherrypy.log("Inventory file Not Found: " + HostFile)
+ return {"StatusCode": 101, "StatusMessage": "PLAYBOOK INVENTORY FILE NOT FOUND"}
+
+ # Cannot use thread because ansible module uses signals which are only supported in main thread.
+ # So use multiprocess with shared object
+ p = Process(target=RunAnsible_Playbook,
+ args=(callback, Id, HostFile, PlaybookDir + '/' + PlayBookFile,
+ NodeList, TestRecord, PlaybookDir + "/" + PlayBookFunction, ArchiveFlag))
+ p.start()
+ ActiveProcess[Id] = p
+ return TestRecord[Id]['Result']
+
+
+def handle_post_method(input_json, time_now):
+ cherrypy.log("Payload: " + str(input_json))
+
+ if 'Id' in input_json and 'PlaybookName' in input_json and 'EnvParameters' in input_json:
+ if input_json['Id'] not in TestRecord:
+ # check if Id exists in previous run directory, if so return error
+ Id = input_json['Id']
+ if glob.glob(ANSIBLE_TEMP + '/*_' + input_json['Id']):
+ cherrypy.log("Old directory found for ID: " + Id)
+ return {"StatusCode": 101, "StatusMessage": "TEST ID FILE ALREADY DEFINED"}
+
+ # if required it should be passed as an argument
+ EnvParameters = input_json.get('EnvParameters', {})
+
+ # The lines below are to test multiple EnvParameters being passed
+ # for i in EnvParameters:
+ # cherrypy.log("EnvParameter object: " + i)
+ # cherrypy.log(" EnvParameter Value: " + EnvParameters[ i ])
+
+ pnf_flag = EnvParameters.get("pnf-flag", "")
+ if pnf_flag == "true":
+ return process_pnf_playbook(input_json, Id, EnvParameters, time_now)
+ else:
+ return process_vnf_playbook(input_json, Id, EnvParameters, time_now)
+ else:
+ cherrypy.log("TEST ID ALREADY DEFINED")
+ return {"StatusCode": 101, "StatusMessage": "TEST ID ALREADY DEFINED"}
+ else:
+ return {"StatusCode": 500, "StatusMessage": "JSON OBJECT MUST INCLUDE: ID, PLAYBOOKNAME, EnvParameters"}
+
+
+def handle_get_method(input_data):
+ # Verify we have a Type passed in GET request
+ if 'Type' not in input_data:
+ return {"StatusCode": 500, "StatusMessage": "RESULTS TYPE UNDEFINED"}
+
+ if AUTH:
+ cherrypy.log("Request USER: " + cherrypy.request.login)
+ cherrypy.log("Payload: " + str(input_data) + " Type " + input_data['Type'])
+
+ if 'LogRest' in input_data['Type']:
+ sys.stdout.close()
+ sys.stdout = open("/var/log/RestServer.log", "w")
+
+ # Just a debug to dump any records
+ if 'GetStatus' in input_data['Type']:
+ cherrypy.log("******** Dump Records **********")
+ if TestRecord.items():
+ for id, record in TestRecord.items():
+ cherrypy.log(" Id: " + id)
+ cherrypy.log("Record: " + str(record))
+ else:
+ cherrypy.log(" No Records to dump")
+
+ if 'Id' in input_data and 'Type' in input_data:
+ if not ('GetResult' in input_data['Type'] or 'GetOutputLog' in input_data['Type'] or
+ 'GetTheOutput' in input_data['Type'] or 'GetOutput' in input_data['Type'] or
+ 'GetLog' in input_data['Type']):
+ return {"StatusCode": 500, "StatusMessage": "RESULTS TYPE UNDEFINED"}
+
+ if input_data['Id'] in TestRecord:
+ if 'GetResult' in input_data['Type']:
+ cherrypy.log(" ** GetResult for: " + str(input_data['Id']))
+ if 'StatusMessage' in TestRecord[input_data['Id']]['Result'] and getresults_block:
+ # check if playbook is still running
+ while ActiveProcess[input_data['Id']].is_alive():
+ cherrypy.log("*** Playbook running returning PENDING for " + str(input_data['Id']))
+ # If still running return PENDING response
+ # if AnsibleServer != 'na':
+ # return {"StatusCode": 100, "StatusMessage": 'PENDING', "AnsibleServer": str(AnsibleServer)}
+ # else:
+ # return {"StatusCode": 100, "StatusMessage": 'PENDING'}
+ time.sleep(3)
+
+ # cherrypy.log( "*** Request released " + input_data['Id'])
+
+ cherrypy.log(str(TestRecord[input_data['Id']]['Result']))
+ cherrypy.log("Output: " + str(TestRecord[input_data['Id']]['Output']))
+ cherrypy.log("StatusCode: " + str(TestRecord[input_data['Id']]['Result']['StatusCode']))
+ cherrypy.log("StatusMessage: " + str(TestRecord[input_data['Id']]['Result']['StatusMessage']))
+
+ # out_obj gets returned to GET request
+ if TestRecord[input_data['Id']]['Result']['StatusCode'] == 500:
+ out_obj = TestRecord[input_data['Id']]['Result']['Results']
+ else:
+ out_obj = {
+ "StatusCode": 200,
+ "StatusMessage": "FINISHED",
+ "PlaybookName": TestRecord[input_data['Id']]["PlaybookName"],
+ "Version": TestRecord[input_data['Id']]["Version"],
+ "Duration": TestRecord[input_data['Id']]["Duration"],
+ "Output": TestRecord[input_data['Id']]["Output"]["Output"],
+ "Results": TestRecord[input_data['Id']]['Result']['Results']
+ }
+ if not TestRecord[input_data['Id']]['Output']['Output'] == {}:
+ cherrypy.log("TestRecord has Output:" + str(TestRecord[input_data['Id']]['Output']['Output']))
+ # PAP
+ for key in out_obj["Results"]:
+ cherrypy.log("Output key: " + str(key))
+ if key in TestRecord[input_data['Id']]['Output']['Output']:
+ out_obj["Results"][key]["Output"] = TestRecord[input_data['Id']]['Output']['Output'][key]
+
+ cherrypy.log("***** GET RETURNING RESULTS Back ****")
+ cherrypy.log(str(out_obj))
+ return out_obj
+ elif 'GetStatus' in input_data['Type']:
+ cherrypy.log(" Dump Records")
+ for id, record in TestRecord.items():
+ cherrypy.log(" id: " + id)
+ cherrypy.log(" Record:" + str(record))
+ elif 'GetTheOutput' in input_data['Type'] or 'GetOutput' in input_data['Type']:
+ if TestRecord[input_data['Id']]['Output'] == {} and getresults_block:
+ cherrypy.log("*** Request blocked " + input_data['Id'])
+
+ while TestRecord[input_data['Id']]['Output'] == {} \
+ or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
+ time.sleep(5)
+
+ cherrypy.log("*** Request released " + input_data['Id'])
+
+ cherrypy.log("Output: " + str(TestRecord[input_data['Id']]['Output']))
+ return {"Output": TestRecord[input_data['Id']]['Output']['Output']}
+ elif 'GetOutputLog' in input_data['Type']:
+ cherrypy.log("GetOutputLog: processing.")
+ if glob.glob(ANSIBLE_TEMP + '/*_' + input_data['Id']):
+ id = input_data['Id']
+ cherrypy.log("Old directory found for ID: " + id)
+ run_dir = glob.glob(ANSIBLE_TEMP + '/*_' + input_data['Id'])
+ for dir in run_dir:
+ rdir = dir
+ if os.path.exists(rdir + "/PlaybookExDir.txt"):
+ cherrypy.log("Found PlaybookExDir.txt file")
+ f = open(rdir + '/PlaybookExDir.txt', 'r')
+ playbookexdir = f.readline()
+ rdir = playbookexdir
+ f.close()
+ cherrypy.log("Id: " + id)
+ cherrypy.log("RunDir: " + rdir)
+ if os.path.exists(rdir + "/output.log"):
+ cherrypy.log("Found output.log file")
+ f = open(rdir + '/output.log', 'r')
+ output_log = f.readline()
+ f.close()
+ return output_log
+ else:
+ cherrypy.log("Globglob failed:")
+ return
+
+ else:
+ # GetLog
+ if TestRecord[input_data['Id']]['Log'] == '' and \
+ getresults_block:
+
+ cherrypy.log("*** Request blocked " + input_data['Id'])
+
+ while TestRecord[input_data['Id']]['Log'] == '' \
+ or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
+ time.sleep(5)
+
+ cherrypy.log("*** Request released " + input_data['Id'])
+
+ cherrypy.log("Log:" + str(TestRecord[input_data['Id']]['Log']))
+ return {"Log": TestRecord[input_data['Id']]['Log']}
+ else:
+ # Not in memory check for a file
+ if glob.glob(ANSIBLE_TEMP + '/*_' + input_data['Id']):
+ id = input_data['Id']
+ cherrypy.log("Old directory found for ID: " + id)
+ run_dir = glob.glob(ANSIBLE_TEMP + '/*_' + input_data['Id'])
+ for dir in run_dir:
+ rdir = dir
+ if os.path.exists(rdir + "/PlaybookExDir.txt"):
+ cherrypy.log("Found PlaybookExDir.txt file")
+ f = open(rdir + '/PlaybookExDir.txt', 'r')
+ playbookexdir = f.readline()
+ rdir = playbookexdir
+ f.close()
+ cherrypy.log("Id: " + id)
+ cherrypy.log("RunDir: " + rdir)
+ if 'GetLog' in input_data['Type']:
+ if os.path.exists(rdir + "/output.log"):
+ cherrypy.log("Found output.log file")
+ f = open(rdir + '/output.log', 'r')
+ output_log = f.readline()
+ f.close()
+ return output_log
+ elif 'GetOutputLog' in input_data['Type']:
+ if os.path.exists(rdir + "/output.log"):
+ cherrypy.log("Found output.log file")
+ f = open(rdir + '/output.log', 'r')
+ output_log = f.readline()
+ f.close()
+ return output_log
+ elif 'GetResult' in input_data['Type']:
+ if os.path.exists(rdir + "/PlaybookName.txt"):
+ cherrypy.log("Found PlaybookName.txt file")
+ f = open(rdir + '/PlaybookName.txt', 'r')
+ playbooknametxt = f.readline()
+ f.close()
+ else:
+ playbooknametxt = "NA"
+
+ # Add code to get other items not just output.log from files
+ if os.path.exists(rdir + "/log.file"):
+ cherrypy.log("Found log.file")
+ out_results = "NA:"
+
+ f = open(rdir + '/log.file', 'r')
+ line = f.readline()
+ while line:
+ if "fatal" in line:
+ out_results = out_results + line
+ elif "RECAP" in line:
+ out_results = out_results + line
+ recap_line = f.readline()
+ while recap_line:
+ out_results = out_results + recap_line
+ recap_line = f.readline()
+ line = f.readline()
+ f.close()
+ out_obj = {
+ "StatusCode": 200,
+ "StatusMessage": "FINISHED",
+ "PlaybookName": playbooknametxt,
+ "Version": "Version",
+ "Duration": 200,
+ "Results": out_results
+ }
+ return out_obj
+ else:
+ return {"StatusCode": 500, "StatusMessage": "PLAYBOOK FAILED "}
+
+ return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
+ else:
+ return {"StatusCode": 500, "StatusMessage": "MALFORMED REQUEST"}
+
+
+def handle_delete_method(input_data):
+ cherrypy.log("***> in RestServer.DELETE")
+ cherrypy.log("Payload: " + str(input_data))
+
+ if input_data['Id'] in TestRecord:
+ if 'PENDING' not in TestRecord[input_data['Id']]['Result']:
+ cherrypy.log(" Path: " + str(TestRecord[input_data['Id']]['Path']))
+ TestRecord.pop(input_data['Id'])
+ if input_data['Id'] in ActiveProcess:
+ ActiveProcess.pop(input_data['Id'])
+ return {"StatusCode": 200, "StatusMessage": "PLAYBOOK EXECUTION RECORDS DELETED"}
+ else:
+ return {"StatusCode": 200, "StatusMessage": "PENDING"}
+ else:
+ return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
+
+
+class TestManager(object):