From 099cc94d485fb7634351dcb813b12ca08ff772f9 Mon Sep 17 00:00:00 2001 From: Matthias Lee Date: Sun, 12 Jun 2011 01:23:41 -0400 Subject: [PATCH] working on minitor feature --- #manage-cluster.py# | 260 ++++++++++++++++++++++++++++++++++++++++++++ .CLnode.py.marks | 1 + CLnode.py | 12 +- CLnode.pyc | Bin 3281 -> 3552 bytes CLnode.py~ | 51 ++++++++- bundle.tar | Bin 0 -> 20480 bytes manage-cluster.py | 61 ++++++++++- manage-cluster.py~ | 61 ++++++++++- payload/GF.py | 50 +++++++++ payload/runconfig | Bin 80 -> 10240 bytes payload/setup.py | 14 +++ payload/start.py | 0 12 files changed, 497 insertions(+), 13 deletions(-) create mode 100644 #manage-cluster.py# create mode 100644 .CLnode.py.marks create mode 100644 bundle.tar create mode 100644 payload/GF.py create mode 100644 payload/setup.py create mode 100644 payload/start.py diff --git a/#manage-cluster.py# b/#manage-cluster.py# new file mode 100644 index 0000000..30557e8 --- /dev/null +++ b/#manage-cluster.py# @@ -0,0 +1,260 @@ +#!/usr/bin/python + +import os +import sys +import time +import CLnode +import GF + + +def curSpotCost(inst_size): + lt = time.localtime(time.time()) + curdate = str(lt[0])+"-"+str(lt[1])+"-"+str(lt[2])+"T"+str(lt[3])+":"+str(lt[4])+":"+str(lt[5])+":"+str(lt[6])+"-0000" + try: + res = GF.run("ec2-describe-spot-price-history -d Linux/UNIX --region us-east-1 --instance-type "+inst_size+" -s "+curdate) + if res.find("timeout")>=0: + print "TIMEOUT: ", res + return -1 + cost=0 + for i in res.split("\n"): + cost += float((i.split("\t"))[1]); + cost = cost/len(res.split("\n")) + except Exception as x: + print x, "\n", res + return -1 + GF.log("Current Instance Cost: "+str(cost), 1); + return cost + +def startNodes(ami, inst_size, keyName, maxPrice, nodecnt): + GF.log("... starting " + str(nodecnt) + " node(s)", 1); + try: + #res = GF.run("ec2-request-spot-instances " + ami + " -p " + maxPrice) + + res = GF.run("ec2-request-spot-instances " + ami + " -p " + str(maxPrice) + " -instance-type " + inst_size + " -n " + str(nodecnt) + " --type one-time" + " --key " + keyName) + if res.find("timeout")>=0: + print "TIMEOUT: ", res + return -1 + if res.find("InvalidAMIID")>=0: + print "INVALID AMI ID: ", res + return -1 + print res + except Exception as x: + print x, "\n", res + return -1 + +def launchCluster(ami, inst_size, keyName, maxPrice, nodes): + GF.log("Maximum Price: "+str(maxPrice), 1); + curPrice=curSpotCost(inst_size) + if curPrice == -1: + print "Error: Failed to get current spot price." + sys.exit(-1) + if curPrice > maxPrice: + print "Error: Current spot price too high." + sys.exit(-2) + GF.log("Launching "+str(nodes)+" nodes.", 1); + #for n in range (0,nodes): + startNodes(ami, inst_size, keyName, maxPrice, nodes) + +def getRunningInstances(): + nodes = [] + try: + res = GF.run("ec2-describe-instances") + if res.find("timeout")>=0: + print "TIMEOUT: ", res + return -1 + for line in res.split("\n"): + if line.find("INSTANCE")>=0: + inst=line.split("\t") + nodes.append(CLnode.CLnode(inst[1],inst[1],inst[5],inst[2],inst[6],inst[9],inst[10],inst[0],inst[3])) + except Exception as x: + print x, "\n", res + return -1 + GF.addNewNodes(nodes) + + #ec2-describe-spot-instance-requests +def getSpotRequests(): + try: + res = GF.run("ec2-describe-spot-instance-requests") + if res.find("timeout")>=0: + print "TIMEOUT: ", res + return -1 + for line in res.split("\n"): + if line.find("INSTANCE")>=0: + inst=line.split("\t") + GF.reqests.append(CLnode.CLnode(inst[1],inst[1],inst[5],'','','',inst[6],inst[0])) + except Exception as x: + print x, "\n", res + return -1 + +def buildBundle(payload, payloadDir): + try: + #RM old bundle + res=GF.run("rm "+payload) + GF.log("rm "+payload,1) + #make new bundle + res=GF.run("tar cvf "+payload+' '+payloadDir+"/*") + GF.log("tar cvf "+payload+' '+payloadDir+"/*",1) + except Exception as x: + print x, "\n", res + sys.exit() + +def monitor(n, timeout): + allStarted=True + + for i in range(0,n): + allStarted=True + getSpotRequests() + #getRunningInstances() + for n in GF.requests: + if n.status=="open": + allStarted=False + if + if allStarted is True: + break + time.sleep(timeout) + if allStarted is False: + print "All instances did not start during designated time." + if GF.confirmQuestion("Would you like to continue?") is True: + monitor(n, timeout) + else: + sys.exit() + else: + for i in range(0,n): + allStarted=True + getRunningInstances() + for n in GF.nodes: + if n.status=="pending": + allStarted=False + if allStarted is True: + break + if allStarted is False: + print "All instances did not start during designated time." + if GF.confirmQuestion("Would you like to continue?") is True: + monitor(n, timeout) + else: + sys.exit() + else: + #launch?! + + + +if __name__ == "__main__": + ami="ami-06ad526f" + size="t1.micro" + key="id_rsa" + maxPrice=.01 + sshKey='/home/madmaze/.ec2/pkey' + rebuildBundle=True + payload='./bundle.tar' + payloadDir='./payload' + print "Cluster manager v0.1"; + argc=0 + for arg in sys.argv[1:]: + argc+=1 + if arg == "-debug": + GF.logLevel=2 + if arg == "-info": + GF.logLevel=1 + if arg == "-list" or arg == "-l": + getRunningInstances() + cnt=0 + for node in GF.nodes: + if node.running() is True: + cnt+=1 + node.desc() + GF.log("There are a totoal of "+str(cnt)+" instances running.",0) + sys.exit() + if arg == "-listblock" or arg == "-lb": + getRunningInstances() + cnt=0 + for node in GF.nodes: + if node.running() is True: + cnt+=1 + node.desc_detail() + GF.log("There are a totoal of "+str(cnt)+" instances running.",0) + sys.exit() + if arg == "-listspots" or arg == "-ls": + getSpotRequests() + runcnt=0 + ocnt=0 + for node in GF.reqests: + if node.status == "active": + runcnt+=1 + if node.status == "open": + ocnt+=1 + node.desc() + GF.log("There are a totoal of "+str(runcnt)+" active and "+str(ocnt)+" waiting to launch",0) + sys.exit() + if arg == "-launch" and len(sys.argv) >= argc+2: + try: + n=int(sys.argv[argc+1]) + if n > 0: + if GF.confirmQuestion("This will create "+str(n)+" instance(s). \nAre you sure you want to continue?") is False: + sys.exit() + print "Launching "+str(n)+" instances" + launchCluster(ami, size, key, maxPrice, n) + else: + print "Please specify positive number" + + except Exception as x: + print "Please specify number after -launch" + print x, sys.argv[argc+1] + sys.exit() + if arg == "-shutdown" or arg == "-killall": + # ask user for confirm + if GF.confirmQuestion("!!This will TERMINATE all running instances!! \nAre you sure you want to continue?") is False: + sys.exit() + getRunningInstances() + if len(GF.nodes)==0: + print "There are currently no nodes to kill" + for n in GF.nodes: + n.kill() + if arg == "-kill": + # ask user for confirm + foundinst=False + getRunningInstances() + if len(sys.argv) >= argc+2: + var=sys.argv[argc+1].strip() + else: + var = raw_input("Which host would you like to deploy?: ").strip() + + for n in GF.nodes: + if n.instName==var: + foundinst=True + if foundinst is False: + print "There is currently no running instance by the ID: "+var + else: + if GF.confirmQuestion("!!This will kill the instance: "+var+"!\nAre you sure you want to continue?") is False: + sys.exit() + for n in GF.nodes: + if n.instName==var: + n.kill() + if arg == "-deploy": + # ask user for confirm + foundinst=False + getRunningInstances() + if len(sys.argv) >= argc+2: + var=sys.argv[argc+1].strip() + else: + var = raw_input("Which host would you like to deploy?: ").strip() + + for n in GF.nodes: + if n.instName==var and n.status=='running': + foundinst=True + if foundinst is False: + print "There is currently no running instance by the ID: "+var + else: + if GF.confirmQuestion("!!This will deploy on the instance: "+var+"!\nAre you sure you want to continue?") is False: + sys.exit() + if rebuildBundle is True: + print "Building Bundle..." + buildBundle(payload, payloadDir) + for n in GF.nodes: + if n.instName==var: + n.deploy(payload,sshKey,True) + if arg == "-monitor": + monitor(10,10) + + #ec2-describe-images -a | grep ami-06ad526f + #getRunningInstances() + #launchCluster("ami-06ad526f", "t1.micro", "id_rsa", .01, 10) diff --git a/.CLnode.py.marks b/.CLnode.py.marks new file mode 100644 index 0000000..431585b --- /dev/null +++ b/.CLnode.py.marks @@ -0,0 +1 @@ +!~;1872;1872 diff --git a/CLnode.py b/CLnode.py index 1f73121..ed6e3d6 100644 --- a/CLnode.py +++ b/CLnode.py @@ -64,17 +64,20 @@ def running(self): def copy(self): return CLnode(self.instID,self.instName,self.status,self.ami,self.key,self.size,self.date,self.ntype,self.url) - def deploy(self,payload,launch=False): + + def deploy(self,payload,sshKey,launch=False): # COPY payload try: - res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + res=GF.run("scp -i "+sshKey+" "+payload+" ubuntu@"+self.url+":~/") + print "scp -i "+sshKey+" "+payload+" ubuntu@"+self.url+":~/" except Exception as x: print x, "\n", res return -1 # EXTRACT payload try: - res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + res=GF.run("ssh -i "+sshKey+" ubuntu@"+self.url+" 'tar xvf ~/bundle.tar;'") + print "ssh -i "+sshKey+" ubuntu@"+self.url+" 'tar xvf ~/bundle.tar;'" except Exception as x: print x, "\n", res return -1 @@ -82,7 +85,8 @@ def deploy(self,payload,launch=False): if launch is True: # LAUNCH Payload try: - res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + res=GF.run("ssh -i "+sshKey+" ubuntu@"+self.url+" 'python ~/payload/setup.py'") + print "ssh -i "+sshKey+" ubuntu@"+self.url+" 'python ~/payload/setup.py'" except Exception as x: print x, "\n", res return -1 diff --git a/CLnode.pyc b/CLnode.pyc index ffa54d977e72f75d800d336aff058891d491e742..cfec76302cf719dd45d388cd252550a1bf6b7a94 100644 GIT binary patch delta 873 zcmah|O-~d-5UrY?kKNft2#Fv8<4DZzh6MJ&NkP#dSwQ5#9`L%@V;0!V4AZ^pBm;Z! z!hI5df)`JQD>wdt#sgRW0U>hNYBvMQOmvc}uB!LCUb?6H+t}H-#eNLflatdf5`v4V!@~D$hHziVqn1R$`w*cW1Ua9qXwx#_KIl@S8 zZwb>AJ;NI(O65EN4$!QX=u+2(rLOjM;7o5jk}en=QB>aPb+@{n>^>EY(nkk%p+I~4 zCw=`rqOJCbf?}uKJ1VKlR_MHc`^Gt_Qw!d4XQ(h&6%)U~Ad+q0BP?h|9lyov!j;`% zCWxvv^`|#(DK`i(3>&rzhm;#3S2L4id(0G~{lblsueQ^lo7F$2x4yXM`P`*uQcVtb zgN`3Pr$|)DfyQtOAK)MkpureU;zU2z%7jpsY?j{LzDvZKVqZIvc_ztF`604owLF_M Iyr0XJU)%u4X#fBK delta 615 zcmaJ;Jx{_w7=Eu;ECLl15{Y53E`*qr@}VRc6HOR!FeXBxtc5lKp&!sTq^8K=;@=>8;*9as8cL)X; zuGC$iO$yo}=oJ7BXh04PWr>2agQ0vXVW`&rFH=^P5&de-p}@q@4nl9dO1e8fS>dI>)!TTOmz8P|(}5%?V9Skp)GR6!Au$`-igtXVop$v`$DS ze~{s`MZS>Z3z>97Q*_Ie`D|JwC7LSs4bOK-ni@t^Fc8rRwSLH&30F1t06sDB*V5m~XsswumVAg3bGUFKqG`h+>eB diff --git a/CLnode.py~ b/CLnode.py~ index 906ab13..1f73121 100644 --- a/CLnode.py~ +++ b/CLnode.py~ @@ -10,8 +10,10 @@ class CLnode: key='' size='' date='' + ntype='' + url='' - def __init__(self, instID='',instName='',status='',ami='',key='',size='',date=''): + def __init__(self, instID='',instName='',status='',ami='',key='',size='',date='',ntype='',url=''): self.instID=instID self.instName=instName self.status=status @@ -19,6 +21,8 @@ class CLnode: self.key=key self.size=size self.date=date + self.ntype=ntype + self.url=url def kill(self): if self.status!="running": @@ -33,8 +37,25 @@ class CLnode: return -1 def desc(self): - print self.instID,self.instName,self.status,self.ami,self.key,self.size,self.date + print self.ntype,self.instID,self.instName,self.status,self.url,self.ami,self.key,self.size,self.date + + def desc_detail(self): + print "Instance Type:\t\t"+self.ntype + print "Instance ID:\t\t"+self.instID + print "Instance Name:\t\t"+self.instName + print "Status:\t\t\t"+self.status + print "Hostname/url:\t"+self.url + print "AMI:\t\t\t"+self.ami + print "Keypair:\t\t"+self.key + print "Instance Size:\t\t"+self.size + print "Date/Time started:\t"+self.date + print "====" + + + def status(self): + return self.status + def running(self): if self.status=="running": return True @@ -42,4 +63,28 @@ class CLnode: return False def copy(self): - return CLnode(self.instID,self.instName,self.status,self.ami,self.key,self.size,self.date) + return CLnode(self.instID,self.instName,self.status,self.ami,self.key,self.size,self.date,self.ntype,self.url) + def deploy(self,payload,launch=False): + # COPY payload + try: + res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + except Exception as x: + print x, "\n", res + return -1 + + # EXTRACT payload + try: + res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + except Exception as x: + print x, "\n", res + return -1 + + if launch is True: + # LAUNCH Payload + try: + res=GF.run("scp -i ~/.ec2/pkey /home/madmaze/.ec2/pkey ubuntu@ec2-50-19-62-60.compute-1.amazonaws.com:~/.ssh/") + except Exception as x: + print x, "\n", res + return -1 + + diff --git a/bundle.tar b/bundle.tar new file mode 100644 index 0000000000000000000000000000000000000000..0b0b297c7e1c56afb8dca3c6bea4f506eecbac66 GIT binary patch literal 20480 zcmeI3QE!_t5XbWxKE;i_5Va#fNFsHjFIziJswz$ETUSjqIH@IKn1QC*!#?}YgwUu; z*M}zCy8Zp)v+sO9euo_%E^a@MmuVI!{ST*ZzU=IydE7=}*x}9}553LasQf_?c6@)x zs$eh(h8>>a)*){n!94U?6=kf6I`cT0$KS<6bvu4a-x|IwLC*6`my{J&BNfY5EahCR zr{A5aED@IVdV8~8lSdJ$ObHf!7NweIECwtl;<}nyX*N3(w<3+aN1Rw@ha$SXvb6Xn zin121L`+Fn%9+fQ-jUUvMp@zJSuR#HR`ebqa%i2-oLwQ23gENr5@(3P-SI?d#1%(U3XdRZs%&qnLE_dg%9I=i!- z2V^e!$M63jWOZ}@`=ekq;QK!eJs^KZ2G`S-^olYeh8 zLjJd;Yv)sK{`o7Y{0s6Q`22my`42qgf9J`DLl6J~5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2Lze~Q3;{pbEF0H3P=3&z8?{y!Y?{{;Ln z@W!bB`W-LY*82ZF7u}b7$+g^?YyC}Ozg=e4b+hx1qoQ literal 0 HcmV?d00001 diff --git a/manage-cluster.py b/manage-cluster.py index c6a3a3d..a4ff2ac 100755 --- a/manage-cluster.py +++ b/manage-cluster.py @@ -85,13 +85,37 @@ def getSpotRequests(): except Exception as x: print x, "\n", res return -1 + +def buildBundle(payload, payloadDir): + try: + #RM old bundle + res=GF.run("rm "+payload) + GF.log("rm "+payload,1) + #make new bundle + res=GF.run("tar cvf "+payload+' '+payloadDir+"/*") + GF.log("tar cvf "+payload+' '+payloadDir+"/*",1) + except Exception as x: + print x, "\n", res + sys.exit() +def monitor(n, timeout): + for i in range(0,n): + getSpotRequests() + getRunningInstances() + time.sleep(timeout) + for n in GF.nodes: + n.desc() + if __name__ == "__main__": ami="ami-06ad526f" size="t1.micro" key="id_rsa" maxPrice=.01 + sshKey='/home/madmaze/.ec2/pkey' + rebuildBundle=True + payload='./bundle.tar' + payloadDir='./payload' print "Cluster manager v0.1"; argc=0 for arg in sys.argv[1:]: @@ -123,9 +147,9 @@ def getSpotRequests(): runcnt=0 ocnt=0 for node in GF.reqests: - if node.statys() == "active": + if node.status == "active": runcnt+=1 - if node.statys() == "open": + if node.status == "open": ocnt+=1 node.desc() GF.log("There are a totoal of "+str(runcnt)+" active and "+str(ocnt)+" waiting to launch",0) @@ -158,18 +182,47 @@ def getSpotRequests(): # ask user for confirm foundinst=False getRunningInstances() - var = raw_input("Which host would you like to kill?: ") + if len(sys.argv) >= argc+2: + var=sys.argv[argc+1].strip() + else: + var = raw_input("Which host would you like to deploy?: ").strip() + for n in GF.nodes: if n.instName==var: foundinst=True if foundinst is False: - print "There is currently no instance by the ID: "+var + print "There is currently no running instance by the ID: "+var else: if GF.confirmQuestion("!!This will kill the instance: "+var+"!\nAre you sure you want to continue?") is False: sys.exit() for n in GF.nodes: if n.instName==var: n.kill() + if arg == "-deploy": + # ask user for confirm + foundinst=False + getRunningInstances() + if len(sys.argv) >= argc+2: + var=sys.argv[argc+1].strip() + else: + var = raw_input("Which host would you like to deploy?: ").strip() + + for n in GF.nodes: + if n.instName==var and n.status=='running': + foundinst=True + if foundinst is False: + print "There is currently no running instance by the ID: "+var + else: + if GF.confirmQuestion("!!This will deploy on the instance: "+var+"!\nAre you sure you want to continue?") is False: + sys.exit() + if rebuildBundle is True: + print "Building Bundle..." + buildBundle(payload, payloadDir) + for n in GF.nodes: + if n.instName==var: + n.deploy(payload,sshKey,True) + if arg == "-monitor": + monitor(10,10) #ec2-describe-images -a | grep ami-06ad526f #getRunningInstances() diff --git a/manage-cluster.py~ b/manage-cluster.py~ index c9d13a0..c6a3a3d 100755 --- a/manage-cluster.py~ +++ b/manage-cluster.py~ @@ -65,12 +65,28 @@ def getRunningInstances(): for line in res.split("\n"): if line.find("INSTANCE")>=0: inst=line.split("\t") - nodes.append(CLnode.CLnode(inst[1],inst[1],inst[5],inst[2],inst[6],inst[9],inst[10])) + nodes.append(CLnode.CLnode(inst[1],inst[1],inst[5],inst[2],inst[6],inst[9],inst[10],inst[0],inst[3])) except Exception as x: print x, "\n", res return -1 GF.addNewNodes(nodes) + #ec2-describe-spot-instance-requests +def getSpotRequests(): + try: + res = GF.run("ec2-describe-spot-instance-requests") + if res.find("timeout")>=0: + print "TIMEOUT: ", res + return -1 + for line in res.split("\n"): + if line.find("INSTANCE")>=0: + inst=line.split("\t") + GF.reqests.append(CLnode.CLnode(inst[1],inst[1],inst[5],'','','',inst[6],inst[0])) + except Exception as x: + print x, "\n", res + return -1 + + if __name__ == "__main__": ami="ami-06ad526f" size="t1.micro" @@ -93,10 +109,33 @@ if __name__ == "__main__": node.desc() GF.log("There are a totoal of "+str(cnt)+" instances running.",0) sys.exit() + if arg == "-listblock" or arg == "-lb": + getRunningInstances() + cnt=0 + for node in GF.nodes: + if node.running() is True: + cnt+=1 + node.desc_detail() + GF.log("There are a totoal of "+str(cnt)+" instances running.",0) + sys.exit() + if arg == "-listspots" or arg == "-ls": + getSpotRequests() + runcnt=0 + ocnt=0 + for node in GF.reqests: + if node.statys() == "active": + runcnt+=1 + if node.statys() == "open": + ocnt+=1 + node.desc() + GF.log("There are a totoal of "+str(runcnt)+" active and "+str(ocnt)+" waiting to launch",0) + sys.exit() if arg == "-launch" and len(sys.argv) >= argc+2: try: n=int(sys.argv[argc+1]) if n > 0: + if GF.confirmQuestion("This will create "+str(n)+" instance(s). \nAre you sure you want to continue?") is False: + sys.exit() print "Launching "+str(n)+" instances" launchCluster(ami, size, key, maxPrice, n) else: @@ -106,13 +145,31 @@ if __name__ == "__main__": print "Please specify number after -launch" print x, sys.argv[argc+1] sys.exit() - if arg == "-shutdown" or arg == "-kill": + if arg == "-shutdown" or arg == "-killall": # ask user for confirm + if GF.confirmQuestion("!!This will TERMINATE all running instances!! \nAre you sure you want to continue?") is False: + sys.exit() getRunningInstances() if len(GF.nodes)==0: print "There are currently no nodes to kill" for n in GF.nodes: n.kill() + if arg == "-kill": + # ask user for confirm + foundinst=False + getRunningInstances() + var = raw_input("Which host would you like to kill?: ") + for n in GF.nodes: + if n.instName==var: + foundinst=True + if foundinst is False: + print "There is currently no instance by the ID: "+var + else: + if GF.confirmQuestion("!!This will kill the instance: "+var+"!\nAre you sure you want to continue?") is False: + sys.exit() + for n in GF.nodes: + if n.instName==var: + n.kill() #ec2-describe-images -a | grep ami-06ad526f #getRunningInstances() diff --git a/payload/GF.py b/payload/GF.py new file mode 100644 index 0000000..13aaed6 --- /dev/null +++ b/payload/GF.py @@ -0,0 +1,50 @@ +import os +import sys +import time +import CLnode + +####################### +# 0 = none +# 1 = info +# 2 = debug +logLevel=0 +###################### +nodes=[] +reqests=[] + +def run(cmd): + f=os.popen(cmd) + buf="" + for i in f.readlines(): + buf+=i + return buf.strip() + +def log(msg, lvl): + if logLevel >= lvl: + print msg + +def addNewNodes(new): + for n in new: + exists=instExists(n) + if exists>=0: + nodes[exists]=n.copy() + else: + nodes.append(n) + +def instExists(node): + cnt=0 + for n in nodes: + if n.instID==node.instID: + return cnt; + cnt+=1 + return -1 + +def confirmQuestion(Question): + var="" + while var != "y" and var != "n": + var = raw_input(Question + " (y/n):" ) + if var == "y": + return True + else: + return False + diff --git a/payload/runconfig b/payload/runconfig index 4a34a9004730ba61f5e91c4ce5615f114b3210ca..be8e0d13ffdafeccf67b16eb4e7c59172af84828 100644 GIT binary patch literal 10240 zcmeIw!3u*g494+1N}pg$oYv%l$!;-N6`u#;oLKbJtiQpzvMX}v$vaGl4p zQJo#CH)u009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** T5I_I{1Q0*~0R#|0;Ku@Qhu|>8 literal 80 zcmWN|I}U@ub!+>@0!)*jA5~U?jV!XYKZ+Q7=f;ANj`>bKvG-#Ms6|g+~g;cG% dIHT#VlXOM+mOD19JkyzC^JB`OV;16oR{b{x8