mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			297 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
 | 
						|
import sys, os, subprocess, errno, re
 | 
						|
 | 
						|
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
 | 
						|
# ---- We do this so cloud_utils can be looked up in the following order:
 | 
						|
# ---- 1) Sources directory
 | 
						|
# ---- 2) waf configured PYTHONDIR
 | 
						|
# ---- 3) System Python path
 | 
						|
for pythonpath in (
 | 
						|
		"@PYTHONDIR@",
 | 
						|
		os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
 | 
						|
	):
 | 
						|
		if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
 | 
						|
# ---- End snippet of code ----
 | 
						|
from cloud_utils import check_selinux, CheckFailed
 | 
						|
 | 
						|
E_GENERIC= 1
 | 
						|
E_NOKVM = 2
 | 
						|
E_NODEFROUTE = 3
 | 
						|
E_DHCP = 4
 | 
						|
E_NOPERSISTENTNET = 5
 | 
						|
E_VIRTRECONFIGFAILED = 7
 | 
						|
E_FWRECONFIGFAILED = 8
 | 
						|
E_AGENTRECONFIGFAILED = 9
 | 
						|
E_AGENTFAILEDTOSTART = 10
 | 
						|
E_NOFQDN = 11
 | 
						|
E_OSUNSUPP = 11
 | 
						|
E_SUDORECONFIGFAILED = 6
 | 
						|
E_SELINUXENABLED=12
 | 
						|
 | 
						|
 | 
						|
def stderr(msgfmt,*args):
 | 
						|
	msgfmt += "\n"
 | 
						|
	if args: sys.stderr.write(msgfmt%args)
 | 
						|
	else: sys.stderr.write(msgfmt)
 | 
						|
	sys.stderr.flush()
 | 
						|
 | 
						|
def bail(errno=E_GENERIC,message=None,*args):
 | 
						|
	if message: stderr(message,*args)
 | 
						|
	stderr("CloudStack Management Server setup aborted")
 | 
						|
	sys.exit(errno)
 | 
						|
 | 
						|
 | 
						|
#---------------- boilerplate for python 2.4 support 
 | 
						|
 | 
						|
 | 
						|
# CENTOS does not have this -- we have to put this here
 | 
						|
try:
 | 
						|
	from subprocess import check_call
 | 
						|
	from subprocess import CalledProcessError
 | 
						|
except ImportError:
 | 
						|
	def check_call(*popenargs, **kwargs):
 | 
						|
		import subprocess
 | 
						|
		retcode = subprocess.call(*popenargs, **kwargs)
 | 
						|
		cmd = kwargs.get("args")
 | 
						|
		if cmd is None: cmd = popenargs[0]
 | 
						|
		if retcode: raise CalledProcessError(retcode, cmd)
 | 
						|
		return retcode
 | 
						|
 | 
						|
	class CalledProcessError(Exception):
 | 
						|
		def __init__(self, returncode, cmd):
 | 
						|
			self.returncode = returncode ; self.cmd = cmd
 | 
						|
		def __str__(self): return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
 | 
						|
 | 
						|
# ------------ end boilerplate -------------------------
 | 
						|
 | 
						|
 | 
						|
def check_kvm(): return check_call(["kvm-ok"])
 | 
						|
def check_hostname(): return check_call(["hostname",'--fqdn'])
 | 
						|
 | 
						|
class Command:
 | 
						|
	def __init__(self,name,parent=None):
 | 
						|
		self.__name = name
 | 
						|
		self.__parent = parent
 | 
						|
	def __getattr__(self,name):
 | 
						|
		if name == "_print": name = "print"
 | 
						|
		return Command(name,self)
 | 
						|
	def __call__(self,*args):
 | 
						|
		cmd = self.__get_recursive_name() + list(args)
 | 
						|
		#print "	",cmd
 | 
						|
		popen = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 | 
						|
		m = popen.communicate()
 | 
						|
		ret = popen.wait()
 | 
						|
		if ret:
 | 
						|
			e = CalledProcessError(ret,cmd)
 | 
						|
			e.stdout,e.stderr = m
 | 
						|
			raise e
 | 
						|
		class CommandOutput:
 | 
						|
			def __init__(self,stdout,stderr):
 | 
						|
				self.stdout = stdout
 | 
						|
				self.stderr = stderr
 | 
						|
		return CommandOutput(*m)
 | 
						|
	def __lt__(self,other):
 | 
						|
		cmd = self.__get_recursive_name()
 | 
						|
		#print "	",cmd,"<",other
 | 
						|
		popen = subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 | 
						|
		m = popen.communicate(other)
 | 
						|
		ret = popen.wait()
 | 
						|
		if ret:
 | 
						|
			e = CalledProcessError(ret,cmd)
 | 
						|
			e.stdout,e.stderr = m
 | 
						|
			raise e
 | 
						|
		class CommandOutput:
 | 
						|
			def __init__(self,stdout,stderr):
 | 
						|
				self.stdout = stdout
 | 
						|
				self.stderr = stderr
 | 
						|
		return CommandOutput(*m)
 | 
						|
		
 | 
						|
	def __get_recursive_name(self,sep=None):
 | 
						|
		m = self
 | 
						|
		l = []
 | 
						|
		while m is not None:
 | 
						|
			l.append(m.__name)
 | 
						|
			m = m.__parent
 | 
						|
		l.reverse()
 | 
						|
		if sep: return sep.join(l)
 | 
						|
		else: return l
 | 
						|
	def __str__(self):
 | 
						|
		return '<Command %r>'%self.__get_recursive_name(sep=" ")
 | 
						|
		
 | 
						|
	def __repr__(self): return self.__str__()
 | 
						|
 | 
						|
