diff --git a/client/pom.xml b/client/pom.xml
index c55d5b7b44b..2fb558691ac 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -693,6 +693,7 @@
+
diff --git a/scripts/installer/windows/WixInstallerDialog.wxs b/scripts/installer/windows/WixInstallerDialog.wxs
index b0f510bf29b..0282d8ace76 100644
--- a/scripts/installer/windows/WixInstallerDialog.wxs
+++ b/scripts/installer/windows/WixInstallerDialog.wxs
@@ -57,6 +57,19 @@
1
1
1
+
+
+ !(loc.GenerateSSLKey)
+ !(loc.DeployDB)
+ !(loc.SetupDatabases)
+ !(loc.DeleteDirectory)
+ !(loc.CopySitePackages)
+ !(loc.SetuptoolsInstallation)
+ !(loc.DeleteFiles)
+ !(loc.UpdateTomcatCatalinaBase)
+ !(loc.UpdateTomcatClassPath)
+
+
diff --git a/scripts/installer/windows/acs.wxs b/scripts/installer/windows/acs.wxs
index 8206afae2cb..58af6509782 100644
--- a/scripts/installer/windows/acs.wxs
+++ b/scripts/installer/windows/acs.wxs
@@ -81,8 +81,11 @@
Name="CATALINA_OPTS" Permanent="no" System="yes"
Value="-XX:MaxPermSize=512m -Xmx1024m -Xms256m" />
+ Permanent="no" System="yes" Part="last"
+ Value="[JAVA_HOME]bin;[PYTHON_HOME];[SEVENZ_HOME];[ProgramFilesFolder]cdrtools;[MYSQL]bin;[INSTALLDIR]scripts" />
+
@@ -235,31 +238,31 @@
+ Property="TOMCATDIRECTORY1" Execute="deferred" Return="check" />
+ Property="TOMCATDIRECTORY1" Execute="deferred" Return="check" />
+ Execute="deferred" Return="check"/>
+ Execute="deferred" Return="check" />
+ Execute="deferred" Return="check" />
+ Execute="deferred" Return="check" />
+ Execute="deferred" Return="check" />
+ Execute="deferred" Return="check" Impersonate="no"/>
+ Execute="deferred" Return="check" Impersonate="no"/>
@@ -270,9 +273,9 @@
Installed
NOT Installed
NOT Installed
- NOT Installed
+ NOT Installed
- NOT Installed
+ NOT Installed
NOT Installed
(NOT Installed) AND (CREATE_DATABASE = "1")
diff --git a/scripts/installer/windows/en-us.wxl b/scripts/installer/windows/en-us.wxl
index b43393c16cc..b5a98ecbc84 100644
--- a/scripts/installer/windows/en-us.wxl
+++ b/scripts/installer/windows/en-us.wxl
@@ -28,6 +28,15 @@
Password
Root Password
Create Cloud Stack Database
+ Generating SSL Keys which is needed to talk to Management Server.
+ Creating Database and needed Schemas for management server.
+ Updating db.properties with the given database configuration.
+ Deleting un-necessary directories from installation directory.
+ Copying Management Server related python libraries.
+ Installing Setup Tools for Python.
+ Deleting un-necessary files from installation directory.
+ Updating Tomcat Catalina Base with Management Server Home.
+ Updating Tomcat Classpath with necessary paths.
Version 4.0.0.0
\ No newline at end of file
diff --git a/scripts/storage/secondary/cloud-install-sys-tmplt.py b/scripts/storage/secondary/cloud-install-sys-tmplt.py
new file mode 100644
index 00000000000..632450e01a1
--- /dev/null
+++ b/scripts/storage/secondary/cloud-install-sys-tmplt.py
@@ -0,0 +1,236 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with 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 argparse
+import sys
+import urllib
+import uuid
+import subprocess
+import os
+import shutil
+import gzip
+import zipfile
+import bz2
+
+class InstallSysTemplate(object):
+ parser = None
+ mountpoint = None
+ args = None
+ hypervisor = None
+ systemvmtemplatepath = None
+ systemvmtemplateurl = None
+ managementsecretkey = None
+ forcecleanup = None
+ databasehostname = None
+ databaseusername = None
+ databaseuserpassword = None
+ templatesuffix = None
+ template = None
+ fileextension = None
+ templateName = None
+ destDir = None
+ fileSize = None
+ dictionary = None
+
+ def __init__(self):
+ self.dictionary = dict(xenserver=('XenServer', 'vhd'), kvm=('KVM', 'qcow2'), vmware=('VMware', 'ova'), lxc=('LXC', 'qcow2'), hyperv=('Hyperv', 'vhd'))
+
+ def parseOptions(self):
+ self.parser = argparse.ArgumentParser(prog="System Template Installer")
+ self.parser.add_argument("-m", "--mount-point", action="store", dest="mountpoint", help="Secondary Storage Mount Point where to install the temlate.", required="true")
+ self.parser.add_argument("-H", "--hypervisor", action="store", dest="hypervisor", help="The Hypervisor name for which template need to be installed", required="true", choices=['kvm','xenserver','vmware','lxc','hyperv'])
+ group = self.parser.add_mutually_exclusive_group(required=True)
+ group.add_argument("-f", "--system-vm-template", action="store", dest="systemvmtemplatepath", help="The local system vm template file path")
+ group.add_argument("-u", "--system-vm-template-url", action="store", dest="systemvmtemplateurl", help="Url to download system vm template")
+ self.parser.add_argument("-s", "--management-secret-key", action="store", dest="managementsecretkey", help="mgmt server secret key, if you specified any when running cloudstack-setup-database, default is password", default="password")
+ self.parser.add_argument("-F", "--force-clean-up", action="store_true", dest="forcecleanup", help="clean up system templates of specified hypervisor", default="false")
+ self.parser.add_argument("-d", "--database-host-name", action="store", dest="databasehostname", help="Database server hostname or ip, e.g localhost", default="localhost", required="true")
+ self.parser.add_argument("-r", "--database-user-name", action="store", dest="databaseusername", help="Database user name, e.g root", default="root", required="true")
+ self.parser.add_argument("-p", "--database-user-password", nargs='?', action="store", dest="databaseuserpassword", help="Database password. Followed by nothing if the password is empty", default="", required="true")
+ self.parser.add_argument("-e", "--template-suffix", action="store", dest="templatesuffix", help="Template suffix, e.g vhd, ova, qcow2",default="vhd")
+ self.parser.add_argument("-t", "--file-extension", action="store", dest="fileextension", help="The template file extension", default="", required="true", choices=['bz2','gz','zip'])
+
+ self.args = self.parser.parse_args()
+
+ def populateOptions(self):
+ self.mountpoint = self.args.mountpoint
+ self.hypervisor = self.args.hypervisor
+ self.fileextension = self.args.fileextension
+ if self.args.systemvmtemplatepath:
+ self.systemvmtemplatepath = self.args.systemvmtemplatepath
+ if self.args.systemvmtemplateurl:
+ self.systemvmtemplateurl = self.args.systemvmtemplateurl
+ if self.args.managementsecretkey:
+ self.managementsecretkey = self.args.managementsecretkey
+ if self.args.forcecleanup:
+ self.forcecleanup = self.args.forcecleanup
+ if self.args.databasehostname:
+ self.databasehostname = self.args.databasehostname
+ if self.args.databaseusername:
+ self.databaseusername = self.args.databaseusername
+ if self.args.databaseuserpassword:
+ self.databaseuserpassword = self.args.databaseuserpassword
+ else:
+ self.databaseuserpassword = ""
+ if self.args.templatesuffix:
+ self.templatesuffix = self.args.templatesuffix
+ print 'Password for DB: %s'%self.databaseuserpassword
+
+ def errorAndExit(self, msg):
+ err = '''\n\nWe apologize for below error:
+***************************************************************
+%s
+***************************************************************
+Please run:
+
+ cloud-install-sys-tmplt -h
+
+for full help
+''' % msg
+ sys.stderr.write(err)
+ sys.stderr.flush()
+ sys.exit(1)
+
+ def runCmd(self, cmds):
+ process = subprocess.Popen(' '.join(cmds), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ print(stdout)
+ if process.returncode != 0:
+ raise Exception(stderr)
+ return stdout
+
+ def runMysql(self, query):
+ try:
+ print 'Running Query: %s' % query
+ mysqlCmds = ['mysql', '--user=%s'%self.databaseusername, '--host=%s'%self.databasehostname, '--password=%s'%self.databaseuserpassword, '--skip-column-names', '-U', 'cloud', '-e "%s"'%query]
+ templateId = self.runCmd(mysqlCmds)
+ print 'TemplateId is : %s' % templateId
+ except Exception, e:
+ err = '''Encountering an error when executing mysql script\n%s''' % str(e)
+ self.errorAndExit(err)
+ return templateId
+
+ def fetchTemplateDetails(self):
+ mysqlQuery = "select max(id) from cloud.vm_template where type = 'SYSTEM' and hypervisor_type = '%s' and removed is null"
+ ht = None
+ hypervisorInfo = self.dictionary[self.hypervisor]
+ ht = hypervisorInfo[0]
+ self.templatesuffix = hypervisorInfo[1]
+
+ self.template = int(self.runMysql(mysqlQuery%ht))
+
+ def downloadTemplate(self):
+ self.systemvmtemplatepath = self.templateName + "." + self.fileextension
+ print 'Downloading template from %s To %s' % (self.systemvmtemplateurl, self.systemvmtemplatepath)
+ try:
+ templateFileDownloadUrl = urllib.urlretrieve(self.systemvmtemplateurl, self.systemvmtemplatepath, reporthook=self.report)
+ except Exception:
+ self.errorAndExit("Failed to download template file from %s" % self.systemvmtemplateurl)
+
+ def report(tmp, blocknr, blocksize, size):
+ current = blocknr*blocksize
+ sys.stdout.write("\rDownloading completed: {0:.2f}%".format(100.0*current/size))
+
+ def installTemplate(self):
+ destDir = self.mountpoint + os.sep + "template" + os.sep + "tmpl" + os.sep + "1" + os.sep + str(self.template)
+ self.destDir = destDir
+ print 'The desination Directory is : %s' % destDir
+ try:
+ if self.forcecleanup:
+ if os.path.exists(destDir):
+ shutil.rmtree(destDir)
+ if not os.path.exists(destDir):
+ os.makedirs(destDir)
+ except Exception, e:
+ self.errorAndExit('Failed to create directories on the mounted path.. %s' % str (e))
+ print 'Installing Template to : %s' % destDir
+ tmpFile = self.templateName + "." + "tmp"
+ self.uncompressFile(tmpFile)
+ print 'Moving the decompressed file to destination directory %s... which could take a long time, please wait' % destDir
+ shutil.move(tmpFile, destDir + os.sep + self.templateName)
+
+ def uncompressFile(self, fileName):
+ print 'Uncompressing the file %s... which could take a long time, please wait' % self.systemvmtemplatepath
+ if self.fileextension == 'gz':
+ compressedFile = gzip.GzipFile(self.systemvmtemplatepath, 'rb')
+ decompressedData = compressedFile.read()
+ compressedFile.close()
+ decompressedFile = file(fileName, 'wb')
+ decompressedFile.write(decompressedData)
+ decompressedFile.close()
+ elif self.fileextension == 'bz2':
+ compressedFile = bz2.BZ2File(self.systemvmtemplatepath)
+ decompressedData = compressedFile.read()
+ compressedFile.close()
+ decompressedFile = file(fileName, 'wb')
+ decompressedFile.write(decompressedData)
+ decompressedFile.close()
+ print ''
+ elif self.fileextension == 'zip':
+ zippedFile = zipfile.ZipFile(self.systemvmtemplatepath, 'r')
+ zippedFiles = zippedFile.namelist()
+ compressedFile = zippedFiles[0]
+ decompressedData = zippedFile.read(compressedFile)
+ decompressedFile = file(fileName, 'wb')
+ decompressedFile.write(decompressedData)
+ decompressedFile.close()
+ zippedFile.close()
+ print ''
+ else:
+ self.errorAndExit('Not supported file type %s to decompress' % self.fileextension)
+ self.fileSize = os.path.getsize(fileName)
+
+ def writeProperties(self):
+ propertiesFile = file(self.destDir + os.sep + 'template.properties', 'wb')
+ propertiesFile.write('filename=%s\n'%self.templateName)
+ propertiesFile.write('description=SystemVM Template\n')
+ propertiesFile.write('checksum=\n')
+ propertiesFile.write('hvm=false\n')
+ propertiesFile.write('size=%s\n'%str(self.fileSize))
+ propertiesFile.write('%s=true\n'%self.templatesuffix)
+ propertiesFile.write('id=%s\n'%str(self.template))
+ propertiesFile.write('public=true\n')
+ propertiesFile.write('%s.filename=%s\n'%(self.templatesuffix, self.templateName))
+ propertiesFile.write('uniquename=routing-%s\n'%str(self.template))
+ propertiesFile.write('%s.virtualsize=%s\n'%(self.templatesuffix, str(self.fileSize)))
+ propertiesFile.write('virtualsize=%s\n'%str(self.fileSize))
+ propertiesFile.write('%s.size=%s'%(self.templatesuffix, str(self.fileSize)))
+
+ propertiesFile.close()
+
+ def run(self):
+ try:
+ self.parseOptions()
+ self.populateOptions()
+ self.fetchTemplateDetails()
+ randomUUID = uuid.uuid1()
+ self.templateName = str(randomUUID) + "." + self.templatesuffix
+ if self.args.systemvmtemplateurl:
+ self.downloadTemplate()
+ self.installTemplate()
+ self.writeProperties()
+ finally:
+ print ''
+ print ''
+ print "CloudStack has successfully installed system template"
+ print ''
+
+if __name__ == "__main__":
+ o = InstallSysTemplate()
+ o.run()
\ No newline at end of file