mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			214 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python
 | |
| #
 | |
| 
 | |
| #copyright 2012 Citrix Systems, Inc. Licensed under the 
 | |
| #Apache License, Version 2.0 (the "License"); you may not use this
 | |
| #file except in compliance with the License.  Citrix Systems, Inc.
 | |
| #reserves all rights not expressly granted by the License.
 | |
| #You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 | |
| #Unless required by applicable law or agreed to in writing, software
 | |
| #distributed under the License is distributed on an "AS IS" BASIS,
 | |
| #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| #See the License for the specific language governing permissions and 
 | |
| #limitations under the License.
 | |
| 
 | |
| import sys, os
 | |
| from subprocess import PIPE, Popen
 | |
| import logging
 | |
| import traceback
 | |
| from os.path import exists, join
 | |
| from signal import alarm, signal, SIGALRM, SIGKILL
 | |
| 
 | |
| class CloudRuntimeException(Exception):
 | |
|     def __init__(self, errMsg):
 | |
|         self.errMsg = errMsg
 | |
|     def __str__(self):
 | |
|         return self.errMsg
 | |
| def formatExceptionInfo(maxTBlevel=5):
 | |
|     cla, exc, trbk = sys.exc_info()
 | |
|     excTb = traceback.format_tb(trbk, maxTBlevel)
 | |
|     msg = str(exc) + "\n"
 | |
|     for tb in excTb:
 | |
|         msg += tb
 | |
|     return msg
 | |
| 
 | |
| class bash:
 | |
|     def __init__(self, args, timeout=600):
 | |
|         self.args = args
 | |
|         logging.debug("execute:%s"%args)
 | |
|         self.timeout = timeout
 | |
|         self.process = None
 | |
|         self.success = False
 | |
|         self.run()
 | |
| 
 | |
|     def run(self):
 | |
|         class Alarm(Exception):
 | |
|             pass
 | |
|         def alarm_handler(signum, frame):
 | |
|             raise Alarm
 | |
| 
 | |
|         try:
 | |
|             self.process = Popen(self.args, shell=True, stdout=PIPE, stderr=PIPE)
 | |
|             if self.timeout != -1:
 | |
|                 signal(SIGALRM, alarm_handler)
 | |
|                 alarm(self.timeout)
 | |
| 
 | |
|             try:
 | |
|                 self.stdout, self.stderr = self.process.communicate()
 | |
|                 if self.timeout != -1:
 | |
|                     alarm(0)
 | |
|             except Alarm:
 | |
|                 os.kill(self.process.pid, SIGKILL)
 | |
|                 raise  CloudRuntimeException("Timeout during command execution")
 | |
| 
 | |
|             self.success = self.process.returncode == 0
 | |
|         except:
 | |
|             raise  CloudRuntimeException(formatExceptionInfo())
 | |
| 
 | |
| #        if not self.success: 
 | |
| #            raise  CloudRuntimeException(self.getStderr())
 | |
| 
 | |
|     def isSuccess(self):
 | |
|         return self.success
 | |
|     
 | |
|     def getStdout(self):
 | |
|         return self.stdout.strip("\n")
 | |
|     
 | |
|     def getLines(self):
 | |
|         return self.stdout.split("\n")
 | |
| 
 | |
|     def getStderr(self):
 | |
|         return self.stderr.strip("\n")
 | |
| 
 | |
| 
 | |
| def initLoging(logFile=None):
 | |
|     try:
 | |
|         if logFile is None:
 | |
|             logging.basicConfig(level=logging.DEBUG) 
 | |
|         else: 
 | |
|             logging.basicConfig(filename=logFile, level=logging.DEBUG) 
 | |
|     except:
 | |
|         logging.basicConfig(level=logging.DEBUG) 
 | |
| 
 | |
| def writeProgressBar(msg, result=None):    
 | |
|     if msg is not None:
 | |
|         output = "%-80s"%msg
 | |
|     elif result is True:
 | |
|         output = "[ \033[92m%-2s\033[0m ]\n"%"OK"
 | |
|     elif result is False:
 | |
|         output = "[ \033[91m%-6s\033[0m ]\n"%"FAILED"
 | |
|     sys.stdout.write(output)
 | |
|     sys.stdout.flush()
 | |
|     
 | |
| def printError(msg):
 | |
|     sys.stderr.write(msg)
 | |
|     sys.stderr.write("\n")
 | |
|     sys.stderr.flush()
 | |
| 
 | |
| def printMsg(msg):
 | |
|     sys.stdout.write(msg+"\n")
 | |
|     sys.stdout.flush()
 | |
| 
 | |
| def checkRpm(pkgName):
 | |
|     chkPkg = bash("rpm -q %s"%pkgName)
 | |
|     writeProgressBar("Checking %s"%pkgName, None)
 | |
|     if not chkPkg.isSuccess():
 | |
