refactore cloud related tools

This commit is contained in:
Edison Su 2011-05-06 19:54:47 -04:00
parent fd24a1e240
commit cbf2b03e31
13 changed files with 1539 additions and 401 deletions

View File

@ -1,148 +1,107 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/python
import os
import logging
import sys
import socket
from cloud.cloudException import CloudRuntimeException, CloudInternalException
from cloud.utilities import initLoging
from cloud.configFileOps import configFileOps
from cloud.globalEnv import globalEnv
from cloud.networkConfig import networkConfig
from cloud.syscfg import sysConfigFactory
import sys, os, subprocess, errno, re, traceback, getopt
from optparse import OptionParser
def getUserInputs():
print "Welcome to myCloud Setup:"
# ---- 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 ----
import cloud_utils
from cloud_utils import stderr,CheckFailed,TaskFailed,backup_etc,restore_etc
from cloud_utils import setup_agent_config,stop_service,enable_service
from cloud_utils import exit as bail
from cloud_utils import all, any
cfo = configFileOps("/etc/cloud/agent/agent.properties")
oldMgt = cfo.getEntry("host")
mgtSvr = raw_input("Please input the Management Server Name/IP:[%s]"%oldMgt)
if mgtSvr == "":
mgtSvr = oldMgt
try:
socket.getaddrinfo(mgtSvr, 443)
except:
print "Failed to resolve %s. Please input correct server name or IP."%mgtSvr
exit(1)
#--------------- procedure starts here ------------
oldToken = cfo.getEntry("zone")
zoneToken = raw_input("Please input the Zone Token:[%s]"%oldToken)
if zoneToken == "":
zoneToken = oldToken
# FÏXME for backup and restore: collect service state for all services so we can restore the system's runtime state back to what it was before
# possible exit states:
# a. system configuration needs administrator attention
# b. automatic reconfiguration failed
# c. process interrupted
# d. everything was configured properly (exit status 0)
try:
defaultNic = networkConfig.getDefaultNetwork()
except:
print "Failed to get default route. Please configure your network to have a default route"
exit(1)
defNic = defaultNic.name
network = raw_input("Please choose which network used to create VM:[%s]"%defNic)
if network == "":
if defNic == "":
print "You need to specifiy one of Nic or bridge on your system"
exit(1)
elif network == "":
network = defNic
brname = "@PACKAGE@br0"
servicename = "@PACKAGE@-agent"
configfile = "@AGENTSYSCONFDIR@/agent.properties"
backupdir = "@SHAREDSTATEDIR@/@AGENTPATH@/etcbackup"
return [mgtSvr, zoneToken, network]
#=================== the magic happens here ====================
if __name__ == '__main__':
initLoging("/var/log/cloud/setupAgent.log")
glbEnv = globalEnv()
glbEnv.mode = "Agent"
glbEnv.agentMode = "Agent"
parser = OptionParser()
parser.add_option("-a", action="store_true", dest="auto", help="auto mode")
parser.add_option("-m", "--host", dest="mgt", help="management server name or IP")
parser.add_option("-z", "--zone", dest="zone", help="zone id")
parser.add_option("-p", "--pod", dest="pod", help="pod id")
parser.add_option("-c", "--cluster", dest="cluster", help="cluster id")
parser.add_option("-g", "--guid", dest="guid", help="guid")
parser.add_option("--pubNic", dest="pubNic", help="public nic")
parser.add_option("--prvNic", dest="prvNic", help="private nic")
parser.add_option("--guestNic", dest="guestNic", help="guest nic")
try:
# parse cmd line
opts, args = getopt.getopt(sys.argv[1:], "a", ["host=", "zone=", "pod=", "cluster=", "no-kvm", "guid=", "pubNic=", "prvNic="])
host=None
zone=None
pod=None
cluster=None
guid=None
pubNic=None
prvNic=None
autoMode=False
do_check_kvm = True
for opt, arg in opts:
if opt == "--host":
if arg != "":
host = arg
elif opt == "--zone":
if arg != "":
zone = arg
elif opt == "--pod":
if arg != "":
pod = arg
elif opt == "--cluster":
if arg != "":
cluster = arg
elif opt == "--guid":
if arg != "":
guid = arg
elif opt == "--pubNic":
pubNic = arg
elif opt == "--prvNic":
prvNic = arg
elif opt == "--no-kvm":
do_check_kvm = False
elif opt == "-a":
autoMode=True
if autoMode:
cloud_utils.setLogFile("/var/log/cloud/setupAgent.log")
stderr("Welcome to the Cloud Agent setup")
stderr("")
# pre-flight checks for things that the administrator must fix
try:
for f,n in cloud_utils.preflight_checks(
do_check_kvm=do_check_kvm
):
stderr(n)
f()
except CheckFailed,e:
stderr(str(e))
bail(cloud_utils.E_NEEDSMANUALINTERVENTION,
"Cloud Agent setup cannot continue until these issues have been addressed")
# system configuration tasks that our Cloud Agent setup performs
try:
tasks = cloud_utils.config_tasks(brname, pubNic, prvNic)
for t in tasks:
t.setAutoMode(autoMode)
if all( [ t.done() for t in tasks ] ):
stderr("All configuration tasks have been performed already")
else:
backup_etc(backupdir)
try:
# run all tasks that have not been done
for t in [ n for n in tasks if not n.done() ]:
t.run()
except:
# oops, something wrong, restore system to earlier state and re-raise
stderr("A fatal issue has been detected -- restoring system configuration.\nPlease be patient; *do not* interrupt this process.")
restore_etc(backupdir)
for t in [ n for n in tasks if hasattr(n,"restore_state") ]:
t.restore_state()
raise
except (TaskFailed,CheckFailed),e:
# some configuration task or post-flight check failed, we exit right away
stderr(str(e))
bail(cloud_utils.E_SETUPFAILED,"Cloud Agent setup failed")
setup_agent_config(configfile, host, zone, pod, cluster, guid, pubNic, prvNic)
stderr("Enabling and starting the Cloud Agent")
stop_service(servicename)
enable_service(servicename)
stderr("Cloud Agent restarted")
except KeyboardInterrupt,e:
# user interrupted, we exit right away
bail(cloud_utils.E_INTERRUPTED,"Cloud Agent setup interrupted")
except SystemExit,e:
# process above handled a failure then called bail(), which raises a SystemExit on CentOS
sys.exit(e.code)
except Exception,e:
# at ths point, any exception has been dealt with cleanly by restoring system config from a backup
# we just inform the user that there was a problem
# and bail prematurely
stderr("Cloud Agent setup has experienced an unrecoverable error. Please report the following technical details to Cloud.com.")
traceback.print_exc()
bail(cloud_utils.E_UNHANDLEDEXCEPTION,"Cloud Agent setup ended prematurely")
(options, args) = parser.parse_args()
if options.auto is None:
userInputs = getUserInputs()
glbEnv.mgtSvr = userInputs[0]
glbEnv.zone = userInputs[1]
glbEnv.defaultNic = userInputs[2]
#generate UUID
glbEnv.uuid = configFileOps("/etc/cloud/agent/agent.properties").getEntry("guid")
if glbEnv.uuid == "":
glbEnv.uuid = bash("uuidgen").getStdout()
else:
for para, value in options.__dict__.items():
if value is None:
print "Missing operand:%s"%para
print "Try %s --help for more information"%sys.argv[0]
sys.exit(1)
stderr("")
stderr("Cloud Agent setup completed successfully")
# ========================= end program ========================
glbEnv.uuid = options.guid
glbEnv.mgtSvr = options.mgt
glbEnv.zone = options.zone
glbEnv.pod = options.pod
glbEnv.cluster = options.cluster
glbEnv.nics.append(options.prvNic)
glbEnv.nics.append(options.pubNic)
glbEnv.nics.append(options.guestNic)
print "Starting to configure your system:"
syscfg = sysConfigFactory.getSysConfigFactory(glbEnv)
try:
syscfg.config()
print "Cloud Agent setup is Done!"
except (CloudRuntimeException,CloudInternalException), e:
print e
print "Try to restore your system:"
try:
syscfg.restore()
except:
pass