def checkselinux():
 | 
						|
	try:
 | 
						|
		check_selinux()
 | 
						|
	except CheckFailed,e:
 | 
						|
		bail(E_SELINUXENABLED,"SELINUX is set to enforcing.  Please set it to permissive in /etc/selinux/config.  Then reboot or run setenforce permissive.  Then run this program again.")
 | 
						|
 | 
						|
 | 
						|
ip = Command("ip")
 | 
						|
service = Command("service")
 | 
						|
chkconfig = Command("chkconfig")
 | 
						|
updatercd = Command("update-rc.d")
 | 
						|
ufw = Command("ufw")
 | 
						|
iptables = Command("iptables")
 | 
						|
iptables_save = Command("iptables-save")
 | 
						|
augtool = Command("augtool")
 | 
						|
kvmok = Command("kvm-ok")
 | 
						|
ifconfig = Command("ifconfig")
 | 
						|
uuidgen = Command("uuidgen")
 | 
						|
 | 
						|
Fedora = os.path.exists("/etc/fedora-release")
 | 
						|
CentOS = os.path.exists("/etc/centos-release") or ( os.path.exists("/etc/redhat-release") and not os.path.exists("/etc/fedora-release") )
 | 
						|
 | 
						|
#--------------- procedure starts here ------------
 | 
						|
 | 
						|
stderr("Welcome to the CloudStack Management setup")
 | 
						|
stderr("")
 | 
						|
 | 
						|
try:
 | 
						|
	check_hostname()
 | 
						|
	stderr("The hostname of this machine is properly set up")
 | 
						|
except CalledProcessError,e:
 | 
						|
	bail(E_NOFQDN,"This machine does not have an FQDN (fully-qualified domain name) for a hostname")
 | 
						|
 | 
						|
if Fedora or CentOS:
 | 
						|
	checkselinux()
 | 
						|
 | 
						|
try:
 | 
						|
	service("@PACKAGE@-management","status")
 | 
						|
	stderr("Stopping the CloudStack Management Server")
 | 
						|
	m = service("@PACKAGE@-management","stop")
 | 
						|
	print m.stdout + m.stderr
 | 
						|
	stderr("CloudStack Management Server stopped")
 | 
						|
except CalledProcessError,e:
 | 
						|
	pass
 | 
						|
 | 
						|
requiretty = augtool._print("/files/etc/sudoers/Defaults/requiretty").stdout.strip()
 | 
						|
sudoeruser = augtool.match("/files/etc/sudoers/spec/user","@MSUSER@").stdout.strip()
 | 
						|
	
 | 
						|
if requiretty:
 | 
						|
	sudoerstext = file("/etc/sudoers").read()
 | 
						|
	def restore():
 | 
						|
		try: file("/etc/sudoers","w").write(sudoerstext)
 | 
						|
		except OSError,e: raise
 | 
						|
		
 | 
						|
	script = """rm %s
 | 
						|
save"""%"/".join(requiretty.split("/")[:-1])
 | 
						|
	
 | 
						|
	stderr("Executing the following reconfiguration script:\n%s",script)
 | 
						|
	
 | 
						|
	try:
 | 
						|
		returned = augtool < script
 | 
						|
		if "Saved 1 file" not in returned.stdout:
 | 
						|
			print returned.stdout + returned.stderr
 | 
						|
			restore()
 | 
						|
			bail(E_SUDORECONFIGFAILED,"sudoers reconfiguration failed.")
 | 
						|
		else:
 | 
						|
			stderr("sudoers reconfiguration complete")
 | 
						|
	except CalledProcessError,e:
 | 
						|
		restore()
 | 
						|
		print e.stdout + e.stderr
 | 
						|
		bail(E_SUDORECONFIGFAILED,"sudoers reconfiguration failed")
 | 
						|
 | 
						|
