#!/usr/bin/env python """builds the entire stack""" #For every matching build change here, that produces new installable #files, the cloud.spec file and the Debian control files must be #revised and tested. import shutil,os import Utils,Node,Options,Logs,Scripting,Environment,Build,Configure from os import unlink as _unlink, makedirs as _makedirs, getcwd as _getcwd, chdir as _chdir from os.path import abspath as _abspath, basename as _basename, dirname as _dirname, exists as _exists, isdir as _isdir, split as _split, join as _join, sep, pathsep, pardir, curdir from glob import glob as _glob from subprocess import Popen as _Popen,PIPE try: set([1,2,3]) except Exception: from Sets import set import re import zipfile,tarfile import time try: from os import chmod as _chmod,chown as _chown import pwd,stat,grp except ImportError: _chmod,_chown,pwd,stat,grp = (None,None,None,None,None) # Global variables setup sourcedir = bld.srcnode.abspath() builddir = bld.path.abspath(bld.env) #buildpremium = _exists(_join(sourcedir,"cloudstack-proprietary")) buildpremium = False filelist = bld.path.ant_glob distdir = Utils.relpath(_join(sourcedir,"dist")) targetdir = Utils.relpath(_join(sourcedir,"target")) def gitinfo(dir=None): if dir and not _isdir(dir): return '' try: p = _Popen(['git','remote','show','-n','origin'],stdin=PIPE,stdout=PIPE,stderr=PIPE,cwd=dir) except OSError,e: if e.errno == 2: return '' # svn command is not installed raise stdout,stderr = p.communicate('') retcode = p.wait() # If the guess fails, just return nothing. if retcode: return stdout = [ s.strip() for s in stdout.splitlines() ] try: url = [ s[11:] for s in stdout if s.startswith("Fetch URL") ][0] except IndexError: url = [ s[5:] for s in stdout if s.startswith("URL") ][0] assert url p = _Popen(['git','log','-1'],stdin=PIPE,stdout=PIPE,stderr=PIPE,cwd=dir) stdout,stderr = p.communicate('') retcode = p.wait() if retcode: return # If the guess fails, just return nothing. stdout = [ s.strip() for s in stdout.splitlines() ] commitid = [ s.split()[1] for s in stdout if s.startswith("commit") ][0] assert commitid return "Git Revision: %s"%commitid + "\n" + "Git URL: %s"%url + "\n" def build_utils_docs (): stdout = gitinfo() if stdout: f = file("sccs-info","w") f.write(stdout) f.flush() f.close() else: if _exists("sccs-info"): # If the file already existed, we preserve it return else: f = file("sccs-info","w") f.write("No revision control information could be detected when the source distribution was built.") f.flush() f.close() sccsinfo = _join(sourcedir,"sccs-info") if _exists(sccsinfo): bld.install_files("${DOCDIR}","sccs-info") tgen = bld(features='subst', name='configure-info', source="configure-info.in", target="configure-info") tgen.dict = {"CONFIGUREVARS":bld.getconfig()} bld.install_files("${DOCDIR}","configure-info") # compile jar files using ant # ant only needs to be reinvoked if the version with build number changes # we here trim all the depended targets from the target list: def build_jars (): Implementation_Version = bld.env.VERSION # this is to trigger recompilation / cache avoidance if the relevant environment for ant changes ant_args = [ "build-all", "-Dimpl.version=%s" % Implementation_Version, "-Dtarget.dir=%s" % targetdir, "-Ddist.dir=%s" % distdir, "-Dbase.dir=%s" % sourcedir, "-f %s" % Utils.relpath (_join(sourcedir, "build.xml")), ] if buildpremium: ant_args.append("-Dbuild.premium=true") tgen = bld(features='subst', name='version-info', source="version-info.in", target="version-info") tgen.dict = { "Implementation_Version":Implementation_Version,"ant_args":ant_args } bld.install_files("${DOCDIR}","version-info") bld.srcnode.ensure_dir_node_from_path("target/jar") bld.srcnode.ensure_dir_node_from_path("dist") tgen = bld.new_task_gen (rule = Utils.runant, name = "runant", antargs = ant_args) jarnode = bld.srcnode.find_dir ('target/jar') jars_str = jarnode.ant_glob ('*.jar').split () ant_jars = [] excludes = ["cloud-xstream-1.3.1.jar", "cloud-commons-dbcp-1.2.2.jar", "cloud-commons-httpclient-3.1.jar", "cloud-commons-pool-1.4.jar", "cloud-servlet-api.jar", "cloud-commons-logging-1.1.1.jar", "cloud-ws-commons-util-1.0.2.jar", "cloud-commons-collections-3.2.1.jar", "vmware*.jar", "cloud-secstorage-extras.jar", "cloud-agent-simulator.jar", "cloud-awsapi.jar", "cloud-test.jar", "cloud-wsdl4j.jar", "cloud-console-proxy.jar"] for a in jars_str: if _basename (a).startswith ("cloud-") \ and not _basename (a) in excludes: a = jarnode.abspath () + os.sep + a ant_jars.append (a) bld.install_files ('${JAVADIR}', ant_jars) def build_premium (): if buildpremium: bld.recurse(["cloudstack-proprietary/"],'build') def build_thirdparty_dir (): start_path = bld.path.find_dir ("thirdparty") bld.install_files('${PREMIUMJAVADIR}','*.jar', cwd = start_path) Utils.pprint ("GREEN", "Installed files of thirdparty/") def build_dependences (): excludes = ["cloud-xstream-1.3.1.jar", "cloud-servlet-api.jar", "cloud-commons-logging-1.1.1.jar", "cloud-ws-commons-util-1.0.2.jar", "cloud-commons-collections-3.2.1.jar", "cloud-wsdl4j.jar"] start_path = bld.path.find_dir ("deps") bld.install_files('${JAVADIR}',start_path.ant_glob("*.jar", excl = excludes), cwd=start_path) if buildpremium: start_path = bld.path.find_dir ("cloudstack-proprietary/premium/deps") bld.install_files('${JAVADIR}',start_path.ant_glob("*.jar", excl = excludes), cwd=start_path) #def build_console_proxy (): # binary unsubstitutable files: # start_path = bld.path.find_dir ("console-proxy") # bld.install_files("${CPLIBDIR}",start_path.ant_glob("images/**",src=True,bld=False,dir=False,flat=True),cwd=start_path,relative_trick=True) # text substitutable files (substitute with tokens from the environment bld.env): # bld.substitute('css/** js/** ui/** scripts/**',install_to="${CPLIBDIR}", cwd=start_path) # config files (do not replace them if preserve config option is true) # if not Options.options.PRESERVECONFIG: bld.install_files_filtered("${CPSYSCONFDIR}","conf.dom0/*", cwd=start_path) def build_patches (): # done here because the patches require substituted files start_path = bld.path.find_dir ("patches") bld.substitute("*/**",name="patchsubst", cwd = start_path) for virttech in Utils.to_list(start_path.ant_glob("*",dir=True)): if virttech in ["shared"]: continue patchfiles = start_path.ant_glob('shared/** %s/debian/config/**'%virttech,src=False,bld=True,dir=False,flat=True) tmp = bld.path bld.path = start_path tgen = bld( features = 'tar',#Utils.tar_up, source = patchfiles, target = 'cloud-scripts.tgz', name = 'cloud-scripts_tgz', root = os.path.join("patches", virttech + "/debian/config"), rename = lambda x: re.sub(".subst$","",x), ) bld.path = tmp def build_systemvm_patch (): if bld.env.DISTRO not in ["Windows","Mac"]: # patch creation bld.install_files ("${AGENTLIBDIR}/vms", "%s/systemvm.zip" % distdir) # ISO creation bld.install_as("${AGENTLIBDIR}/vms/systemvm.iso", "%s/systemvm.iso" % distdir) def build_systemvm_iso (): if buildpremium: bld.install_as("${AGENTLIBDIR}/vms/systemvm-premium.iso", "%s/systemvm-premium.iso" % distdir) # =================== Empty directory / symlink creation on install target ==================== def build_dirs_symlinks (): bld.createuser(bld.env.MSUSER,bld.env.MSENVIRON,'/bin/sh') # 7. make log and cache dirs (this actually runs first) if bld.env.DISTRO in 'Windows Mac': pass else: x = ("root",bld.env.MSUSER) directories = [ ("${MSLOGDIR}",0770,x), ("${AGENTLOGDIR}",0770,x), ("${USAGELOGDIR}",0770,x), # ("${CPLOGDIR}",0770,x), ("${IPALLOCATORLOGDIR}",0770,x), ("${LOCALSTATEDIR}/cache/${MSPATH}",0770,x), ("${LOCALSTATEDIR}/cache/${MSPATH}/temp",0770,x), ("${LOCALSTATEDIR}/cache/${MSPATH}/work",0770,x), ("${SHAREDSTATEDIR}/${MSPATH}",0770,x), ("${MSMNTDIR}",0770,x), ("${MSCONF}/Catalina",0770,x), ("${MSCONF}/Catalina/localhost",0770,x), ("${MSCONF}/Catalina/localhost/client",0770,x), ("${PIDDIR}",0755,("root","root")), ("${LOCKDIR}",0755,("root","root")), ] for a,mode,owner in directories: s = bld.subst_add_destdir(a,bld) if Options.is_install: bld.install_dir(a) bld.setownership(a,owner[0],owner[1],mode) # 8. create environment symlinks symlinks = [ ('${MSENVIRON}/bin', '${TOMCATHOME}/bin'), ('${MSENVIRON}/lib', '${TOMCATHOME}/lib'), ('${MSENVIRON}/logs', "${MSLOGDIR}"), ('${MSENVIRON}/temp', '${LOCALSTATEDIR}/cache/${MSPATH}/temp'), ('${MSENVIRON}/work','${LOCALSTATEDIR}/cache/${MSPATH}/work'), ('${MSENVIRON}/conf', '${SYSCONFDIR}/${MSPATH}'), # ("${AGENTLIBDIR}/css", '${CPLIBDIR}/css'), # ("${AGENTLIBDIR}/images", '${CPLIBDIR}/images'), # ("${AGENTLIBDIR}/js", '${CPLIBDIR}/js'), # ("${AGENTLIBDIR}/ui", '${CPLIBDIR}/ui'), ("${MSCONF}/server.xml", '${MSCONF}/server-nonssl.xml'), ("${MSCONF}/tomcat6.conf", '${MSCONF}/tomcat6-nonssl.conf'), ] for lnk,dst in symlinks: bld.symlink_as(lnk,Utils.subst_vars(dst,bld.env)) def build_scripts (): start_path = bld.path.find_dir ("scripts") bld.substitute('**',"${AGENTLIBDIR}/scripts",chmod=0755, cwd=start_path) def build_bin_exec_dirs (): #bld.install_files_filtered("${LIBEXECDIR}","*/libexec/* cloudstack-proprietary/*/libexec/*",chmod=0755) #bld.install_files_filtered("${BINDIR}","*/bindir/* cloudstack-proprietary/*/bindir/*",chmod=0755) #bld.install_files_filtered("${SBINDIR}","*/sbindir/* cloudstack-proprietary/*/sbindir/*",chmod=0755) bld.install_files_filtered("${LIBEXECDIR}","*/libexec/*",chmod=0755) bld.install_files_filtered("${BINDIR}","*/bindir/*",chmod=0755) bld.install_files_filtered("${SBINDIR}","*/sbindir/*",chmod=0755) def build_server_client (): start_path = bld.path.find_dir("client/WEB-INF") bld.install_files('${MSENVIRON}/webapps/client/WEB-INF', start_path.ant_glob("**",src=True,bld=False,dir=False,flat=True), cwd=start_path,relative_trick=True) start_path = bld.path.find_dir("client") bld.install_files("${MSCONF}/resources",'WEB-INF/classes/resources/*.properties',chmod=0640, cwd=start_path) if not Options.options.PRESERVECONFIG: bld.install_files_filtered("${MSCONF}","tomcatconf/*", cwd=start_path) bld.install_files("${MSCONF}",'tomcatconf/db.properties',chmod=0640, cwd=start_path) bld.setownership("${MSCONF}/db.properties","root",bld.env.MSUSER) start_path = bld.path.find_dir("server") if not Options.options.PRESERVECONFIG: bld.install_files_filtered("${SERVERSYSCONFDIR}","conf/*", cwd=start_path) def build_agent (): start_path = bld.path.find_dir ("agent") bld.install_files("${AGENTLIBDIR}", start_path.ant_glob("storagepatch/**",src=True,bld=False,dir=False,flat=True), cwd=start_path,relative_trick=True) if not Options.options.PRESERVECONFIG: bld.install_files_filtered("${AGENTSYSCONFDIR}","conf/*", cwd = start_path) def build_ui (): # binary unsubstitutable files: start_path = bld.path.find_dir ("ui") bld.install_files ("${MSENVIRON}/webapps/client",start_path.ant_glob("*.ico **/*png **/*jpg **/*gif",src=True,bld=False,dir=False,flat=True),cwd=start_path,relative_trick=True) # text substitutable files (substitute with tokens from the environment bld.env): bld.substitute ("*html **/*html **/*js **/*css **/*properties **/*jsp *jsp",install_to="${MSENVIRON}/webapps/client", cwd=start_path) def build_conf_files (): # apply distro-specific config on top of the 'all' generic cloud-management config globspec = _join("*","distro",bld.env.DISTRO.lower(),"*") # matches premium/distro/centos/SYSCONFDIR #distrospecificdirs=_glob(globspec) + _glob(_join("cloudstack-proprietary",globspec)) distrospecificdirs=_glob(globspec) for dsdir in distrospecificdirs: start_path = bld.srcnode.find_dir(dsdir) subpath,varname = _split(dsdir) dsdirwithvar = _join("${%s}"%varname) files = filelist('%s/**'%dsdir,src=True,bld=False,dir=False,flat=True) mode = 0644 if "SYSCONFDIR" in dsdir: mode = 0755 if Options.options.PRESERVECONFIG: continue bld.install_files_filtered(dsdirwithvar, files, cwd=start_path, relative_trick=True,chmod=mode) # cloudstack-proprietary still has db files for usage def build_db_files (): #bld.install_files_filtered("${SETUPDATADIR}",filelist("*/db/* cloudstack-proprietary/*/db/*",excl=Node.exclude_regs + "\ncloud-gate\ncloud-bridge")) start_path = bld.path.find_dir ("setup/db") bld.substitute('**',"${SETUPDATADIR}", cwd=start_path) if buildpremium: start_path = bld.path.find_dir ("cloudstack-proprietary/premium/db") bld.substitute('**',"${SETUPDATADIR}", cwd=start_path) def build_plugins (): # ====================== Feature-specific plugins ======================== for plugin in _glob(_join("plugins","*")) + _glob(_join("cloudstack-proprietary","plugins","*")): if not _exists(_join(plugin,"build.xml")): continue pluginname = _basename(plugin) target = 'target/jar/cloud-%s.jar' % pluginname sources = filelist( '%s/**/*.java' % plugin.replace(sep,"/") , src=True, bld=False, dir=False ) tgen = bld(rule=lambda x: runant("compile-%s"%pluginname), name='compile_%s'%pluginname, source=sources, target=target, after='runant') bld.install_files('${PLUGINJAVADIR}',target) # ====================== End feature-specific plugins ==================== # ====================== Vendor-specific plugins ======================== for vendor in _glob(_join("vendor","*")) + _glob(_join("cloudstack-proprietary","vendor","*")): if not Options.options.PRESERVECONFIG: bld.install_files_filtered("${MSCONF}/%s"%vendor,filelist("%s/tomcatconf/*"%vendor)) # ====================== End vendor-specific plugins ==================== def build_xml_api_description (): def generate_xml_api_description(task): relationship = Utils.relpath(sourcedir,os.getcwd()) cp = [ _join(relationship,x) for x in task.generator.env.CLASSPATH.split(pathsep) ] jarnames = ['utils','server','core', 'api', 'server-extras'] props = ["client/tomcatconf/commands.properties.in"] sources = [] for i in jarnames: str = 'target/jar/cloud-%s.jar' % i sources.append (str) sources.append ("client/tomcatconf/commands.properties.in") if buildpremium: sources.append("client/tomcatconf/commands-ext.properties.in") buildproducts = [] for i in sources: path = bld.path.abspath() + os.sep + i buildproducts.append (path) jars = [ x for x in buildproducts if x.endswith("jar") ] properties = [ x for x in buildproducts if x.endswith("properties.in") ] cp += jars cp = pathsep.join(cp) arguments = ["-f",",".join(properties),"-d",builddir] ret = Utils.exec_command(["java","-cp",cp,"com.cloud.api.doc.ApiXmlDocWriter"]+arguments,log=True) return ret #TODO: We can't use 'source' token here because task_gen check if sources # exist before all task_gen. This bring a problem that 'runant' task doesn't # run when the check happen, which results in no source found at target/jar. # Ask waf community to fix that tgen = bld.new_task_gen ( rule = generate_xml_api_description, target = 'commands.xml', name = 'xmlapi', after = 'runant', install_path="${CLIDIR}" ) bld.install_as("${PYTHONDIR}/cloud_utils.py", 'python/lib/cloud_utils.py') 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') def build_ovm(): start_path = bld.path.find_dir("plugins/hypervisors/ovm/scripts") bld.substitute('**',"${AGENTLIBDIR}/scripts",chmod=0755, cwd=start_path) def build_test(): start_path = bld.path.find_dir("test/scripts") bld.install_files('${LIBDIR}/${PACKAGE}/test', \ start_path.ant_glob("**",src=True,bld=False,dir=False,flat=True), \ cwd=start_path,relative_trick=True) start_path = bld.path.find_dir("test/metadata") bld.install_files('${SHAREDSTATEDIR}/${PACKAGE}/test', \ start_path.ant_glob("**",src=True,bld=False,dir=False,flat=True), \ cwd=start_path,relative_trick=True) if not Options.options.PRESERVECONFIG: start_path = bld.path.find_dir("test") bld.install_files('${SYSCONFDIR}/${PACKAGE}/test','conf/*', cwd = start_path) Utils.pprint ("GREEN", "Installed files of test/") def build_usage_dir (): start_path = bld.path.find_dir ("usage") bld.install_files_filtered("${USAGESYSCONFDIR}","conf/*", cwd = start_path) bld.symlink_as("${USAGESYSCONFDIR}/db.properties", \ Utils.subst_vars("${MSCONF}/db.properties",bld.env)) Utils.pprint ("GREEN", "Installed files of usage/") # Get started to execute here build_utils_docs () build_jars () build_premium () #build_thirdparty_dir() build_dependences () #build_patches () build_systemvm_patch () build_dirs_symlinks () build_scripts () build_bin_exec_dirs () build_server_client () build_agent () build_ui () build_conf_files () build_db_files () build_plugins () build_xml_api_description () build_ovm () #build_test() build_usage_dir() # ====================== Magic! ========================================= bld.use_the_magic()