View File

@ -1,263 +1,22 @@
#!/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("/sbin/service")
chkconfig = Command("/sbin/chkconfig")
updatercd = Command("update-rc.d")
ufw = Command("ufw")
iptables = Command("/sbin/iptables")
iptables_save = Command("/sbin/iptables-save")
kvmok = Command("kvm-ok")
ifconfig = Command("/sbin/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
sudoerstext = file("/etc/sudoers").readlines()
def restore():
try: file("/etc/sudoers","w").write(''.join(sudoerstext))
except OSError,e: raise
try:
stderr("Configure /etc/sudoers")
newtext = []
clouder = "cloud ALL = NOPASSWD : ALL"
hasClouder = False
for line in sudoerstext:
if "Defaults" in line and "requiretty" in line:
continue
if clouder in line:
hasClouder = True
newtext.append(line)
if not hasClouder:
newtext.append(clouder+'\n')
file("/etc/sudoers", "w").write(''.join(newtext))
except:
restore()
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
from cloud.syscfg import sysConfigFactory
from cloud.utilities import initLoging
from cloud.cloudException import CloudRuntimeException, CloudInternalException
from cloud.globalEnv import globalEnv
if __name__ == '__main__':
initLoging("/var/log/cloud/setupManagement.log")
glbEnv = globalEnv()
glbEnv.mode = "Server"
print "Starting to configure CloudStack Management Server:"
syscfg = sysConfigFactory.getSysConfigFactory(glbEnv)
try:
syscfg.config()
print "CloudStack Management Server setup is Done!"
except (CloudRuntimeException, CloudInternalException), e:
print e
print "Try to restore your system:"
try:
syscfg.restore()
except:
pass

View File

View File

@ -0,0 +1,29 @@
import sys
import traceback
class CloudRuntimeException(Exception):
def __init__(self, errMsg):
self.errMsg = errMsg
value = sys.exc_info()[1]
if value is not None:
self.errMsg += ", due to:" + str(value)
self.details = formatExceptionInfo()
def __str__(self):
return self.errMsg
def getDetails(self):
return self.details
class CloudInternalException(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

View File

@ -0,0 +1,148 @@
import re
import tempfile
import shutil
from utilities import bash
class configFileOps:
class entry:
def __init__(self, name, value, op, separator):
self.name = name
self.value = value
self.state = "new"
self.op = op
self.separator = separator
def setState(self, state):
self.state = state
def getState(self):
return self.state
def __init__(self, fileName, cfg=None):
self.fileName = fileName
self.entries = []
self.backups = []
if cfg is not None:
cfg.cfoHandlers.append(self)
def addEntry(self, name, value, separator="="):
e = self.entry(name, value, "add", separator)
self.entries.append(e)
def rmEntry(self, name, value, separator="="):
entry = self.entry(name, value, "rm", separator)
self.entries.append(entry)
def getEntry(self, name, separator="="):
try:
ctx = file(self.fileName).read(-1)
match = re.search("^" + name + ".*", ctx, re.MULTILINE)
if match is None:
return ""
line = match.group(0).split(separator, 1)
return line[1]
except:
return ""
def save(self):
fp = open(self.fileName, "r")
newLines = []
for line in fp.readlines():
matched = False
for entry in self.entries:
if entry.op == "add":
if entry.separator == "=":
matchString = "^\ *" + entry.name + ".*"
elif entry.separator == " ":
matchString = "^\ *" + entry.name + "\ *" + entry.value
else:
if entry.separator == "=":
matchString = "^\ *" + entry.name + "\ *=\ *" + entry.value
else:
matchString = "^\ *" + entry.name + "\ *" + entry.value
match = re.match(matchString, line)
if match is not None:
if entry.op == "add" and entry.separator == "=":
newline = entry.name + "=" + entry.value + "\n"
entry.setState("set")
newLines.append(newline)
self.backups.append([line, newline])
matched = True
break
elif entry.op == "rm":
entry.setState("set")
self.backups.append([line, None])
matched = True
break
if not matched:
newLines.append(line)
for entry in self.entries:
if entry.getState() != "set":
if entry.op == "add":
newline = entry.name + entry.separator + entry.value + "\n"
newLines.append(newline)
self.backups.append([None, newline])
entry.setState("set")
fp.close()
file(self.fileName, "w").writelines(newLines)
def replace_line(self, startswith,stanza,always_add=False):
lines = [ s.strip() for s in file(self.fileName).readlines() ]
newlines = []
replaced = False
for line in lines:
if re.search(startswith, line):
if stanza is not None:
newlines.append(stanza)
self.backups.append([line, stanza])
replaced = True
else: newlines.append(line)
if not replaced and always_add:
newlines.append(stanza)
self.backups.append([None, stanza])
newlines = [ s + '\n' for s in newlines ]
file(self.fileName,"w").writelines(newlines)
def replace_or_add_line(self, startswith,stanza):
return self.replace_line(startswith,stanza,always_add=True)
def add_lines(self, lines, addToBackup=True):
fp = file(self.fileName).read(-1)
sh = re.escape(lines)
match = re.search(sh, fp, re.MULTILINE)
if match is not None:
return
fp += lines
file(self.fileName, "w").write(fp)
self.backups.append([None, lines])
def replace_lines(self, src, dst, addToBackup=True):
fp = file(self.fileName).read(-1)
sh = re.escape(src)
if dst is None:
dst = ""
repl,nums = re.subn(sh, dst, fp)
if nums <=0:
return
file(self.fileName, "w").write(repl)
if addToBackup:
self.backups.append([src, dst])
def backup(self):
for oldLine, newLine in self.backups:
if newLine is None:
self.add_lines(oldLine, False)
else:
self.replace_lines(newLine, oldLine, False)
if __name__ == '__main__':
cfo = configFileOps("./sudoers")
#cloud ALL = NOPASSWD : ALL
cfo.addEntry("cloud ALL ", "NOPASSWD : ALL")
cfo.rmEntry("Defaults", "requiretty", " ")
#cfo.addEntry("zone", "test", " ")
cfo.save()

View File

@ -0,0 +1,66 @@
import MySQLdb
import os
from utilities import bash
from cloudException import CloudRuntimeException
import sys
class Database:
"""Database connection"""
def __init__(self, username, password=None, host='localhost', port='3306', db="cloud"):
self.host = host
self.username = username
self.password = password
self.port = port
self.db = db
def execute(self, statement):
txn = None
try:
if self.password is not None:
txn = MySQLdb.Connect(host=self.host, user=self.username,
passwd=self.password, db=self.db)
else:
txn = MySQLdb.Connect(host=self.host, user=self.username,
db=self.db)
cursor = txn.cursor()
cursor.execute(statement)
cursor.close()
txn.commit()
if txn is not None:
try:
txn.close()
except:
pass
except:
if txn is not None:
try:
txn.close()
except:
pass
raise CloudRuntimeException("Failed to execute:%s"%statement)
def testConnection(self):
try:
if self.password is not None:
db = MySQLdb.Connect(host=self.host, user=self.username,
passwd=self.password, db=self.db)
else:
db = MySQLdb.Connect(host=self.host, user=self.username,
db=self.db)
return True
except:
raise CloudRuntimeException("Failed to Connect to DB")
def executeFromFile(self, file):
if not os.path.exists(file):
return False
cmdLine = "mysql --host=" + self.host + " --port=" + str(self.port) + " --user=" + self.username
if self.password is not None:
cmdLine += " --password=" + self.password
cmdLine += " < " + file
try:
bash(cmdLine)
except:
raise CloudRuntimeException("Failed to execute " + cmdLine)

View File

@ -0,0 +1,24 @@
class globalEnv:
def __init__(self):
#Agent/Server/Db
self.mode = None
#server mode: normal/mycloud
self.svrMode = None
#myCloud/Agent/Console
self.agentMode = None
#debug
self.debug = False
#management server IP
self.mgtSvr = None
#zone id or zone name
self.zone = None
#pod id or pod name
self.pod = None
#cluster id or cluster name
self.cluster = None
#nics: 0: private nic, 1: guest nic, 2: public nic used by agent
self.nics = []
#uuid
self.uuid = None
#default private network
self.privateNet = "cloudbr0"

View File

@ -0,0 +1,135 @@
from utilities import bash
from cloudException import CloudRuntimeException, CloudInternalException
import logging
import os
import re
class networkConfig:
class devInfo:
def __init__(self, macAddr, ipAddr, netmask, gateway, type, name):
self.name = name
self.macAdrr = macAddr
self.ipAddr = ipAddr
self.netmask = netmask
self.gateway = gateway
self.type = type
self.name = name
#dhcp or static
self.method = None
@staticmethod
def getDefaultNetwork():
cmd = bash("route -n|awk \'/^0.0.0.0/ {print $2,$8}\'")
if not cmd.isSuccess():
logging.debug("Failed to get default route")
raise CloudRuntimeException("Failed to get default route")
result = cmd.getStdout().split(" ")
gateway = result[0]
dev = result[1]
pdi = networkConfig.getDevInfo(dev)
logging.debug("Found default network device:%s"%pdi.name)
pdi.gateway = gateway
return pdi
@staticmethod
def createBridge(dev, brName):
if not networkConfig.isBridgeSupported():
logging.debug("bridge is not supported")
return False
if networkConfig.isBridgeEnslavedWithDevices(brName):
logging.debug("bridge: %s has devices enslaved"%brName)
return False
cmds = ""
if not networkConfig.isBridge(brName):
cmds = "brctl addbr %s ;"%brName
cmds += "ifconfig %s up;"%brName
cmds += "brctl addif %s %s"%(brName, dev)
return bash(cmds).isSuccess()
@staticmethod
def isBridgeEnslavedWithDevices(brName):
if not networkConfig.isBridge(brName):
return False
if not os.listdir("/sys/class/net/%s/brif"%brName):
return False
return True
@staticmethod
def isBridgeSupported():
if os.path.exists("/proc/sys/net/bridge"):
return True
return bash("modprobe bridge").isSucess()
@staticmethod
def isNetworkDev(devName):
return os.path.exists("/sys/class/net/%s"%devName)
@staticmethod
def isBridgePort(devName):
return os.path.exists("/sys/class/net/%s/brport"%devName)
@staticmethod
def isBridge(devName):
return os.path.exists("/sys/class/net/%s/bridge"%devName)
@staticmethod
def getBridge(devName):
bridgeName = None
if os.path.exists("/sys/class/net/%s/brport/bridge"%devName):
realPath = os.path.realpath("/sys/class/net/%s/brport/bridge"%devName)
bridgeName = realPath.split("/")[-1]
return bridgeName
@staticmethod
def getEnslavedDev(br, brPort):
if not networkConfig.isBridgeEnslavedWithDevices(br):
return None
for dev in os.listdir("/sys/class/net/%s/brif"%br):
br_port = int(file("/sys/class/net/%s/brif/%s/port_no"%(br,dev)).readline().strip("\n"), 16)
if br_port == brPort:
return dev
return None
@staticmethod
def getDevInfo(dev):
if not networkConfig.isNetworkDev(dev):
logging.debug("dev: " + dev + " is not a network device")
raise CloudInternalException("dev: " + dev + " is not a network device")
netmask = None
ipAddr = None
macAddr = None
cmd = bash("ifconfig " + dev)
if not cmd.isSuccess():
logging.debug("Failed to get address from ifconfig")
raise CloudInternalException("Failed to get network info by ifconfig %s"%dev)
for line in cmd.getLines():
if line.find("HWaddr") != -1:
macAddr = line.split("HWaddr ")[1].strip(" ")
elif line.find("inet ") != -1:
m = re.search("addr:(.*)\ *Bcast:(.*)\ *Mask:(.*)", line)
if m is not None:
ipAddr = m.group(1).rstrip(" ")
netmask = m.group(3).rstrip(" ")
if networkConfig.isBridgePort(dev):
type = "brport"
elif networkConfig.isBridge(dev):
type = "bridge"
else:
type = "dev"
return networkConfig.devInfo(macAddr, ipAddr, netmask, None, type, dev)

View File

@ -0,0 +1,627 @@
from utilities import writeProgressBar, bash
from cloudException import CloudRuntimeException, CloudInternalException, formatExceptionInfo
import logging
from networkConfig import networkConfig
import re
from configFileOps import configFileOps
import os
import shutil
class serviceCfgBase(object):
def __init__(self, syscfg):
self.status = None
self.serviceName = ""
self.cfoHandlers = []
self.syscfg = syscfg
self.netMgrRunning = False
def configration(self):
writeProgressBar("Configure " + self.serviceName + " ...", None)
result = False
try:
result = self.config()
self.status = result
writeProgressBar(None, result)
return result
except CloudRuntimeException, e:
self.status = result
writeProgressBar(None, result)
logging.debug(e.getDetails())
raise e
except CloudInternalException, e:
self.status = result
writeProgressBar(None, result)
raise e
except:
logging.debug(formatExceptionInfo())
if self.syscfg.env.mode == "Server":
raise CloudRuntimeException("Configure %s failed, Please check the /var/log/cloud/setupManagement.log for detail"%self.serviceName)
else:
raise CloudRuntimeException("Configure %s failed, Please check the /var/log/cloud/setupAgent.log for detail"%self.serviceName)
def backup(self):
if self.status is None:
return True
writeProgressBar("Restore " + self.serviceName + " ...", None)
result = False
try:
for cfo in self.cfoHandlers:
cfo.backup()
result = self.restore()
except (CloudRuntimeException, CloudInternalException), e:
logging.debug(e)
writeProgressBar(None, result)
def config(self):
return True
def restore(self):
return True
class networkConfigBase:
def __init__(self, syscfg):
self.netcfg = networkConfig()
self.serviceName = "Network"
self.brName = None
self.dev = None
self.syscfg = syscfg
def isPreConfiged(self):
preCfged = False
for br in self.syscfg.env.nics:
if not self.netcfg.isNetworkDev(br):
raise CloudInternalException("%s is not a network device, is it down?"%br)
if not self.netcfg.isBridge(br):
raise CloudInternalException("%s is not a bridge"%br)
preCfged = True
return preCfged
def cfgNetwork(self, dev=None, brName=None):
if dev is None:
device = self.netcfg.getDefaultNetwork()
else:
device = self.netcfg.getDevInfo(dev)
if device.type == "dev":
if brName is None:
brName = "cloudbr0"
self.writeToCfgFile(brName, device)
elif device.type == "brport":
brName = self.netcfg.getBridge(dev)
brDevice = self.netcfg.getDevInfo(brName)
self.writeToCfgFile(brDevice.name, device)
elif device.type == "bridge":
#Fixme, assuming the outgoing physcial device is on port 1
enslavedDev = self.netcfg.getEnslavedDev(device.name, 1)
if enslavedDev is None:
raise CloudInternalException("Failed to get enslaved devices on bridge:%s"%device.name)
brDevice = device
device = self.netcfg.getDevInfo(enslavedDev)
brName = brDevice.name
self.writeToCfgFile(brName, device)
self.brName = brName
self.dev = device.name
def writeToCfgFile(self):
pass
class networkConfigUbuntu(serviceCfgBase, networkConfigBase):
def __init__(self, syscfg):
super(networkConfigUbuntu, self).__init__(syscfg)
networkConfigBase.__init__(self, syscfg)
self.netCfgFile = "/etc/network/interfaces"
def getNetworkMethod(self, line):
if line.find("static") != -1:
return "static"
elif line.find("dhcp") != -1:
return "dhcp"
else:
logging.debug("Failed to find the network method from:%s"%line)
raise CloudInternalException("Failed to find the network method from /etc/network/interfaces")
def addBridge(self, br, dev):
bash("ifdown %s"%dev.name)
for line in file(self.netCfgFile).readlines():
match = re.match("^ *iface %s.*"%dev.name, line)
if match is not None:
dev.method = self.getNetworkMethod(match.group(0))
bridgeCfg = "\niface %s inet manual\n \
auto %s\n \
iface %s inet %s\n \
bridge_ports %s\n"%(dev.name, br, br, dev.method, dev.name)
cfo = configFileOps(self.netCfgFile, self)
cfo.replace_line("^ *iface %s.*"%dev.name, bridgeCfg)
def addDev(self, br, dev):
logging.debug("Haven't implement yet")
def addBridgeAndDev(self, br, dev):
logging.debug("Haven't implement yet")
def writeToCfgFile(self, br, dev):
cfg = file(self.netCfgFile).read()
ifaceDev = re.search("^ *iface %s.*"%dev.name, cfg, re.MULTILINE)
ifaceBr = re.search("^ *iface %s.*"%br, cfg, re.MULTILINE)
if ifaceDev is not None and ifaceBr is not None:
logging.debug("%s:%s already configured"%(br, dev.name))
return True
elif ifaceDev is not None and ifaceBr is None:
#reconfig bridge
self.addBridge(br, dev)
elif ifaceDev is None and ifaceBr is not None:
#reconfig dev
raise CloudInternalException("Missing device configuration, Need to add your network configuration into /etc/network/interfaces at first")
else:
raise CloudInternalException("Missing bridge/device network configuration, need to add your network configuration into /etc/network/interfaces at first")
def config(self):
try:
if super(networkConfigUbuntu, self).isPreConfiged():
return True
self.netMgrRunning = self.syscfg.svo.isServiceRunning("network-manager")
super(networkConfigUbuntu, self).cfgNetwork()
if self.netMgrRunning:
self.syscfg.svo.stopService("network-manager")
self.syscfg.svo.disableService("network-manager")
if not bash("ifup %s"%self.brName).isSuccess():
raise CloudInternalException("Can't start network:%s"%self.brName, bash.getErrMsg(self))
self.syscfg.env.nics.append(self.brName)
self.syscfg.env.nics.append(self.brName)
self.syscfg.env.nics.append(self.brName)
return True
except:
raise
def restore(self):
try:
if self.netMgrRunning:
self.syscfg.svo.enableService("network-manager")
self.syscfg.svo.startService("network-manager")
bash("/etc/init.d/networking stop")
bash("/etc/init.d/networking start")
return True
except:
logging.debug(formatExceptionInfo())
return False
class networkConfigRedhat(serviceCfgBase, networkConfigBase):
def __init__(self, syscfg):
super(networkConfigRedhat, self).__init__(syscfg)
networkConfigBase.__init__(self, syscfg)
def writeToCfgFile(self, brName, dev):
self.devCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%dev.name
self.brCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%brName
isDevExist = os.path.exists(self.devCfgFile)
isBrExist = os.path.exists(self.brCfgFile)
if isDevExist and isBrExist:
logging.debug("%s:%s already configured"%(brName, dev.name))
return True
elif isDevExist and not isBrExist:
#reconfig bridge
self.addBridge(brName, dev)
elif not isDevExist and isBrExist:
#reconfig dev
raise CloudInternalException("Missing device configuration, Need to add your network configuration into /etc/sysconfig/network-scripts at first")
else:
raise CloudInternalException("Missing bridge/device network configuration, need to add your network configuration into /etc/sysconfig/network-scripts at first")
def addBridge(self, brName, dev):
bash("ifdown %s"%dev.name)
if not os.path.exists(self.brCfgFile):
shutil.copy(self.devCfgFile, self.brCfgFile)
#config device file at first: disable nm, set onboot=yes if not
cfo = configFileOps(self.devCfgFile, self)
cfo.addEntry("NM_CONTROLLED", "no")
cfo.addEntry("ONBOOT", "yes")
cfo.addEntry("BRIDGE", brName)
cfo.save()
cfo = configFileOps(self.brCfgFile, self)
cfo.addEntry("NM_CONTROLLED", "no")
cfo.addEntry("ONBOOT", "yes")
cfo.addEntry("DEVICE", brName)
cfo.addEntry("TYPE", "Bridge")
cfo.save()
def config(self):
try:
if super(networkConfigRedhat, self).isPreConfiged():
return True
super(networkConfigRedhat, self).cfgNetwork()
self.netMgrRunning = self.syscfg.svo.isServiceRunning("NetworkManager")
if self.netMgrRunning:
self.syscfg.svo.stopService("NetworkManager")
self.syscfg.svo.disableService("NetworkManager")
if not bash("service network restart").success():
raise CloudInternalException("Can't restart network")
self.syscfg.env.nics.append(self.brName)
self.syscfg.env.nics.append(self.brName)
self.syscfg.env.nics.append(self.brName)
return True
except:
raise
def restore(self):
try:
if self.netMgrRunning:
self.syscfg.svo.enableService("NetworkManager")
self.syscfg.svo.startService("NetworkManager")
bash("service network restart")
return True
except:
logging.debug(formatExceptionInfo())
return False
class cgroupConfig(serviceCfgBase):
def __init__(self, syscfg):
super(cgroupConfig, self).__init__(syscfg)
self.serviceName = "Cgroup"
def config(self):
try:
cfo = configFileOps("/etc/cgconfig.conf", self)
addConfig = "group virt {\n \
cpu {\n \
cpu.shares = 9216;\n \
}\n \
}\n"
cfo.add_lines(addConfig)
self.syscfg.svo.stopService("cgconfig")
self.syscfg.svo.enableService("cgconfig",forcestart=True)
cfo = configFileOps("/etc/cgrules.conf", self)
cfgline = "root:/usr/sbin/libvirtd cpu virt/\n"
cfo.add_lines(cfgline)
self.syscfg.svo.stopService("cgred")
if not self.syscfg.svo.enableService("cgred"):
return False
return True
except:
raise
def restore(self):
try:
self.syscfg.svo.stopService("cgconfig")
self.syscfg.svo.enableService("cgconfig",forcestart=True)
self.syscfg.svo.stopService("cgred")
self.syscfg.svo.enableService("cgred")
return True
except:
logging.debug(formatExceptionInfo())
return False
class securityPolicyConfigUbuntu(serviceCfgBase):
def __init__(self, syscfg):
super(securityPolicyConfigUbuntu, self).__init__(syscfg)
self.serviceName = "Apparmor"
def config(self):
try:
if bash("service apparmor status").getStdout() == "":
self.spRunning = False
return True
bash("service apparmor stop")
bash("update-rc.d -f apparmor remove")
return True
except:
raise CloudRuntimeException("Failed to configure apparmor, please see the /var/log/cloud/setupAgent.log for detail, \
or you can manually disable it before starting myCloud")
def restore(self):
try:
self.syscfg.svo.enableService("apparmor")
self.syscfg.svo.startService("apparmor")
return True
except:
logging.debug(formatExceptionInfo())
return False
class securityPolicyConfigRedhat(serviceCfgBase):
def __init__(self, syscfg):
super(securityPolicyConfigRedhat, self).__init__(syscfg)
self.serviceName = "SElinux"
def config(self):
selinuxEnabled = True
if not bash("selinuxenabled").isSuccess():
selinuxEnabled = False
if selinuxEnabled:
try:
bash("setenforce 0")
cfo = configFileOps("/etc/selinux/config", self)
cfo.replace_line("SELINUX=", "SELINUX=permissive")
return True
except:
raise CloudRuntimeException("Failed to configure selinux, please see the /var/log/cloud/setupAgent.log for detail, \
or you can manually disable it before starting myCloud")
def restore(self):
try:
bash("setenforce 1")
return True
except:
logging.debug(formatExceptionInfo())
return False
class libvirtConfigRedhat(serviceCfgBase):
def __init__(self, syscfg):
super(libvirtConfigRedhat, self).__init__(syscfg)
self.serviceName = "Libvirt"
def config(self):
try:
cfo = configFileOps("/etc/libvirt/libvirtd.conf", self)
cfo.addEntry("listen_tcp", "1")
cfo.addEntry("tcp_port", "\"16509\"")
cfo.addEntry("auth_tcp", "\"none\"")
cfo.addEntry("listen_tls", "0")
cfo.save()
cfo = configFileOps("/etc/sysconfig/libvirtd", self)
cfo.addEntry("export CGROUP_DAEMON", "'cpu:/virt'")
cfo.addEntry("LIBVIRTD_ARGS", "-l")
cfo.save()
cfgline = "cgroup_controllers = [ \"cpu\" ]\n" \
"security_driver = \"none\"\n"
filename = "/etc/libvirt/qemu.conf"
cfo = configFileOps(filename, self)
cfo.add_lines(cfgline)
self.syscfg.svo.stopService("libvirtd")
if not self.syscfg.svo.startService("libvirtd"):
return False
return True
except:
raise
def restore(self):
pass
class libvirtConfigUbuntu(serviceCfgBase):
def __init__(self, syscfg):
super(libvirtConfigUbuntu, self).__init__(syscfg)
self.serviceName = "Libvirt"
def setupLiveMigration(self):
cfo = configFileOps("/etc/libvirt/libvirtd.conf", self)
cfo.addEntry("listen_tcp", "1")
cfo.addEntry("tcp_port", "16509")
cfo.addEntry("auth_tcp", "none")
cfo.addEntry("listen_tls", "0")
cfo.save()
if os.path.exists("/etc/init/libvirt-bin.conf"):
cfo = configFileOps("/etc/init/libvirt-bin.conf", self)
cfo.replace_line("exec /usr/sbin/libvirtd","exec /usr/sbin/libvirtd -d -l")
else:
cfo = configFileOps("/etc/default/libvirt-bin", self)
cfo.replace_or_add_line("libvirtd_opts=","libvirtd_opts='-l -d'")
def config(self):
try:
cfgline = "export CGROUP_DAEMON='cpu:/virt'"
libvirtfile = "/etc/default/libvirt-bin"
cfo = configFileOps(libvirtfile, self)
cfo.add_lines(cfgline)
self.setupLiveMigration()
cfgline = "cgroup_controllers = [ \"cpu\" ]\n" \
"security_driver = \"none\"\n"
filename = "/etc/libvirt/qemu.conf"
cfo = configFileOps(filename, self)
cfo.add_lines(cfgline)
self.syscfg.svo.stopService("libvirt-bin")
self.syscfg.svo.enableService("libvirt-bin")
return True
except:
raise
def restore(self):
try:
self.syscfg.svo.stopService("libvirt-bin")
self.syscfg.svo.startService("libvirt-bin")
return True
except:
logging.debug(formatExceptionInfo())
return False
class firewallConfigUbuntu(serviceCfgBase):
def __init__(self, syscfg):
super(firewallConfigUbuntu, self).__init__(syscfg)
self.serviceName = "Firewall"
def config(self):
try:
ports = "22 1798 16509".split()
for p in ports:
bash("ufw allow %s"%p)
bash("ufw allow proto tcp from any to any port 5900:6100")
bash("ufw allow proto tcp from any to any port 49152:49216")
self.syscfg.svo.stopService("ufw")
self.syscfg.svo.startService("ufw")
return True
except:
raise
def restore(self):
return True
class firewallConfigBase(serviceCfgBase):
def __init__(self, syscfg):
super(firewallConfigBase, self).__init__(syscfg)
self.serviceName = "Firewall"
def allowPort(self, port):
status = False
try:
status = bash("iptables-save|grep INPUT|grep -w %s"%port).isSuccess()
except:
pass
if not status:
bash("iptables -I INPUT -p tcp -m tcp --dport %s -j ACCEPT"%port)
def config(self):
try:
for port in self.ports:
self.allowPort(port)
bash("iptables-save > /etc/sysconfig/iptables")
self.syscfg.svo.stopService("iptables")
self.syscfg.svo.startService("iptables")
return True
except:
raise
def restore(self):
return True
class firewallConfigAgent(firewallConfigBase):
def __init__(self, syscfg):
super(firewallConfigAgent, self).__init__(syscfg)
self.ports = "22 16509 5900:6100 49152:49216".split()
class cloudAgentConfig(serviceCfgBase):
def __init__(self, syscfg):
super(cloudAgentConfig, self).__init__(syscfg)
if syscfg.env.agentMode == "Agent":
self.serviceName = "cloudAgent"
elif syscfg.env.agentMode == "myCloud":
self.serviceName = "myCloud"
elif syscfg.env.agentMode == "Console":
self.serviceName = "Console Proxy"
def configMyCloud(self):
try:
cfo = configFileOps("/etc/cloud/agent/agent.properties", self)
cfo.addEntry("host", self.syscfg.env.mgtSvr)
cfo.addEntry("zone", self.syscfg.env.zone)
cfo.addEntry("port", "443")
cfo.addEntry("private.network.device", self.syscfg.env.nics[0])
cfo.addEntry("public.network.device", self.syscfg.env.nics[1])
cfo.addEntry("guest.network.device", self.syscfg.env.nics[2])
cfo.addEntry("guid", str(self.syscfg.env.uuid))
cfo.addEntry("mount.path", "/mnt")
cfo.addEntry("resource", "com.cloud.storage.resource.LocalSecondaryStorageResource|com.cloud.agent.resource.computing.CloudZonesComputingResource")
cfo.save()
self.syscfg.svo.stopService("cloud-agent")
self.syscfg.svo.startService("cloud-agent")
return True
except:
raise
def configAgent(self):
try:
cfo = configFileOps("/etc/cloud/agent/agent.properties", self)
cfo.addEntry("host", self.syscfg.env.mgtSvr)
cfo.addEntry("zone", self.syscfg.env.zone)
cfo.addEntry("pod", self.syscfg.env.pod)
cfo.addEntry("cluster", self.syscfg.env.cluster)
cfo.addEntry("port", "8250")
cfo.addEntry("private.network.device", self.syscfg.env.nics[0])
cfo.addEntry("public.network.device", self.syscfg.env.nics[1])
cfo.addEntry("guest.network.device", self.syscfg.env.nics[2])
cfo.addEntry("guid", str(self.syscfg.env.uuid))
cfo.addEntry("resource", "com.cloud.agent.resource.computing.LibvirtComputingResource")
cfo.save()
self.syscfg.svo.stopService("cloud-agent")
self.syscfg.svo.startService("cloud-agent")
return True
except:
raise
def configConsole(self):
try:
cfo = configFileOps("/etc/cloud/agent/agent.properties", self)
cfo.addEntry("host", self.syscfg.env.mgtSvr)
cfo.addEntry("zone", self.syscfg.env.zone)
cfo.addEntry("pod", self.syscfg.env.pod)
cfo.addEntry("cluster", self.syscfg.env.cluster)
cfo.addEntry("port", "8250")
cfo.addEntry("private.network.device", self.syscfg.env.nics[0])
cfo.addEntry("public.network.device", self.syscfg.env.nics[1])
cfo.addEntry("guest.network.device", self.syscfg.env.nics[2])
cfo.addEntry("guid", str(self.syscfg.env.uuid))
cfo.addEntry("resource", "com.cloud.agent.resource.computing.consoleProxyResource")
cfo.save()
self.syscfg.svo.stopService("cloud-agent")
self.syscfg.svo.startService("cloud-agent")
return True
except:
raise
def config(self):
if self.syscfg.env.agentMode == "Agent":
return self.configAgent()
elif self.syscfg.env.agentMode == "myCloud":
return self.configMyCloud()
elif self.syscfg.env.agentMode == "console":
return self.configConsole()
def restore(self):
return True
class sudoersConfig(serviceCfgBase):
def __init__(self, syscfg):
super(sudoersConfig, self).__init__(syscfg)
self.serviceName = "sudoers"
def config(self):
try:
cfo = configFileOps("/etc/sudoers", self)
cfo.addEntry("cloud ALL ", "NOPASSWD : ALL")
cfo.rmEntry("Defaults", "requiretty", " ")
cfo.save()
return True
except:
raise
def restore(self):
return True
class firewallConfigServer(firewallConfigBase):
def __init__(self, syscfg):
super(firewallConfigServer, self).__init__(syscfg)
if self.syscfg.env.svrMode == "myCloud":
self.ports = "443 8080 8096 8250 8443".split()
else:
self.ports = "8080 8096 8250".split()

View File

@ -0,0 +1,74 @@
from db import Database
from configFileOps import configFileOps
from serviceConfig import serviceCfgBase
from cloudException import CloudRuntimeException, CloudInternalException
from utilities import bash
import os
class cloudManagementConfig(serviceCfgBase):
def __init__(self, syscfg):
super(cloudManagementConfig, self).__init__(syscfg)
self.serviceName = "CloudStack Management Server"
def config(self):
if self.syscfg.env.svrMode == "mycloud":
cfo = configFileOps("/usr/share/cloud/management/conf/environment.properties", self)
cfo.addEntry("cloud-stack-components-specification", "components-cloudzones.xml")
cfo.save()
cfo = configFileOps("/usr/share/cloud/management/conf/db.properties", self)
dbHost = cfo.getEntry("db.cloud.host")
dbPort = cfo.getEntry("db.cloud.port")
dbUser = cfo.getEntry("db.cloud.username")
dbPass = cfo.getEntry("db.cloud.password")
if dbPass.strip() == "":
dbPass = None
dbName = cfo.getEntry("db.cloud.name")
db = Database(dbUser, dbPass, dbHost, dbPort, dbName)
try:
db.testConnection()
except CloudRuntimeException, e:
raise e
except:
raise CloudInternalException("Failed to connect to Mysql server")
try:
statement = """ UPDATE configuration SET value='%s' WHERE name='%s'"""
db.execute(statement%('true','use.local.storage'))
db.execute(statement%('20','max.template.iso.size'))
statement = """ UPDATE vm_template SET url='%s',checksum='%s' WHERE id='%s' """
db.execute(statement%('https://rightscale-cloudstack.s3.amazonaws.com/kvm/RightImage_CentOS_5.4_x64_v5.6.28.qcow2.bz2', '90fcd2fa4d3177e31ff296cecb9933b7', '4'))
statement="""UPDATE disk_offering set use_local_storage=1"""
db.execute(statement)
except:
raise e
#add DNAT 443 to 8250
if not bash("iptables-save |grep PREROUTING | grep 8250").isSuccess():
bash("iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 8250 ")
#generate keystore
keyPath = "/var/lib/cloud/management/web.keystore"
if not os.path.exists(keyPath):
cmd = bash("keytool -genkey -keystore %s -storepass \"cloud.com\" -keypass \"cloud.com\" -validity 3650 -dname cn=\"Cloudstack User\",ou=\"mycloud.cloud.com\",o=\"mycloud.cloud.com\",c=\"Unknown\""%keyPath)
if not cmd.isSuccess():
raise CloudInternalException(cmd.getErrMsg())
cfo = configFileOps("/etc/cloud/management/tomcat6.conf", self)
cfo.add_lines("JAVA_OPTS+=\" -Djavax.net.ssl.trustStore=%s \""%keyPath)
try:
self.syscfg.svo.disableService("tomcat6")
except:
pass
if self.syscfg.svo.enableService("cloud-management"):
return True
else:
raise CloudRuntimeException("Failed to configure %s, please see the /var/log/cloud/setupManagement.log for detail"%self.serviceName)

View File

@ -0,0 +1,141 @@
from utilities import DistributionDetector, serviceOpsRedhat,serviceOpsUbuntu
from serviceConfig import *
class sysConfigFactory:
@staticmethod
def getSysConfigFactory(glbEnv):
if glbEnv.mode == "Agent":
return sysConfigAgentFactory.getAgent(glbEnv)
elif glbEnv.mode == "Server":
return sysConfigServerFactory.getServer(glbEnv)
elif glbEnv.mode == "Db":
return sysConfigDbFactory.getDb(glbEnv)
else:
raise CloudInternalException("Need to specify which mode are u running: Agent/Server/Db")
class sysConfigAgentFactory:
@staticmethod
def getAgent(glbEnv):
distribution = DistributionDetector().getVersion()
if distribution == "Ubuntu":
return sysConfigAgentUbuntu(glbEnv)
elif distribution == "Fedora":
return sysConfigRedhat6(glbEnv)
elif distribution == "CentOS" or distribution == "RHEL5":
return sysConfigRedhat5(glbEnv)
else:
print "Can't find the distribution version"
return sysConfig()
class sysConfigServerFactory:
@staticmethod
def getServer(glbEnv):
distribution = DistributionDetector().getVersion()
if distribution == "Ubuntu":
return sysConfigServerUbuntu(glbEnv)
elif distribution != "Unknown":
return sysConfigServerRedhat(glbEnv)
else:
print "Can't find the distribution version"
return sysConfig()
class sysConfigDbFactory:
@staticmethod
def getDb(glbEnv):
pass
class sysConfig(object):
def __init__(self, env):
self.env = env
self.services = []
def registerService(self, service):
self.services.append(service)
def config(self):
if not self.check():
return False
for service in self.services:
if not service.configration():
raise CloudInternalException()
def restore(self):
for service in self.services:
service.backup()
def check(self):
return True
class sysConfigAgent(sysConfig):
def check(self):
if self.env.debug:
return True
if os.geteuid() != 0:
raise CloudInternalException("Need to execute with root permission")
kvmEnabled = self.svo.isKVMEnabled()
if not kvmEnabled:
raise CloudInternalException("Checking KVM...[Failed]\nPlease enable KVM on this machine\n")
return True
class sysConfigAgentRedhatBase(sysConfigAgent):
def __init__(self, env):
self.svo = serviceOpsRedhat()
super(sysConfigAgentRedhatBase, self).__init__(env)
class sysConfigAgentUbuntu(sysConfigAgent):
def __init__(self, glbEnv):
super(sysConfigAgentUbuntu, self).__init__(glbEnv)
self.svo = serviceOpsUbuntu()
self.services = [cgroupConfig(self),
securityPolicyConfigUbuntu(self),
networkConfigUbuntu(self),
libvirtConfigUbuntu(self),
firewallConfigUbuntu(self),
cloudAgentConfig(self)]
#it covers RHEL6/Fedora13/Fedora14
class sysConfigRedhat6(sysConfigAgentRedhatBase):
def __init__(self, glbEnv):
super(sysConfigRedhat6, self).__init__(glbEnv)
self.services = [cgroupConfig(self),
securityPolicyConfigRedhat(self),
networkConfigRedhat(self),
libvirtConfigRedhat(self),
firewallConfigAgent(self),
cloudAgentConfig(self)]
#It covers RHEL5/CentOS5, the mainly difference is that there is no cgroup
class sysConfigRedhat5(sysConfigAgentRedhatBase):
def __init__(self, glbEnv):
super(sysConfigRedhat5, self).__init__(glbEnv)
self.services = [
securityPolicyConfigRedhat(self),
networkConfigRedhat(self),
libvirtConfigRedhat(self),
firewallConfigAgent(self),
cloudAgentConfig(self)]
class sysConfigServer(sysConfig):
def check(self):
if os.geteuid() != 0:
raise CloudInternalException("Need to execute with root permission")
return True
class sysConfigServerRedhat(sysConfigServer):
def __init__(self, glbEnv):
super(sysConfigServerRedhat, self).__init__(glbEnv)
self.svo = serviceOpsRedhat()
self.services = [sudoersConfig(self),
firewallConfigServer(self)]
class sysConfigServerUbuntu(sysConfigServer):
def __init__(self, glbEnv):
super(sysConfigServerUbuntu, self).__init__(glbEnv)
self.svo = serviceOpsUbuntu()
self.services = [sudoersConfig(self),
firewallConfigServer(self)]

View File

@ -0,0 +1,175 @@
from cloudException import CloudRuntimeException, formatExceptionInfo
import logging
from subprocess import PIPE, Popen
from signal import alarm, signal, SIGALRM, SIGKILL
import sys
import os
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:
logging.debug("Failed to execute:" + self.getErrMsg())
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 getErrMsg(self):
if self.isSuccess():
return ""
if self.getStderr() is None or self.getStderr() == "":
return self.getStdout()
else:
return self.getStderr()
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):
if msg is not None:
output = "%-30s"%msg
elif result is True:
output = "[%-2s]\n"%"OK"
elif result is False:
output = "[%-6s]\n"%"Failed"
sys.stdout.write(output)
sys.stdout.flush()
class DistributionDetector:
def __init__(self):
self.distro = "Unknown"
if os.path.exists("/etc/fedora-release"):
self.distro = "Fedora"
elif os.path.exists("/etc/centos-release"):
self.distro = "CentOS"
elif os.path.exists("/etc/redhat-release"):
version = file("/etc/redhat-release").readline()
if version.find("Red Hat Enterprise Linux Server release 6") != -1:
self.distro = "RHEL6"
elif version.find("CentOS release") != -1:
self.distro = "CentOS"
else:
self.distro = "RHEL5"
elif os.path.exists("/etc/legal") and "Ubuntu" in file("/etc/legal").read(-1):
self.distro = "Ubuntu"
else:
self.distro = "Unknown"
def getVersion(self):
return self.distro
class serviceOps:
pass
class serviceOpsRedhat(serviceOps):
def isServiceRunning(self, servicename):
try:
o = bash("service " + servicename + " status")
if "start/running" in o.getStdout():
return True
else:
return False
except:
return False
def stopService(self, servicename,force=False):
if self.isServiceRunning(servicename) or force:
return bash("service " + servicename +" stop").isSuccess()
return True
def disableService(self, servicename):
result = self.stopService(servicename)
bash("chkconfig --del " + servicename)
return result
def startService(self, servicename,force=False):
if not self.isServiceRunning(servicename) or force:
return bash("service " + servicename + " start").isSuccess()
return True
def enableService(self, servicename,forcestart=False):
bash("chkconfig --level 2345 " + servicename + " on")
return self.startService(servicename,force=forcestart)
def isKVMEnabled(self):
if os.path.exists("/dev/kvm"):
return True
else:
return False
class serviceOpsUbuntu(serviceOps):
def isServiceRunning(self, servicename):
try:
o = bash("service " + servicename + " status")
if "start/running" in o.getStdout():
return True
else:
return False
except:
return False
def stopService(self, servicename,force=False):
if self.isServiceRunning(servicename) or force:
return bash("service " + servicename +" stop").isSuccess()
def disableService(self, servicename):
result = self.stopService(servicename)
bash("update-rc.d -f " + servicename + " remove")
return result
def startService(self, servicename,force=False):
if not self.isServiceRunning(servicename) or force:
return bash("service " + servicename + " start").isSuccess()
def enableService(self, servicename,forcestart=False):
bash("update-rc.d -f " + servicename + " remove")
bash("update-rc.d -f " + servicename + " start 2 3 4 5 .")
return self.startService(servicename,force=forcestart)
def isKVMEnabled(self):
return bash("kvm-ok").isSuccess()

View File

@ -343,6 +343,7 @@ def build_xml_api_description ():
)
bld.install_files("${PYTHONDIR}/cloudtool", 'cloud-cli/cloudtool/*')
bld.install_files("${PYTHONDIR}/cloudutils", 'python/lib/cloudutils/*')
bld.install_as("${PYTHONDIR}/cloudapis.py", 'cloud-cli/cloudapis/cloud.py')