if "@MSUSER@" not in sudoeruser:
 | 
						|
	sudoerstext = file("/etc/sudoers").read()
 | 
						|
	def restore():
 | 
						|
		try: file("/etc/sudoers","w").write(sudoerstext)
 | 
						|
		except OSError,e: raise
 | 
						|
		
 | 
						|
	script = """ins spec after /files/etc/sudoers/spec[last()]
 | 
						|
set /files/etc/sudoers/spec[last()]/user @MSUSER@
 | 
						|
set /files/etc/sudoers/spec[last()]/host_group/host ALL
 | 
						|
set /files/etc/sudoers/spec[last()]/host_group/command ALL
 | 
						|
set /files/etc/sudoers/spec[last()]/host_group/command/tag NOPASSWD
 | 
						|
save"""
 | 
						|
	
 | 
						|
	stderr("Executing the following reconfiguration script:\n%s",script)
 | 
						|
	
 | 
						|
	try:
 | 
						|
		returned = augtool < script
 | 
						|
		if "Saved 1 file" not in returned.stdout:
 | 
						|
			print returned.stdout + returned.stderr
 | 
						|
			restore()
 | 
						|
			bail(E_SUDORECONFIGFAILED,"sudoers reconfiguration failed.")
 | 
						|
		else:
 | 
						|
			stderr("sudoers reconfiguration complete")
 | 
						|
	except CalledProcessError,e:
 | 
						|
		restore()
 | 
						|
		print e.stdout + e.stderr
 | 
						|
		bail(E_SUDORECONFIGFAILED,"sudoers reconfiguration failed")
 | 
						|
 | 
						|
ports = "80 8080 8096 8250 9090".split()
 | 
						|
if Fedora or CentOS:
 | 
						|
	try:
 | 
						|
		o = chkconfig("--list","iptables")
 | 
						|
		iptableschkconfig = True
 | 
						|
	except CalledProcessError,e:
 | 
						|
		stderr("No need to set up iptables as the service is not registered in the SysV init system")
 | 
						|
		iptableschkconfig = False
 | 
						|
	if iptableschkconfig is True:
 | 
						|
		try:
 | 
						|
			o = chkconfig("--list","iptables")
 | 
						|
			if ":on" in o.stdout and os.path.exists("/etc/sysconfig/iptables"):
 | 
						|
				stderr("Setting up firewall rules to permit traffic to CloudStack services")
 | 
						|
				service.iptables.start() ; print o.stdout + o.stderr
 | 
						|
				o = iptables_save()
 | 
						|
				for p in ports:
 | 
						|
					r = "INPUT -p tcp -m tcp --dport %s -j ACCEPT" % p
 | 
						|
					if r in o.stdout:
 | 
						|
						continue
 | 
						|
					iptables("-I","INPUT","1","-p","tcp","--dport",p,"-j","ACCEPT")
 | 
						|
 | 
						|
				o = service.iptables.save() ; print o.stdout + o.stderr
 | 
						|
			else:
 | 
						|
				stderr("No need to set up iptables as the service is unconfigured or not set to start up at boot")
 | 
						|
		except CalledProcessError,e:
 | 
						|
			print e.stdout+e.stderr
 | 
						|
			bail(E_FWRECONFIGFAILED,"Firewall rules could not be set")
 | 
						|
else:
 | 
						|
	stderr("Setting up firewall rules to permit traffic to CloudStack services")
 | 
						|
	try:
 | 
						|
		for p in ports: ufw.allow(p)
 | 
						|
		stderr("Rules set")
 | 
						|
	except CalledProcessError,e:
 | 
						|
		print e.stdout+e.stderr
 | 
						|
		bail(E_FWRECONFIGFAILED,"Firewall rules could not be set")
 | 
						|
 | 
						|
	stderr("We are going to enable ufw now.  This may disrupt network connectivity and service availability.  See the ufw documentation for information on how to manage ufw firewall policies.")
 | 
						|
	try:
 | 
						|
		o = ufw.enable < "y\n" ; print o.stdout + o.stderr
 | 
						|
	except CalledProcessError,e:
 | 
						|
		print e.stdout+e.stderr
 | 
						|
		bail(E_FWRECONFIGFAILED,"Firewall could not be enabled")
 | 
						|
 | 
						|
stderr("")
 | 
						|
stderr("CloudStack Management Server setup completed successfully")
 | 
						|
 | 
						|
try:
 | 
						|
	if Fedora or CentOS:			chkconfig("tomcat6","off")
 | 
						|
	else:		updatercd("tomcat6","disable")
 | 
						|
	service("tomcat6","status")
 | 
						|
	stderr("Stopping Tomcat")
 | 
						|
	m = service("tomcat6","stop")
 | 
						|
	print m.stdout + m.stderr
 | 
						|
	stderr("Tomcat stopped")
 | 
						|
except CalledProcessError,e:
 | 
						|
	pass
 | 
						|
 | 
						|
try:
 | 
						|
    	if Fedora or CentOS:
 | 
						|
		chkconfig("--level","35","network","on")
 | 
						|
except CalledProcessError,e:
 | 
						|
	pass
 | 
						|
 | 
						|
stderr("Starting the CloudStack Management Server")
 | 
						|
try:
 | 
						|
	m = service("@PACKAGE@-management","start")
 | 
						|
	print m.stdout + m.stderr
 | 
						|
except CalledProcessError,e:
 | 
						|
	print e.stdout + e.stderr
 | 
						|
	bail(E_AGENTFAILEDTOSTART,"@PACKAGE@-management failed to start")
 | 
						|
 | 
						|
 | 
						|
# FIXMES: 1) nullify networkmanager on ubuntu (asking the user first) and enable the networking service permanently
 |