|         writeProgressBar(None, False)
 | |
|         printError("%s is not found, please make sure it is installed. You may try 'yum install %s'\n"%(pkgName, pkgName))
 | |
|         return False
 | |
|     else:
 | |
|         writeProgressBar(None, True)
 | |
|         return True
 | |
|       
 | |
| def checkEnv():
 | |
|    writeProgressBar("Checking is root")
 | |
|    ret = bash("whoami")
 | |
|    if ret.getStdout() != "root":
 | |
|        writeProgressBar(None, False)
 | |
|        printError("This script must run as root")
 | |
|        return False
 | |
|    else:
 | |
|        writeProgressBar(None, True)
 | |
|        
 | |
|    pkgList = ['tftp-server', 'syslinux', 'xinetd', 'chkconfig', 'dhcp']
 | |
|    for pkg in pkgList:
 | |
|        if not checkRpm(pkg):
 | |
|            return False
 | |
|    return True
 | |
| 
 | |
| def exitIfFail(ret):
 | |
|     if not ret: sys.exit(1) 
 | |
|     
 | |
| def bashWithResult(cmd):
 | |
|     writeProgressBar("Executing '%s'"%cmd)
 | |
|     ret = bash(cmd)
 | |
|     if not ret.isSuccess():
 | |
|         writeProgressBar(None, False)
 | |
|         writeProgressBar(ret.getStderr() + '\n')
 | |
|         return False
 | |
|     else:
 | |
|         writeProgressBar(None, True)
 | |
|         return True
 | |
|     
 | |
| def configurePxeStuff(): 
 | |
|     stuff = ['tftp', 'xinetd', 'dhcpd']
 | |
|     cmds = ['chkconfig --level 345 %s on' % i for i in stuff]
 | |
|     cmds.append('/etc/init.d/xinetd restart')
 | |
|     
 | |
|     for cmd in cmds:
 | |
|         if not bashWithResult(cmd): return False
 | |
|         
 | |
|     chkIptable = bash('chkconfig --list iptables')
 | |
|     if 'on' in chkIptable.getStdout():
 | |
|         printMsg("Detected iptables is running, need to open tftp port 69")
 | |
|         if not bashWithResult('iptables -I INPUT 1 -p udp --dport 69 -j ACCEPT'): return False
 | |
|         if not bashWithResult('/etc/init.d/iptables save'): return False
 | |
|         
 | |
|     return True  
 | |
|     
 | |
| def getTftpRootDir(tftpRootDirList):
 | |
|     tftpRoot = bash("cat /etc/xinetd.d/tftp | grep server_args")
 | |
|     if not tftpRoot.isSuccess():
 | |
|         printError("Cannot get tftp root directory from /etc/xinetd.d/tftp, here may be something wrong with your tftp-server, try reinstall it\n")
 | |
|         return False
 | |
|     tftpRootDir = tftpRoot.getStdout()
 | |
|     index = tftpRootDir.find("/")
 | |
|     if index == -1:
 | |
|         printError("Wrong server_arg in /etc/xinetd.d/tftp (%s)"%tftpRootDir)
 | |
|         return False
 | |
|     tftpRootDir = tftpRootDir[index:]
 | |
|     tftpRootDirList.append(tftpRootDir)
 | |
|     return True
 | |
| 
 | |
| def preparePING(tftpRootDir):
 | |
|     pingFiles = ['boot.msg', 'initrd.gz', 'kernel', 'pxelinux.0']
 | |
|     pingDir = "/usr/share/PING"
 | |
|     
 | |
|     for f in pingFiles:
 | |
|         path = join(pingDir, f)
 | |
|         if not exists(path):
 | |
|             printError("Cannot find %s, please make sure PING-3.01 is installed"%path)
 | |
|             return False
 | |
|         if not bashWithResult("cp -f %s %s"%(path, tftpRootDir)): return False
 | |
|      
 | |
|     if not bashWithResult("mkdir -p %s/pxelinux.cfg"%tftpRootDir): return False
 | |
|     
 | |
|     return True
 | |
|             
 | |
|         
 | |
| if __name__ == "__main__":
 | |
|     initLoging("/tmp/cloud-setup-baremetal.log")
 | |
|     tftpRootDirList = []
 | |
|     
 | |
|     exitIfFail(checkEnv())
 | |
|     exitIfFail(configurePxeStuff())
 | |
|     exitIfFail(getTftpRootDir(tftpRootDirList))
 | |
|     
 | |
|     tftpRootDir = tftpRootDirList[0].strip()
 | |
|     exitIfFail(preparePING(tftpRootDir))
 | |
|     printMsg("")
 | |
|     printMsg("Setup BareMetal PXE server successfully")
 | |
|     printMsg("TFTP root directory is: %s\n"%tftpRootDir)
 | |
|     sys.exit(0)
 | |
|     
 |