Files
CyberPanel/CyberTronAPI/virtualMachineAPIKVM.py
2018-09-10 01:45:43 +05:00

613 lines
23 KiB
Python
Executable File

from CyberTronLogger import CyberTronLogger as logger
from inspect import stack
from shlex import split
from subprocess import call,CalledProcessError
from os.path import join
from os import remove, path
from random import randint
import libvirt
from logLevel import logLevel
from xml.etree import ElementTree
class virtualMachineAPI:
## os.path.join
templatesPath = join('/var','lib','libvirt','templates')
imagesPath = join('/var','lib','libvirt','images')
@staticmethod
def obtainVirtualMachineObject(virtualMachineName):
try:
connection = libvirt.open('qemu:///system')
if connection == None:
return 0, 'Failed to establish connection.'
virtualMachine = connection.lookupByName(virtualMachineName)
if virtualMachine == None:
return 0, 'Can not find virtual machine.'
return 1, virtualMachine
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def limitVMSpeed(vpsID, vpsIP, interface, interfaceLimit):
try:
## Creating class
command = 'tc class add dev ' + interface + ' parent 2:1 classid ' + '2:' + vpsID + ' htb rate ' + interfaceLimit
logger.writeToFile(command,'Info',stack()[0][3])
result = call(split(command))
if result == 1:
raise CalledProcessError
else:
pass
## Create IP Filter.
command = 'tc filter add dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 match ip src ' + vpsIP + ' flowid 2:' + vpsID
logger.writeToFile(command,'Info',stack()[0][3])
result = call(split(command))
if result == 1:
raise CalledProcessError
else:
pass
return 1
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
except CalledProcessError, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def removeVMSpeedLimit(vpsID, interface):
try:
## Removing filter.
command = 'tc filter del dev ' + interface + ' parent 2:0 protocol ip prio 1 u32 flowid 2:' + vpsID
result = call(split(command))
if result == 1:
raise CalledProcessError
else:
pass
## Removing class.
command = 'tc class del dev ' + interface + ' classid 2:' + vpsID
result = call(split(command))
if result == 1:
raise CalledProcessError
else:
pass
return 1
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
except CalledProcessError, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def deleteVirtualMachine(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.hasCurrentSnapshot():
snapShots = virtualMachine.listAllSnapshots()
for snapShot in snapShots:
snapShot.delete()
if virtualMachine.isActive():
virtualMachine.destroy()
virtualMachine.undefine()
## Removing virtual machine file.
try:
pathToImg = join(virtualMachineAPI.imagesPath, virtualMachineName + '.qcow2')
remove(pathToImg)
except BaseException,msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
##
return 1,'No error.'
else:
return 0,'Failed to obtain virtual machine object.'
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def revertToSnapshot(virtualMachineName, snapshotName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
snapshot = virtualMachine.snapshotLookupByName(snapshotName)
virtualMachine.revertToSnapshot(snapshot)
return 1, 'No error.'
else:
return 0,'Failed to obtain virtual machine object.'
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def softReboot(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.isActive():
virtualMachine.reboot()
return 1, 'No error.'
else:
command = 'virsh start ' + virtualMachineName
call(split(command))
return 1, 'No error.'
else:
return 0,'Failed to obtain virtual machine object.'
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def hardShutdown(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.isActive():
virtualMachine.destroy()
return 1, 'No error.'
else:
return 0, 'VPS is not running.'
else:
return 0,'Failed to obtain virtual machine object.'
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def setupNetworkingFiles(vmName, ipAddress, netmask, gateway, hostName):
try:
if logLevel.debug == True:
logger.operationsLog('Setting up network for: ' + vmName + '.', 'Debug', stack()[0][3])
uploadSource = []
###### /etc/sysconfig/network-scripts/ifcfg-eth0
eth0 = "ifcfg-eth0_" + str(randint(10000, 99999))
eth0File = open(eth0, 'w')
eth0File.writelines('DEVICE="eth0"\n')
eth0File.writelines('NM_CONTROLLED="yes"\n')
eth0File.writelines('ONBOOT=yes\n')
eth0File.writelines('TYPE=Ethernet\n')
eth0File.writelines('BOOTPROTO=static\n')
eth0File.writelines('NAME="System eth0"\n')
eth0File.writelines('IPADDR=' + ipAddress + '\n')
eth0File.writelines('NETMASK=' + netmask + '\n')
eth0File.close()
uploadSource.append(eth0)
###### /etc/sysconfig/network
network = "network_" + str(randint(10000, 99999) + 1)
networkFile = open(network, 'w')
networkFile.writelines('NETWORKING=yes\n')
networkFile.writelines('HOSTNAME=' + hostName + '\n')
networkFile.writelines('GATEWAY=' + gateway + '\n')
networkFile.close()
uploadSource.append(network)
###### /etc/resolv.conf
resolv = "resolv_" + str(randint(10000, 99999) + 2)
resolvFile = open(resolv, 'w')
resolvFile.writelines("nameserver 8.8.8.8\n")
resolvFile.close()
uploadSource.append(resolv)
if logLevel.debug == True:
logger.operationsLog('Network settings installed for: ' + vmName + '.', 'Debug', stack()[0][3])
return uploadSource
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
'''
vmName = Usually IP Address.
osName = Examples operatingSystem-X.xx.x86
uploadSource = An array containing complete path of files to be uploaded to the image after creation.
rootPassword = Virtual Machine root password.
'''
@staticmethod
def setupVMDisk(vmName, package, uploadSource, rootPassword):
try:
if logLevel.debug == True:
logger.operationsLog('Creating disk image for: ' + vmName + '.', 'Debug', stack()[0][3])
sourcePath = join(virtualMachineAPI.templatesPath, package + ".qcow2")
finalPath = join(virtualMachineAPI.imagesPath, vmName + ".qcow2")
## Build upload command
uploadCommand = ""
uploadCommand = " --upload " + uploadSource[0] + ":" + "/etc/sysconfig/network-scripts/ifcfg-eth0"
uploadCommand = uploadCommand + " --upload " + uploadSource[1] + ":" + "/etc/sysconfig/network"
uploadCommand = uploadCommand + " --upload " + uploadSource[2] + ":" + "/etc/resolv.conf"
## Creating temporary disk image.
command = "qemu-img create -b " + sourcePath + " -f qcow2 " + finalPath
result = call(split(command))
if result == 1:
raise CalledProcessError
if logLevel.debug == True:
logger.operationsLog("Temporary image created for: " + vmName + ".", "Debug", stack()[0][3])
## Setup network and customize root password
command = "virt-customize -a " + finalPath + " --root-password password:" + rootPassword + uploadCommand
call(split(command))
if result == 1:
raise CalledProcessError
if logLevel.debug == True:
logger.operationsLog("Root password and network configured for: " + vmName + ".", "Debug",
stack()[0][3])
return 1
return 1
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
except CalledProcessError, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
"""
vmName = Name of the virtual machine, usually the IP Address.
vmRam = Ram to be assigned to this virtual machine.
vmVCPUs = Virtual CPUs to be assigned to this virtual machine.
vmDestination = Path where VM image will be housed.
format = Examples, qcow2, img, qcow, recommend is qcow2.
vncPort = VNC Port for this virtual machine.
osType = OS Type e.g. linux,windows.
osVariant = OS Variant e.g. centos 6, centos 7.
bridgeName = Bridge name to which the interface of this VM will be attached.
debug = Enable or disable extended debug logging. Defaults to false.
"""
@staticmethod
def bootVirtualMachine(vmName, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, webSocketPort, vncPassword):
try:
if logLevel.debug == True:
logger.operationsLog('Booting: ' + vmName + '.', 'Debug', stack()[0][3])
finalImageLocation = join(virtualMachineAPI.imagesPath, vmName + ".qcow2")
# virt-install --name 109.238.12.214 --ram 2048 --vcpus=1 --disk 109.238.12.214.qcow2 --graphics vnc,listen=localhost,port=5500 --noautoconsole --hvm --import --os-type=linux --os-variant=rhel7 --network bridge=virbr0
command = "virt-install --name " + vmName + " --ram " + vmRam + " --vcpu " + vmVCPUs + " --disk " + \
finalImageLocation + " --graphics vnc,listen=" + vncHost + ",port=" + vncPort + ",password=" + vncPassword + \
' --qemu-commandline=' + '"' + '-vnc :' + webSocketPort + ',websocket' + '"' + \
" --noautoconsole --hvm --import --autostart --os-type=linux " \
+ "--network bridge=" + bridgeName
logger.writeToFile(command,"Info", stack()[0][3])
result = call(split(command))
if result == 1:
raise CalledProcessError
if logLevel.debug == True:
logger.operationsLog("Successfully booted: " + vmName + ".", "Debug", stack()[0][3])
return 1
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
except CalledProcessError, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
"""
osName = Name of OS, with which this image should be created.
imgDestination = Destination on disk where this image should be placed.
imgName = Name of vps, this will be combined with imgDestination.
size = Size in GBs.
format = Examples, qcow2, img, qcow, recommend is qcow2.
uploadSource = An array containing complete path of files to be uploaded to the image after creation.
UploadDestination = Corressponding array of upload source, defining upload destination of files.
--
vmName = Name of the virtual machine, usually the IP Address.
vmRam = Ram to be assigned to this virtual machine.
vmVCPUs = Virtual CPUs to be assigned to this virtual machine.
diskImage = A complete path to disk image for this virtual machine.
vncPort = VNC Port for this virtual machine.
osType = OS Type e.g. linux,windows.
osVariant = OS Variant e.g. centos 6, centos 7.
bridgeName = Bridge name to which the interface of this VM will be attached.
"""
@staticmethod
def createVirtualMachine(vmName, package, rootPassword, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, ipAddress, netmask, gateway, hostName, webSocketPort, vncPassword):
try:
logger.operationsLog('Starting to create virtual machine: ' + vmName, 'Info', stack()[0][3])
##
uploadSource = virtualMachineAPI.setupNetworkingFiles(vmName, ipAddress, netmask, gateway, hostName)
##
if virtualMachineAPI.setupVMDisk(vmName, package, uploadSource, rootPassword) == 0:
return 0
##
if virtualMachineAPI.bootVirtualMachine(vmName, vmVCPUs, vmRam, vncHost, vncPort, bridgeName, webSocketPort, vncPassword) == 0:
return 0
##
logger.operationsLog('Virtual machine ' + vmName + ' successfully created.', 'Success', stack()[0][3])
return 1
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
#virtualMachineAPI.createVirtualMachine('192.111.145.237', 'forthPlan', 'litespeed12', '2', '2048', '192.111.145.234', '5904','virbr0','192.111.145.237','255.255.255.248','192.111.145.233','usman.cybertronproject.com')
#print virtualMachineAPI.deleteVirtualMachine('109.238.12.214')
#print virtualMachineAPI.revertToSnapshot('109.238.12.214','CyberPanel')
#virtualMachineAPI.softReboot('109.238.12.214')
@staticmethod
def isActive(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.isActive():
return 1
else:
return 0
else:
return 0
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def getCurrentUsedRam(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.isActive():
memStats = virtualMachine.memoryStats()
return int(memStats['unused']/1024)
else:
return 0
else:
return 0
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def getBandwidthUsage(virtualMachineName):
try:
obtainStatus, virtualMachine = virtualMachineAPI.obtainVirtualMachineObject(virtualMachineName)
if obtainStatus == 1:
if virtualMachine.isActive():
tree = ElementTree.fromstring(virtualMachine.XMLDesc())
iface = tree.find('devices/interface/target').get('dev')
memStats = virtualMachine.interfaceStats(iface)
## memStats[0] are read bytes, memStats[4] write bytes
return (memStats[0] + memStats[4])/(1024 * 1024)
else:
return 0
else:
return 0
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def calculateDiskPercentage(virtualMachineName, actualDisk):
try:
vpsImagePath = '/var/lib/libvirt/images/' + virtualMachineName + ".qcow2"
sizeInMB = float(path.getsize(vpsImagePath)) / (1024.0 * 1024)
diskUsagePercentage = float(100) / float((int(actualDisk.rstrip('GB')) * 1024))
diskUsagePercentage = float(diskUsagePercentage) * float(sizeInMB)
diskUsagePercentage = int(diskUsagePercentage)
if diskUsagePercentage > 100:
return 100, sizeInMB
return diskUsagePercentage, sizeInMB
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0,0
@staticmethod
def calculateRamPercentage(virtualMachineName, actualRam):
try:
unUsedRam = virtualMachineAPI.getCurrentUsedRam(virtualMachineName)
usedRam = int(actualRam.rstrip('MB')) - unUsedRam
ramUsagePercentage = float(100) / int(actualRam.rstrip('MB'))
ramUsagePercentage = int(float(ramUsagePercentage) * float(usedRam))
if ramUsagePercentage > 100:
return 100
return ramUsagePercentage
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def calculateBWPercentage(virtualMachineName, actualBW):
try:
usedBW = virtualMachineAPI.getBandwidthUsage(virtualMachineName)
availBW = int(actualBW.rstrip('TB')) * 1024 * 1024
bwPercentage = float(100) / availBW
bwPercentage = int(float(bwPercentage) * usedBW)
if bwPercentage > 100:
return 100
return bwPercentage
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0
@staticmethod
def changeHostname(virtualMachineName, newHostname):
try:
command = "virt-customize -d " + virtualMachineName + " --hostname " + newHostname
call(split(command))
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def changeRootPassword(virtualMachineName, newPassword):
try:
command = "virt-customize -d " + virtualMachineName + " --root-password password:" + newPassword
call(split(command))
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def createSnapshot(virtualMachineName, snapshotName):
try:
command = "virsh snapshot-create-as --domain " + virtualMachineName + " --name " + snapshotName
call(split(command))
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)
@staticmethod
def deleteSnapshot(virtualMachineName, snapshotName):
try:
command = "virsh snapshot-delete --domain " + virtualMachineName + " --snapshotname " + snapshotName
call(split(command))
except BaseException, msg:
if logLevel.debug == True:
logger.operationsLog(str(msg), "Error", stack()[0][3])
logger.writeToFile(str(msg), "Error", stack()[0][3])
return 0, str(msg)