You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2012/09/10 22:55:52 UTC
[26/50] [abbrv] Remove tools/migration
https://reviews.apache.org/r/6976/diff/
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5a9d7a79/tools/migration/upgrade.py
----------------------------------------------------------------------
diff --git a/tools/migration/upgrade.py b/tools/migration/upgrade.py
deleted file mode 100644
index bdc0d2c..0000000
--- a/tools/migration/upgrade.py
+++ /dev/null
@@ -1,1612 +0,0 @@
-# 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.
-
-
-
-from xml.dom.minidom import *
-import urllib2
-import MySQLdb
-from XenAPI import *
-import time
-import datetime
-import os
-import sys
-import paramiko
-import traceback
-
-### Logging functions
-
-def getTimestamp():
- return datetime.datetime.now().strftime("%m/%d/%Y | %I:%M:%S %p")
-
-def nonExitingLogDecorator(entryMessage):
- return genDecoratorFn(entryMessage, False, False)
-
-def basicLogDecorator(entryMessage):
- return genDecoratorFn(entryMessage, True, True)
-
-def verboseLogDecorator(entryMessage):
- return genDecoratorFn(entryMessage, False, True)
-
-def genDecoratorFn(entryMessage, printToScreen, exitOnError):
- def wrap(f):
- def g(*args):
- writeToLog("", printToScreen)
- writeToLog(getTimestamp() + " | " + entryMessage, printToScreen)
-
- if (len(args) > 0):
- argString = ""
- for i in range(len(args)):
- arg = args[i]
- argString += str(arg)
- if (i != len(args) - 1):
- argString += ", "
- writeToLog("args: " + argString, False)
-
- returnValue = None
- try:
- returnValue = f(*args)
- except SystemExit:
- sys.exit(1)
- except Exception, e:
- if (exitOnError):
- handleError(str(e), True)
- traceback.print_exc(file = GLOBALS["LOG_FILE"])
- sys.exit(1)
- else:
- return False
-
- if (returnValue in (None, False)):
- if (exitOnError):
- writeToLog(str(f) + " returned " + str(returnValue), False)
- handleError(None, True)
- sys.exit(1)
- else:
- return False
- else:
- return returnValue
- return g
- return wrap
-
-def handleError(msg, printToScreen):
- writeToLog(getTimestamp() + " | " + "Failed to complete this step.", printToScreen)
- if (msg != None):
- writeToLog("Details: " + msg, printToScreen)
-
-def writeToLog(message, printToScreen):
- logFile = GLOBALS.get("LOG_FILE")
- if (logFile != None):
- logFile.write(message)
- logFile.write("\n")
- if (printToScreen):
- print message
-
-### Util classes
-
-class System:
- def __init__(self, managementServerIp, asyncApi, xenServerIp, xenServerPassword, xenServerPasswordMap, dbName, dbLogin, dbPassword, zoneId, templateId, isoId, defaultServiceOfferingId, defaultDiskOfferingId):
- self.zoneId = zoneId
- self.templateId = templateId
- self.isoId = isoId
- self.defaultServiceOfferingId = defaultServiceOfferingId
- self.defaultDiskOfferingId = defaultDiskOfferingId
- self.api = System.API(managementServerIp, asyncApi)
- if (dbPassword == None):
- dbPassword = ""
- self.db = System.DB(managementServerIp, dbName, dbLogin, dbPassword)
-
- self.xenServerIp = None
- self.xenapi = None
- if (xenServerIp != None or xenServerPasswordMap != None):
- self.findXenApi(xenServerIp, xenServerPassword, xenServerPasswordMap)
- self.controlDomainRef = self.findControlDomainRef()
- self.sshConn = paramiko.SSHClient()
- self.sshConn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- self.sshConn.connect(self.xenServerIp, username = "root", password = self.xenServerPassword)
-
- @verboseLogDecorator("Finding the XenAPI connection...")
- def findXenApi(self, xenServerIp, xenServerPassword, xenServerPasswordMap):
- if (xenServerPasswordMap != None):
- xenServerIp = xenServerPasswordMap.keys()[0]
- xenServerPassword = xenServerPasswordMap[xenServerIp]
-
- masterXenServerIp = xenServerIp
- masterXenServerPassword = xenServerPassword
- session = None
- try:
- session = Session("http://" + masterXenServerIp + "/var/run/xend/xen-api.sock")
- session.login_with_password("root", masterXenServerPassword)
- except Exception, e:
- if (e.details != None and len(e.details) == 2 and e.details[0] == "HOST_IS_SLAVE"):
- masterXenServerIp = e.details[1]
- if (xenServerPasswordMap != None):
- masterXenServerPassword = xenServerPasswordMap[masterXenServerIp]
- else:
- masterXenServerPassword = xenServerPassword
- session = Session("http://" + masterXenServerIp + "/var/run/xend/xen-api.sock")
- session.login_with_password("root", masterXenServerPassword)
- else:
- raise
-
- self.xenServerIp = masterXenServerIp
- self.xenServerPassword = masterXenServerPassword
- self.xenapi = session.xenapi
- return True
-
- @verboseLogDecorator("Finding the control domain for the dest system...")
- def findControlDomainRef(self):
- # Find the host ref for this system
- hostRefs = self.xenapi.host.get_all()
- systemHostRef = None
- for hostRef in hostRefs:
- address = self.xenapi.host.get_address(hostRef)
- if (address == self.xenServerIp):
- systemHostRef = hostRef
- break
-
- if (systemHostRef == None):
- raise Exception("Failed to find the XenServer host ref for " + str(self))
-
- # Find the control domain ref that corresponds to this host
- vmRefs = self.xenapi.VM.get_all()
- for vmRef in vmRefs:
- if (self.xenapi.VM.get_is_control_domain(vmRef)):
- controlDomainHostRef = self.xenapi.VM.get_resident_on(vmRef)
- if (controlDomainHostRef == systemHostRef):
- return vmRef
- return None
-
- @nonExitingLogDecorator("Running ssh command...")
- def runSshCommand(self, command):
- stdin, stdout, stderr = self.sshConn.exec_command(command)
- return (stdin.channel.recv_exit_status() == 0)
-
- def updateIsoPermissions(self):
- setParams = {"public":"1"}
- whereParams = {"id":self.isoId}
- return self.db.updateDbValues("vm_template", setParams, whereParams)
-
- def __str__(self):
- description = "Management Server: %s" % (self.api.ip)
- if (self.xenServerIp != None):
- description += " | XenServer: %s" %(self.xenServerIp)
- return description
-
- class API:
- # Vars: ip
- def __init__(self, ip, asyncApi):
- self.ip = ip
- self.asyncApi = asyncApi
-
- # Runs a synchronous API command and returns the ID of the created object, or success/failure
- def runSyncApiCommand(self, command, params, objectName):
- requestURL = self.buildRequestUrl(command, params)
- xmlText = urllib2.urlopen(requestURL).read()
- if (objectName == None):
- responseName = (command + "response").lower()
- return (System.API.getTagValue(xmlText, responseName, "success") == "true")
- else:
- return System.API.getTagValue(xmlText, objectName, "id")
-
- # Runs a asynchronous API command and returns the ID of the created object, or success/failure
- def runAsyncApiCommand(self, command, params, objectName):
- requestURL = self.buildRequestUrl(command, params)
- xmlText = urllib2.urlopen(requestURL).read()
- responseName = (command + "response").lower()
- jobId = System.API.getTagValue(xmlText, responseName, "jobid")
- objectId = System.API.getTagValue(xmlText, responseName, objectName + "id")
- params = dict()
- params["jobId"] = jobId
- requestURL = self.buildRequestUrl("queryAsyncJobResult", params)
- retries = int(GLOBALS["ASYNC_RETRIES"])
- jobResult = None
- while (retries > 0):
- time.sleep(float(GLOBALS["ASYNC_SLEEP_TIME"]))
- xmlText = urllib2.urlopen(requestURL).read()
- if (System.API.getTagValue(xmlText, "queryasyncjobresultresponse", "jobstatus") == "1"):
- if (objectId != None):
- return objectId
- else:
- return True
- jobResult = System.API.getTagValue(xmlText, "queryasyncjobresultresponse", "jobresult")
- retries -= 1
- raise Exception(jobResult)
-
- def buildRequestUrl(self, command, params):
- requestURL = "http://" + self.ip + ":8096/client/api/?command=" + command
- for paramKey in params.keys():
- paramVal = params.get(paramKey)
- requestURL += "&" + str(paramKey) + "=" + str(paramVal)
- return requestURL
-
- @staticmethod
- def getTagValue(xmlText, objectName, tagName):
- xmlDoc = parseString(xmlText)
- response = xmlDoc.getElementsByTagName(objectName)[0]
- for x in response.childNodes:
- if (x.tagName == tagName):
- return " ".join(z.wholeText for z in x.childNodes)
- return None
-
- @staticmethod
- def printApiValues(listOfAPIObjects):
- for apiObject in listOfAPIObjects:
- for key in apiObject.keys():
- print key + ":" + apiObject.get(key)
- print " "
-
- class DB:
- # Vars: conn
- def __init__(self, ip, dbName, dbLogin, dbPassword):
- self.conn = MySQLdb.connect(host = ip, user = dbLogin, passwd = dbPassword, db = dbName)
- self.conn.autocommit(True)
-
- def getTable(self, table):
- cursor = self.conn.cursor()
- sql = "SELECT * from " + table
- cursor.execute(sql)
- for row in cursor.fetchall():
- print row
- cursor.close()
-
- # Returns a list of hashtables, each one representing a row and using column names as keys.
- def getDbValues(self, table, columns, whereParams):
- values = []
- cursor = self.conn.cursor()
- columnsText = ",".join(columns)
- sql = "SELECT " + columnsText + " FROM " + table
- if (len(whereParams) > 0):
- sql += System.DB.buildSqlWhereClause(whereParams)
- cursor.execute(sql)
- rows = cursor.fetchall()
- cursor.close()
- for row in rows:
- value = dict()
- for i in range(len(columns)):
- val = str(row[i])
- value[columns[i]] = val
- values.append(value)
- return values
-
- def updateDbValues(self, table, setParams, whereParams):
- setClause = System.DB.buildSqlSetClause(setParams)
- sql = "UPDATE " + table + setClause
- if (len(whereParams) > 0):
- sql += System.DB.buildSqlWhereClause(whereParams)
-
- cursor = self.conn.cursor()
- cursor.execute(sql)
- self.conn.commit()
- cursor.close()
- return True
-
- def insertIntoDb(self, table, setParams):
- existingRecords = self.getDbValues(table, ["id"], setParams)
- if (len(existingRecords) > 0):
- return existingRecords[0]["id"]
- columns = setParams.keys()
- values = []
- for column in columns:
- values.append(setParams[column])
- sql = "INSERT INTO " + table + System.DB.buildSqlInsertClause(columns, values)
- cursor = self.conn.cursor()
- cursor.execute(sql)
- insertId = self.conn.insert_id()
- self.conn.commit()
- cursor.close()
- return insertId
-
- @staticmethod
- def buildSqlInsertClause(columns, values):
- columnsSql = " ("
- valuesSql = " VALUES ("
- for i in range(len(columns)):
- if (str(values[i]) == "null"):
- continue
-
- columnsSql += columns[i]
- valuesSql += "'" + str(values[i]) + "'"
- if (i != (len(columns) - 1)):
- columnsSql += ", "
- valuesSql += ", "
- else:
- columnsSql += ")"
- valuesSql += ")"
- return columnsSql + valuesSql
-
- @staticmethod
- def buildSqlWhereClause(params):
- sql = " WHERE "
- keys = params.keys()
- for i in range(len(keys)):
- key = str(keys[i])
- val = str(params[key])
- if ("like" in val):
- val = val.split(":")[1]
- sql += key + " like '" + val + "'"
- elif ("neq" in val):
- val = val.split(":")[1]
- sql += key + " != '" + val + "'"
- elif (val == "null" or val == "not null"):
- sql += key + " IS " + val
- else:
- sql += key + " = '" + val + "'"
- if (i != (len(keys) - 1)):
- sql += " AND "
- return sql
-
- @staticmethod
- def buildSqlSetClause(params):
- sql = " SET "
- keys = params.keys()
- for i in range(len(keys)):
- key = keys[i]
- val = params[key]
- sql += key + " = "
- if (val == "null"):
- sql += "null"
- else:
- sql += "'" + val + "'"
- if (i != (len(keys) - 1)):
- sql += ", "
- return sql
-
-### Data classes
-
-class User:
- # Vars: system, id, username, password, accountId, firstname, lastname, email, accountType, accountName, domainId
-
- def __init__(self, system, userId, username, password, accountId, firstname, lastname, email, accountType, accountName, domainId):
- self.system = system
- self.id = userId
- self.username = username
- self.password = password
- self.accountId = accountId
- self.firstname = firstname
- self.lastname = lastname
- self.email = email
- self.accountType = accountType
- self.accountName = accountName
- self.domainId = domainId
-
- def __str__(self):
- return "(User: %s | %s)" % (self.username, self.system)
-
- def alreadyMigrated(self):
- f = open(GLOBALS["MIGRATED_ACCOUNTS_FILE"], "a+")
- migratedUsersCsv = f.read()
- f.close()
- migratedUsersEntries = migratedUsersCsv.split(",")
- for migratedUsersEntry in migratedUsersEntries:
- if (migratedUsersEntry.strip() == self.accountId):
- return True
- return False
-
- def tagAsMigrated(self):
- if (not self.alreadyMigrated()):
- f = open(GLOBALS["MIGRATED_ACCOUNTS_FILE"], "a")
- f.write(self.accountId + ",")
- f.close()
- return True
-
- @staticmethod
- def getByName(system, username):
- columns = ["id"]
- users = system.db.getDbValues("user", columns, {"username":username, "removed":"null"})
- if (len(users) > 0):
- return User.get(system, users[0]["id"])
- else:
- return None
-
- @staticmethod
- def get(system, userId):
- columns = ["id", "username", "password", "account_id", "firstname", "lastname", "email"]
- users = system.db.getDbValues("user", columns, {"id":userId})
- if (len(users) == 0):
- return None
- user = users[0]
- columns = ["type", "account_name", "domain_id"]
- account = system.db.getDbValues("account", columns, {"id":user["account_id"]})[0]
- return User(system, userId, user["username"], user["password"], user["account_id"], user["firstname"], user["lastname"], user["email"], account["type"], account["account_name"], account["domain_id"])
-
- @staticmethod
- def getDomain(system, domainId):
- columns = ["id", "parent", "name", "owner"]
- return system.db.getDbValues("domain", columns, {"id":domainId})[0]
-
- @staticmethod
- def getDomainByName(system, domainName):
- columns = ["id"]
- domains = system.db.getDbValues("domain", columns, {"name":domainName})
- if (len(domains) > 0):
- return domains[0]
- else:
- return None
-
- @staticmethod
- def createDomain(srcSystem, destSystem, srcDomainId):
- # Get the source domain
- srcDomain = User.getDomain(srcSystem, srcDomainId)
-
- # If a domain with the same name exists in the dest system, return its ID
- destDomain = User.getDomainByName(destSystem, srcDomain["name"])
- if (destDomain != None):
- return destDomain["id"]
- else:
- # Otherwise, create a new domain in the dest system with the same name, and return its ID
- # If the src domain has parent domains, we need to create these first
- parentId = None
- if (srcDomain["parent"] != "null"):
- parentId = User.createDomain(srcSystem, destSystem, srcDomain["parent"])
- params = dict()
- params["name"] = srcDomain["name"]
- if (parentId != None):
- params["parent"] = parentId
- newDomainId = destSystem.api.runSyncApiCommand("createDomain", params, "domain")
- if (newDomainId == None):
- raise Exception("Failed to create domain " + srcDomain["name"])
- else:
- # Set the owner for the new domain
- srcOwner = User.get(srcSystem, srcDomain["owner"])
- destOwner = User.create(destSystem, srcOwner)
- if (not destSystem.db.updateDbValues("domain", {"owner":destOwner.id}, {"id":newDomainId})):
- raise Exception("Failed to update the owner for domain " + srcDomain["name"])
- return newDomainId
-
- @staticmethod
- @basicLogDecorator("Creating new user...")
- def create(system, srcUser):
- user = User.getByName(system, srcUser.username)
- if (user != None):
- return user
- else:
- # If the user's domain doesn't exist in the system, create it
- domainId = User.createDomain(srcUser.system, system, srcUser.domainId)
-
- params = dict()
- params["username"] = srcUser.username
- params["password"] = "temp"
- params["firstname"] = srcUser.firstname
- params["lastname"] = srcUser.lastname
- params["email"] = srcUser.email
- accountType = srcUser.accountType
- if (accountType == "2"):
- accountType = "0"
- params["accounttype"] = accountType
- params["account"] = srcUser.accountName
- params["domainid"] = domainId
- newUserId = system.api.runSyncApiCommand("createUser", params, "user")
- if (newUserId != None):
- if (system.db.updateDbValues("user", {"password":srcUser.password}, {"id":newUserId})):
- return User.get(system, newUserId)
- else:
- return None
- else:
- return None
-
-class ServiceOffering:
- # Vars: system, id, numCpus, speed, memory, disk
-
- def __init__(self, system, offeringId, numCpus, speed, memory, disk):
- self.system = system
- self.id = offeringId
- self.numCpus = numCpus
- self.speed = speed
- self.memory = memory
- self.disk = disk
-
- def __str__(self):
- return "ServiceOffering: %s | id: %s | numCpus: %s | speed: %s | memory: %s | disk: %s" % (self.system, self.id, self.numCpus, self.speed, self.memory, self.disk)
-
- @staticmethod
- def getCorrespondingServiceOffering(srcServiceOfferingId):
- srcServiceOffering = ServiceOffering.getSrcSystemServiceOfferingById(srcServiceOfferingId)
- destServiceOffering = ServiceOffering.getDestSystemServiceOffering(srcServiceOffering.numCpus, srcServiceOffering.speed, srcServiceOffering.memory)
- return destServiceOffering
-
- @staticmethod
- def getDestSystemServiceOffering(numCpus, speed, memory):
- serviceOfferings = GLOBALS["DEST_SYSTEM"].db.getDbValues("service_offering", ["id"], {"cpu":numCpus, "speed":speed, "ram_size":memory, "guest_ip_type":"Virtualized"})
- if (len(serviceOfferings) > 0):
- return ServiceOffering(GLOBALS["DEST_SYSTEM"], serviceOfferings[0]["id"], numCpus, speed, memory, None)
- else:
- return None
-
- @staticmethod
- def getSrcSystemServiceOfferingByVmId(vmId):
- serviceOfferingId = GLOBALS["SRC_SYSTEM"].db.getDbValues("user_vm", ["service_offering_id"], {"id":vmId})[0]["service_offering_id"]
- return getSrcSystemServiceOfferingById(serviceOfferingId)
-
- @staticmethod
- def getSrcSystemServiceOfferingById(serviceOfferingId):
- columns = ["id", "cpu", "speed", "ram_size", "disk"]
- serviceOfferings = GLOBALS["SRC_SYSTEM"].db.getDbValues("service_offering", columns, {"id":serviceOfferingId})
- if (len(serviceOfferings) > 0):
- offering = serviceOfferings[0]
- return ServiceOffering(GLOBALS["SRC_SYSTEM"], offering["id"], offering["cpu"], offering["speed"], offering["ram_size"], offering["disk"])
- else:
- return None
-
- @staticmethod
- def getSrcSystemServiceOfferings():
- serviceOfferings = []
- columns = ["id", "cpu", "speed", "ram_size", "disk"]
- srcServiceOfferings = GLOBALS["SRC_SYSTEM"].db.getDbValues("service_offering", columns, {})
- for offering in srcServiceOfferings:
- serviceOfferings.append(ServiceOffering(GLOBALS["SRC_SYSTEM"], offering["id"], offering["cpu"], offering["speed"], offering["ram_size"], offering["disk"]))
- return serviceOfferings
-
-class DiskOffering:
- # Vars: id, size
-
- def __init__(self, diskOfferingId, size):
- self.id = diskOfferingId
- self.size = size
-
- def __str__(self):
- return "Disk Offering: size = %s" % (self.size)
-
- @staticmethod
- def getDestDiskOffering(size):
- columns = ["id"]
- diskOfferingRows = GLOBALS["DEST_SYSTEM"].db.getDbValues("disk_offering", ["id"], {"disk_size":size, "type":"Disk"})
- if (len(diskOfferingRows) > 0):
- return DiskOffering(diskOfferingRows[0]["id"], size)
- else:
- size = ((int(size) / 1024) + 1) * 1024
- diskOfferingRows = GLOBALS["DEST_SYSTEM"].db.getDbValues("disk_offering", ["id"], {"disk_size":size, "type":"Disk"})
- if (len(diskOfferingRows) > 0):
- return DiskOffering(diskOfferingRows[0]["id"], size)
- else:
- return None
-
- @staticmethod
- def getCorrespondingDiskOffering(srcServiceOfferingId):
- srcServiceOffering = ServiceOffering.getSrcSystemServiceOfferingById(srcServiceOfferingId)
- diskOffering = DiskOffering.getDestDiskOffering(srcServiceOffering.disk)
- return diskOffering
-
-
-class VM:
- # Vars: id, system, user, serviceOfferingId, name, templateId, guestOsId
-
- def __init__(self, vmId, user, serviceOfferingId, guestOsId, guestOsCategoryId):
- self.id = vmId
- self.system = user.system
- self.user = user
- self.serviceOfferingId = serviceOfferingId
- self.guestOsId = guestOsId
- self.guestOsCategoryId = guestOsCategoryId
-
- def __str__(self):
- return "UserVM: id = %s | username = %s | system = %s" % (self.id, self.user.username, self.system)
-
- def getName(self):
- columns = ["name"]
- return self.system.db.getDbValues("vm_instance", columns, {"id":self.id})[0]["name"]
-
- @basicLogDecorator("Deploying a temporary VM...")
- def deployTemp(self):
- params = {"account":self.user.accountName, "domainid":self.user.domainId, "zoneId":self.system.zoneId, "serviceofferingid":self.system.defaultServiceOfferingId, "templateid":self.system.templateId}
- vmId = self.system.api.runAsyncApiCommand("deployVirtualMachine", params, "virtualmachine")
- if (vmId in (None, False)):
- return False
- self.id = vmId
- self.name = self.getName() + "-temp-vm"
- success = self.system.db.updateDbValues("vm_instance", {"name":self.name}, {"id":self.id})
- return success
-
- @basicLogDecorator("Deploying a new VM for the user ...")
- def deploy(self, srcVm):
- params = dict()
- params["account"] = self.user.accountName
- params["domainid"] = self.user.domainId
- params["zoneid"] = self.system.zoneId
- params["serviceofferingid"] = self.serviceOfferingId
- params["templateid"] = self.system.isoId
- params["diskofferingid"] = self.system.defaultDiskOfferingId
- vmId = self.system.api.runAsyncApiCommand("deployVirtualMachine", params, "virtualmachine")
- if (vmId in (None, False)):
- return None
- self.id = vmId
- self.name = self.getName() + "-" + str(srcVm.id) + " (" + VM.getGuestOsName(GLOBALS["DEST_SYSTEM"], self.guestOsId) + ")"
- success = self.system.db.updateDbValues("vm_instance", {"name":self.name}, {"id":self.id})
- return success
-
- @verboseLogDecorator("Updating the guest OS ID for the VM...")
- def updateGuestOsId(self):
- setParams = {"guest_os_id":self.guestOsId}
- whereParams = {"id":self.id}
- return self.system.db.updateDbValues("vm_instance", setParams, whereParams)
-
- @basicLogDecorator("Starting VM...")
- def start(self):
- params = {"id":self.id}
- return self.system.api.runAsyncApiCommand("startVirtualMachine", params, "virtualmachine")
-
- @basicLogDecorator("Stopping VM...")
- def stop(self):
- params = {"id":self.id}
- if (self.system.api.asyncApi):
- return self.system.api.runAsyncApiCommand("stopVirtualMachine", params, "virtualmachine")
- else:
- return self.system.api.runSyncApiCommand("stopVirtualMachine", params, None)
-
- @basicLogDecorator("Destroying temporary VM...")
- def destroy(self):
- params = {"id":self.id}
- return self.system.api.runAsyncApiCommand("destroyVirtualMachine", params, "virtualmachine")
-
- @verboseLogDecorator("Detaching ISO from VM...")
- def detachIso(self):
- isoId = self.system.db.getDbValues("vm_instance", ["iso_id"], {"id":self.id})[0]["iso_id"]
- if (isoId == "None"):
- return True
-
- params = {"virtualmachineid":self.id}
- return self.system.api.runAsyncApiCommand("detachIso", params, "virtualmachine")
-
- def isLinuxVm(self):
- return (self.guestOsCategoryId != str(GLOBALS["DEST_WINDOWS_GUEST_OS_CATEGORY_ID"]))
-
- @staticmethod
- def getGuestOsName(system, guestOsId):
- columns = ["id", "display_name"]
- guestOsList = system.db.getDbValues("guest_os", columns, {"id":guestOsId})
- if (len(guestOsList) > 0):
- return guestOsList[0]["display_name"]
- else:
- return None
-
- @staticmethod
- def getGuestOsCategoryId(system, guestOsId):
- columns = ["category_id"]
- return system.db.getDbValues("guest_os", columns, {"id":guestOsId})[0]["category_id"]
-
- @staticmethod
- def getVmId(system, accountId, guestIpAddress):
- userVms = system.db.getDbValues("user_vm", ["id"], {"account_id":accountId, "guest_ip_address":guestIpAddress})
- for userVm in userVms:
- vmInstances = system.db.getDbValues("vm_instance", ["id"], {"id":userVm["id"], "removed":"null", "state":"neq:Destroyed"})
- if (len(vmInstances) > 0):
- return vmInstances[0]["id"]
- return None
-
- @staticmethod
- def getVms(user):
- system = user.system
- vms = []
- columns = ["id", "service_offering_id"]
- userVmRows = system.db.getDbValues("user_vm", columns, {"account_id":user.accountId})
- for userVmRow in userVmRows:
- vmInstanceRow = system.db.getDbValues("vm_instance", ["vm_template_id", "removed"], {"id":userVmRow["id"]})[0]
- if (vmInstanceRow["removed"] != "None"):
- continue
-
- # Determine the service offering ID
- serviceOfferingId = userVmRow["service_offering_id"]
-
- # Determine the new guest OS id and category id
- templateId = vmInstanceRow["vm_template_id"]
- guestOsId = GLOBALS["GUEST_OS_MAP"][templateId]
- guestOsCategoryId = VM.getGuestOsCategoryId(GLOBALS["DEST_SYSTEM"], guestOsId)
-
- vms.append(VM(userVmRow["id"], user, serviceOfferingId, guestOsId, guestOsCategoryId))
- return vms
-
- @staticmethod
- def getCorrespondingVm(destUser, srcVm):
- system = destUser.system
- columns = ["id", "guest_os_id"]
- correspondingVms = system.db.getDbValues("vm_instance", columns, {"name":"like:%-" + srcVm.id + " (%"})
- if (len(correspondingVms) > 0):
- correspondingVm = correspondingVms[0]
- newServiceOffering = ServiceOffering.getCorrespondingServiceOffering(srcVm.serviceOfferingId)
- vmId = correspondingVm["id"]
- guestOsId = srcVm.guestOsId
- guestOsCategoryId = VM.getGuestOsCategoryId(GLOBALS["DEST_SYSTEM"], guestOsId)
- return VM(vmId, destUser, newServiceOffering.id, guestOsId, guestOsCategoryId)
- else:
- return None
-
- @staticmethod
- def getTempVm(user):
- system = user.system
- columns = ["id"]
- tempVms = system.db.getDbValues("vm_instance", columns, {"removed":"null", "state":"neq:Destroyed", "name":"like:%-temp-vm"})
- if (len(tempVms) > 0):
- tempVm = tempVms[0]
- return VM(tempVm["id"], user, None, None, None)
- else:
- return None
-
- @staticmethod
- def getTemplate(system, templateId):
- columns = ["id", "name", "format"]
- templates = system.db.getDbValues("vm_template", columns, {"id":templateId})
- if (len(templates) > 0):
- return templates[0]
- else:
- return None
-
- @staticmethod
- def getTemplateIds(system):
- templateIds = []
- columns = ["id", "unique_name"]
- templates = system.db.getDbValues("vm_template", columns, {})
- for template in templates:
- if (template["unique_name"] == "routing"):
- continue
- templateIds.append(template["id"])
- return templateIds
-
- @staticmethod
- @basicLogDecorator("Migrating the user's VMs...")
- def migrateVirtualMachines(srcUser, destUser):
- # Maintain a map of src system VM IDs to dest system VM ids
- vmIdMap = dict()
-
- # Get a list of user VMs for the source user
- srcVms = VM.getVms(srcUser)
-
- for srcVm in srcVms:
- # Try to find an existing VM in the dest system that corresponds to the VM in the src system
- destVm = VM.getCorrespondingVm(destUser, srcVm)
-
- # If there is no corresponding VM, deploy a new VM in the dest system
- if (destVm == None):
- destVm = VM(None, destUser, srcVm.serviceOfferingId, srcVm.guestOsId, srcVm.guestOsCategoryId)
- destVm.deploy(srcVm)
-
- # Add a mapping between the src VM and the dest VM
- vmIdMap[srcVm.id] = destVm.id
-
- # Get a list of volumes for the source VM
- srcVolumes = Volume.getSrcVolumes(srcUser, srcVm)
-
- # If these volumes have already been copied to the dest system, skip migration for this VM
- vmAlreadyMigrated = True
- for srcVolume in srcVolumes:
- destVolume = Volume.getDestVolume(None, destVm, srcVolume.type)
- if (destVolume == None):
- vmAlreadyMigrated = False
- break
- elif (srcVolume.id != destVolume.name.split("-")[-1]):
- vmAlreadyMigrated = False
- break
-
- if (vmAlreadyMigrated):
- writeToLog("\n" + str(srcVm) + " has already been migrated.", True)
- continue
- else:
- writeToLog("\nMigrating volumes for source VM: " + str(srcVm), True)
-
- # Stop the dest VM
- destVm.stop()
-
- # Stop the source VM
- srcVm.stop()
-
- for srcVolume in srcVolumes:
- destVolume = None
- if (srcVolume.type == "DATADISK"):
- destVolume = Volume.getDestVolume(None, destVm, "DATADISK")
- if (destVolume == None):
- diskOffering = DiskOffering.getCorrespondingDiskOffering(srcVm.serviceOfferingId)
- destVolume = Volume(GLOBALS["DEST_SYSTEM"], None, str(destVm.id) + "-DATADISK", None, None, None, "DATA", diskOffering.id)
- destVolume.createAndAttach(destVm)
- else:
- destVolume = Volume.getDestVolume(None, destVm, "ROOT")
-
- # If the dest volume is already tagged with the source volume's ID, we don't need to do a copy
- if (srcVolume.id == destVolume.name.split("-")[-1]):
- writeToLog(str(srcVolume) + " has already been migrated.")
- continue
-
- # If the srcVolume's iSCSI SR isn't created on the XenServer, create it
- srcHost = Host.getHost(GLOBALS["SRC_SYSTEM"], srcVolume.hostId)
- srcSR = SR.getExistingSrcSr(srcHost.ip, srcHost.iqn)
- if (srcSR == None):
- srcSR = SR(GLOBALS["DEST_SYSTEM"], srcHost.ip, srcHost.iqn, None)
- srcSR.create()
- else:
- writeToLog("Found existing SR: " + str(srcSR), False)
-
- # Find the VDI corresponding to the src volume
- srcVdi = VDI(srcSR, srcVolume, None)
-
- # Find the SR corresponding to the dest storage pool
- destStoragePool = StoragePool.getStoragePool(GLOBALS["DEST_SYSTEM"], destVolume.poolId)
- destSR = SR(GLOBALS["DEST_SYSTEM"], None, None, destStoragePool.uuid)
- destSR.find()
-
- # Copy the src VDI to the dest SR
- copiedVdiUuid = srcVdi.copy(destSR)
-
- # If this is the rootdisk of a Linux VM, change the disk name
- destVdi = VDI(destSR, destVolume, copiedVdiUuid)
- if (destVolume.type == "ROOT" and srcVm.isLinuxVm()):
- destVdi.changeBootableDeviceName()
-
- # Destroy the VM's old VDI
- oldDestVdi = VDI(destSR, destVolume, destVolume.path)
- oldDestVdi.destroy()
-
- # Update the destVolume's database record to have the UUID of the copied VDI, the virtual size of the copied VDI, and the ID of the source volume
- destVolume.update(copiedVdiUuid, destVdi.getVirtualSize(), destVolume.name + "-" + srcVolume.id)
-
- # Detach the dest VM's ISO
- destVm.detachIso()
-
- # Update the guest OS ID for the VM
- destVm.updateGuestOsId()
-
- # Start the dest VM
- destVm.start()
-
- return vmIdMap
-
-class Volume:
- # vars: system, id, hostId, poolId, path, zoneId, iscsiName, type, diskOfferingId
-
- def __init__(self, system, volumeId, name, poolOrHostId, path, iscsiName, volumeType, diskOfferingId):
- self.system = system
- self.id = volumeId
- self.name = name
- if (iscsiName == None):
- self.poolId = poolOrHostId
- self.iscsiName = None
- else:
- self.hostId = poolOrHostId
- self.iscsiName = iscsiName
- self.path = path
- self.type = volumeType
- self.diskOfferingId = diskOfferingId
-
- def __str__(self):
- return "Volume: %s | type: %s | path: %s" % (self.system, self.type, self.path)
-
- @basicLogDecorator("Creating a new volume and attaching it to the user's VM...")
- def createAndAttach(self, destVm):
- params = dict()
- params["account"] = destVm.user.accountName
- params["domainid"] = destVm.user.domainId
- params["name"] = self.name
- params["zoneid"] = self.system.zoneId
- params["diskofferingid"] = self.diskOfferingId
- volumeId = self.system.api.runAsyncApiCommand("createVolume", params, "volume")
- if (volumeId in (None, False)):
- return False
- self.id = volumeId
- params = dict()
- params["id"] = volumeId
- params["virtualmachineid"] = destVm.id
- success = self.system.api.runAsyncApiCommand("attachVolume", params, "volume")
- if (success in (None, False)):
- return False
- newVolume = Volume.getDestVolume(volumeId, None, None)
- self.poolId = newVolume.poolId
- self.path = newVolume.path
- return True
-
- def update(self, volumeUuid, volumeSize, name):
- setParams = {"path":volumeUuid, "size":volumeSize, "name":name}
- whereParams = {"id":self.id}
- return self.system.db.updateDbValues("volumes", setParams, whereParams)
-
- @staticmethod
- def getSrcVolumes(user, vm):
- volumes = []
- columns = ["id", "name", "host_id", "path", "iscsi_name", "volume_type", "offering_id"]
- volumeRows = GLOBALS["SRC_SYSTEM"].db.getDbValues("volumes", columns, {"account_id":user.accountId, "instance_id":vm.id, "removed":"null"})
- for volumeRow in volumeRows:
- volumes.append(Volume(GLOBALS["SRC_SYSTEM"], volumeRow["id"], volumeRow["name"], volumeRow["host_id"], volumeRow["path"], volumeRow["iscsi_name"], volumeRow["volume_type"], volumeRow["offering_id"]))
- return volumes
-
- @staticmethod
- def getDestVolume(volumeId, vm, volumeType):
- columns = ["id", "name", "pool_id", "path", "disk_offering_id"]
- whereParams = None
- if (volumeId != None):
- whereParams = {"id":volumeId}
- else:
- whereParams = {"instance_id":vm.id, "volume_type":volumeType}
- volumeRows = GLOBALS["DEST_SYSTEM"].db.getDbValues("volumes", columns, whereParams)
- if (len(volumeRows) > 0):
- volumeRow = volumeRows[0]
- return Volume(GLOBALS["DEST_SYSTEM"], volumeRow["id"], volumeRow["name"], volumeRow["pool_id"], volumeRow["path"], None, volumeType, volumeRow["disk_offering_id"])
- else:
- return None
-
-class DomainRouter:
- # Vars: id, system, user
-
- def __init__(self, user):
- self.system = user.system
- self.user = user
- self.id = self.getId()
-
- def __str__(self):
- return "DomainRouter: %s" % (self.user)
-
- @basicLogDecorator("Stopping user's router...")
- def stop(self):
- if (self.id == None):
- raise Exception("Could not find router for " + str(self.user))
- params = {"id":self.id}
- if (self.system.api.asyncApi):
- return self.system.api.runAsyncApiCommand("stopRouter", params, "router")
- else:
- return self.system.api.runSyncApiCommand("stopRouter", params, None)
-
- @basicLogDecorator("Starting user's router...")
- def start(self):
- if (self.id == None):
- return False
- params = {"id":self.id}
- if (self.system.api.asyncApi):
- return self.system.api.runAsyncApiCommand("startRouter", params, "router")
- else:
- return self.system.api.runSyncApiCommand("startRouter", params, None)
-
- @basicLogDecorator("Rebooting user's router...")
- def reboot(self):
- if (self.id == None):
- return False
- params = {"id":self.id}
- return self.system.api.runAsyncApiCommand("rebootRouter", params, "router")
-
- def getId(self):
- routers = self.system.db.getDbValues("domain_router", ["id"], {"account_id":self.user.accountId})
- if (len(routers) > 0):
- return routers[0]["id"]
- else:
- return None
-
-class PublicIp:
- # Vars: system, user, address, zoneId, sourceNat, allocated
-
- def __init__(self, system, user, address, zoneId, sourceNat, allocated):
- self.system = system
- self.user = user
- self.address = address
- self.zoneId = zoneId
- self.sourceNat = sourceNat
- self.allocated = allocated
-
- def __str__(self):
- return self.address
-
- def __repr__(self):
- return self.address
-
- def allocate(self):
- setParams = {"account_id":self.user.accountId,
- "domain_id":self.user.domainId,
- "source_nat":self.sourceNat,
- "allocated":self.allocated}
- whereParams = {"public_ip_address":self.address,
- "data_center_id":self.zoneId}
- return self.system.db.updateDbValues("user_ip_address", setParams, whereParams)
-
- @staticmethod
- @basicLogDecorator("Clearing existing public IPs...")
- def clearPublicIps(user):
- system = user.system
- setParams = {"account_id":"null", "domain_id":"null", "source_nat":"0", "allocated":"null"}
- whereParams = {"account_id":user.accountId}
- return system.db.updateDbValues("user_ip_address", setParams, whereParams)
-
- @staticmethod
- @basicLogDecorator("Migrating allocated public IPs...")
- def migrateAllocatedPublicIps(srcUser, destUser):
- # Get a list of public IPs allocated to the source user
- ips = PublicIp.getAllocatedPublicIps(srcUser)
-
- # Allocate each one of these IPs in the dest system
- for ip in ips:
- ip.system = GLOBALS["DEST_SYSTEM"]
- ip.user = destUser
- if (not ip.allocate()):
- return None
-
- return ips
-
- @staticmethod
- def getAllocatedPublicIps(user):
- system = user.system
- ips = []
- columns = ["public_ip_address", "data_center_id", "source_nat", "allocated"]
- ipRows = system.db.getDbValues("user_ip_address", columns, {"account_id":user.accountId})
- for ipRow in ipRows:
- ips.append(PublicIp(system, user, ipRow["public_ip_address"], ipRow["data_center_id"], ipRow["source_nat"], ipRow["allocated"]))
- return ips
-
- @staticmethod
- def getGuestIpAddress(system, vmId):
- columns = ["guest_ip_address"]
- guestIp = system.db.getDbValues("user_vm", columns, {"id":vmId})[0]
- return guestIp["guest_ip_address"]
-
-class ForwardingRule:
- @staticmethod
- @basicLogDecorator("Migrating port forwarding and load balancer rules...")
- def migrateForwardingRules(srcUser, destUser, publicIps, vmIdMap):
- for publicIp in publicIps:
- forwardingRules = ForwardingRule.getSrcForwardingRules(srcUser, destUser, publicIp.address, vmIdMap)
- for forwardingRule in forwardingRules:
- newRuleId = forwardingRule.createInDestSystem()
- if (newRuleId == None):
- return False
- return True
-
- @staticmethod
- def getSrcForwardingRules(srcUser, destUser, address, vmIdMap):
- # vmIdMap maps UserVM database IDs in the src system to UserVM database IDs in the dest system
- columns = ["id", "public_port", "private_ip_address", "private_port", "enabled", "protocol", "forwarding", "algorithm"]
- ruleRows = GLOBALS["SRC_SYSTEM"].db.getDbValues("ip_forwarding", columns, {"public_ip_address":address})
- activeRules = []
- for ruleRow in ruleRows:
- srcVmId = VM.getVmId(GLOBALS["SRC_SYSTEM"], srcUser.accountId, ruleRow["private_ip_address"])
- destVmId = vmIdMap.get(srcVmId)
- if (destVmId == None):
- continue
-
- if (ruleRow["forwarding"] == "1"):
- activeRules.append(ForwardingRule.PortForwardingRule(address, ruleRow["public_port"], PublicIp.getGuestIpAddress(GLOBALS["DEST_SYSTEM"], destVmId), ruleRow["private_port"], ruleRow["enabled"], ruleRow["protocol"]))
- else:
- activeRules.append(ForwardingRule.LoadBalancerRule(destUser.accountId, address, ruleRow["public_port"], ruleRow["private_port"], destVmId, ruleRow["algorithm"]))
-
- return activeRules
-
- class PortForwardingRule:
- def __init__(self, publicIp, publicPort, privateIp, privatePort, enabled, protocol):
- self.publicIp = publicIp
- self.publicPort = publicPort
- self.privateIp = privateIp
- self.privatePort = privatePort
- self.enabled = enabled
- self.protocol = protocol
-
- def createInDestSystem(self):
- setParams = dict()
- setParams["public_ip_address"] = self.publicIp
- setParams["public_port"] = self.publicPort
- setParams["private_ip_address"] = self.privateIp
- setParams["private_port"] = self.privatePort
- setParams["enabled"] = self.enabled
- setParams["protocol"] = self.protocol
- setParams["forwarding"] = "1"
- setParams["algorithm"] = "null"
- setParams["group_id"] = "null"
- return GLOBALS["DEST_SYSTEM"].db.insertIntoDb("ip_forwarding", setParams)
-
- class LoadBalancerRule:
- def __init__(self, accountId, ip, publicPort, privatePort, vmId, algorithm):
- self.accountId = accountId
- self.ip = ip
- self.publicPort = publicPort
- self.privatePort = privatePort
- self.vmId = vmId
- self.algorithm = algorithm
-
- def createInDestSystem(self):
- setParams = dict()
- setParams["name"] = str(self.publicPort) + "-" + str(self.privatePort)
- setParams["account_id"] = self.accountId
- setParams["ip_address"] = self.ip
- setParams["public_port"] = self.publicPort
- setParams["private_port"] = self.privatePort
- setParams["algorithm"] = self.algorithm
- newLoadBalancerRuleId = GLOBALS["DEST_SYSTEM"].db.insertIntoDb("load_balancer", setParams)
- if (newLoadBalancerRuleId == None or newLoadBalancerRuleId == "0"):
- return None
- setParams = dict()
- setParams["load_balancer_id"] = newLoadBalancerRuleId
- setParams["instance_id"] = self.vmId
- return GLOBALS["DEST_SYSTEM"].db.insertIntoDb("load_balancer_vm_map", setParams)
-
-class SR:
- def __init__(self, system, ip, iqn, uuid):
- self.system = system
- self.ip = ip
- self.iqn = iqn
- self.uuid = uuid
-
- def __str__(self):
- return "SR: %s | ip: %s | iqn: %s | uuid: %s" % (self.system, self.ip, self.iqn, self.uuid)
-
- @verboseLogDecorator("Finding SR...")
- def find(self):
- xenapi = self.system.xenapi
- self.ref = xenapi.SR.get_by_name_label(self.uuid)[0]
- return True
-
- @verboseLogDecorator("Finding source system's iSCSI SR...")
- def create(self):
- xenapi = self.system.xenapi
- host = xenapi.host.get_all()[0]
- deviceConfig = {'targetIQN': self.iqn, 'target': self.ip}
- srRef = None
- name = "1.0 iSCSI pool: " + self.ip + "-" + self.iqn
- srRef = xenapi.SR.create(host, deviceConfig, "0", name, name, "iscsi", "user", True)
- if (srRef != None):
- self.ref = srRef
- return True
- else:
- return False
-
- @staticmethod
- def getExistingSrcSr(ip, iqn):
- xenapi = GLOBALS["DEST_SYSTEM"].xenapi
- srRefs = xenapi.SR.get_all()
- for srRef in srRefs:
- srNameLabel = xenapi.SR.get_name_label(srRef)
- if (srNameLabel == "1.0 iSCSI pool: " + ip + "-" + iqn):
- sr = SR(GLOBALS["DEST_SYSTEM"], ip, iqn, xenapi.SR.get_uuid(srRef))
- sr.ref = srRef
- return sr
- return None
-
- @staticmethod
- @verboseLogDecorator("Forgetting all src iSCSI SRs...")
- def forgetAllSrcSrs():
- xenapi = GLOBALS["DEST_SYSTEM"].xenapi
- srRefs = xenapi.SR.get_all()
- for srRef in srRefs:
- srNameLabel = xenapi.SR.get_name_label(srRef)
- if ("1.0 iSCSI pool" in srNameLabel):
- # Unplug and destroy the SR's PBDs
- pbdRefs = xenapi.SR.get_PBDs(srRef)
- for pbdRef in pbdRefs:
- xenapi.PBD.unplug(pbdRef)
- xenapi.PBD.destroy(pbdRef)
-
- # Forget the SR
- xenapi.SR.forget(srRef)
-
- return True
-
-class VDI:
- def __init__(self, sr, volume, uuid):
- self.sr = sr
- self.volume = volume
- self.uuid = uuid
- self.find()
-
- def __str__(self):
- return "VDI: %s | uuid: %s" % (self.volume, self.uuid)
-
- @verboseLogDecorator("Getting virtual size for VDI...")
- def getVirtualSize(self):
- xenapi = self.sr.system.xenapi
- return xenapi.VDI.get_virtual_size(self.ref)
-
- @basicLogDecorator("Copying source system volume to dest system...")
- def copy(self, destSR):
- xenapi = self.sr.system.xenapi
- newVdiRef = xenapi.VDI.copy(self.ref, destSR.ref)
- return xenapi.VDI.get_uuid(newVdiRef)
-
- @basicLogDecorator("Destroying old volume...")
- def destroy(self):
- xenapi = self.sr.system.xenapi
- xenapi.VDI.destroy(self.ref)
- return True
-
- @verboseLogDecorator("Finding VDI in SR...")
- def find(self):
- xenapi = self.sr.system.xenapi
- if (self.uuid == None):
- # Run an sr-scan
- xenapi.SR.scan(self.sr.ref)
-
- # Get a list of VDIs in the SR
- vdiRefs = xenapi.SR.get_VDIs(self.sr.ref)
-
- # Find the VDI that has the same SCSI ID as the specified volume
- volumeScsiId = self.volume.iscsiName.split(":")[-1].strip()
- for vdiRef in vdiRefs:
- smConfig = xenapi.VDI.get_sm_config(vdiRef)
- vdiScsiId = smConfig["SCSIid"].strip()[1:]
- if (vdiScsiId == volumeScsiId):
- self.ref = vdiRef
- self.uuid = xenapi.VDI.get_uuid(vdiRef)
- return True
-
- return False
- else:
- self.ref = xenapi.VDI.get_by_uuid(self.uuid)
- return True
-
- @basicLogDecorator("Changing disk name for VDI...")
- def changeBootableDeviceName(self):
- system = self.volume.system
- xenapi = system.xenapi
- controlDomainRef = system.controlDomainRef
-
- vbdRef = None
- try:
- # Create a VBD for the VDI
- vbd = {'bootable': True, 'userdevice': '0', 'VDI': self.ref,
- 'other_config': {}, 'VM': controlDomainRef,
- 'mode': 'rw', 'qos_algorithm_type': '', 'qos_algorithm_params': {},
- 'type': 'Disk', 'empty': False, 'unpluggable': True}
- vbdRef = xenapi.VBD.create(vbd)
-
- # Plug the VBD
- xenapi.VBD.plug(vbdRef)
-
- # Create a temporary directory
- if (not system.runSshCommand("mkdir -p /root/temp")):
- raise Exception ("Failed to create directory /root/temp")
-
- # Check if /dev/xvda1 exists
- xvda1Exists = system.runSshCommand("ls /dev/xvda1")
-
- # If /dev/xvda1 doesn't exist, work with /dev/xvda
- if (not xvda1Exists):
- # Mount /dev/xvda to /root/temp
- if (not system.runSshCommand("mount /dev/xvda /root/temp")):
- raise Exception("Failed to mount /dev/xvda to /root/temp")
- writeToLog("Using /dev/xvda to change bootable device name.", False)
- else:
- # Mount /dev/xvda1 to /root/temp
- if (not system.runSshCommand("mount /dev/xvda1 /root/temp")):
- raise Exception("Failed to mount /dev/xvda1 to /root/temp")
-
- # If the boot directory exists under /root/temp, we can work with xvda1
- if (system.runSshCommand("ls /root/temp/boot")):
- writeToLog("Using /dev/xvda1 to change bootable device name.", False)
- else:
- # If the boot directory doesn't exist under /root/temp, we need to work with /dev/xvda2
-
- # Check that /dev/xvda2 exists
- if (not system.runSshCommand("ls /dev/xvda2")):
- raise Exception("/dev/xvda1 exists but /dev/xvda2 doesn't exist")
-
- # Unmount /dev/xvda1
- if (not system.runSshCommand("umount /root/temp")):
- raise Exception("Failed to unmount /dev/xvda1")
-
- # Mount /dev/xvda2
- if (not system.runSshCommand("mount /dev/xvda2 /root/temp")):
- raise Exception("Failed to mount /dev/xvda2")
-
- writeToLog("Using /dev/xvda2 to change bootable device name.", False)
-
- # Modify fstab, grub.conf, and device.map, if they exist
- for fileToModify in ["/root/temp/etc/fstab", "/root/temp/boot/grub/grub.conf", "/root/temp/boot/grub/device.map"]:
- if (system.runSshCommand("ls " + fileToModify)):
- if (not system.runSshCommand("sed -i 's_/dev/sda_/dev/xvda_' " + fileToModify)):
- raise Exception("Failed to modify " + fileToModify)
- finally:
- # Unmount /root/temp if necessary
- if (system.runSshCommand("mount | grep '/root/temp'")):
- if (not system.runSshCommand("umount /root/temp")):
- raise Exception("Failed to unmount /root/temp")
-
- # Delete /root/temp
- system.runSshCommand("rm -rf /root/temp")
-
- if (vbdRef != None):
- # Unplug the VBD
- xenapi.VBD.unplug(vbdRef)
-
- # Destroy the VBD
- xenapi.VBD.destroy(vbdRef)
-
- return True
-
-class StoragePool:
- # Vars: id, uuid
-
- def __init__(self, storagePoolId, uuid):
- self.id = storagePoolId
- self.uuid = uuid
-
- @staticmethod
- def getStoragePool(system, storagePoolId):
- columns = ["id", "uuid"]
- storagePoolRow = system.db.getDbValues("storage_pool", columns, {"id":storagePoolId})[0]
- return StoragePool(storagePoolRow["id"], storagePoolRow["uuid"])
-
-class Host:
- # Vars: id, ip, iqn
-
- def __init__(self, hostId, ip, iqn):
- self.id = hostId
- self.ip = ip
- self.iqn = iqn
-
- def __str__(self):
- return "Host: id: %s | ip %s" % (self.id, self.ip)
-
- @staticmethod
- @basicLogDecorator("Sharing LUs...")
- def shareAllLus():
- return Host.shareOrUnshareAllLus(True)
-
- @staticmethod
- @basicLogDecorator("Unsharing LUs...")
- def unshareAllLus():
- return Host.shareOrUnshareAllLus(False)
-
- @staticmethod
- def shareOrUnshareAllLus(share):
- # Get a map of XenServer IPs -> IQNs
- xenServerIqns = Host.getXenServerIqns()
-
- # Get a map of storage host IPs in the source system -> passwords
- storageHostPasswords = GLOBALS["STORAGE_HOST_PASSWORDS"]
-
- # Copy share_all_lus.sh to each storage host and run with each XenServer IQN
- for ip in storageHostPasswords.keys():
- password = storageHostPasswords[ip]
- sshConn = paramiko.SSHClient()
- sshConn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- sshConn.connect(ip, username = "root", password = password)
- sftpConn = sshConn.open_sftp()
- sftpConn.put("share_all_lus.sh", "/root/share_all_lus.sh")
- for xenServerIp in xenServerIqns.keys():
- iqn = xenServerIqns[xenServerIp]
- command = "bash /root/share_all_lus.sh -i " + iqn
- if (share):
- command += " -s"
- else:
- command += " -u"
- stdin, stdout, stderr = sshConn.exec_command(command)
- if (stdin.channel.recv_exit_status() != 0):
- return False
- if (not share):
- sftpConn.remove("/root/share_all_lus.sh")
- sshConn.close()
- sftpConn.close()
-
- return True
-
- @staticmethod
- def getHost(system, hostId):
- columns = ["id", "private_ip_address", "iqn"]
- hostRow = system.db.getDbValues("host", columns, {"id":hostId})[0]
- return Host(hostRow["id"], hostRow["private_ip_address"], hostRow["iqn"])
-
- @staticmethod
- def getStorageHostIps():
- storageHostIps = []
- columns = ["private_ip_address"]
- hostRows = GLOBALS["SRC_SYSTEM"].db.getDbValues("host", columns, {"type":"Storage"})
- for hostRow in hostRows:
- storageHostIps.append(hostRow["private_ip_address"])
- return storageHostIps
-
- @staticmethod
- def getXenServerIqns():
- xenServerIqns = dict()
- columns = ["private_ip_address", "url"]
- hostRows = GLOBALS["DEST_SYSTEM"].db.getDbValues("host", columns, {"type":"Routing"})
- for hostRow in hostRows:
- xenServerIqns[hostRow["private_ip_address"]] = hostRow["url"]
- return xenServerIqns
-
-
-### Runtime
-
-GLOBALS = dict()
-
-@basicLogDecorator("Reading upgrade.properties...")
-def readUpgradeProperties():
- upgradePropertiesFile = open("upgrade.properties", "r")
- upgradeProperties = upgradePropertiesFile.read().splitlines()
- for upgradeProperty in upgradeProperties:
- if (upgradeProperty.strip() == ""):
- continue
- elif (upgradeProperty.startswith("#")):
- continue
- else:
- propList = upgradeProperty.split("=")
- var = propList[0].strip()
- val = propList[1].strip()
- if (val == ""):
- continue
- GLOBALS[var] = val
-
- # Create the log file
- logFilePath = GLOBALS["LOG_FILE"]
- GLOBALS["LOG_FILE"] = open(logFilePath, "a")
-
- # Create the guest OS map
- GLOBALS["GUEST_OS_MAP"] = csvToMap(GLOBALS["GUEST_OS_MAP"])
-
- # Create the XenServer passwords map
- if (GLOBALS.get("DEST_XENSERVER_PASSWORDS") != None):
- GLOBALS["DEST_XENSERVER_PASSWORDS"] = csvToMap(GLOBALS.get("DEST_XENSERVER_PASSWORDS"))
-
- # Create the Storage Host passwords map
- if (GLOBALS.get("STORAGE_HOST_PASSWORDS") == None):
- raise Exception ("Please fill out the variable STORAGE_HOST_PASSWORDS in upgrade.properties.")
- else:
- GLOBALS["STORAGE_HOST_PASSWORDS"] = csvToMap(GLOBALS["STORAGE_HOST_PASSWORDS"])
-
- # Create the list of users to upgrade
- if GLOBALS.has_key("USERS"):
- GLOBALS["USERS"] = [userId.strip() for userId in GLOBALS["USERS"].split(",")]
- else:
- GLOBALS["USERS"] = None
-
- return True
-
-def csvToMap(csv):
- entries = csv.split(",")
- entryMap = dict()
- for entry in entries:
- entryList = entry.strip().split(":")
- key = entryList[0].strip()
- val = entryList[1].strip()
- entryMap[key] = val
- return entryMap
-
-@basicLogDecorator("Running diagnostic...")
-def runDiagnostic():
- # Either one XenServer IP and password should be specified, or a mapping between XenServer IPs and passwords should be specified
- if ((GLOBALS.get("DEST_XENSERVER_IP") == None and (GLOBALS.get("DEST_XENSERVER_PASSWORD") != None or GLOBALS.get("DEST_XENSERVER_PASSWORDS") == None))
- or (GLOBALS.get("DEST_XENSERVER_IP") != None and (GLOBALS.get("DEST_XENSERVER_PASSWORD") == None or GLOBALS.get("DEST_XENSERVER_PASSWORDS") != None))):
- raise Exception("Please specify the IP and root password for one XenServer (if all XenServers have the same root password), or the IPs and root passwords of all XenServers.")
-
- GLOBALS["SRC_SYSTEM"] = System(GLOBALS["SRC_MANAGEMENT_SERVER_IP"], False, None, None, None, "vmops", GLOBALS["SRC_DB_LOGIN"],
- GLOBALS.get("SRC_DB_PASSWORD"), GLOBALS["SRC_ZONE_ID"], None, None, None, None)
-
- GLOBALS["DEST_SYSTEM"] = System(GLOBALS["DEST_MANAGEMENT_SERVER_IP"], True, GLOBALS.get("DEST_XENSERVER_IP"),
- GLOBALS.get("DEST_XENSERVER_PASSWORD"), GLOBALS.get("DEST_XENSERVER_PASSWORDS"),
- "cloud", GLOBALS["DEST_DB_LOGIN"], GLOBALS.get("DEST_DB_PASSWORD"), GLOBALS["DEST_ZONE_ID"],
- GLOBALS["DEST_TEMPLATE_ID"], GLOBALS["DEST_ISO_ID"], GLOBALS["DEST_SERVICE_OFFERING_ID"],
- GLOBALS["DEST_DISK_OFFERING_ID"])
-
- srcSystemServiceOfferings = ServiceOffering.getSrcSystemServiceOfferings()
- for srcSystemServiceOffering in srcSystemServiceOfferings:
- # Every service offering in the src system must have a corresponding service offering in the dest system
- destSystemServiceOffering = ServiceOffering.getCorrespondingServiceOffering(srcSystemServiceOffering.id)
- if (destSystemServiceOffering == None):
- raise Exception("No corresponding service offering found for: " + str(srcSystemServiceOffering))
-
- # Every service offering in the src system has a corresponding disk offering in the dest system
- destSystemDiskOffering = DiskOffering.getCorrespondingDiskOffering(srcSystemServiceOffering.id)
- if (destSystemDiskOffering == None):
- raise Exception("No corresponding disk offering found for: " + str(srcSystemServiceOffering))
-
- # Every template ID in the src system has a valid entry in GUEST_OS_MAP
- srcSystemTemplateIds = VM.getTemplateIds(GLOBALS["SRC_SYSTEM"])
- for templateId in srcSystemTemplateIds:
- if (not GLOBALS["GUEST_OS_MAP"].has_key(templateId)):
- raise Exception("No corresponding guest OS ID for templateId: " + templateId)
- else:
- guestOsId = GLOBALS["GUEST_OS_MAP"][templateId]
- guestOsName = VM.getGuestOsName(GLOBALS["DEST_SYSTEM"], guestOsId)
- if (guestOsName == None):
- raise Exception("The guest OS ID that corresponds to template ID: " + templateId + " is not valid.")
-
- # The dest system's ISO id must be valid
- template = VM.getTemplate(GLOBALS["DEST_SYSTEM"], GLOBALS["DEST_ISO_ID"])
- if (template == None or template["format"] != "ISO"):
- raise Exception("The dest system ISO ID is not valid.")
-
- # Verify that all source system storage hosts have a password
- storageHostIps = Host.getStorageHostIps()
- for ip in storageHostIps:
- if (ip not in GLOBALS["STORAGE_HOST_PASSWORDS"].keys()):
- raise Exception("The storage host IP: " + str(ip) + " has no entry in STORAGE_HOST_PASSWORDS.")
-
- return True
-
-@basicLogDecorator("Starting CloudStack Migration (1.0 -> 2.1)...")
-def upgradeUsers(userIds, onlyMigratePublicIps):
- # Read variables from upgrade.properties
- readUpgradeProperties()
-
- # Run the diagnostic
- runDiagnostic()
-
- if (userIds == None):
- if (GLOBALS["USERS"] == None):
- raise Exception("Please specify one or more users to upgrade.")
- else:
- userIds = GLOBALS["USERS"]
-
- # Make sure all users are valid
- for userId in userIds:
- if (User.get(GLOBALS["SRC_SYSTEM"], userId) == None):
- raise Exception("The user ID: " + str(userId) + " is not valid.")
-
- if (not onlyMigratePublicIps):
- # Share all LUs
- Host.shareAllLus()
-
- try:
- for userId in userIds:
- doUpgrade(userId, onlyMigratePublicIps)
- return True
- finally:
- if (not onlyMigratePublicIps):
- # Forget all iSCSI SRs
- SR.forgetAllSrcSrs()
- # Unshare all LUs
- Host.unshareAllLus()
-
-def doUpgrade(userId, onlyMigratePublicIps):
- # Get the specified user from the source system
- srcUser = User.get(GLOBALS["SRC_SYSTEM"], userId)
-
- writeToLog("\nStarting migration for " + str(srcUser), True)
-
- # Create a new user in the destination system with the same attributes as the original user
- destUser = User.create(GLOBALS["DEST_SYSTEM"], srcUser)
-
- if (not srcUser.alreadyMigrated()):
- # Allocate the src user's public IPs in the dest system
- allocatedPublicIps = PublicIp.migrateAllocatedPublicIps(srcUser, destUser)
-
- if (onlyMigratePublicIps):
- writeToLog("\nMigrated public IPs for " + str(srcUser), True)
- return
-
- # Stop the source user's DomR
- srcUserDomR = DomainRouter(srcUser)
-
- # Only migrate the user's VMs if there is a DomR
- if (srcUserDomR.id != None):
- srcUserDomR.stop()
-
- # If the dest user doesn't have a DomR, deploy a temporary VM
- destUserDomR = DomainRouter(destUser)
- tempVm = None
- if (destUserDomR.id == None):
- tempVm = VM(None, destUser, None, None, None)
- tempVm.deployTemp()
- destUserDomR.id = destUserDomR.getId()
- else:
- tempVm = VM.getTempVm(destUser)
-
- # Migrate the source user's VM's to the dest system
- vmIdMap = VM.migrateVirtualMachines(srcUser, destUser)
-
- # Migrate the source user's port forwarding and load balancer rules
- ForwardingRule.migrateForwardingRules(srcUser, destUser, allocatedPublicIps, vmIdMap)
-
- # Reboot the dest user's router
- destUserDomR.reboot()
-
- # Destroy the temporary VM
- if (tempVm != None):
- tempVm.destroy()
-
- srcUser.tagAsMigrated()
- else:
- writeToLog("\n" + str(srcUser) + " has already been migrated.", True)
-
- writeToLog("\nMigration was successful for " + str(srcUser), True)
-
-if (len(sys.argv) > 1):
- if (sys.argv[1].lower() == "publicips"):
- if (len(sys.argv) > 2):
- upgradeUsers(sys.argv[2:], True)
- else:
- upgradeUsers(None, True)
- else:
- upgradeUsers(sys.argv[1:], False)
-else:
- upgradeUsers(None, False)
-