3 * ============LICENSE_START=======================================================
5 * ================================================================================
6 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
7 * ================================================================================
8 * Copyright (C) 2017 Amdocs
9 * =============================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
22 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 * ============LICENSE_END=========================================================
27 import time, datetime, json, os, sys, subprocess, re
35 from cherrypy.lib.httputil import parse_query_string
36 from cherrypy.lib import auth_basic
38 from multiprocessing import Process, Manager
40 from AnsibleModule import ansibleSysCall
43 from AnsibleSql import readPlaybook, readCredentials
45 from os import listdir
46 from os.path import isfile, join
48 TestRecord = Manager().dict()
52 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
53 output = p.stdout.readlines()
56 for i in range(len(output)):
57 output[i] = output[i].strip()
60 def callback (Id, Result, Output, Log, returncode):
62 print "***> in RestServer.callback"
65 time_now = datetime.datetime.utcnow()
66 delta_time = (time_now - TestRecord[Id]['Time']).total_seconds()
67 Result['PlaybookName'] = TestRecord[Id]['PlaybookName']
68 Result['Version'] = TestRecord[Id]['Version']
70 Result['StatusCode'] = 500
71 Result['StatusMessage'] = "TERMINATED"
73 Result['StatusCode'] = 200
74 Result['StatusMessage'] = "FINISHED"
76 # Need to update the whole data structure for key=Id otherwise Manager is not updated
77 TestRecord[Id] = {'PlaybookName': TestRecord[Id]['PlaybookName'],
78 'LCM': TestRecord[Id]['LCM'],
79 'Version': TestRecord[Id]['Version'],
80 'NodeList': TestRecord[Id]['NodeList'],
81 'HostGroupList': TestRecord[Id]['HostGroupList'],
82 'HostNameList': TestRecord[Id]['HostNameList'],
83 'Time': TestRecord[Id]['Time'],
84 'Timeout': TestRecord[Id]['Timeout'],
85 'Duration': str(delta_time),
86 'EnvParameters': TestRecord[Id]['EnvParameters'],
87 'LocalParameters': TestRecord[Id]['LocalParameters'],
88 'FileParameters': TestRecord[Id]['FileParameters'],
89 'CallBack': TestRecord[Id]['CallBack'],
93 'Path': TestRecord[Id]['Path'],
94 'Mandatory': TestRecord[Id]['Path']}
96 if not TestRecord[Id]['CallBack'] == None:
98 # Posting results to callback server
100 data = {"StatusCode": 200,
101 "StatusMessage": "FINISHED",
102 "PlaybookName": TestRecord[Id]["PlaybookName"],
103 "Version": TestRecord[Id]["Version"],
104 "Duration": TestRecord[Id]["Duration"],
105 "Results": TestRecord[Id]['Result']['Results']}
107 if not TestRecord[Id]['Output']['Output'] == {}:
108 for key in data["Results"]:
109 if key in TestRecord[Id]['Output']['Output']:
110 data["Results"][key]["Output"] = TestRecord[Id]['Output']['Output'][key]
112 print " Posting to", TestRecord[Id]['CallBack']
114 s = requests.Session()
115 r = s.post(TestRecord[Id]['CallBack'], data = json.dumps(data),
116 headers = {'content-type': 'application/json'})
117 print " Response", r.status_code, r.text
119 def RunAnsible_Playbook (callback, Id, Inventory, Playbook, NodeList, TestRecord,
122 print "***> in RestServer.RunAnsible_Playbook"
124 # Run test in playbook for given target
127 retval, log, returncode = ansibleSysCall (Inventory, Playbook, NodeList,
128 TestRecord[Id]['Mandatory'],
129 TestRecord[Id]['EnvParameters'],
130 TestRecord[Id]['LocalParameters'],
131 TestRecord[Id]['LCM'],
132 TestRecord[Id]['Timeout'])
135 print " returncode:", returncode
136 print " retval: ", retval
140 Output = {'Output': {}}
142 onlyfiles = [f for f in listdir(Path)
143 if isfile(join(Path, f))]
145 for file in onlyfiles:
146 if "results.txt" in file:
147 f = open(Path + "/" + file, "r")
148 key = file.split("_")[0]
149 Output['Output'][key] = f.read()
152 Result = {'Results': {}}
153 if 'could not be found' in Log:
154 Result['Results'] = {"StatusCode": 101,
155 "StatusMessage": "PLAYBOOK NOT FOUND"}
156 if returncode == 137:
157 Result['Results'] = {"StatusCode": 500,
158 "StatusMessage": "TERMINATED"}
160 elif TestRecord[Id]['NodeList'] == []:
164 if 'TargetNode' in TestRecord[Id]['EnvParameters']:
165 targetlist = TestRecord[Id]['EnvParameters']['TargetNode'].split(' ')
167 targetlist = ["localhost"]
170 for i in range (len(targetlist)):
171 if key in targetlist[i]:
174 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
175 int(retval[key][3]) == 0:
178 Result['Results'][targetlist[host_index]] = \
179 {"GroupName": 'na', "StatusCode": 200, \
180 "StatusMessage": "SUCCESS"}
182 Result['Results'][key] = \
183 {"GroupName": 'na', "StatusCode": 200, \
184 "StatusMessage": "SUCCESS"}
185 elif int(retval[key][2]) > 0:
187 Result['Results'][targetlist[host_index]] = \
188 {"GroupName": 'na', "StatusCode": 400, \
189 "StatusMessage": "NOT REACHABLE"}
191 Result['Results'][key] = \
192 {"GroupName": 'na', "StatusCode": 400, \
193 "StatusMessage": "NOT REACHABLE"}
194 elif int(retval[key][3]) > 0:
196 Result['Results'][targetlist[host_index]] = \
197 {"GroupName": 'na', "StatusCode": 400, \
198 "StatusMessage": "FAILURE"}
200 Result['Results'][key] = \
201 {"GroupName": 'na', "StatusCode": 400, \
202 "StatusMessage": "FAILURE"}
207 if len(TestRecord[Id]['HostNameList']) > 0:
210 for i in range (len(TestRecord[Id]['HostNameList'])):
211 if key in TestRecord[Id]['HostNameList'][i]:
214 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
215 int(retval[key][3]) == 0:
217 if len(host_index) > 0:
218 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
219 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
220 "StatusCode": 200, "StatusMessage": "SUCCESS"}
222 for i in range (1, len(host_index)):
223 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
224 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
226 Result['Results'][key] = \
228 "StatusCode": 200, "StatusMessage": "SUCCESS"}
230 elif int(retval[key][2]) > 0:
232 if len(host_index) > 0:
233 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
234 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
235 "StatusCode": 400, "StatusMessage": "NOT REACHABLE"}
237 for i in range (1, len(host_index)):
238 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
239 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
241 Result['Results'][key] = \
243 "StatusCode": 200, "StatusMessage": "NOT REACHABLE"}
245 elif int(retval[key][3]) > 0:
247 if len(host_index) > 0:
248 Result['Results'][TestRecord[Id]['HostNameList'][host_index[0]]] = \
249 {"GroupName": TestRecord[Id]['HostGroupList'][host_index[0]],
250 "StatusCode": 400, "StatusMessage": "FAILURE"}
252 for i in range (1, len(host_index)):
253 Result['Results'][TestRecord[Id]['HostNameList'][host_index[i]]]["GroupName"]+=\
254 "," + TestRecord[Id]['HostGroupList'][host_index[i]]
256 Result['Results'][key] = \
258 "StatusCode": 200, "StatusMessage": "FAILURE"}
261 for i in range (len(TestRecord[Id]['NodeList'])):
262 if key in TestRecord[Id]['NodeList'][i]:
265 if int(retval[key][0]) > 0 and int(retval[key][2]) == 0 and \
266 int(retval[key][3]) == 0:
267 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
268 {"GroupName": 'na', "StatusCode": 200, \
269 "StatusMessage": "SUCCESS"}
270 elif int(retval[key][2]) > 0:
271 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
272 {"GroupName": 'na', "StatusCode": 400, "StatusMessage": "NOT REACHABLE"}
273 elif int(retval[key][3]) > 0:
274 Result['Results'][TestRecord[Id]['NodeList'][host_index]] = \
275 {"GroupName": 'na', "StatusCode": 400, "StatusMessage": "FAILURE"}
277 callback (Id, Result, Output, Log, returncode)
279 class TestManager (object):
282 @cherrypy.tools.json_out()
283 @cherrypy.tools.json_in()
284 @cherrypy.tools.allow(methods=['POST', 'GET', 'DELETE'])
286 def Dispatch(self, **kwargs):
288 # Let cherrypy error handler deal with malformed requests
289 # No need for explicit error handler, we use default ones
291 time_now = datetime.datetime.utcnow()
293 # Erase old test results (2x timeout)
295 for key in TestRecord.copy():
296 delta_time = (time_now - TestRecord[key]['Time']).seconds
297 if delta_time > 2*TestRecord[key]['Timeout']:
298 print "Deleted history for test", key
299 if os.path.exists(TestRecord[key]['Path']):
300 shutil.rmtree (TestRecord[key]['Path'])
303 print "***> in RestServer.Dispatch:", cherrypy.request.method
305 HomeDir = os.path.dirname(os.path.realpath("~/"))
307 if 'POST' in cherrypy.request.method:
309 input_json = cherrypy.request.json
310 print " Payload: ", input_json
312 if 'Id' in input_json and 'PlaybookName' in input_json:
316 if not input_json['Id'] in TestRecord:
318 Id = input_json['Id']
319 PlaybookName = input_json['PlaybookName']
322 if 'Version' in input_json:
323 version = input_json['Version']
325 AnsibleInvFail = True
326 AnsiblePlaybookFail = True
333 str_uuid = str (uuid.uuid4())
335 LCM = PlaybookName.split(".")[0].split('_')[-1]
336 PlaybookDir = HomeDir + "/" + ansible_temp + "/" + \
337 PlaybookName.split(".")[0] + "_" + str_uuid
338 AnsibleInv = LCM + "_" + "inventory"
342 print " PlaybookDir: ", ansible_temp + PlaybookDir.split(ansible_temp)[1]
343 print " AnsibleInv: ", AnsibleInv
344 print " ansible_temp: ", ansible_temp
346 if not os.path.exists(HomeDir + "/" + ansible_temp):
347 os.makedirs(HomeDir + "/" + ansible_temp)
349 os.mkdir(PlaybookDir)
351 # Process inventory file for target
357 if 'NodeList' in input_json:
358 NodeList = input_json['NodeList']
360 print " NodeList: ", NodeList
363 # By default set to local host
364 AnsibleInvFail = False
366 LocalNodeList = "host"
367 LocalCredentials = "localhost ansible_connection=local"
368 f = open(PlaybookDir + "/" + AnsibleInv, "w")
369 f.write("[" + LocalNodeList + "]\n")
370 f.write(LocalCredentials)
377 # Get credentials from file
379 data_inventory_orig = {}
380 data_inventory_target = {}
383 print "***>", ansible_path + "/" + ansible_inv
384 f = open(ansible_path + "/" + ansible_inv, "r")
390 if "[" in line and "]" in line:
391 data_inventory_orig[line] = []
394 data_inventory_orig[curr_group].append(line)
397 for node in NodeList:
399 if "[" + node + "]" in data_inventory_orig:
400 if not "[" + node + "]" in data_inventory_target:
402 print "RESET", "[" + node + "]"
403 data_inventory_target["[" + node + "]"] = []
405 print "OK", "[" + node + "]"
407 for cred in data_inventory_orig["[" + node + "]"]:
408 data_inventory_target["[" + node + "]"].append(cred)
411 for key in data_inventory_orig:
412 if node in " ".join(data_inventory_orig[key]):
413 if not key in data_inventory_target:
414 data_inventory_target[key] = []
415 for cred in data_inventory_orig[key]:
417 data_inventory_target[key].append(cred)
421 data_inventory_target["["+node+"]"] = \
422 [node + " ansible_connection=ssh ansible_ssh_user=na ansible_ssh_private_key_file=na"]
424 AnsibleInvFail = False
426 f = open(PlaybookDir + "/" + AnsibleInv, "w")
427 for key in data_inventory_target:
429 for rec in data_inventory_target[key]:
430 hostgrouplist.append(key.replace("[", '').replace("]", ''))
431 hostnamelist.append(rec.split(' ')[0])
437 # Get credentials from mySQL
439 sqlintf = AnsibleSql.mySql (host, user, passwd,
443 errorCode, diag = readCredentials (sqlintf,
446 print errorCode, diag
448 f = open(PlaybookDir + "/" + AnsibleInv,
450 AnsibleInvFail = False
451 # [hostgroup, hostname, credentials]
452 for i in range(len(diag)):
453 f.write('[' + diag[i][0] + ']' + "\n")
454 f.write(diag[i][1]+ " " + diag[i][2] + "\n\n")
455 hostgrouplist.append(diag[i][0])
456 hostnamelist.append(diag[i][1])
459 MySqlConFailCause = sqlintf.error
462 timeout = timeout_seconds
463 if 'Timeout' in input_json:
464 timeout = int (input_json['Timeout'])
467 if 'EnvParameters' in input_json:
468 EnvParam = input_json['EnvParameters']
471 if 'LocalParameters' in input_json:
472 LocalParam = input_json['LocalParameters']
475 if 'FileParameters' in input_json:
476 FileParam = input_json['FileParameters']
479 if 'CallBack' in input_json:
480 callback_flag = input_json['CallBack']
482 TestRecord[Id] = {'PlaybookName': PlaybookName,
485 'NodeList': NodeList,
486 'HostGroupList': hostgrouplist,
487 'HostNameList': hostnamelist,
491 'EnvParameters': EnvParam,
492 'LocalParameters': LocalParam,
493 'FileParameters': FileParam,
494 'CallBack': callback_flag,
495 'Result': {"StatusCode": 100,
496 "StatusMessage": 'PENDING',
497 "ExpectedDuration": str(timeout) + "sec"},
505 if not TestRecord[Id]['FileParameters'] == {}:
506 for key in TestRecord[Id]['FileParameters']:
508 filecontent = TestRecord[Id]['FileParameters'][key]
509 f = open(PlaybookDir + "/" + filename, "w")
518 # Get playbooks from files
523 target_PlaybookName = None
525 if '@' in PlaybookName:
526 version = PlaybookName.split("@")[1]
527 version = version.replace('.yml','')
528 version = version.replace('.tar.gz','')
530 onlyfiles = [f for f in listdir(ansible_path)
531 if isfile(join(ansible_path, f))]
536 for file in onlyfiles:
538 temp_version = file.split("@")[1]
539 temp_version = temp_version.replace('.yml','')
540 temp_version = temp_version.replace('.tar.gz','')
541 if version_max < temp_version:
542 version_max = temp_version
544 if not version == None:
545 if version in PlaybookName:
546 version_target = version
547 target_PlaybookName = file
549 if target_PlaybookName == None:
550 for file in onlyfiles:
551 if LCM in file and version_max in file:
552 target_PlaybookName = file
553 version_target = version_max
555 if target_PlaybookName:
556 AnsiblePlaybookFail = False
557 readversion = version_target
558 src = ansible_path + "/" + target_PlaybookName
559 if ".tar.gz" in target_PlaybookName:
560 dest = PlaybookDir + "/" + LCM + ".tar.gz"
561 shutil.copy2(src, dest)
562 retcode = subprocess.call(['tar', '-xvzf',
563 dest, "-C", PlaybookDir])
566 dest = PlaybookDir + "/" + LCM + ".yml"
567 shutil.copy2(src, dest)
570 # Get playbooks from mySQL
572 sqlintf = AnsibleSql.mySql (host, user, passwd, db)
576 name, readversion, AnsiblePlaybookFail, diag = \
577 readPlaybook (sqlintf, PlaybookName.split(".")[0],
580 if not AnsiblePlaybookFail:
582 f = open(PlaybookDir + "/" + LCM + diag[1], "w")
586 if ".tar.gz" in diag[1]:
587 retcode = subprocess.call(['tar', '-xvzf',
588 PlaybookDir + "/" + LCM + diag[1], "-C", PlaybookDir])
592 MySqlConFailCause = sqlintf.error
596 if os.path.exists(PlaybookDir):
597 shutil.rmtree (PlaybookDir)
599 return {"StatusCode": 101,
600 "StatusMessage": "CANNOT CONNECT TO MYSQL: " \
602 elif AnsiblePlaybookFail:
603 if os.path.exists(PlaybookDir):
604 shutil.rmtree (PlaybookDir)
606 return {"StatusCode": 101,
607 "StatusMessage": "PLAYBOOK NOT FOUND"}
609 if os.path.exists(PlaybookDir):
610 shutil.rmtree (PlaybookDir)
612 return {"StatusCode": 101,
613 "StatusMessage": "NODE LIST CREDENTIALS NOT FOUND"}
619 for dName, sdName, fList in os.walk(PlaybookDir):
620 if LCM+".yml" in fList:
621 playbook_path = dName
623 playbook_path = PlaybookDir
626 if not os.path.exists(playbook_path + "/vars"):
627 os.mkdir(playbook_path + "/vars")
628 if not os.path.isfile(playbook_path + "/vars/defaults.yml"):
629 os.mknod(playbook_path + "/vars/defaults.yml")
631 for key in TestRecord[Id]['LocalParameters']:
633 for i in range(len(TestRecord[Id]['HostNameList'])):
634 if key in TestRecord[Id]['HostNameList'][i]:
636 if len(host_index) == 0:
637 for i in range(len(TestRecord[Id]['HostGroupList'])):
638 if key in TestRecord[Id]['HostGroupList'][i]:
640 if len(host_index) > 0:
641 for i in range(len(host_index)):
642 f = open(playbook_path + "/vars/" +
643 TestRecord[Id]['HostNameList'][host_index[i]] +
645 for param in TestRecord[Id]['LocalParameters'][key]:
646 f.write(param + ": " +
647 str (TestRecord[Id]['LocalParameters'][key][param]) +
651 # Get mandatory parameters from playbook
653 with open(playbook_path + "/" + LCM + ".yml") as origin_file:
654 for line in origin_file:
655 if "Mandatory" in line:
656 temp = line.split(":")[1].strip().replace(' ', '')
658 Mandatory = temp.split(",")
660 TestRecord[Id] = {'PlaybookName': TestRecord[Id]['PlaybookName'],
661 'LCM': TestRecord[Id]['LCM'],
662 'Version': readversion,
663 'NodeList': TestRecord[Id]['NodeList'],
664 'HostGroupList': TestRecord[Id]['HostGroupList'],
665 'HostNameList': TestRecord[Id]['HostNameList'],
666 'Time': TestRecord[Id]['Time'],
667 'Timeout': TestRecord[Id]['Timeout'],
668 'Duration': TestRecord[Id]['Duration'],
669 'EnvParameters': TestRecord[Id]['EnvParameters'],
670 'LocalParameters': TestRecord[Id]['LocalParameters'],
671 'FileParameters': TestRecord[Id]['FileParameters'],
672 'CallBack': TestRecord[Id]['CallBack'],
673 'Result': TestRecord[Id]['Result'],
674 'Log': TestRecord[Id]['Log'],
675 'Output': TestRecord[Id]['Output'],
676 'Path': TestRecord[Id]['Path'],
677 'Mandatory': Mandatory}
682 for val in Mandatory:
688 for key in TestRecord[Id]['NodeList']:
689 if key in LocalParam:
690 if val in LocalParam[key]:
694 for key in TestRecord[Id]['NodeList']:
695 if key in LocalParam:
696 if val in LocalParam[key]:
700 if os.path.exists(PlaybookDir):
701 shutil.rmtree (PlaybookDir)
703 return {"StatusCode": 101,
704 "StatusMessage": "MISSING MANDATORY PARAMETER: " + \
705 " ".join(str(x) for x in Mandatory)}
708 # Cannot use thread because ansible module uses
709 # signals which are only supported in main thread.
710 # So use multiprocess with shared object
712 p = Process(target = RunAnsible_Playbook,
713 args = (callback, Id, PlaybookDir + "/" + AnsibleInv,
714 playbook_path + "/" + LCM + ".yml",
715 NodeList, TestRecord, PlaybookDir,
718 ActiveProcess[Id] = p
719 return TestRecord[Id]['Result']
721 return {"StatusCode": 101, "StatusMessage": "TEST ID ALREADY DEFINED"}
724 return {"StatusCode": 500, "StatusMessage": "REQUEST MUST INCLUDE: NODELIST"}
727 return {"StatusCode": 500, "StatusMessage": "JSON OBJECT MUST INCLUDE: ID, PLAYBOOKNAME"}
729 elif 'GET' in cherrypy.request.method:
731 input_data = parse_query_string(cherrypy.request.query_string)
733 print "***> in RestServer.GET"
734 print " Payload: ", input_data, input_data['Type']
736 if 'Id' in input_data and 'Type' in input_data:
737 if not ('GetResult' in input_data['Type'] or 'GetOutput' in input_data['Type'] or 'GetLog' in input_data['Type']):
738 return {"StatusCode": 500, "StatusMessage": "RESULTS TYPE UNDEFINED"}
739 if input_data['Id'] in TestRecord:
741 if 'GetResult' in input_data['Type']:
743 print "Result:", TestRecord[input_data['Id']]['Result']
745 if 'StatusMessage' in TestRecord[input_data['Id']]['Result'] and getresults_block:
747 print "*** Request blocked", input_data['Id']
749 while ActiveProcess[input_data['Id']].is_alive():
752 print "*** Request released ", input_data['Id']
754 print TestRecord[input_data['Id']]['Result']
755 if TestRecord[input_data['Id']]['Result']['StatusCode'] == 500:
756 out_obj = TestRecord[input_data['Id']]['Result']['Results']
758 out_obj = {"StatusCode": 200,
759 "StatusMessage": "FINISHED",
760 "PlaybookName": TestRecord[input_data['Id']]["PlaybookName"],
761 "Version": TestRecord[input_data['Id']]["Version"],
762 "Duration": TestRecord[input_data['Id']]["Duration"],
763 "Results": TestRecord[input_data['Id']]['Result']['Results']}
764 if not TestRecord[input_data['Id']]['Output']['Output'] == {}:
765 for key in out_obj["Results"]:
766 if key in TestRecord[input_data['Id']]['Output']['Output']:
767 out_obj["Results"][key]["Output"] = TestRecord[input_data['Id']]['Output']['Output'][key]
771 elif 'GetOutput' in input_data['Type']:
773 if TestRecord[input_data['Id']]['Output'] == {} and \
776 print "*** Request blocked", input_data['Id']
778 while TestRecord[input_data['Id']]['Output'] == {} \
779 or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
782 print "*** Request released ", input_data['Id']
784 print "Output:", TestRecord[input_data['Id']]['Output']
785 return {"Output": TestRecord[input_data['Id']]['Output']['Output']}
789 if TestRecord[input_data['Id']]['Log'] == '' and \
792 print "*** Request blocked", input_data['Id']
794 while TestRecord[input_data['Id']]['Log'] == '' \
795 or 'StatusMessage' in TestRecord[input_data['Id']]['Result']:
798 print "*** Request released ", input_data['Id']
800 print "Log:", TestRecord[input_data['Id']]['Log']
801 return {"Log": TestRecord[input_data['Id']]['Log']}
803 return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
805 return {"StatusCode": 500, "StatusMessage": "MALFORMED REQUEST"}
806 elif 'DELETE' in cherrypy.request.method:
807 input_data = parse_query_string(cherrypy.request.query_string)
809 print "***> in RestServer.DELETE"
810 print " Payload: ", input_data
812 if input_data['Id'] in TestRecord:
813 if not 'PENDING' in TestRecord[input_data['Id']]['Result']:
814 print " Path:", TestRecord[input_data['Id']]['Path']
815 if os.path.exists(TestRecord[input_data['Id']]['Path']):
816 shutil.rmtree (TestRecord[input_data['Id']]['Path'])
817 TestRecord.pop (input_data['Id'])
818 if input_data['Id'] in ActiveProcess:
819 ActiveProcess.pop (input_data['Id'])
821 return {"StatusCode": 200, "StatusMessage": "PLAYBOOK EXECUTION RECORDS DELETED"}
823 return {"StatusCode": 200, "StatusMessage": "PENDING"}
825 return {"StatusCode": 500, "StatusMessage": "TEST ID UNDEFINED"}
828 if __name__ == '__main__':
832 config_file_path = "RestServer_config"
834 if not os.path.exists(config_file_path):
835 print '[INFO] The config file does not exist'
846 timeout_seconds = 'na'
854 getresults_block = False
857 file = open(config_file_path, 'r')
858 for line in file.readlines():
861 ip = line.split(':')[1].strip()
862 elif 'port:' in line:
863 port = line.split(':')[1].strip()
865 tls = 'YES' in line.split(':')[1].strip().upper()
866 elif 'auth:' in line:
867 auth = 'YES' in line.split(':')[1].strip().upper()
868 if tls and 'priv:' in line:
869 priv = line.split(':')[1].strip()
870 if tls and 'pub:' in line:
871 pub = line.split(':')[1].strip()
872 if auth and 'id:' in line:
873 id = line.split(':')[1].strip()
874 if auth and 'psswd:' in line:
875 psswd = line.split(':')[1].strip()
876 if 'timeout_seconds' in line:
877 timeout_seconds = int (line.split(':')[1].strip())
878 if 'ansible_path' in line:
879 ansible_path = line.split(':')[1].strip()
880 if 'ansible_inv' in line:
881 ansible_inv = line.split(':')[1].strip()
882 if not os.path.exists(ansible_path + "/" + ansible_inv):
883 print '[INFO] The ansible_inv file does not exist'
885 if 'ansible_temp' in line:
886 ansible_temp = line.split(':')[1].strip()
888 host = line.split(':')[1].strip()
890 user = line.split(':')[1].strip()
892 passwd = line.split(':')[1].strip()
894 db = line.split(':')[1].strip()
895 if 'getresults_block' in line:
896 getresults_block = 'YES' in line.split(':')[1].strip().upper()
897 if 'from_files' in line:
898 from_files = 'YES' in line.split(':')[1].strip().upper()
905 'server.socket_host': ip,
906 'server.socket_port': int(port),
907 'server.protocol_version': 'HTTP/1.1'
912 # Use pythons built-in SSL
913 cherrypy.server.ssl_module = 'builtin'
915 # Point to certificate files
917 if not os.path.exists(pub):
918 print '[INFO] The public certificate does not exist'
921 if not os.path.exists(priv):
922 print '[INFO] The private key does not exist'
925 cherrypy.server.ssl_certificate = pub
926 cherrypy.server.ssl_private_key = priv
929 userpassdict = {id: psswd}
930 checkpassword = cherrypy.lib.auth_basic.checkpassword_dict(userpassdict)
933 {'tools.auth_basic.on': True,
934 'tools.auth_basic.realm': 'earth',
935 'tools.auth_basic.checkpassword': checkpassword,
939 cherrypy.tree.mount(TestManager(), '/', app_conf)
941 cherrypy.tree.mount(TestManager(), '/')
943 cherrypy.config.update(global_conf)
947 cherrypy.engine.start()
948 cherrypy.engine.block()