4 * ============LICENSE_START=======================================================
6 * ================================================================================
7 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
8 * ================================================================================
9 * Copyright (C) 2017 Amdocs
10 * =============================================================================
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
24 * ============LICENSE_END=========================================================
28 import time, datetime, json, os, sys, subprocess, re
36 from cherrypy.lib.httputil import parse_query_string
37 from cherrypy.lib import auth_basic
39 from multiprocessing import Process, Manager
41 from AnsibleModule import ansibleSysCall
44 from AnsibleSql import readPlaybook, readCredentials
46 from os import listdir
47 from os.path import isfile, join
49 TestRecord = Manager().dict()
53 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
54 output = p.stdout.readlines()
57 for i in range(len(output)):
58 output[i] = output[i].strip()
61 def callback (Id, Result, Output, Log, returncode):
63 print "***> in RestServer.callback"
66 time_now = datetime.datetime.utcnow()
67 delta_time = (time_now - TestRecord[Id]['Time']).total_seconds()
68 Result['PlaybookName'] = TestRecord[Id]['PlaybookName']
69 Result['Version'] = TestRecord[Id]['Version']
71 Result['StatusCode'] = 500
72 Result['StatusMessage'] = "TERMINATED"
74 Result['StatusCode'] = 200
75 Result['StatusMessage'] = "FINISHED"
77 # Need to update the whole data structure for key=Id otherwise Manager is not updated
78 TestRecord[Id] = {'PlaybookName': TestRecord[Id]['PlaybookName'],
79 'LCM': TestRecord[Id]['LCM'],
80 'Version': TestRecord[Id]['Version'],
81 'NodeList': TestRecord[Id]['NodeList'],
82 'HostGroupList': TestRecord[Id]['HostGroupList'],
83 'HostNameList': TestRecord[Id]['HostNameList'],
84 'Time': TestRecord[Id]['Time'],
85 'Timeout': TestRecord[Id]['Timeout'],
86 'Duration': str(delta_time),
87 'EnvParameters': TestRecord[Id]['EnvParameters'],
88 'LocalParameters': TestRecord[Id]['LocalParameters'],
89 'FileParameters': TestRecord[Id]['FileParameters'],
90 'CallBack': TestRecord[Id]['CallBack'],
94 'Path': TestRecord[Id]['Path'],
95 'Mandatory': TestRecord[Id]['Path']}
97 if not TestRecord[Id]['CallBack'] == None:
99 # Posting results to callback server
101 data = {"StatusCode": 200,
102 "StatusMessage": "FINISHED",
103 "PlaybookName": TestRecord[Id]["PlaybookName"],
104 "Version": TestRecord[Id]["Version"],
105 "Duration": TestRecord[Id]["Duration"],
106 "Results": TestRecord[Id]['Result']['Results']}
108 if not TestRecord[Id]['Output']['Output'] == {}:
109 for key in data["Results"]:
110 if key in TestRecord[Id]['Output']['Output']:
111 data["Results"][key]["Output"] = TestRecord[Id]['Output']['Output'][key]
113 print " Posting to", TestRecord[Id]['CallBack']
115 s = requests.Session()
116 r = s.post(TestRecord[Id]['CallBack'], data = json.dumps(data),
117 headers = {'content-type': 'application/json'})
118 print " Response", r.status_code, r.text
120 def RunAnsible_Playbook (callback, Id, Inventory, Playbook, NodeList, TestRecord,
123 print "***> in RestServer.RunAnsible_Playbook"
125 # Run test in playbook for given target
128 retval, log, returncode = ansibleSysCall (Inventory, Playbook, NodeList,
129 TestRecord[Id]['Mandatory'],
130 TestRecord[Id]['EnvParameters'],
131 TestRecord[Id]['LocalParameters'],
132 TestRecord[Id]['LCM'],
133 TestRecord[Id]['Timeout'])
136 print " returncode:", returncode
137 print " retval: ", retval
141 Output = {'Output': {}}
143 onlyfiles = [f for f in listdir(Path)
144 if isfile(join(Path, f))]
146 for file in onlyfiles:
147 if "results.txt" in file:
148 f = open(Path + "/" + file, "r")
149 key = file.split("_")[0]
150 Output['Output'][key] = f.read()
153 Result = {'Results': {}}
154 if 'could not be found' in Log:
155 Result['Results'] = {"StatusCode": 101,
156 "StatusMessage": "PLAYBOOK NOT FOUND"}
157 if returncode == 137:
158 Result['Results'] = {"StatusCode": 500,
159 "StatusMessage": "TERMINATED"}
161 elif TestRecord[Id]['NodeList'] == []:
165 if 'TargetNode' in TestRecord[Id]['EnvParameters']:
166 targetlist = TestRecord[Id]['EnvParameters']['TargetNode'].split(' ')
168 targetlist = ["localhost"]
171 for i in range (len(targetlist)):
172 if key in targetlist[i]:
175 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
176 int(retval[key][3]) == 0:
179 Result['Results'][targetlist[host_index]] = \
180 {"GroupName": 'na', "StatusCode": 200, \
181 "StatusMessage": "SUCCESS"}
183 Result['Results'][key] = \
184 {"GroupName": 'na', "StatusCode": 200, \
185 "StatusMessage": "SUCCESS"}
186 elif int(retval[key][2]) > 0:
188 Result['Results'][targetlist[host_index]] = \
189 {"GroupName": 'na', "StatusCode": 400, \
190 "StatusMessage": "NOT REACHABLE"}
192 Result['Results'][key] = \
193 {"GroupName": 'na', "StatusCode": 400, \
194 "StatusMessage": "NOT REACHABLE"}
195 elif int(retval[key][3]) > 0:
197 Result['Results'][targetlist[host_index]] = \
198 {"GroupName": 'na', "StatusCode": 400, \
199 "StatusMessage": "FAILURE"}
201 Result['Results'][key] = \
202 {"GroupName": 'na', "StatusCode": 400, \
203 "StatusMessage": "FAILURE"}
208 if len(TestRecord[Id]['HostNameList']) > 0:
211 for i in range (len(TestRecord[Id]['HostNameList'])):
212 if key in TestRecord[Id]['HostNameList'][i]:
215 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
216 int(retval[key][3]) == 0:
218 if len(host_index) > 0:
219 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
220 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
221 "StatusCode": 200, "StatusMessage": "SUCCESS"}
223 for i in range (1, len(host_index)):
224 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
225 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
227 Result['Results'][key] = \
229 "StatusCode": 200, "StatusMessage": "SUCCESS"}
231 elif int(retval[key][2]) > 0:
233 if len(host_index) > 0:
234 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
235 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
236 "StatusCode": 400, "StatusMessage": "NOT REACHABLE"}
238 for i in range (1, len(host_index)):
239 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
240 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
242 Result['Results'][key] = \
244 "StatusCode": 200, "StatusMessage": "NOT REACHABLE"}
246 elif int(retval[key][3]) > 0:
248 if len(host_index) > 0:
249 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
250 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
251 "StatusCode": 400, "StatusMessage": "FAILURE"}
253 for i in range (1, len(host_index)):
254 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
255 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
257 Result['Results'][key] = \
259 "StatusCode": 200, "StatusMessage": "FAILURE"}
262 for i in range (len(TestRecord[Id]['NodeList'])):
263 if key in TestRecord[Id]['NodeList'][i]:
266 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
267 int(retval[key][3]) == 0:
268 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
269 {"GroupName": 'na', "StatusCode": 200, \
270 "StatusMessage": "SUCCESS"}
271 elif int(retval[key][2]) > 0:
272 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
273 {"GroupName": 'na', "StatusCode": 400, "StatusMessage": "NOT REACHABLE"}
274 elif int(retval[key][3]) > 0:
275 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
276 {"GroupName": 'na', "StatusCode": 400, "StatusMessage": "FAILURE"}
278 callback (Id, Result, Output, Log, returncode)
280 class TestManager (object):
283 @cherrypy.tools.json_out()
284 @cherrypy.tools.json_in()
285 @cherrypy.tools.allow(methods=['POST', 'GET', 'DELETE'])
287 def Dispatch(self, **kwargs):
289 # Let cherrypy error handler deal with malformed requests
290 # No need for explicit error handler, we use default ones
292 time_now = datetime.datetime.utcnow()
294 # Erase old test results (2x timeout)
296 for key in TestRecord.copy():
297 delta_time = (time_now - TestRecord[key]['Time']).seconds
298 if delta_time > 2*TestRecord[key]['Timeout']:
299 print "Deleted history for test", key
300 if os.path.exists(TestRecord[key]['Path']):
301 shutil.rmtree (TestRecord[key]['Path'])
304 print "***> in RestServer.Dispatch:", cherrypy.request.method
306 HomeDir = os.path.dirname(os.path.realpath("~/"))
308 if 'POST' in cherrypy.request.method:
310 input_json = cherrypy.request.json
311 print " Payload: ", input_json
313 if 'Id' in input_json and 'PlaybookName' in input_json:
317 if not input_json['Id'] in TestRecord:
319 Id = input_json['Id']
320 PlaybookName = input_json['PlaybookName']
323 if 'Version' in input_json:
324 version = input_json['Version']
326 AnsibleInvFail = True
327 AnsiblePlaybookFail = True
334 str_uuid = str (uuid.uuid4())
336 LCM = PlaybookName.split(".")[0].split('_')[-1]
337 PlaybookDir = HomeDir + "/" + ansible_temp + "/" + \
338 PlaybookName.split(".")[0] + "_" + str_uuid
339 AnsibleInv = LCM + "_" + "inventory"
343 print " PlaybookDir: ", ansible_temp + PlaybookDir.split(ansible_temp)[1]
344 print " AnsibleInv: ", AnsibleInv
345 print " ansible_temp: ", ansible_temp
347 if not os.path.exists(HomeDir + "/" + ansible_temp):
348 os.makedirs(HomeDir + "/" + ansible_temp)
350 os.mkdir(PlaybookDir)
352 # Process inventory file for target
358 if 'NodeList' in input_json:
359 NodeList = input_json['NodeList']
361 print " NodeList: ", NodeList
364 # By default set to local host
365 AnsibleInvFail = False
367 LocalNodeList = "host"
368 LocalCredentials = "localhost ansible_connection=local"
369 f = open(PlaybookDir + "/" + AnsibleInv, "w")
370 f.write("[" + LocalNodeList + "]\n")
371 f.write(LocalCredentials)
378 # Get credentials from file
380 data_inventory_orig = {}
381 data_inventory_target = {}
384 print "***>", ansible_path + "/" + ansible_inv
385 f = open(ansible_path + "/" + ansible_inv, "r")
391 if "[" in line and "]" in line:
392 data_inventory_orig[line] = []
395 data_inventory_orig[curr_group].append(line)
398 for node in NodeList:
400 if "[" + node + "]" in data_inventory_orig:
401 if not "[" + node + "]" in data_inventory_target:
403 print "RESET", "[" + node + "]"
404 data_inventory_target["[" + node + "]"] = []
406 print "OK", "[" + node + "]"
408 for cred in data_inventory_orig["[" + node + "]"]:
409 data_inventory_target["[" + node + "]"].append(cred)
412 for key in data_inventory_orig:
413 if node in " ".join(data_inventory_orig[key]):
414 if not key in data_inventory_target:
415 data_inventory_target[key] = []
416 for cred in data_inventory_orig[key]:
418 data_inventory_target[key].append(cred)
422 data_inventory_target["["+node+"]"] = \
423 [node + " ansible_connection=ssh ansible_ssh_user=na ansible_ssh_private_key_file=na"]
425 AnsibleInvFail = False
427 f = open(PlaybookDir + "/" + AnsibleInv, "w")
428 for key in data_inventory_target:
430 for rec in data_inventory_target[key]:
431 hostgrouplist.append(key.replace("[", '').replace("]", ''))
432 hostnamelist.append(rec.split(' ')[0])
438 # Get credentials from mySQL
440 sqlintf = AnsibleSql.mySql (host, user, passwd,
444 errorCode, diag = readCredentials (sqlintf,
447 print errorCode, diag
449 f = open(PlaybookDir + "/" + AnsibleInv,
451 AnsibleInvFail = False
452 # [hostgroup, hostname, credentials]
453 for i in range(len(diag)):
454 f.write('[' + diag[i][0] + ']' + "\n")
455 f.write(diag[i][1]+ " " + diag[i][2] + "\n\n")
456 hostgrouplist.append(diag[i][0])
457 hostnamelist.append(diag[i][1])
460 MySqlConFailCause = sqlintf.error
463 timeout = timeout_seconds
464 if 'Timeout' in input_json:
465 timeout = int (input_json['Timeout'])
468 if 'EnvParameters' in input_json:
469 EnvParam = input_json['EnvParameters']
472 if 'LocalParameters' in input_json:
473 LocalParam = input_json['LocalParameters']
476 if 'FileParameters' in input_json:
477 FileParam = input_json['FileParameters']
480 if 'CallBack' in input_json:
481 callback_flag = input_json['CallBack']
483 TestRecord[Id] = {'PlaybookName': PlaybookName,
486 'NodeList': NodeList,
487 'HostGroupList': hostgrouplist,
488 'HostNameList': hostnamelist,
492 'EnvParameters': EnvParam,
493 'LocalParameters': LocalParam,
494 'FileParameters': FileParam,
495 'CallBack': callback_flag,
496 'Result': {"StatusCode": 100,
497 "StatusMessage": 'PENDING',
498 "ExpectedDuration": str(timeout) + "sec"},
506 if not TestRecord[Id]['FileParameters'] == {}:
507 for key in TestRecord[Id]['FileParameters']:
509 filecontent = TestRecord[Id]['FileParameters'][key]
510 f = open(PlaybookDir + "/" + filename, "w")
519 # Get playbooks from files
524 target_PlaybookName = None
526 if '@' in PlaybookName:
527 version = PlaybookName.split("@")[1]
528 version = version.replace('.yml','')
529 version = version.replace('.tar.gz','')
531 onlyfiles = [f for f in listdir(ansible_path)
532 if isfile(join(ansible_path, f))]
537 for file in onlyfiles:
539 temp_version = file.split("@")[1]
540 temp_version = temp_version.replace('.yml','')
541 temp_version = temp_version.replace('.tar.gz','')
542 if version_max < temp_version:
543 version_max = temp_version
545 if not version == None:
546 if version in PlaybookName:
547 version_target = version
548 target_PlaybookName = file
550 if target_PlaybookName == None:
551 for file in onlyfiles:
552 if LCM in file and version_max in file:
553 target_PlaybookName = file
554 version_target = version_max
556 if target_PlaybookName:
557 AnsiblePlaybookFail = False
558 readversion = version_target
559 src = ansible_path + "/" + target_PlaybookName
560 if ".tar.gz" in target_PlaybookName:
561 dest = PlaybookDir + "/" + LCM + ".tar.gz"
562 shutil.copy2(src, dest)
563 retcode = subprocess.call(['tar', '-xvzf',
564 dest, "-C", PlaybookDir])
567 dest = PlaybookDir + "/" + LCM + ".yml"
568 shutil.copy2(src, dest)
571 # Get playbooks from mySQL
573 sqlintf = AnsibleSql.mySql (host, user, passwd, db)
577 name, readversion, AnsiblePlaybookFail, diag = \
578 readPlaybook (sqlintf, PlaybookName.split(".")[0],
581 if not AnsiblePlaybookFail:
583 f = open(PlaybookDir + "/" + LCM + diag[1], "w")
587 if ".tar.gz" in diag[1]:
588 retcode = subprocess.call(['tar', '-xvzf',
589 PlaybookDir + "/" + LCM + diag[1], "-C", PlaybookDir])
593 MySqlConFailCause = sqlintf.error
597 if os.path.exists(PlaybookDir):
598 shutil.rmtree (PlaybookDir)
600 return {"StatusCode": 101,
601 "StatusMessage": "CANNOT CONNECT TO MYSQL: " \
603 elif AnsiblePlaybookFail:
604 if os.path.exists(PlaybookDir):
605 shutil.rmtree (PlaybookDir)
607 return {"StatusCode": 101,
608 "StatusMessage": "PLAYBOOK NOT FOUND"}
610 if os.path.exists(PlaybookDir):
611 shutil.rmtree (PlaybookDir)
613 return {"StatusCode": 101,
614 "StatusMessage": "NODE LIST CREDENTIALS NOT FOUND"}
620 for dName, sdName, fList in os.walk(PlaybookDir):
621 if LCM+".yml" in fList:
622 playbook_path = dName
624 playbook_path = PlaybookDir
627 if not os.path.exists(playbook_path + "/vars"):
628 os.mkdir(playbook_path + "/vars")
629 if not os.path.isfile(playbook_path + "/vars/defaults.yml"):
630 os.mknod(playbook_path + "/vars/defaults.yml")
632 for key in TestRecord[Id]['LocalParameters']:
634 for i in range(len(TestRecord[Id]['HostNameList'])):
635 if key in TestRecord[Id]['HostNameList'][i]:
637 if len(host_index) == 0:
638 for i in range(len(TestRecord[Id]['HostGroupList'])):
639 if key in TestRecord[Id]['HostGroupList'][i]:
641 if len(host_index) > 0:
642 for i in range(len(host_index)):
643 f = open(playbook_path + "/vars/" +
644 TestRecord[Id]['HostNameList'][host_index[i]] +
646 for param in TestRecord[Id]['LocalParameters'][key]:
647 f.write(param + ": " +
648 str (TestRecord[Id]['LocalParameters'][key][param]) +
652 # Get mandatory parameters from playbook
654 with open(playbook_path + "/" + LCM + ".yml") as origin_file:
655 for line in origin_file:
656 if "Mandatory" in line:
657 temp = line.split(":")[1].strip().replace(' ', '')
659 Mandatory = temp.split(",")
661 TestRecord[Id] = {'PlaybookName': TestRecord[Id]['PlaybookName'],
662 'LCM': TestRecord[Id]['LCM'],
663 'Version': readversion,
664 'NodeList': TestRecord[Id]['NodeList'],
665 'HostGroupList': TestRecord[Id]['HostGroupList'],
666 'HostNameList': TestRecord[Id]['HostNameList'],
667 'Time': TestRecord[Id]['Time'],
668 'Timeout': TestRecord[Id]['Timeout'],
669 'Duration': TestRecord[Id]['Duration'],
670 'EnvParameters': TestRecord[Id]['EnvParameters'],
671 'LocalParameters': TestRecord[Id]['LocalParameters'],
672 'FileParameters': TestRecord[Id]['FileParameters'],
673 'CallBack': TestRecord[Id]['CallBack'],
674 'Result': TestRecord[Id]['Result'],
675 'Log': TestRecord[Id]['Log'],
676 'Output': TestRecord[Id]['Output'],
677 'Path': TestRecord[Id]['Path'],
678 'Mandatory': Mandatory}
683 for val in Mandatory:
689 for key in TestRecord[Id]['NodeList']:
690 if key in LocalParam:
691 if val in LocalParam[key]:
695 for key in TestRecord[Id]['NodeList']:
696 if key in LocalParam:
697 if val in LocalParam[key]:
701 if os.path.exists(PlaybookDir):
702 shutil.rmtree (PlaybookDir)
704 return {"StatusCode": 101,
705 "StatusMessage": "MISSING MANDATORY PARAMETER: " + \
706 " ".join(str(x) for x in Mandatory)}
709 # Cannot use thread because ansible module uses
710 # signals which are only supported in main thread.
711 # So use multiprocess with shared object
713 p = Process(target = RunAnsible_Playbook,
714 args = (callback, Id, PlaybookDir + "/" + AnsibleInv,
715 playbook_path + "/" + LCM + ".yml",
716 NodeList, TestRecord, PlaybookDir,
719 ActiveProcess[Id] = p
720 return TestRecord[Id]['Result']
722 return {"StatusCode": 101, "StatusMessage": "TEST ID ALREADY DEFINED"}
725 return {"StatusCode": 500, "StatusMessage": "REQUEST MUST INCLUDE: NODELIST"}
728 return {"StatusCode": 500, "StatusMessage": "JSON OBJECT MUST INCLUDE: ID, PLAYBOOKNAME"}
730 elif 'GET' in cherrypy.request.method:
732 input_data = parse_query_string(cherrypy.request.query_string)
734 print "***> in RestServer.GET"
735 print " Payload: ", input_data, input_data['Type']
737 if 'Id' in input_data and 'Type' in input_data:
738 if not ('GetResult' in input_data['Type'] or 'GetOutput' in input_data['Type'] or 'GetLog' in input_data['Type']):
739 return {"StatusCode": 500, "StatusMessage": "RESULTS TYPE UNDEFINED"}
740 if input_data['Id'] in TestRecord:
742 if 'GetResult' in input_data['Type']:
744 print "Result:", TestRecord[input_data['Id']]['Result']
746 if 'StatusMessage' in TestRecord[input_data['Id']]['Result'] and getresults_block:
748 print "*** Request blocked", input_data['Id']
750 while ActiveProcess[input_data['Id']].is_alive():
753 print "*** Request released ", input_data['Id']
755 print TestRecord[input_data['Id']]['Result']
756 if TestRecord[input_data['Id']]['Result']['StatusCode'] == 500:
757 out_obj = TestRecord[input_data['Id']]['Result']['Results']
759 out_obj = {"StatusCode": 200,
760 "StatusMessage": "FINISHED",
761 "PlaybookName": TestRecord[input_data['Id']]["PlaybookName"],
762 "Version": TestRecord[input_data['Id']]["Version"],
763 "Duration": TestRecord[input_data['Id']]["Duration"],
764 "Results": TestRecord[input_data['Id']]['Result']['Results']}
765 if not TestRecord[input_data['Id']]['Output']['Output'] == {}:
766 for key in out_obj["Results"]:
767 if key in TestRecord[input_data['Id']]['Output']['Output']:
768 out_obj["Results"][key]["Output"] = TestRecord[input_data['Id']]['Output']['Output'][key]
772 elif 'GetOutput' in input_data['Type']:
774 if TestRecord[input_data['Id']]['Output'] == {} and \
777 print "*** Request blocked", input_data['Id']
779 while TestRecord[input_data['Id']]['Output'] == {} \
780 or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
783 print "*** Request released ", input_data['Id']
785 print "Output:", TestRecord[input_data['Id']]['Output']
786 return {"Output": TestRecord[input_data['Id']]['Output']['Output']}
790 if TestRecord[input_data['Id']]['Log'] == '' and \
793 print "*** Request blocked", input_data['Id']
795 while TestRecord[input_data['Id']]['Log'] == '' \
796 or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
799 print "*** Request released ", input_data['Id']
801 print "Log:", TestRecord[input_data['Id']]['Log']
802 return {"Log": TestRecord[input_data['Id']]['Log']}
804 return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
806 return {"StatusCode": 500, "StatusMessage": "MALFORMED REQUEST"}
807 elif 'DELETE' in cherrypy.request.method:
808 input_data = parse_query_string(cherrypy.request.query_string)
810 print "***> in RestServer.DELETE"
811 print " Payload: ", input_data
813 if input_data['Id'] in TestRecord:
814 if not 'PENDING' in TestRecord[input_data['Id']]['Result']:
815 print " Path:", TestRecord[input_data['Id']]['Path']
816 if os.path.exists(TestRecord[input_data['Id']]['Path']):
817 shutil.rmtree (TestRecord[input_data['Id']]['Path'])
818 TestRecord.pop (input_data['Id'])
819 if input_data['Id'] in ActiveProcess:
820 ActiveProcess.pop (input_data['Id'])
822 return {"StatusCode": 200, "StatusMessage": "PLAYBOOK EXECUTION RECORDS DELETED"}
824 return {"StatusCode": 200, "StatusMessage": "PENDING"}
826 return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
829 if __name__ == '__main__':
833 config_file_path = "RestServer_config"
835 if not os.path.exists(config_file_path):
836 print '[INFO] The config file does not exist'
847 timeout_seconds = 'na'
855 getresults_block = False
858 file = open(config_file_path, 'r')
859 for line in file.readlines():
862 ip = line.split(':')[1].strip()
863 elif 'port:' in line:
864 port = line.split(':')[1].strip()
866 tls = 'YES' in line.split(':')[1].strip().upper()
867 elif 'auth:' in line:
868 auth = 'YES' in line.split(':')[1].strip().upper()
869 if tls and 'priv:' in line:
870 priv = line.split(':')[1].strip()
871 if tls and 'pub:' in line:
872 pub = line.split(':')[1].strip()
873 if auth and 'id:' in line:
874 id = line.split(':')[1].strip()
875 if auth and 'psswd:' in line:
876 psswd = line.split(':')[1].strip()
877 if 'timeout_seconds' in line:
878 timeout_seconds = int (line.split(':')[1].strip())
879 if 'ansible_path' in line:
880 ansible_path = line.split(':')[1].strip()
881 if 'ansible_inv' in line:
882 ansible_inv = line.split(':')[1].strip()
883 if not os.path.exists(ansible_path + "/" + ansible_inv):
884 print '[INFO] The ansible_inv file does not exist'
886 if 'ansible_temp' in line:
887 ansible_temp = line.split(':')[1].strip()
889 host = line.split(':')[1].strip()
891 user = line.split(':')[1].strip()
893 passwd = line.split(':')[1].strip()
895 db = line.split(':')[1].strip()
896 if 'getresults_block' in line:
897 getresults_block = 'YES' in line.split(':')[1].strip().upper()
898 if 'from_files' in line:
899 from_files = 'YES' in line.split(':')[1].strip().upper()
906 'server.socket_host': ip,
907 'server.socket_port': int(port),
908 'server.protocol_version': 'HTTP/1.1'
913 # Use pythons built-in SSL
914 cherrypy.server.ssl_module = 'builtin'
916 # Point to certificate files
918 if not os.path.exists(pub):
919 print '[INFO] The public certificate does not exist'
922 if not os.path.exists(priv):
923 print '[INFO] The private key does not exist'
926 cherrypy.server.ssl_certificate = pub
927 cherrypy.server.ssl_private_key = priv
930 userpassdict = {id: psswd}
931 checkpassword = cherrypy.lib.auth_basic.checkpassword_dict(userpassdict)
934 {'tools.auth_basic.on': True,
935 'tools.auth_basic.realm': 'earth',
936 'tools.auth_basic.checkpassword': checkpassword,
940 cherrypy.tree.mount(TestManager(), '/', app_conf)
942 cherrypy.tree.mount(TestManager(), '/')
944 cherrypy.config.update(global_conf)
948 cherrypy.engine.start()
949 cherrypy.engine.block()