def __processDeleteImagePacket(self, data):
     
     isBootable = self.__commandsDBConnector.getBootableFlag(data["ImageID"])
     
     if(isBootable):            
         osImagePath = os.path.join(self.__parser.getConfigurationParameter("sourceImagePath") 
                                ,self.__commandsDBConnector.getOSImagePath(data["ImageID"]))
         definitionFilePath = os.path.join(self.__parser.getConfigurationParameter("configFilePath") 
                                ,self.__commandsDBConnector.getDefinitionFilePath(data["ImageID"]))
         
         try :
             
             self.__commandsDBConnector.deleteImage(data["ImageID"])                
             ChildProcessManager.runCommandInForeground("rm -rf " + os.path.dirname(osImagePath), VMServerException)                
             ChildProcessManager.runCommandInForeground("rm -rf " + os.path.dirname(definitionFilePath), VMServerException)
             p = self.__packetManager.createConfirmationPacket(VM_SERVER_PACKET_T.IMAGE_DELETED, data["ImageID"], data["CommandID"])
         except Exception:
             p = self.__packetManager.createErrorPacket(VM_SERVER_PACKET_T.IMAGE_DELETION_ERROR, ERROR_DESC_T.VM_SRVR_INTERNAL_ERROR, 
                                                         data["CommandID"])                
         
     else:
         if (isBootable != None) :
             errorCode = ERROR_DESC_T.VMSRVR_LOCKED_IMAGE
         else :
             errorCode = ERROR_DESC_T.VMSRVR_UNKNOWN_IMAGE
         
         p = self.__packetManager.createErrorPacket(VM_SERVER_PACKET_T.IMAGE_DELETION_ERROR, errorCode, 
                                                    data["CommandID"])
     
     self.__networkManager.sendPacket('', self.__listenningPort, p)
Exemple #2
0
    def createVirtualNetwork(self,
                             networkName,
                             gatewayIPAddress,
                             netmask,
                             dhcpStartIPAddress,
                             dhcpEndIPAddress,
                             bridgeName=None):
        """
        Creates a virtual network.
        Args:
            networkName: the virtual network's name
            gatewayIPAddress: the gateway's IPv4 address
            netmask: the gateway's netmask
            dhcpStartIPAddress: the DHCP server start address
            dhcpStopIPAddress: the DHCP server stop address
            bridgeName: bridge name. If it's none, it will be named after the virtual network.
        Returns:
            Nothing   
        """
        # Check errors
        if (self.__networksByIP.has_key(gatewayIPAddress) != 0):
            raise VirtualNetworkManagerException("The gateway IP address " + \
                                                 gatewayIPAddress + " is already in use")
        if (self.__networksByName.has_key(networkName)):
            raise VirtualNetworkManagerException("The virtual network name " + networkName + \
                                                 " is already in use")
        xmlFilePath = "/tmp/networkConfig.xml"
        # Build the definition file
        self.__generateConfigurationFile(xmlFilePath, networkName, bridgeName,\
                                         gatewayIPAddress, netmask, dhcpStartIPAddress, dhcpEndIPAddress)

        # Create the virtual network. If it exists, it will be previously destroyed
        if (self.__runAsRoot):
            runMethod = ChildProcessManager.runCommandInForegroundAsRoot
        else:
            runMethod = ChildProcessManager.runCommandInForeground

        try:
            runMethod("virsh net-destroy " + networkName, Exception)
        except Exception:
            pass
        try:
            runMethod("virsh net-undefine " + networkName, Exception)
        except Exception:
            pass

        runMethod("virsh net-define " + xmlFilePath,
                  VirtualNetworkManagerException)

        # Enable the virtual network
        runMethod("virsh net-start " + networkName,
                  VirtualNetworkManagerException)

        # Delete the definition file
        ChildProcessManager.runCommandInForeground(
            "rm " + xmlFilePath, VirtualNetworkManagerException)

        # Start the virtual network
        self.__networksByIP[gatewayIPAddress] = networkName
        self.__networksByName[networkName] = gatewayIPAddress
    def __freeDomainResources(self, domainName, deleteDiskImages=True):
        """
        Free the resources assigned to a domain
        Args:
            domainName: a domain name
            deleteDiskImages: indicates wether the disk images must be deleted or not
        Returns:
            Nothing
        """
        dataImagePath = self.__commandsDBConnector.getDomainDataImagePath(
            domainName)
        osImagePath = self.__commandsDBConnector.getDomainOSImagePath(
            domainName)
        imageID = self.__commandsDBConnector.getDomainImageID(domainName)
        websockify_pid = self.__commandsDBConnector.getWebsockifyDaemonPID(
            domainName)
        isBootable = self.__commandsDBConnector.getBootableFlag(imageID)
        commandID = self.__commandsDBConnector.getVMBootCommand(domainName)

        self.__commandsDBConnector.unregisterDomainResources(domainName)

        if (websockify_pid != -1):
            ChildProcessManager.runCommandInForeground(
                "kill -s TERM " + str(websockify_pid), None)

        if isBootable:
            # If the domain was manually stopped, libvirt has already got rid of the disk images.
            # ==> we don't have to complain if we can't find them
            ChildProcessManager.runCommandInForeground("rm " + dataImagePath,
                                                       None)
            ChildProcessManager.runCommandInForeground("rm " + osImagePath,
                                                       None)
            dataDirectory = path.dirname(dataImagePath)
            osDirectory = path.dirname(osImagePath)
            if (path.exists(dataDirectory) and listdir(dataDirectory) == []):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + dataDirectory, None)
            if (osDirectory != dataDirectory and path.exists(osDirectory)
                    and listdir(osDirectory) == []):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + osDirectory, None)

        else:
            data = dict()
            connectionData = self.__commandsDBConnector.getImageRepositoryConnectionData(
                commandID)
            data["Transfer_Type"] = TRANSFER_T.STORE_IMAGE
            data["DataImagePath"] = dataImagePath
            data["OSImagePath"] = osImagePath
            data[
                "DefinitionFilePath"] = self.__commandsDBConnector.getDefinitionFilePath(
                    imageID)
            data["RepositoryIP"] = connectionData["RepositoryIP"]
            data["RepositoryPort"] = connectionData["RepositoryPort"]
            data["CommandID"] = commandID
            data["TargetImageID"] = imageID
            self.__commandsDBConnector.addToCompressionQueue(data)
            self.__commandsDBConnector.removeImageRepositoryConnectionData(
                commandID)
            self.__commandsDBConnector.deleteImage(imageID)
 def __init__(self, dbConnector, vncServerIP, networkManager, packetManager,
              listenningPort, useQEMUWebsockets, websockifyPath,
              definitionFileDirectory, sourceImageDirectory,
              executionImageDirectory, vncPasswordLength):
     """
     Initializes the domain handler's state
     Args:
         dbConnector: a database connector
         vncServerIP: the VNC server's IPv4 address
         networkManager: a network manager
         packetManager: a virtual machine server packet handler
         listenningPort: the control connection's port
         definitionFileDirectory: the directory where the definition files are
         sourceImageDirectory: the directory where the source disk images are
         executionImageDirectory: the directory where the active virtual machines' disk images are
         vncPasswordLength: the generated VNC password's length
     """
     self.__commandsDBConnector = dbConnector
     self.__vncServerIP = vncServerIP
     self.__childProcessManager = ChildProcessManager()
     self.__networkManager = networkManager
     self.__packetManager = packetManager
     self.__listenningPort = listenningPort
     self.__useQEMUWebsockets = useQEMUWebsockets
     self.__websockifyPath = websockifyPath
     self.__definitionFileDirectory = definitionFileDirectory
     self.__sourceImagePath = sourceImageDirectory
     self.__executionImagePath = executionImageDirectory
     self.__vncPasswordLength = vncPasswordLength
     self.__libvirtConnection = None
     self.__virtualNetworkManager = None
     self.__virtualNetworkName = None
Exemple #5
0
 def __deleteImage(self, data):
     """
     Handles an image deletion request
     Args:
         data: the received packet's content
     Returns:
         Nothing
     """
     imageData = self.__dbConnector.getImageData(data["imageID"])
     if (imageData == None):
         p = self.__repositoryPacketHandler.createImageDeletionErrorPacket(
             data["imageID"], ERROR_DESC_T.IR_UNKNOWN_IMAGE)
         self.__networkManager.sendPacket('', self.__commandsListenningPort,
                                          p, data['clientIP'],
                                          data['clientPort'])
     elif (imageData["imageStatus"] == IMAGE_STATUS_T.EDITION):
         p = self.__repositoryPacketHandler.createImageDeletionErrorPacket(
             data["imageID"], ERROR_DESC_T.IR_IMAGE_EDITED)
         self.__networkManager.sendPacket('', self.__commandsListenningPort,
                                          p, data['clientIP'],
                                          data['clientPort'])
     else:
         if (not "undefined" in imageData["compressedFilePath"]):
             imageDirectory = path.dirname(imageData["compressedFilePath"])
             ChildProcessManager.runCommandInForeground(
                 "rm -rf " + imageDirectory, Exception)
         self.__dbConnector.deleteImage(
             data["imageID"])  # TODO: poner encima del if
         p = self.__repositoryPacketHandler.createDeleteRequestReceivedPacket(
             data["imageID"])
         self.__networkManager.sendPacket('', self.__commandsListenningPort,
                                          p, data['clientIP'],
                                          data['clientPort'])
 def on_incomplete_f_received(self, f):    
     """
     Handles a file partially received event
     Args:
         f: a filename
     Returns:
         Nothing
     """
     remove(f)
     ChildProcessManager.runCommandInForeground("rm -rf " + path.dirname(f), Exception)
Exemple #7
0
 def on_incomplete_f_received(self, f):
     """
     Handles a file partially received event
     Args:
         f: a filename
     Returns:
         Nothing
     """
     remove(f)
     ChildProcessManager.runCommandInForeground("rm -rf " + path.dirname(f),
                                                Exception)
 def createVirtualNetwork(self, networkName, gatewayIPAddress, netmask,
                                 dhcpStartIPAddress, dhcpEndIPAddress, bridgeName=None):
     """
     Creates a virtual network.
     Args:
         networkName: the virtual network's name
         gatewayIPAddress: the gateway's IPv4 address
         netmask: the gateway's netmask
         dhcpStartIPAddress: the DHCP server start address
         dhcpStopIPAddress: the DHCP server stop address
         bridgeName: bridge name. If it's none, it will be named after the virtual network.
     Returns:
         Nothing   
     """
     # Check errors
     if (self.__networksByIP.has_key(gatewayIPAddress) != 0) :
         raise VirtualNetworkManagerException("The gateway IP address " + \
                                              gatewayIPAddress + " is already in use")
     if (self.__networksByName.has_key(networkName)):
         raise VirtualNetworkManagerException("The virtual network name " + networkName + \
                                              " is already in use")
     xmlFilePath = "/tmp/networkConfig.xml"
     # Build the definition file
     self.__generateConfigurationFile(xmlFilePath, networkName, bridgeName,\
                                      gatewayIPAddress, netmask, dhcpStartIPAddress, dhcpEndIPAddress)
     
     # Create the virtual network. If it exists, it will be previously destroyed
     if (self.__runAsRoot) :
         runMethod = ChildProcessManager.runCommandInForegroundAsRoot
     else :
         runMethod = ChildProcessManager.runCommandInForeground
         
     try :
         runMethod("virsh net-destroy " + networkName, Exception)
     except Exception :
         pass
     try :
         runMethod("virsh net-undefine " + networkName, Exception)
     except Exception :
         pass
     
     runMethod("virsh net-define " + xmlFilePath, VirtualNetworkManagerException)
     
     # Enable the virtual network
     runMethod("virsh net-start " + networkName, VirtualNetworkManagerException)
     
     # Delete the definition file
     ChildProcessManager.runCommandInForeground("rm " + xmlFilePath, VirtualNetworkManagerException)
     
     # Start the virtual network
     self.__networksByIP[gatewayIPAddress] = networkName
     self.__networksByName[networkName] = gatewayIPAddress
 def runSQLScript(self, database, sqlFilePath, username="******", password=None):
     '''
         Runs a SQL script
         Args:
             databaseName: the MySQL database to use
             sqlFilePath: the SQL script path
             username: a MySQL user name.
             password: the user's password
     '''
     passwordCommand = ""
     if (password != None and len(password) != 0) :
         passwordCommand = "-p" + str(password)
     filePath = os.path.abspath(sqlFilePath)
     command = "mysql -uroot {0} -e \"source {1}\"".format(passwordCommand, filePath)
     ChildProcessManager.runCommandInForeground(command, Exception)
 def extractFile(self, path, outputDirectory):
     '''
     Extracts a .zip file.
     Args:
         path: the .zip file path to extract
         outputDirectory: the directory where the .zip file content will be extracted.
     Returns:
         Nothing
     Raises: Exception
         When the compressed file cannot be extracted, an exception will be
         raised.
     '''
     if (outputDirectory == None) :
         outputDirectory = path.dirname(path)
     ChildProcessManager.runCommandInForeground("unzip " + path + " -d " + outputDirectory, Exception)
 def __init__(self, dbConnector, vncServerIP, networkManager, packetManager, listenningPort, 
              useQEMUWebsockets, websockifyPath, definitionFileDirectory,
              sourceImageDirectory, executionImageDirectory, vncPasswordLength):
     """
     Initializes the domain handler's state
     Args:
         dbConnector: a database connector
         vncServerIP: the VNC server's IPv4 address
         networkManager: a network manager
         packetManager: a virtual machine server packet handler
         listenningPort: the control connection's port
         definitionFileDirectory: the directory where the definition files are
         sourceImageDirectory: the directory where the source disk images are
         executionImageDirectory: the directory where the active virtual machines' disk images are
         vncPasswordLength: the generated VNC password's length
     """
     self.__commandsDBConnector = dbConnector        
     self.__vncServerIP = vncServerIP
     self.__childProcessManager = ChildProcessManager()        
     self.__networkManager = networkManager
     self.__packetManager = packetManager
     self.__listenningPort = listenningPort
     self.__useQEMUWebsockets = useQEMUWebsockets
     self.__websockifyPath = websockifyPath
     self.__definitionFileDirectory = definitionFileDirectory
     self.__sourceImagePath = sourceImageDirectory
     self.__executionImagePath = executionImageDirectory
     self.__vncPasswordLength = vncPasswordLength
     self.__libvirtConnection = None
     self.__virtualNetworkManager = None
     self.__virtualNetworkName = None
    def __sendStatusData(self):
        """
        Sends the server's status data to the cluster server
        Args:
            None
        Returns:
            Nothing
        """
        info = self.__domainHandler.getLibvirtStatusData()
        realCPUNumber = multiprocessing.cpu_count()
        freeOutput = ChildProcessManager.runCommandInForeground(
            "free -k", VMServerException)

        # free's output contains the following lines and collumns:
        #              total       used       free     shared    buffers     cached
        # Mem:    4146708480 3939934208  206774272          0  224706560 1117671424
        # -/+ buffers/cache: 2597556224 1549152256
        # Swap:   2046816256   42455040 2004361216
        #
        # We must get the third line

        availableMemory = int(freeOutput.split("\n")[1].split()[1])
        freeMemory = int(freeOutput.split("\n")[2].split()[2])

        freeStorageSpace, availableStorageSpace, freeTemporaryStorage, availableTemporaryStorage = self.__generateDiskStats(
        )
        packet = self.__packetManager.createVMServerStatusPacket(
            self.__vncServerIP, info["#domains"], freeMemory, availableMemory,
            freeStorageSpace, availableStorageSpace, freeTemporaryStorage,
            availableTemporaryStorage, info["#vcpus"], realCPUNumber)
        self.__networkManager.sendPacket('', self.__listenningPort, packet)
Exemple #13
0
 def extractFile(self, path, outputDirectory):
     '''
     Extracts a .zip file.
     Args:
         path: the .zip file path to extract
         outputDirectory: the directory where the .zip file content will be extracted.
     Returns:
         Nothing
     Raises: Exception
         When the compressed file cannot be extracted, an exception will be
         raised.
     '''
     if (outputDirectory == None):
         outputDirectory = path.dirname(path)
     ChildProcessManager.runCommandInForeground(
         "unzip " + path + " -d " + outputDirectory, Exception)
 def __sendStatusData(self):
     """
     Sends the server's status data to the cluster server
     Args:
         None
     Returns:
         Nothing
     """
     info = self.__domainHandler.getLibvirtStatusData()
     realCPUNumber = multiprocessing.cpu_count()
     freeOutput = ChildProcessManager.runCommandInForeground("free -k", VMServerException)
     
     # free's output contains the following lines and collumns:
     #              total       used       free     shared    buffers     cached
     # Mem:    4146708480 3939934208  206774272          0  224706560 1117671424
     # -/+ buffers/cache: 2597556224 1549152256
     # Swap:   2046816256   42455040 2004361216
     #
     # We must get the third line
        
     availableMemory = int(freeOutput.split("\n")[1].split()[1])
     freeMemory = int(freeOutput.split("\n")[2].split()[2])
     
     freeStorageSpace, availableStorageSpace, freeTemporaryStorage, availableTemporaryStorage = self.__generateDiskStats()
     packet = self.__packetManager.createVMServerStatusPacket(self.__vncServerIP, info["#domains"], freeMemory, availableMemory, 
                                                              freeStorageSpace, availableStorageSpace, 
                                                              freeTemporaryStorage, availableTemporaryStorage,
                                                              info["#vcpus"], realCPUNumber)
     self.__networkManager.sendPacket('', self.__listenningPort, packet) 
 def __freeDomainResources(self, domainName, deleteDiskImages=True):
     """
     Free the resources assigned to a domain
     Args:
         domainName: a domain name
         deleteDiskImages: indicates wether the disk images must be deleted or not
     Returns:
         Nothing
     """
     dataImagePath = self.__commandsDBConnector.getDomainDataImagePath(domainName)
     osImagePath = self.__commandsDBConnector.getDomainOSImagePath(domainName)
     imageID = self.__commandsDBConnector.getDomainImageID(domainName)
     websockify_pid = self.__commandsDBConnector.getWebsockifyDaemonPID(domainName)
     isBootable = self.__commandsDBConnector.getBootableFlag(imageID)        
     commandID = self.__commandsDBConnector.getVMBootCommand(domainName)
     
     self.__commandsDBConnector.unregisterDomainResources(domainName)     
     
     if (websockify_pid != -1) :
         ChildProcessManager.runCommandInForeground("kill -s TERM " + str(websockify_pid), None)   
     
     if isBootable :
         # If the domain was manually stopped, libvirt has already got rid of the disk images.
         # ==> we don't have to complain if we can't find them
         ChildProcessManager.runCommandInForeground("rm " + dataImagePath, None)
         ChildProcessManager.runCommandInForeground("rm " + osImagePath, None)
         dataDirectory = path.dirname(dataImagePath)
         osDirectory = path.dirname(osImagePath)
         if (path.exists(dataDirectory) and listdir(dataDirectory) == []) :
             ChildProcessManager.runCommandInForeground("rm -rf " + dataDirectory, None)
         if (osDirectory != dataDirectory and path.exists(osDirectory) and listdir(osDirectory) == []) :
             ChildProcessManager.runCommandInForeground("rm -rf " + osDirectory, None)            
                 
     else :
         data = dict()            
         connectionData = self.__commandsDBConnector.getImageRepositoryConnectionData(commandID)
         data["Transfer_Type"] = TRANSFER_T.STORE_IMAGE
         data["DataImagePath"] = dataImagePath
         data["OSImagePath"] = osImagePath
         data["DefinitionFilePath"] = self.__commandsDBConnector.getDefinitionFilePath(imageID)
         data["RepositoryIP"] = connectionData["RepositoryIP"]
         data["RepositoryPort"] = connectionData["RepositoryPort"]
         data["CommandID"] = commandID            
         data["TargetImageID"] = imageID
         self.__commandsDBConnector.addToCompressionQueue(data)
         self.__commandsDBConnector.removeImageRepositoryConnectionData(commandID)
         self.__commandsDBConnector.deleteImage(imageID)              
 def __generateVNCPassword(self):
     """
     Generates a VNC random password
     Args:
         None
     Returns:
         a string containing the generated password
     """
     return ChildProcessManager.runCommandInForeground("openssl rand -base64 " + str(self.__vncPasswordLength), VMServerException)
    def __processDeleteImagePacket(self, data):

        isBootable = self.__commandsDBConnector.getBootableFlag(
            data["ImageID"])

        if (isBootable):
            osImagePath = os.path.join(
                self.__parser.getConfigurationParameter("sourceImagePath"),
                self.__commandsDBConnector.getOSImagePath(data["ImageID"]))
            definitionFilePath = os.path.join(
                self.__parser.getConfigurationParameter("configFilePath"),
                self.__commandsDBConnector.getDefinitionFilePath(
                    data["ImageID"]))

            try:

                self.__commandsDBConnector.deleteImage(data["ImageID"])
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + os.path.dirname(osImagePath),
                    VMServerException)
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + os.path.dirname(definitionFilePath),
                    VMServerException)
                p = self.__packetManager.createConfirmationPacket(
                    VM_SERVER_PACKET_T.IMAGE_DELETED, data["ImageID"],
                    data["CommandID"])
            except Exception:
                p = self.__packetManager.createErrorPacket(
                    VM_SERVER_PACKET_T.IMAGE_DELETION_ERROR,
                    ERROR_DESC_T.VM_SRVR_INTERNAL_ERROR, data["CommandID"])

        else:
            if (isBootable != None):
                errorCode = ERROR_DESC_T.VMSRVR_LOCKED_IMAGE
            else:
                errorCode = ERROR_DESC_T.VMSRVR_UNKNOWN_IMAGE

            p = self.__packetManager.createErrorPacket(
                VM_SERVER_PACKET_T.IMAGE_DELETION_ERROR, errorCode,
                data["CommandID"])

        self.__networkManager.sendPacket('', self.__listenningPort, p)
 def __generateVNCPassword(self):
     """
     Generates a VNC random password
     Args:
         None
     Returns:
         a string containing the generated password
     """
     return ChildProcessManager.runCommandInForeground(
         "openssl rand -base64 " + str(self.__vncPasswordLength),
         VMServerException)
 def runSQLScript(self,
                  database,
                  sqlFilePath,
                  username="******",
                  password=None):
     '''
         Runs a SQL script
         Args:
             databaseName: the MySQL database to use
             sqlFilePath: the SQL script path
             username: a MySQL user name.
             password: the user's password
     '''
     passwordCommand = ""
     if (password != None and len(password) != 0):
         passwordCommand = "-p" + str(password)
     filePath = os.path.abspath(sqlFilePath)
     command = "mysql -uroot {0} -e \"source {1}\"".format(
         passwordCommand, filePath)
     ChildProcessManager.runCommandInForeground(command, Exception)
 def __deleteImage(self, data):
     """
     Handles an image deletion request
     Args:
         data: the received packet's content
     Returns:
         Nothing
     """  
     imageData = self.__dbConnector.getImageData(data["imageID"])
     if (imageData == None) :
         p = self.__repositoryPacketHandler.createImageDeletionErrorPacket(data["imageID"], ERROR_DESC_T.IR_UNKNOWN_IMAGE)
         self.__networkManager.sendPacket('', self.__commandsListenningPort, p, data['clientIP'], data['clientPort'])
     elif (imageData["imageStatus"] == IMAGE_STATUS_T.EDITION):
         p = self.__repositoryPacketHandler.createImageDeletionErrorPacket(data["imageID"], ERROR_DESC_T.IR_IMAGE_EDITED)
         self.__networkManager.sendPacket('', self.__commandsListenningPort, p, data['clientIP'], data['clientPort'])
     else :            
         if (not "undefined" in imageData["compressedFilePath"]) :
             imageDirectory = path.dirname(imageData["compressedFilePath"])
             ChildProcessManager.runCommandInForeground("rm -rf " + imageDirectory, Exception)
         self.__dbConnector.deleteImage(data["imageID"]) # TODO: poner encima del if
         p = self.__repositoryPacketHandler.createDeleteRequestReceivedPacket(data["imageID"])
         self.__networkManager.sendPacket('', self.__commandsListenningPort, p, data['clientIP'], data['clientPort'])            
 def createCompressedFile(self, filePath, fileNameList):
     '''
     Generates a .zip file.
     Args:
         filePath: the new .zip file path
         fileNameList: the files that will be added to the .zip file.
     Returns:
         Nothing
     Raises: Exception
         When the compressed file cannot be created, an exception will be
         raised.
     '''
     args = filePath + " "
     for fileName in fileNameList :
         args += fileName + " "
     try :
         ChildProcessManager.runCommandInForeground("zip -j " + args, Exception)
     except Exception as e:
         if ("Nothing to do" in e.message) :
             pass
         else :
             raise e
Exemple #22
0
 def createCompressedFile(self, filePath, fileNameList):
     '''
     Generates a .zip file.
     Args:
         filePath: the new .zip file path
         fileNameList: the files that will be added to the .zip file.
     Returns:
         Nothing
     Raises: Exception
         When the compressed file cannot be created, an exception will be
         raised.
     '''
     args = filePath + " "
     for fileName in fileNameList:
         args += fileName + " "
     try:
         ChildProcessManager.runCommandInForeground("zip -j " + args,
                                                    Exception)
     except Exception as e:
         if ("Nothing to do" in e.message):
             pass
         else:
             raise e
 def startListenning(self, networkInterface, useSSL, certificatesDirectory, commandsListenningPort, ftpListenningPort, maxConnections,
                     maxConnectionsPerIP, uploadBandwidthRatio, downloadBandwidthRatio, ftpUsername, ftpPasswordLength): 
     """
     Boots up the FTP server and creates the control connection.
     Args:
         networkInterface: the network interface that will be used by the FTP server
         useSSL: indicates if SSL encryption must be used in the control connection or not
         certificatesDirectory: the directory where the files server.crt and server.key are
         commandsListenningPort: the control connection's port
         ftpListenningPort: the FTP server listenning port
         maxConnections: maximum FTP connections
         maxConnectionsPerIP: maximum FTP connections per IP address
         uploadBandwidthRatio: maximum download bandwidth fraction
         downloadBandwidthRatio: maximum upload bandwidth fraction
         ftpUsername: the FTP user that the virtual machine servers will use
         ftpPasswordLength: the random FTP password length
     Returns:
         Nothing
     @attention: The FTP password will be randomly generated at every boot.
     """
     try :
         self.__maxConnections = maxConnections      
         self.__commandsListenningPort = commandsListenningPort
         self.__FTPListenningPort = ftpListenningPort
         self.__networkManager = NetworkManager(certificatesDirectory)
         self.__repositoryPacketHandler = ImageRepositoryPacketHandler(self.__networkManager)        
         
         self.__commandsCallback = CommandsCallback(self.__networkManager, self.__repositoryPacketHandler, commandsListenningPort, self.__dbConnector,
                                                    self.__retrieveQueue, self.__storeQueue, self.__diskImagesDirectory)        
         
         self.__networkManager.startNetworkService()
         self.__networkManager.listenIn(commandsListenningPort, self.__commandsCallback, useSSL)
         
         dataCallback = FTPServerCallback(self.__slotCounter, self.__dbConnector)
         
         self.__ftpUsername = ftpUsername
         self.__ftpPassword = ChildProcessManager.runCommandInForeground("openssl rand -base64 {0}".format(ftpPasswordLength), Exception)        
         
         self.__ftpServer = ConfigurableFTPServer("Image repository FTP Server")
    
         self.__ftpServer.startListenning(networkInterface, ftpListenningPort, maxConnections, maxConnectionsPerIP, 
                                          dataCallback, downloadBandwidthRatio, uploadBandwidthRatio)
         self.__ftpServer.addUser(self.__ftpUsername, self.__ftpPassword, self.__diskImagesDirectory, "eramw")      
     except Exception as e:
         print "Error: " + e.message
         self.__finish = True
 def __getAllocatedSpace(self, imagePath):
     """
     Returns the disk space that must be allocated for a disk image
     Args:
         imagePath: the disk image's path
     Returns:
         Nothing
     """
     try :
         output = ChildProcessManager.runCommandInForeground("qemu-img info " + imagePath, Exception)
         lines = output.split("\n")
         virtualSize = VMServerReactor.__extractImageSize(lines[2].split(":")[1].split("(")[0])
         usedSpace = VMServerReactor.__extractImageSize(lines[3].split(":")[1])            
         return virtualSize - usedSpace
     except Exception as e:
         print e
         return 0
Exemple #25
0
 def startListenning(self,
                     networkInterface,
                     port,
                     maxConnections,
                     maxConnectionsPerIP,
                     ftpCallback=None,
                     downloadBandwidthRatio=0.8,
                     uploadBandwitdhRatio=0.8):
     """
     Starts the FTP server
     Args:
         networkInterface: the network interface that will be used to perform the FTP transfers
         port: a listenning port
         maxConnections: maximum connection number
         maxConnectionsPerIP: maximum connection number per IP address
         ftpCallback: the callback that will handle the events. If it's none, almost nothing will be
             done to handle them.
         downloadBandwidthRatio: maximum download bandwidth fraction
         uploadBandwidthRatio: maximum upload bandwidth fraction
     Returns:
         Nothing
     """
     ip_address = get_ip_address(networkInterface)
     handler = CygnusCloudFTPHandler
     handler.ftpCallback = ftpCallback
     handler.authorizer = self.__authorizer
     handler.banner = self.__banner
     link_bandwidth = ChildProcessManager.runCommandInForeground(
         "/sbin/ethtool eth0 | grep -i Speed | cut -b 9-", Exception)
     if ("Mb/s" in link_bandwidth):
         power = 1024**2
     else:
         power = 1024**3
     link_bandwidth = int(sub('[^0-9]', '', link_bandwidth))
     dtp_handler = ThrottledDTPHandler
     dtp_handler.read_limit = link_bandwidth * downloadBandwidthRatio * power
     dtp_handler.write_limit = link_bandwidth * uploadBandwitdhRatio * power
     handler.dtp_handler = dtp_handler
     address = (ip_address, port)
     self.__ftpServer = FTPServer(address, handler)
     self.__ftpServer.max_cons = maxConnections
     self.__ftpServer.max_cons_per_ip = maxConnectionsPerIP
     self.__thread = FTPServerThread(self.__ftpServer)
     self.__thread.start()
 def __getAllocatedSpace(self, imagePath):
     """
     Returns the disk space that must be allocated for a disk image
     Args:
         imagePath: the disk image's path
     Returns:
         Nothing
     """
     try:
         output = ChildProcessManager.runCommandInForeground(
             "qemu-img info " + imagePath, Exception)
         lines = output.split("\n")
         virtualSize = VMServerReactor.__extractImageSize(
             lines[2].split(":")[1].split("(")[0])
         usedSpace = VMServerReactor.__extractImageSize(
             lines[3].split(":")[1])
         return virtualSize - usedSpace
     except Exception as e:
         print e
         return 0
 def startListenning(self, networkInterface, port, maxConnections, maxConnectionsPerIP, ftpCallback = None,
                     downloadBandwidthRatio=0.8, uploadBandwitdhRatio=0.8):
     """
     Starts the FTP server
     Args:
         networkInterface: the network interface that will be used to perform the FTP transfers
         port: a listenning port
         maxConnections: maximum connection number
         maxConnectionsPerIP: maximum connection number per IP address
         ftpCallback: the callback that will handle the events. If it's none, almost nothing will be
             done to handle them.
         downloadBandwidthRatio: maximum download bandwidth fraction
         uploadBandwidthRatio: maximum upload bandwidth fraction
     Returns:
         Nothing
     """
     ip_address = get_ip_address(networkInterface)
     handler = CygnusCloudFTPHandler
     handler.ftpCallback = ftpCallback
     handler.authorizer = self.__authorizer
     handler.banner = self.__banner  
     link_bandwidth = ChildProcessManager.runCommandInForeground("/sbin/ethtool eth0 | grep -i Speed | cut -b 9-", Exception)
     if ("Mb/s" in link_bandwidth) :
         power = 1024 ** 2
     else :
         power = 1024 ** 3
     link_bandwidth = int(sub('[^0-9]', '', link_bandwidth))
     dtp_handler = ThrottledDTPHandler
     dtp_handler.read_limit = link_bandwidth * downloadBandwidthRatio * power
     dtp_handler.write_limit = link_bandwidth * uploadBandwitdhRatio * power 
     handler.dtp_handler = dtp_handler
     address = (ip_address, port)
     self.__ftpServer = FTPServer(address, handler)
     self.__ftpServer.max_cons = maxConnections
     self.__ftpServer.max_cons_per_ip = maxConnectionsPerIP
     self.__thread = FTPServerThread(self.__ftpServer)
     self.__thread.start()        
class DomainHandler(DomainStartCallback, DomainStopCallback):
    """
    These objects interact with libvirt to handle domains.
    """    
    def __init__(self, dbConnector, vncServerIP, networkManager, packetManager, listenningPort, 
                 useQEMUWebsockets, websockifyPath, definitionFileDirectory,
                 sourceImageDirectory, executionImageDirectory, vncPasswordLength):
        """
        Initializes the domain handler's state
        Args:
            dbConnector: a database connector
            vncServerIP: the VNC server's IPv4 address
            networkManager: a network manager
            packetManager: a virtual machine server packet handler
            listenningPort: the control connection's port
            definitionFileDirectory: the directory where the definition files are
            sourceImageDirectory: the directory where the source disk images are
            executionImageDirectory: the directory where the active virtual machines' disk images are
            vncPasswordLength: the generated VNC password's length
        """
        self.__commandsDBConnector = dbConnector        
        self.__vncServerIP = vncServerIP
        self.__childProcessManager = ChildProcessManager()        
        self.__networkManager = networkManager
        self.__packetManager = packetManager
        self.__listenningPort = listenningPort
        self.__useQEMUWebsockets = useQEMUWebsockets
        self.__websockifyPath = websockifyPath
        self.__definitionFileDirectory = definitionFileDirectory
        self.__sourceImagePath = sourceImageDirectory
        self.__executionImagePath = executionImageDirectory
        self.__vncPasswordLength = vncPasswordLength
        self.__libvirtConnection = None
        self.__virtualNetworkManager = None
        self.__virtualNetworkName = None
    
    def connectToLibvirt(self, networkInterface, virtualNetworkName, gatewayIP, netmask, 
                         dhcpStartIP, dhcpEndIP, createVirtualNetworkAsRoot) :
        """
        Creates the libvirt connection and the virtual network
        Args:
            createVirtualNetworkAsRoot: indicates wether the virtual network must be
                created as the super-user or not. This is required in some systems.
        Returns:
            Nothing
        """
        self.__libvirtConnection = LibvirtConnector(LibvirtConnector.KVM, self, self)
        self.__virtualNetworkManager = VirtualNetworkManager(createVirtualNetworkAsRoot)
        self.__virtualNetworkManager.createVirtualNetwork(virtualNetworkName, gatewayIP, 
                                                          netmask, dhcpStartIP, 
                                                          dhcpEndIP)
        self.__virtualNetworkName = virtualNetworkName
    
    def doInitialCleanup(self):
        """
        Does the initial cleanup, freeing the unused resources assigned to the
            registered virtual machines.
        Args:
            None
        Returns:
            Nothing
        """
        activeDomainNames = self.__libvirtConnection.getActiveDomainNames()
        registeredDomainNames = self.__commandsDBConnector.getRegisteredDomainNames()
        for domainName in registeredDomainNames :
            if (not domainName in activeDomainNames) :
                self.__freeDomainResources(domainName)
        self.__commandsDBConnector.allocateAssignedMACsUUIDsAndVNCPorts()
        
    def shutdown(self, timeout):
        """
        Destroys all the domains.
        Args:
            timeout: the number of seconds to wait before destruction all the domains.
        Returns:
            Nothing
        """
        if (self.__libvirtConnection != None) :
            if (timeout == 0) :
                self.__libvirtConnection.destroyAllDomains()
            else :
                self.__waitForDomainsToTerminate(timeout)
        try :
            self.__virtualNetworkManager.destroyVirtualNetwork(self.__virtualNetworkName)  
        except Exception:
            pass
        self.__childProcessManager.waitForBackgroundChildrenToTerminate()
        
    def createDomain(self, imageID, userID, commandID):
        """
        Creates a domain
        Args:
            imageID: the image to use's ID
            userID: the domain owner's ID
            commandID: the domain boot command's ID
        Returns:
            Nothing
        """    
        
        try : 
            diskImagesCreated = False
            websockifyPID = -1       
            imageFound = False
            newUUID = None
            newMAC = None
            
            definitionFile = self.__definitionFileDirectory + self.__commandsDBConnector.getDefinitionFilePath(imageID)
            originalName = "{0}_".format(imageID)
            dataImagePath = self.__commandsDBConnector.getDataImagePath(imageID)
            osImagePath = self.__commandsDBConnector.getOSImagePath(imageID)
            isBootable = self.__commandsDBConnector.getBootableFlag(imageID)        
            imageFound = True
            
            # Generate the configuration parameters
            newUUID, newMAC = self.__commandsDBConnector.extractFreeMACAndUUID()
            newPort = self.__commandsDBConnector.extractFreeVNCPort()
            newName = originalName + str(newPort)        
            newPassword = self.__generateVNCPassword()
            sourceOSDisk = self.__sourceImagePath + osImagePath               
            
            if(isBootable):                           
                # Create the disk images in copy-on-write mode
                trimmedDataImagePath = dataImagePath
                try:
                    trimmedDataImagePath = dataImagePath[0:dataImagePath.index(".qcow2")]
                except:
                    pass
                trimmedOSImagePath = osImagePath
                try:
                    trimmedOSImagePath = osImagePath[0:osImagePath.index(".qcow2")]
                except:
                    pass   
                
                newDataDisk = self.__executionImagePath + trimmedDataImagePath + str(newPort) + ".qcow2"
                newOSDisk = self.__executionImagePath + trimmedOSImagePath + str(newPort) + ".qcow2"                
               
                # If one of the files already exist, we'll get rid of it.
                if (path.exists(newDataDisk)):
                    print("Warning: the file " + newDataDisk + " already exists")
                    ChildProcessManager.runCommandInForeground("rm " + newDataDisk, VMServerException)
                    
                if (path.exists(newOSDisk)):
                    print("Warning: the file " + newOSDisk + " already exists")
                    ChildProcessManager.runCommandInForeground("rm " + newOSDisk, VMServerException)
                    
                try :
                    ChildProcessManager.runCommandInForeground("cd " + self.__sourceImagePath + ";" + "cp --parents "+ dataImagePath + " " + self.__executionImagePath, VMServerException)
                    ChildProcessManager.runCommandInForeground("mv " + self.__executionImagePath + dataImagePath +" " + newDataDisk, VMServerException)
                    ChildProcessManager.runCommandInForeground("qemu-img create -b " + sourceOSDisk + " -f qcow2 " + newOSDisk, VMServerException)
                    diskImagesCreated = True
                except Exception as e:
                    diskImagesCreated = False
                    raise e
            
            else :
                # The images will not be created in copy-on-write mode. In fact, their stored copies will be
                # modified (we're editing them)
                newDataDisk = path.join(self.__sourceImagePath, dataImagePath)
                newOSDisk = path.join(self.__sourceImagePath, osImagePath)            
            
            # Build dthe definition file
            xmlFile = DefinitionFileEditor(definitionFile)
            xmlFile.setDomainIdentifiers(newName, newUUID)
            xmlFile.setImagePaths(newOSDisk, newDataDisk)            
            xmlFile.setVirtualNetworkConfiguration(self.__virtualNetworkName, newMAC)
            xmlFile.setVNCServerConfiguration(self.__vncServerIP, newPort, newPassword, self.__useQEMUWebsockets)
            
            string = xmlFile.generateConfigurationString()        
            # Start the domain
            self.__libvirtConnection.startDomain(string)
            
            if (not self.__useQEMUWebsockets) :
                websockifyPID = self.__childProcessManager.runCommandInBackground([self.__websockifyPath,
                                            self.__vncServerIP + ":" + str(newPort + 1),
                                            self.__vncServerIP + ":" + str(newPort)])
            
            # Everything went OK => register the resources on the database
        
            self.__commandsDBConnector.registerVMResources(newName, imageID, newPort, newPassword, userID, websockifyPID, newOSDisk,  newDataDisk, newMAC, newUUID)
            self.__commandsDBConnector.addVMBootCommand(newName, commandID)
       
        except Exception as e:
            print e
            # Free the allocated resources, generate an error packet and send it.
            if (imageFound and not isBootable) :                
                self.__commandsDBConnector.deleteImage(imageID)
            if (newUUID != None) :
                self.__commandsDBConnector.freeMACAndUUID(newUUID, newMAC)
            if (diskImagesCreated) :
                ChildProcessManager.runCommandInForeground("rm " + newOSDisk, None)
                ChildProcessManager.runCommandInForeground("rm " + newDataDisk, None)
                directoryName = path.dirname(newOSDisk)
                if (listdir(directoryName) == []) :
                    ChildProcessManager.runCommandInForeground("rm -rf " + directoryName)
            if (websockifyPID != -1) :
                ChildProcessManager.runCommandInForeground("kill " + websockifyPID, None)
            p = self.__packetManager.createInternalErrorPacket(commandID)
            self.__networkManager.sendPacket('', self.__listenningPort, p)
            

        
    def destroyDomain(self, domainUID):
        """
        Destroys a domain
        Args:
            domainUID: the domain to destroy's unique identifier
        Returns:
            Nothing
        """
        domainName = self.__commandsDBConnector.getDomainNameFromVMBootCommand(domainUID)
        if (domainName == None) :
            # Ignoramos la petición: el dominio ya está apagado
            return
        bootableFlag = self.__commandsDBConnector.getBootableFlag(self.__commandsDBConnector.getDomainImageID(domainName))
        if (bootableFlag) :
            self.__libvirtConnection.destroyDomain(domainName)
        else:
            self.__libvirtConnection.shutdownDomain(domainName)
            
    def rebootDomain(self, domainUID):
        """
        Reboots a domain
        Args:
            domainUID: the domain to reboot's unique identifier
        Returns:
            Nothing
        """
        domainName = self.__commandsDBConnector.getDomainNameFromVMBootCommand(domainUID)
        if (domainName == None) :
            # Ignoramos la petición: el dominio ya está apagado
            return
        self.__libvirtConnection.rebootDomain(domainName)
        
    def _onDomainStart(self, domain):
        """
        This method will be called to handle a domain creation event.
        Args:
            domain: an object containing the domain's data
        Returns:
            Nothing
        """
        self.__sendConnectionData(domain)
        
    def __sendConnectionData(self, domainInfo):
        """
        Sends a domain's connection data
        Args:
            domainInfo: an object containing the domain's data
        Returns:
            Nothing
        """
        ip = domainInfo["VNCip"]
        port = domainInfo["VNCport"]
        password = domainInfo["VNCpassword"]
        domainName = domainInfo["name"]
        commandID = None
        while (commandID == None) :
            commandID = self.__commandsDBConnector.getVMBootCommand(domainName)
            if (commandID == None) :
                sleep(0.1)
        packet = self.__packetManager.createVMConnectionParametersPacket(ip, port + 1, password, commandID)
        self.__networkManager.sendPacket('', self.__listenningPort, packet)
        
    def _onDomainStop(self, domainName):
        """
        This method will be called to handle a domain stop event.
        Args:
            domainName: the stopped domain's name
        Returns:
            Nothing
        """
        if (self.__commandsDBConnector.getVMBootCommand(domainName) != None) :            
            self.__freeDomainResources(domainName)
            
    def __freeDomainResources(self, domainName, deleteDiskImages=True):
        """
        Free the resources assigned to a domain
        Args:
            domainName: a domain name
            deleteDiskImages: indicates wether the disk images must be deleted or not
        Returns:
            Nothing
        """
        dataImagePath = self.__commandsDBConnector.getDomainDataImagePath(domainName)
        osImagePath = self.__commandsDBConnector.getDomainOSImagePath(domainName)
        imageID = self.__commandsDBConnector.getDomainImageID(domainName)
        websockify_pid = self.__commandsDBConnector.getWebsockifyDaemonPID(domainName)
        isBootable = self.__commandsDBConnector.getBootableFlag(imageID)        
        commandID = self.__commandsDBConnector.getVMBootCommand(domainName)
        
        self.__commandsDBConnector.unregisterDomainResources(domainName)     
        
        if (websockify_pid != -1) :
            ChildProcessManager.runCommandInForeground("kill -s TERM " + str(websockify_pid), None)   
        
        if isBootable :
            # If the domain was manually stopped, libvirt has already got rid of the disk images.
            # ==> we don't have to complain if we can't find them
            ChildProcessManager.runCommandInForeground("rm " + dataImagePath, None)
            ChildProcessManager.runCommandInForeground("rm " + osImagePath, None)
            dataDirectory = path.dirname(dataImagePath)
            osDirectory = path.dirname(osImagePath)
            if (path.exists(dataDirectory) and listdir(dataDirectory) == []) :
                ChildProcessManager.runCommandInForeground("rm -rf " + dataDirectory, None)
            if (osDirectory != dataDirectory and path.exists(osDirectory) and listdir(osDirectory) == []) :
                ChildProcessManager.runCommandInForeground("rm -rf " + osDirectory, None)            
                    
        else :
            data = dict()            
            connectionData = self.__commandsDBConnector.getImageRepositoryConnectionData(commandID)
            data["Transfer_Type"] = TRANSFER_T.STORE_IMAGE
            data["DataImagePath"] = dataImagePath
            data["OSImagePath"] = osImagePath
            data["DefinitionFilePath"] = self.__commandsDBConnector.getDefinitionFilePath(imageID)
            data["RepositoryIP"] = connectionData["RepositoryIP"]
            data["RepositoryPort"] = connectionData["RepositoryPort"]
            data["CommandID"] = commandID            
            data["TargetImageID"] = imageID
            self.__commandsDBConnector.addToCompressionQueue(data)
            self.__commandsDBConnector.removeImageRepositoryConnectionData(commandID)
            self.__commandsDBConnector.deleteImage(imageID)              
    
    def __waitForDomainsToTerminate(self, timeout):
        """
        Waits until all the active domains have finished, stopping at timeout seconds.
        Args:
            timeout: a timeout in seconds
        Returns:
            Nothing
        """
        wait_time = 0
        while (self.__libvirtConnection.getNumberOfDomains() != 0 and wait_time < timeout) :
            sleep(0.5)
            wait_time += 0.5
            
    def __generateVNCPassword(self):
        """
        Generates a VNC random password
        Args:
            None
        Returns:
            a string containing the generated password
        """
        return ChildProcessManager.runCommandInForeground("openssl rand -base64 " + str(self.__vncPasswordLength), VMServerException)
    
    def getLibvirtStatusData(self):
        """
        Returns libvirt's status data.
        Args:
            None
        Returns:
            A dictionary containing libvirt's status data.
        """
        return self.__libvirtConnection.getStatusData()
    def __processElement(self, data):
        """
        Processes a compression/decompression requiest
        Args:
            data: a dictionary containing the request's data
        Returns:
            Nothing
        """
        try:
            imageDirectory = None
            definitionFileDirectory = None
            zipFilePath = None
            if (data["Transfer_Type"] != TRANSFER_T.STORE_IMAGE):

                self.__dbConnector.deleteImage(data["SourceImageID"])

                # Extract the .zip file
                imageDirectory = path.join(self.__diskImagesDirectory,
                                           str(data["TargetImageID"]))
                # Change the extracted files' permissions, and look for the definition file.
                definitionFileDirectory = path.join(
                    self.__definitionFileDirectory, str(data["TargetImageID"]))

                try:
                    ChildProcessManager.runCommandInForeground(
                        "rm -rf " + imageDirectory, Exception)
                    ChildProcessManager.runCommandInForeground(
                        "rm -rf " + definitionFileDirectory, Exception)
                except Exception:
                    pass
                zipFilePath = path.join(self.__transferDirectory,
                                        str(data["SourceImageID"]) + ".zip")
                self.__compressor.extractFile(zipFilePath, imageDirectory)

                # Move the three extracted files
                if not path.exists(definitionFileDirectory):
                    makedirs(definitionFileDirectory)

                definitionFileFound = False
                containsDataFile = False
                containsOSFile = False
                for fileName in listdir(imageDirectory):
                    ChildProcessManager.runCommandInForegroundAsRoot(
                        "chmod 666 " + path.join(imageDirectory, fileName),
                        VMServerException)
                    if fileName.endswith(".xml"):
                        definitionFile = fileName
                        shutil.move(path.join(imageDirectory, fileName),
                                    definitionFileDirectory)
                        definitionFileFound = True
                    containsDataFile = fileName == "Data.qcow2" or containsDataFile
                    containsOSFile = fileName == "OS.qcow2" or containsOSFile
                if (not definitionFileFound):
                    raise Exception("The definition file was not found")
                if (not containsDataFile):
                    raise Exception("The data disk image was not found")
                if (not containsOSFile):
                    raise Exception("The OS disk image was not found")

                # Register the new image
                self.__dbConnector.createImage(
                    data["TargetImageID"],
                    path.join(str(data["TargetImageID"]), "OS.qcow2"),
                    path.join(str(data["TargetImageID"]), "Data.qcow2"),
                    path.join(str(data["TargetImageID"]), definitionFile),
                    data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE)

                if (data["Transfer_Type"] != TRANSFER_T.DEPLOY_IMAGE):
                    # Edition request => boot the virtual machine, store the image repository connection data
                    self.__dbConnector.addValueToConnectionDataDictionary(
                        data["CommandID"], {
                            "RepositoryIP": data["RepositoryIP"],
                            "RepositoryPort": data["RepositoryPort"]
                        })

                    self.__domainHandler.createDomain(data["TargetImageID"],
                                                      data["UserID"],
                                                      data["CommandID"])
                else:
                    p = self.__packetHandler.createConfirmationPacket(
                        VM_SERVER_PACKET_T.IMAGE_DEPLOYED,
                        data["TargetImageID"], data["CommandID"])
                    self.__networkManager.sendPacket(
                        '', self.__serverListenningPort, p)

                # Delete the .zip file
                ChildProcessManager.runCommandInForeground(
                    "rm " + zipFilePath, VMServerException)
            else:
                # Build the .zip file

                zipFilePath = path.join(self.__transferDirectory,
                                        str(data["TargetImageID"]) + ".zip")

                self.__compressor.createCompressedFile(zipFilePath, [
                    data["OSImagePath"], data["DataImagePath"],
                    path.join(self.__definitionFileDirectory,
                              data["DefinitionFilePath"])
                ])

                # Delete the source files
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + path.dirname(
                        path.join(self.__definitionFileDirectory,
                                  data["DefinitionFilePath"])), Exception)
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + path.dirname(data["OSImagePath"]), Exception)

                # Queue a transfer request

                data.pop("DataImagePath")
                data.pop("OSImagePath")
                data.pop("DefinitionFilePath")

                data["SourceFilePath"] = path.basename(zipFilePath)

                self.__dbConnector.addToTransferQueue(data)
        except Exception:
            if (data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE):
                packet_type = VM_SERVER_PACKET_T.IMAGE_DEPLOYMENT_ERROR
            else:
                packet_type = VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR

            p = self.__packetHandler.createErrorPacket(
                packet_type, ERROR_DESC_T.VMSRVR_COMPRESSION_ERROR,
                data["CommandID"])
            self.__networkManager.sendPacket('', self.__serverListenningPort,
                                             p)
            if (data["Transfer_Type"] != TRANSFER_T.DEPLOY_IMAGE):
                # Build a special transfer to unlock the disk image
                transfer = dict()
                transfer["Transfer_Type"] = TRANSFER_T.CANCEL_EDITION
                transfer["RepositoryIP"] = data["RepositoryIP"]
                transfer["RepositoryPort"] = data["RepositoryPort"]
                transfer["CommandID"] = data["CommandID"]
                transfer["ImageID"] = data["TargetImageID"]
                self.__dbConnector.addToTransferQueue(transfer)

            # Delete the disk images, the definition file and the .zip file.
            if (imageDirectory != None):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + imageDirectory, None)
            if (definitionFileDirectory != None):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + definitionFileDirectory, None)
            if (zipFilePath != None):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + zipFilePath, None)
 def __processElement(self, data):
     """
     Processes a compression/decompression requiest
     Args:
         data: a dictionary containing the request's data
     Returns:
         Nothing
     """        
     try :
         imageDirectory = None
         definitionFileDirectory = None
         zipFilePath = None
         if(data["Transfer_Type"] != TRANSFER_T.STORE_IMAGE):                   
             
             self.__dbConnector.deleteImage(data["SourceImageID"])
                 
             # Extract the .zip file
             imageDirectory = path.join(self.__diskImagesDirectory, str(data["TargetImageID"]))
             # Change the extracted files' permissions, and look for the definition file.
             definitionFileDirectory = path.join(self.__definitionFileDirectory, str(data["TargetImageID"]))            
             
             try :
                 ChildProcessManager.runCommandInForeground("rm -rf " + imageDirectory, Exception)
                 ChildProcessManager.runCommandInForeground("rm -rf " + definitionFileDirectory, Exception)
             except Exception:
                 pass
             zipFilePath = path.join(self.__transferDirectory, str(data["SourceImageID"]) + ".zip")
             self.__compressor.extractFile(zipFilePath, imageDirectory)                     
             
             # Move the three extracted files
             if not path.exists(definitionFileDirectory):
                 makedirs(definitionFileDirectory)
         
             definitionFileFound = False
             containsDataFile = False
             containsOSFile = False
             for fileName in listdir(imageDirectory):
                 ChildProcessManager.runCommandInForegroundAsRoot("chmod 666 " + path.join(imageDirectory, fileName), VMServerException)
                 if fileName.endswith(".xml"):
                     definitionFile = fileName
                     shutil.move(path.join(imageDirectory, fileName), definitionFileDirectory)
                     definitionFileFound = True
                 containsDataFile = fileName == "Data.qcow2" or containsDataFile
                 containsOSFile = fileName == "OS.qcow2" or containsOSFile 
             if(not definitionFileFound):
                 raise Exception("The definition file was not found")
             if (not containsDataFile) :
                 raise Exception("The data disk image was not found")
             if (not containsOSFile) :
                 raise Exception("The OS disk image was not found")
 
             # Register the new image
             self.__dbConnector.createImage(data["TargetImageID"], path.join(str(data["TargetImageID"]), "OS.qcow2"),
                                            path.join(str(data["TargetImageID"]), "Data.qcow2"),
                                            path.join(str(data["TargetImageID"]), definitionFile), data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE)
             
             if (data["Transfer_Type"] != TRANSFER_T.DEPLOY_IMAGE):                
                 # Edition request => boot the virtual machine, store the image repository connection data
                 self.__dbConnector.addValueToConnectionDataDictionary(data["CommandID"], {"RepositoryIP": data["RepositoryIP"], "RepositoryPort" : data["RepositoryPort"]})                
                 
                 self.__domainHandler.createDomain(data["TargetImageID"], data["UserID"], data["CommandID"])        
             else :
                 p = self.__packetHandler.createConfirmationPacket(VM_SERVER_PACKET_T.IMAGE_DEPLOYED, data["TargetImageID"], data["CommandID"])
                 self.__networkManager.sendPacket('', self.__serverListenningPort, p)
                 
             # Delete the .zip file
             ChildProcessManager.runCommandInForeground("rm " + zipFilePath, VMServerException)    
         else:        
             # Build the .zip file
             
             zipFilePath = path.join(self.__transferDirectory, str(data["TargetImageID"]) + ".zip")                
             
             self.__compressor.createCompressedFile(zipFilePath, [data["OSImagePath"], 
                 data["DataImagePath"], path.join(self.__definitionFileDirectory, data["DefinitionFilePath"])])
             
             
             # Delete the source files
             ChildProcessManager.runCommandInForeground("rm -rf " + path.dirname(path.join(self.__definitionFileDirectory, data["DefinitionFilePath"])), Exception)
             ChildProcessManager.runCommandInForeground("rm -rf " + path.dirname(data["OSImagePath"]), Exception)
             
             # Queue a transfer request
             
             data.pop("DataImagePath")
             data.pop("OSImagePath")
             data.pop("DefinitionFilePath")
            
             data["SourceFilePath"] = path.basename(zipFilePath)        
             
             self.__dbConnector.addToTransferQueue(data)
     except Exception:
         if (data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE):
             packet_type = VM_SERVER_PACKET_T.IMAGE_DEPLOYMENT_ERROR
         else :
             packet_type = VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR
             
         p = self.__packetHandler.createErrorPacket(packet_type, ERROR_DESC_T.VMSRVR_COMPRESSION_ERROR, data["CommandID"])
         self.__networkManager.sendPacket('', self.__serverListenningPort, p)
         if (data["Transfer_Type"] != TRANSFER_T.DEPLOY_IMAGE):
             # Build a special transfer to unlock the disk image
             transfer = dict()
             transfer["Transfer_Type"] = TRANSFER_T.CANCEL_EDITION
             transfer["RepositoryIP"] = data["RepositoryIP"]
             transfer["RepositoryPort"] = data["RepositoryPort"]
             transfer["CommandID"] = data["CommandID"]
             transfer["ImageID"] = data["TargetImageID"]
             self.__dbConnector.addToTransferQueue(transfer)
         
         # Delete the disk images, the definition file and the .zip file.
         if (imageDirectory != None):
             ChildProcessManager.runCommandInForeground("rm -rf " + imageDirectory, None)
         if (definitionFileDirectory != None):
             ChildProcessManager.runCommandInForeground("rm -rf " + definitionFileDirectory, None)
         if (zipFilePath != None):
             ChildProcessManager.runCommandInForeground("rm -rf " + zipFilePath, None)
    def __processElement(self, data):
        """
        Performs a transfer request
        Args:
            data: a dictionary containing the request's data
        Returns:
            Nothing
        """
        attempts = 0
        while attempts < self.__maxTransferAttempts:
            try:
                # Prepare for the new transfer

                if (data["Transfer_Type"] == TRANSFER_T.CREATE_IMAGE
                        or data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE):
                    p = self.__repositoryPacketHandler.createRetrieveRequestPacket(
                        data["SourceImageID"],
                        data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE)
                    sourceFilePath = None
                elif (data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE):
                    p = self.__repositoryPacketHandler.createRetrieveRequestPacket(
                        data["SourceImageID"], False)
                    sourceFilePath = None
                elif (data["Transfer_Type"] == TRANSFER_T.STORE_IMAGE):
                    p = self.__repositoryPacketHandler.createStoreRequestPacket(
                        int(data["TargetImageID"]))
                    sourceFilePath = data["SourceFilePath"]
                else:
                    p = self.__repositoryPacketHandler.createCancelEditionPacket(
                        data["ImageID"])

                # Establish the connection with the image repository
                callback = FileTransferCallback(self.__repositoryPacketHandler,
                                                self.__transferDirectory,
                                                data["RepositoryIP"],
                                                self.__ftpTimeout,
                                                sourceFilePath)
                callback.prepareForNewTransfer()
                self.__networkManager.connectTo(data["RepositoryIP"],
                                                data["RepositoryPort"],
                                                self.__ftpTimeout, callback,
                                                self.__useSSL)
                while not self.__networkManager.isConnectionReady(
                        data["RepositoryIP"], data["RepositoryPort"]):
                    sleep(0.1)

                # Send the transfer request packet

                self.__networkManager.sendPacket(data["RepositoryIP"],
                                                 data["RepositoryPort"], p)

                if (data["Transfer_Type"] != TRANSFER_T.CANCEL_EDITION):
                    # Wait until the transfer finishes
                    while not callback.isTransferCompleted():
                        sleep(0.1)
                    timeout = False
                else:
                    elapsed_time = 0
                    while not callback.isTransferCompleted(
                    ) and elapsed_time < self.__max_cancel_timeout:
                        sleep(0.1)
                        elapsed_time += 0.1
                    timeout = elapsed_time >= self.__max_cancel_timeout

                if (callback.getErrorDescription() != None or timeout):
                    if callback.getImageNotFound():
                        attempts = self.__maxTransferAttempts
                    else:
                        attempts += 1
                    if (attempts == self.__maxTransferAttempts):
                        if (data["Transfer_Type"] !=
                                TRANSFER_T.CANCEL_EDITION):
                            # Error => abort the transfer and warn the user
                            p = self.__vmServerPacketHandler.createErrorPacket(
                                VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR,
                                callback.getErrorDescription(),
                                data["CommandID"])
                        else:
                            p = self.__vmServerPacketHandler.createInternalErrorPacket(
                                data["CommandID"])

                        self.__networkManager.sendPacket(
                            '', self.__serverListeningPort, p)
                    else:
                        sleep(4**attempts)
                else:
                    # The transfer has finished => do something with the .zip file

                    if (data["Transfer_Type"] == TRANSFER_T.CREATE_IMAGE):
                        # Image creation => ask for a new image ID and add a request to the compression queue
                        callback.prepareForNewTransfer()
                        self.__networkManager.sendPacket(
                            data["RepositoryIP"], data["RepositoryPort"],
                            self.__repositoryPacketHandler.
                            createAddImagePacket())
                        while not callback.isTransferCompleted():
                            sleep(0.1)
                        data["TargetImageID"] = callback.getDomainImageID()
                        self.__dbConnector.addToCompressionQueue(data)
                    elif (data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE
                          or data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE):
                        # Add a request to the compression queue
                        data["TargetImageID"] = data["SourceImageID"]
                        self.__dbConnector.addToCompressionQueue(data)
                    elif (data["Transfer_Type"] == TRANSFER_T.STORE_IMAGE):
                        # The image was successfully uploaded => delete the .zip file and send the confirmation packet
                        ChildProcessManager.runCommandInForeground(
                            "rm " + path.join(self.__transferDirectory,
                                              data["SourceFilePath"]),
                            Exception)
                        p = self.__vmServerPacketHandler.createImageEditedPacket(
                            data["TargetImageID"], data["CommandID"])
                        self.__networkManager.sendPacket(
                            '', self.__serverListeningPort, p)

                # Disconnect from the image repository
                self.__networkManager.closeConnection(data["RepositoryIP"],
                                                      data["RepositoryPort"])
                attempts = self.__maxTransferAttempts

            except Exception:
                # Something went wrong => increment the attempts counter and, if necessary, abort the transfer and warn the user
                attempts += 1
                if (attempts == self.__maxTransferAttempts):
                    errorCode = ERROR_DESC_T.VMSRVR_IR_CONNECTION_ERROR
                    try:
                        self.__networkManager.closeConnection(
                            data["RepositoryIP"], data["RepositoryPort"])
                    except Exception:
                        pass
                    p = self.__vmServerPacketHandler.createErrorPacket(
                        VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR, errorCode,
                        data["CommandID"])
                    self.__networkManager.sendPacket(
                        '', self.__serverListeningPort, p)
                else:
                    sleep(4**attempts)
    def __processElement(self, data):
        """
        Performs a transfer request
        Args:
            data: a dictionary containing the request's data
        Returns:
            Nothing
        """
        attempts = 0
        while attempts < self.__maxTransferAttempts:
            try:
                # Prepare for the new transfer

                if data["Transfer_Type"] == TRANSFER_T.CREATE_IMAGE or data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE:
                    p = self.__repositoryPacketHandler.createRetrieveRequestPacket(
                        data["SourceImageID"], data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE
                    )
                    sourceFilePath = None
                elif data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE:
                    p = self.__repositoryPacketHandler.createRetrieveRequestPacket(data["SourceImageID"], False)
                    sourceFilePath = None
                elif data["Transfer_Type"] == TRANSFER_T.STORE_IMAGE:
                    p = self.__repositoryPacketHandler.createStoreRequestPacket(int(data["TargetImageID"]))
                    sourceFilePath = data["SourceFilePath"]
                else:
                    p = self.__repositoryPacketHandler.createCancelEditionPacket(data["ImageID"])

                # Establish the connection with the image repository
                callback = FileTransferCallback(
                    self.__repositoryPacketHandler,
                    self.__transferDirectory,
                    data["RepositoryIP"],
                    self.__ftpTimeout,
                    sourceFilePath,
                )
                callback.prepareForNewTransfer()
                self.__networkManager.connectTo(
                    data["RepositoryIP"], data["RepositoryPort"], self.__ftpTimeout, callback, self.__useSSL
                )
                while not self.__networkManager.isConnectionReady(data["RepositoryIP"], data["RepositoryPort"]):
                    sleep(0.1)

                # Send the transfer request packet

                self.__networkManager.sendPacket(data["RepositoryIP"], data["RepositoryPort"], p)

                if data["Transfer_Type"] != TRANSFER_T.CANCEL_EDITION:
                    # Wait until the transfer finishes
                    while not callback.isTransferCompleted():
                        sleep(0.1)
                    timeout = False
                else:
                    elapsed_time = 0
                    while not callback.isTransferCompleted() and elapsed_time < self.__max_cancel_timeout:
                        sleep(0.1)
                        elapsed_time += 0.1
                    timeout = elapsed_time >= self.__max_cancel_timeout

                if callback.getErrorDescription() != None or timeout:
                    if callback.getImageNotFound():
                        attempts = self.__maxTransferAttempts
                    else:
                        attempts += 1
                    if attempts == self.__maxTransferAttempts:
                        if data["Transfer_Type"] != TRANSFER_T.CANCEL_EDITION:
                            # Error => abort the transfer and warn the user
                            p = self.__vmServerPacketHandler.createErrorPacket(
                                VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR,
                                callback.getErrorDescription(),
                                data["CommandID"],
                            )
                        else:
                            p = self.__vmServerPacketHandler.createInternalErrorPacket(data["CommandID"])

                        self.__networkManager.sendPacket("", self.__serverListeningPort, p)
                    else:
                        sleep(4 ** attempts)
                else:
                    # The transfer has finished => do something with the .zip file

                    if data["Transfer_Type"] == TRANSFER_T.CREATE_IMAGE:
                        # Image creation => ask for a new image ID and add a request to the compression queue
                        callback.prepareForNewTransfer()
                        self.__networkManager.sendPacket(
                            data["RepositoryIP"],
                            data["RepositoryPort"],
                            self.__repositoryPacketHandler.createAddImagePacket(),
                        )
                        while not callback.isTransferCompleted():
                            sleep(0.1)
                        data["TargetImageID"] = callback.getDomainImageID()
                        self.__dbConnector.addToCompressionQueue(data)
                    elif (
                        data["Transfer_Type"] == TRANSFER_T.EDIT_IMAGE
                        or data["Transfer_Type"] == TRANSFER_T.DEPLOY_IMAGE
                    ):
                        # Add a request to the compression queue
                        data["TargetImageID"] = data["SourceImageID"]
                        self.__dbConnector.addToCompressionQueue(data)
                    elif data["Transfer_Type"] == TRANSFER_T.STORE_IMAGE:
                        # The image was successfully uploaded => delete the .zip file and send the confirmation packet
                        ChildProcessManager.runCommandInForeground(
                            "rm " + path.join(self.__transferDirectory, data["SourceFilePath"]), Exception
                        )
                        p = self.__vmServerPacketHandler.createImageEditedPacket(
                            data["TargetImageID"], data["CommandID"]
                        )
                        self.__networkManager.sendPacket("", self.__serverListeningPort, p)

                # Disconnect from the image repository
                self.__networkManager.closeConnection(data["RepositoryIP"], data["RepositoryPort"])
                attempts = self.__maxTransferAttempts

            except Exception:
                # Something went wrong => increment the attempts counter and, if necessary, abort the transfer and warn the user
                attempts += 1
                if attempts == self.__maxTransferAttempts:
                    errorCode = ERROR_DESC_T.VMSRVR_IR_CONNECTION_ERROR
                    try:
                        self.__networkManager.closeConnection(data["RepositoryIP"], data["RepositoryPort"])
                    except Exception:
                        pass
                    p = self.__vmServerPacketHandler.createErrorPacket(
                        VM_SERVER_PACKET_T.IMAGE_EDITION_ERROR, errorCode, data["CommandID"]
                    )
                    self.__networkManager.sendPacket("", self.__serverListeningPort, p)
                else:
                    sleep(4 ** attempts)
Exemple #33
0
if __name__ == "__main__":
    if (len(sys.argv) != 2):
        print "A configuration file path is needed"
        sys.exit()
    try:
        parser = VMServerConfigurationFileParser()
        parser.parseConfigurationFile(sys.argv[1])
    except Exception as e:
        print e.message
        sys.exit()

    # Read root's password. It's vital to change the downloaded files' permissions.
    password_ok = False
    while (not password_ok):
        try:
            ChildProcessManager.runCommandInForegroundAsRoot("ls", Exception)
            password_ok = True
        except Exception:
            print "Wrong password. Please, key it in again."
            RootPasswordHandler().clear()

    # Configure the database
    rootPassword = parser.getConfigurationParameter("mysqlRootsPassword")
    configurator = DBConfigurator(rootPassword)
    configurator.runSQLScript("VMServerDB", "./database/VMServerDB.sql",
                              "root", rootPassword)
    configurator.addUser(parser.getConfigurationParameter("databaseUserName"),
                         parser.getConfigurationParameter("databasePassword"),
                         "VMServerDB", True)

    # Create the directories (if necessary)
 def createDomain(self, imageID, userID, commandID):
     """
     Creates a domain
     Args:
         imageID: the image to use's ID
         userID: the domain owner's ID
         commandID: the domain boot command's ID
     Returns:
         Nothing
     """    
     
     try : 
         diskImagesCreated = False
         websockifyPID = -1       
         imageFound = False
         newUUID = None
         newMAC = None
         
         definitionFile = self.__definitionFileDirectory + self.__commandsDBConnector.getDefinitionFilePath(imageID)
         originalName = "{0}_".format(imageID)
         dataImagePath = self.__commandsDBConnector.getDataImagePath(imageID)
         osImagePath = self.__commandsDBConnector.getOSImagePath(imageID)
         isBootable = self.__commandsDBConnector.getBootableFlag(imageID)        
         imageFound = True
         
         # Generate the configuration parameters
         newUUID, newMAC = self.__commandsDBConnector.extractFreeMACAndUUID()
         newPort = self.__commandsDBConnector.extractFreeVNCPort()
         newName = originalName + str(newPort)        
         newPassword = self.__generateVNCPassword()
         sourceOSDisk = self.__sourceImagePath + osImagePath               
         
         if(isBootable):                           
             # Create the disk images in copy-on-write mode
             trimmedDataImagePath = dataImagePath
             try:
                 trimmedDataImagePath = dataImagePath[0:dataImagePath.index(".qcow2")]
             except:
                 pass
             trimmedOSImagePath = osImagePath
             try:
                 trimmedOSImagePath = osImagePath[0:osImagePath.index(".qcow2")]
             except:
                 pass   
             
             newDataDisk = self.__executionImagePath + trimmedDataImagePath + str(newPort) + ".qcow2"
             newOSDisk = self.__executionImagePath + trimmedOSImagePath + str(newPort) + ".qcow2"                
            
             # If one of the files already exist, we'll get rid of it.
             if (path.exists(newDataDisk)):
                 print("Warning: the file " + newDataDisk + " already exists")
                 ChildProcessManager.runCommandInForeground("rm " + newDataDisk, VMServerException)
                 
             if (path.exists(newOSDisk)):
                 print("Warning: the file " + newOSDisk + " already exists")
                 ChildProcessManager.runCommandInForeground("rm " + newOSDisk, VMServerException)
                 
             try :
                 ChildProcessManager.runCommandInForeground("cd " + self.__sourceImagePath + ";" + "cp --parents "+ dataImagePath + " " + self.__executionImagePath, VMServerException)
                 ChildProcessManager.runCommandInForeground("mv " + self.__executionImagePath + dataImagePath +" " + newDataDisk, VMServerException)
                 ChildProcessManager.runCommandInForeground("qemu-img create -b " + sourceOSDisk + " -f qcow2 " + newOSDisk, VMServerException)
                 diskImagesCreated = True
             except Exception as e:
                 diskImagesCreated = False
                 raise e
         
         else :
             # The images will not be created in copy-on-write mode. In fact, their stored copies will be
             # modified (we're editing them)
             newDataDisk = path.join(self.__sourceImagePath, dataImagePath)
             newOSDisk = path.join(self.__sourceImagePath, osImagePath)            
         
         # Build dthe definition file
         xmlFile = DefinitionFileEditor(definitionFile)
         xmlFile.setDomainIdentifiers(newName, newUUID)
         xmlFile.setImagePaths(newOSDisk, newDataDisk)            
         xmlFile.setVirtualNetworkConfiguration(self.__virtualNetworkName, newMAC)
         xmlFile.setVNCServerConfiguration(self.__vncServerIP, newPort, newPassword, self.__useQEMUWebsockets)
         
         string = xmlFile.generateConfigurationString()        
         # Start the domain
         self.__libvirtConnection.startDomain(string)
         
         if (not self.__useQEMUWebsockets) :
             websockifyPID = self.__childProcessManager.runCommandInBackground([self.__websockifyPath,
                                         self.__vncServerIP + ":" + str(newPort + 1),
                                         self.__vncServerIP + ":" + str(newPort)])
         
         # Everything went OK => register the resources on the database
     
         self.__commandsDBConnector.registerVMResources(newName, imageID, newPort, newPassword, userID, websockifyPID, newOSDisk,  newDataDisk, newMAC, newUUID)
         self.__commandsDBConnector.addVMBootCommand(newName, commandID)
    
     except Exception as e:
         print e
         # Free the allocated resources, generate an error packet and send it.
         if (imageFound and not isBootable) :                
             self.__commandsDBConnector.deleteImage(imageID)
         if (newUUID != None) :
             self.__commandsDBConnector.freeMACAndUUID(newUUID, newMAC)
         if (diskImagesCreated) :
             ChildProcessManager.runCommandInForeground("rm " + newOSDisk, None)
             ChildProcessManager.runCommandInForeground("rm " + newDataDisk, None)
             directoryName = path.dirname(newOSDisk)
             if (listdir(directoryName) == []) :
                 ChildProcessManager.runCommandInForeground("rm -rf " + directoryName)
         if (websockifyPID != -1) :
             ChildProcessManager.runCommandInForeground("kill " + websockifyPID, None)
         p = self.__packetManager.createInternalErrorPacket(commandID)
         self.__networkManager.sendPacket('', self.__listenningPort, p)
 def initTransfers(self):
     """
     Initializes the upload and download transfers
     Args:
         None
     Returns:
         Nothing
     """
     store = False
     while not (self.__finish or self.__commandsCallback.haltReceived()):
         if (self.__slotCounter.read() == self.__maxConnections) :
             # No free slots => sleep
             sleep(0.1)
         else :
             # There are slots => enable uploads and downloads in parallel
             self.__slotCounter.decrement()
             
             if (self.__retrieveQueue.isEmpty() and self.__storeQueue.isEmpty()) :
                 sleep(0.1)
                 continue                
             if (not self.__retrieveQueue.isEmpty() and self.__storeQueue.isEmpty()) :
                 queue = self.__retrieveQueue
                 store = False
             elif (self.__retrieveQueue.isEmpty() and not self.__storeQueue.isEmpty()) :
                 queue = self.__storeQueue
                 store = True
             else :
                 if (store) :
                     queue = self.__retrieveQueue
                     store = False
                 else :
                     queue = self.__storeQueue
                     store = True
             
                                
             (imageID, clientIP, clientPort) = queue.pop(0)
                 
             imageData = self.__dbConnector.getImageData(imageID)
             if (imageData == None) :
                 if (store) :
                     packet_type = PACKET_T.STOR_ERROR
                 else :
                     packet_type = PACKET_T.RETR_ERROR
                 p = self.__repositoryPacketHandler.createErrorPacket(packet_type, ERROR_DESC_T.IR_IMAGE_DELETED)
                 self.__networkManager.sendPacket('', self.__commandsListenningPort, p, clientIP, clientPort)
             else :
                 compressedFilePath = imageData["compressedFilePath"]    
                 
                 if (not "undefined" in compressedFilePath) :                                
                     serverDirectory = path.relpath(path.dirname(compressedFilePath), self.__diskImagesDirectory)
                     compressedFileName = path.basename(compressedFilePath)
                 else :
                     serverDirectory = str(imageID)
                     compressedFileName = ""
                     serverDirectoryPath = path.join(self.__diskImagesDirectory, serverDirectory)
                     if (path.exists(serverDirectoryPath)) :
                         # The directory exists, and can store shit => clean it up!
                         ChildProcessManager.runCommandInForeground("rm -rf " + serverDirectoryPath, Exception)
                     mkdir(serverDirectoryPath)                        
                 
                 if (store) :
                     packet_type = PACKET_T.STOR_START
                 else :
                     packet_type = PACKET_T.RETR_START
                                 
                 p = self.__repositoryPacketHandler.createTransferEnabledPacket(packet_type, imageID, self.__FTPListenningPort, 
                                 self.__ftpUsername, self.__ftpPassword, serverDirectory, compressedFileName)
                     
                 self.__networkManager.sendPacket('', self.__commandsListenningPort, p, clientIP, clientPort)
class DomainHandler(DomainStartCallback, DomainStopCallback):
    """
    These objects interact with libvirt to handle domains.
    """
    def __init__(self, dbConnector, vncServerIP, networkManager, packetManager,
                 listenningPort, useQEMUWebsockets, websockifyPath,
                 definitionFileDirectory, sourceImageDirectory,
                 executionImageDirectory, vncPasswordLength):
        """
        Initializes the domain handler's state
        Args:
            dbConnector: a database connector
            vncServerIP: the VNC server's IPv4 address
            networkManager: a network manager
            packetManager: a virtual machine server packet handler
            listenningPort: the control connection's port
            definitionFileDirectory: the directory where the definition files are
            sourceImageDirectory: the directory where the source disk images are
            executionImageDirectory: the directory where the active virtual machines' disk images are
            vncPasswordLength: the generated VNC password's length
        """
        self.__commandsDBConnector = dbConnector
        self.__vncServerIP = vncServerIP
        self.__childProcessManager = ChildProcessManager()
        self.__networkManager = networkManager
        self.__packetManager = packetManager
        self.__listenningPort = listenningPort
        self.__useQEMUWebsockets = useQEMUWebsockets
        self.__websockifyPath = websockifyPath
        self.__definitionFileDirectory = definitionFileDirectory
        self.__sourceImagePath = sourceImageDirectory
        self.__executionImagePath = executionImageDirectory
        self.__vncPasswordLength = vncPasswordLength
        self.__libvirtConnection = None
        self.__virtualNetworkManager = None
        self.__virtualNetworkName = None

    def connectToLibvirt(self, networkInterface, virtualNetworkName, gatewayIP,
                         netmask, dhcpStartIP, dhcpEndIP,
                         createVirtualNetworkAsRoot):
        """
        Creates the libvirt connection and the virtual network
        Args:
            createVirtualNetworkAsRoot: indicates wether the virtual network must be
                created as the super-user or not. This is required in some systems.
        Returns:
            Nothing
        """
        self.__libvirtConnection = LibvirtConnector(LibvirtConnector.KVM, self,
                                                    self)
        self.__virtualNetworkManager = VirtualNetworkManager(
            createVirtualNetworkAsRoot)
        self.__virtualNetworkManager.createVirtualNetwork(
            virtualNetworkName, gatewayIP, netmask, dhcpStartIP, dhcpEndIP)
        self.__virtualNetworkName = virtualNetworkName

    def doInitialCleanup(self):
        """
        Does the initial cleanup, freeing the unused resources assigned to the
            registered virtual machines.
        Args:
            None
        Returns:
            Nothing
        """
        activeDomainNames = self.__libvirtConnection.getActiveDomainNames()
        registeredDomainNames = self.__commandsDBConnector.getRegisteredDomainNames(
        )
        for domainName in registeredDomainNames:
            if (not domainName in activeDomainNames):
                self.__freeDomainResources(domainName)
        self.__commandsDBConnector.allocateAssignedMACsUUIDsAndVNCPorts()

    def shutdown(self, timeout):
        """
        Destroys all the domains.
        Args:
            timeout: the number of seconds to wait before destruction all the domains.
        Returns:
            Nothing
        """
        if (self.__libvirtConnection != None):
            if (timeout == 0):
                self.__libvirtConnection.destroyAllDomains()
            else:
                self.__waitForDomainsToTerminate(timeout)
        try:
            self.__virtualNetworkManager.destroyVirtualNetwork(
                self.__virtualNetworkName)
        except Exception:
            pass
        self.__childProcessManager.waitForBackgroundChildrenToTerminate()

    def createDomain(self, imageID, userID, commandID):
        """
        Creates a domain
        Args:
            imageID: the image to use's ID
            userID: the domain owner's ID
            commandID: the domain boot command's ID
        Returns:
            Nothing
        """

        try:
            diskImagesCreated = False
            websockifyPID = -1
            imageFound = False
            newUUID = None
            newMAC = None

            definitionFile = self.__definitionFileDirectory + self.__commandsDBConnector.getDefinitionFilePath(
                imageID)
            originalName = "{0}_".format(imageID)
            dataImagePath = self.__commandsDBConnector.getDataImagePath(
                imageID)
            osImagePath = self.__commandsDBConnector.getOSImagePath(imageID)
            isBootable = self.__commandsDBConnector.getBootableFlag(imageID)
            imageFound = True

            # Generate the configuration parameters
            newUUID, newMAC = self.__commandsDBConnector.extractFreeMACAndUUID(
            )
            newPort = self.__commandsDBConnector.extractFreeVNCPort()
            newName = originalName + str(newPort)
            newPassword = self.__generateVNCPassword()
            sourceOSDisk = self.__sourceImagePath + osImagePath

            if (isBootable):
                # Create the disk images in copy-on-write mode
                trimmedDataImagePath = dataImagePath
                try:
                    trimmedDataImagePath = dataImagePath[0:dataImagePath.
                                                         index(".qcow2")]
                except:
                    pass
                trimmedOSImagePath = osImagePath
                try:
                    trimmedOSImagePath = osImagePath[0:osImagePath.
                                                     index(".qcow2")]
                except:
                    pass

                newDataDisk = self.__executionImagePath + trimmedDataImagePath + str(
                    newPort) + ".qcow2"
                newOSDisk = self.__executionImagePath + trimmedOSImagePath + str(
                    newPort) + ".qcow2"

                # If one of the files already exist, we'll get rid of it.
                if (path.exists(newDataDisk)):
                    print("Warning: the file " + newDataDisk +
                          " already exists")
                    ChildProcessManager.runCommandInForeground(
                        "rm " + newDataDisk, VMServerException)

                if (path.exists(newOSDisk)):
                    print("Warning: the file " + newOSDisk + " already exists")
                    ChildProcessManager.runCommandInForeground(
                        "rm " + newOSDisk, VMServerException)

                try:
                    ChildProcessManager.runCommandInForeground(
                        "cd " + self.__sourceImagePath + ";" +
                        "cp --parents " + dataImagePath + " " +
                        self.__executionImagePath, VMServerException)
                    ChildProcessManager.runCommandInForeground(
                        "mv " + self.__executionImagePath + dataImagePath +
                        " " + newDataDisk, VMServerException)
                    ChildProcessManager.runCommandInForeground(
                        "qemu-img create -b " + sourceOSDisk + " -f qcow2 " +
                        newOSDisk, VMServerException)
                    diskImagesCreated = True
                except Exception as e:
                    diskImagesCreated = False
                    raise e

            else:
                # The images will not be created in copy-on-write mode. In fact, their stored copies will be
                # modified (we're editing them)
                newDataDisk = path.join(self.__sourceImagePath, dataImagePath)
                newOSDisk = path.join(self.__sourceImagePath, osImagePath)

            # Build dthe definition file
            xmlFile = DefinitionFileEditor(definitionFile)
            xmlFile.setDomainIdentifiers(newName, newUUID)
            xmlFile.setImagePaths(newOSDisk, newDataDisk)
            xmlFile.setVirtualNetworkConfiguration(self.__virtualNetworkName,
                                                   newMAC)
            xmlFile.setVNCServerConfiguration(self.__vncServerIP, newPort,
                                              newPassword,
                                              self.__useQEMUWebsockets)

            string = xmlFile.generateConfigurationString()
            # Start the domain
            self.__libvirtConnection.startDomain(string)

            if (not self.__useQEMUWebsockets):
                websockifyPID = self.__childProcessManager.runCommandInBackground(
                    [
                        self.__websockifyPath,
                        self.__vncServerIP + ":" + str(newPort + 1),
                        self.__vncServerIP + ":" + str(newPort)
                    ])

            # Everything went OK => register the resources on the database

            self.__commandsDBConnector.registerVMResources(
                newName, imageID, newPort, newPassword, userID, websockifyPID,
                newOSDisk, newDataDisk, newMAC, newUUID)
            self.__commandsDBConnector.addVMBootCommand(newName, commandID)

        except Exception as e:
            print e
            # Free the allocated resources, generate an error packet and send it.
            if (imageFound and not isBootable):
                self.__commandsDBConnector.deleteImage(imageID)
            if (newUUID != None):
                self.__commandsDBConnector.freeMACAndUUID(newUUID, newMAC)
            if (diskImagesCreated):
                ChildProcessManager.runCommandInForeground(
                    "rm " + newOSDisk, None)
                ChildProcessManager.runCommandInForeground(
                    "rm " + newDataDisk, None)
                directoryName = path.dirname(newOSDisk)
                if (listdir(directoryName) == []):
                    ChildProcessManager.runCommandInForeground("rm -rf " +
                                                               directoryName)
            if (websockifyPID != -1):
                ChildProcessManager.runCommandInForeground(
                    "kill " + websockifyPID, None)
            p = self.__packetManager.createInternalErrorPacket(commandID)
            self.__networkManager.sendPacket('', self.__listenningPort, p)

    def destroyDomain(self, domainUID):
        """
        Destroys a domain
        Args:
            domainUID: the domain to destroy's unique identifier
        Returns:
            Nothing
        """
        domainName = self.__commandsDBConnector.getDomainNameFromVMBootCommand(
            domainUID)
        if (domainName == None):
            # Ignoramos la petición: el dominio ya está apagado
            return
        bootableFlag = self.__commandsDBConnector.getBootableFlag(
            self.__commandsDBConnector.getDomainImageID(domainName))
        if (bootableFlag):
            self.__libvirtConnection.destroyDomain(domainName)
        else:
            self.__libvirtConnection.shutdownDomain(domainName)

    def rebootDomain(self, domainUID):
        """
        Reboots a domain
        Args:
            domainUID: the domain to reboot's unique identifier
        Returns:
            Nothing
        """
        domainName = self.__commandsDBConnector.getDomainNameFromVMBootCommand(
            domainUID)
        if (domainName == None):
            # Ignoramos la petición: el dominio ya está apagado
            return
        self.__libvirtConnection.rebootDomain(domainName)

    def _onDomainStart(self, domain):
        """
        This method will be called to handle a domain creation event.
        Args:
            domain: an object containing the domain's data
        Returns:
            Nothing
        """
        self.__sendConnectionData(domain)

    def __sendConnectionData(self, domainInfo):
        """
        Sends a domain's connection data
        Args:
            domainInfo: an object containing the domain's data
        Returns:
            Nothing
        """
        ip = domainInfo["VNCip"]
        port = domainInfo["VNCport"]
        password = domainInfo["VNCpassword"]
        domainName = domainInfo["name"]
        commandID = None
        while (commandID == None):
            commandID = self.__commandsDBConnector.getVMBootCommand(domainName)
            if (commandID == None):
                sleep(0.1)
        packet = self.__packetManager.createVMConnectionParametersPacket(
            ip, port + 1, password, commandID)
        self.__networkManager.sendPacket('', self.__listenningPort, packet)

    def _onDomainStop(self, domainName):
        """
        This method will be called to handle a domain stop event.
        Args:
            domainName: the stopped domain's name
        Returns:
            Nothing
        """
        if (self.__commandsDBConnector.getVMBootCommand(domainName) != None):
            self.__freeDomainResources(domainName)

    def __freeDomainResources(self, domainName, deleteDiskImages=True):
        """
        Free the resources assigned to a domain
        Args:
            domainName: a domain name
            deleteDiskImages: indicates wether the disk images must be deleted or not
        Returns:
            Nothing
        """
        dataImagePath = self.__commandsDBConnector.getDomainDataImagePath(
            domainName)
        osImagePath = self.__commandsDBConnector.getDomainOSImagePath(
            domainName)
        imageID = self.__commandsDBConnector.getDomainImageID(domainName)
        websockify_pid = self.__commandsDBConnector.getWebsockifyDaemonPID(
            domainName)
        isBootable = self.__commandsDBConnector.getBootableFlag(imageID)
        commandID = self.__commandsDBConnector.getVMBootCommand(domainName)

        self.__commandsDBConnector.unregisterDomainResources(domainName)

        if (websockify_pid != -1):
            ChildProcessManager.runCommandInForeground(
                "kill -s TERM " + str(websockify_pid), None)

        if isBootable:
            # If the domain was manually stopped, libvirt has already got rid of the disk images.
            # ==> we don't have to complain if we can't find them
            ChildProcessManager.runCommandInForeground("rm " + dataImagePath,
                                                       None)
            ChildProcessManager.runCommandInForeground("rm " + osImagePath,
                                                       None)
            dataDirectory = path.dirname(dataImagePath)
            osDirectory = path.dirname(osImagePath)
            if (path.exists(dataDirectory) and listdir(dataDirectory) == []):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + dataDirectory, None)
            if (osDirectory != dataDirectory and path.exists(osDirectory)
                    and listdir(osDirectory) == []):
                ChildProcessManager.runCommandInForeground(
                    "rm -rf " + osDirectory, None)

        else:
            data = dict()
            connectionData = self.__commandsDBConnector.getImageRepositoryConnectionData(
                commandID)
            data["Transfer_Type"] = TRANSFER_T.STORE_IMAGE
            data["DataImagePath"] = dataImagePath
            data["OSImagePath"] = osImagePath
            data[
                "DefinitionFilePath"] = self.__commandsDBConnector.getDefinitionFilePath(
                    imageID)
            data["RepositoryIP"] = connectionData["RepositoryIP"]
            data["RepositoryPort"] = connectionData["RepositoryPort"]
            data["CommandID"] = commandID
            data["TargetImageID"] = imageID
            self.__commandsDBConnector.addToCompressionQueue(data)
            self.__commandsDBConnector.removeImageRepositoryConnectionData(
                commandID)
            self.__commandsDBConnector.deleteImage(imageID)

    def __waitForDomainsToTerminate(self, timeout):
        """
        Waits until all the active domains have finished, stopping at timeout seconds.
        Args:
            timeout: a timeout in seconds
        Returns:
            Nothing
        """
        wait_time = 0
        while (self.__libvirtConnection.getNumberOfDomains() != 0
               and wait_time < timeout):
            sleep(0.5)
            wait_time += 0.5

    def __generateVNCPassword(self):
        """
        Generates a VNC random password
        Args:
            None
        Returns:
            a string containing the generated password
        """
        return ChildProcessManager.runCommandInForeground(
            "openssl rand -base64 " + str(self.__vncPasswordLength),
            VMServerException)

    def getLibvirtStatusData(self):
        """
        Returns libvirt's status data.
        Args:
            None
        Returns:
            A dictionary containing libvirt's status data.
        """
        return self.__libvirtConnection.getStatusData()
Exemple #37
0
if __name__ == "__main__" :
    if (len(sys.argv) != 2) :
        print "A configuration file path is needed"
        sys.exit()
    try :
        parser = VMServerConfigurationFileParser()
        parser.parseConfigurationFile(sys.argv[1])
    except Exception as e:
        print e.message
        sys.exit()
        
    # Read root's password. It's vital to change the downloaded files' permissions.
    password_ok = False
    while (not password_ok) :        
        try :            
            ChildProcessManager.runCommandInForegroundAsRoot("ls", Exception)
            password_ok = True
        except Exception:
            print "Wrong password. Please, key it in again."
            RootPasswordHandler().clear()
        
    # Configure the database
    rootPassword = parser.getConfigurationParameter("mysqlRootsPassword")
    configurator = DBConfigurator(rootPassword)
    configurator.runSQLScript("VMServerDB", "./database/VMServerDB.sql", "root", rootPassword) 
    configurator.addUser(parser.getConfigurationParameter("databaseUserName"), parser.getConfigurationParameter("databasePassword"), "VMServerDB", True)
    
    # Create the directories (if necessary)
    parameters = ["configFilePath", "sourceImagePath", "executionImagePath", "TransferDirectory"]
    for param in parameters :
        param_path = parser.getConfigurationParameter(param)
    def createDomain(self, imageID, userID, commandID):
        """
        Creates a domain
        Args:
            imageID: the image to use's ID
            userID: the domain owner's ID
            commandID: the domain boot command's ID
        Returns:
            Nothing
        """

        try:
            diskImagesCreated = False
            websockifyPID = -1
            imageFound = False
            newUUID = None
            newMAC = None

            definitionFile = self.__definitionFileDirectory + self.__commandsDBConnector.getDefinitionFilePath(
                imageID)
            originalName = "{0}_".format(imageID)
            dataImagePath = self.__commandsDBConnector.getDataImagePath(
                imageID)
            osImagePath = self.__commandsDBConnector.getOSImagePath(imageID)
            isBootable = self.__commandsDBConnector.getBootableFlag(imageID)
            imageFound = True

            # Generate the configuration parameters
            newUUID, newMAC = self.__commandsDBConnector.extractFreeMACAndUUID(
            )
            newPort = self.__commandsDBConnector.extractFreeVNCPort()
            newName = originalName + str(newPort)
            newPassword = self.__generateVNCPassword()
            sourceOSDisk = self.__sourceImagePath + osImagePath

            if (isBootable):
                # Create the disk images in copy-on-write mode
                trimmedDataImagePath = dataImagePath
                try:
                    trimmedDataImagePath = dataImagePath[0:dataImagePath.
                                                         index(".qcow2")]
                except:
                    pass
                trimmedOSImagePath = osImagePath
                try:
                    trimmedOSImagePath = osImagePath[0:osImagePath.
                                                     index(".qcow2")]
                except:
                    pass

                newDataDisk = self.__executionImagePath + trimmedDataImagePath + str(
                    newPort) + ".qcow2"
                newOSDisk = self.__executionImagePath + trimmedOSImagePath + str(
                    newPort) + ".qcow2"

                # If one of the files already exist, we'll get rid of it.
                if (path.exists(newDataDisk)):
                    print("Warning: the file " + newDataDisk +
                          " already exists")
                    ChildProcessManager.runCommandInForeground(
                        "rm " + newDataDisk, VMServerException)

                if (path.exists(newOSDisk)):
                    print("Warning: the file " + newOSDisk + " already exists")
                    ChildProcessManager.runCommandInForeground(
                        "rm " + newOSDisk, VMServerException)

                try:
                    ChildProcessManager.runCommandInForeground(
                        "cd " + self.__sourceImagePath + ";" +
                        "cp --parents " + dataImagePath + " " +
                        self.__executionImagePath, VMServerException)
                    ChildProcessManager.runCommandInForeground(
                        "mv " + self.__executionImagePath + dataImagePath +
                        " " + newDataDisk, VMServerException)
                    ChildProcessManager.runCommandInForeground(
                        "qemu-img create -b " + sourceOSDisk + " -f qcow2 " +
                        newOSDisk, VMServerException)
                    diskImagesCreated = True
                except Exception as e:
                    diskImagesCreated = False
                    raise e

            else:
                # The images will not be created in copy-on-write mode. In fact, their stored copies will be
                # modified (we're editing them)
                newDataDisk = path.join(self.__sourceImagePath, dataImagePath)
                newOSDisk = path.join(self.__sourceImagePath, osImagePath)

            # Build dthe definition file
            xmlFile = DefinitionFileEditor(definitionFile)
            xmlFile.setDomainIdentifiers(newName, newUUID)
            xmlFile.setImagePaths(newOSDisk, newDataDisk)
            xmlFile.setVirtualNetworkConfiguration(self.__virtualNetworkName,
                                                   newMAC)
            xmlFile.setVNCServerConfiguration(self.__vncServerIP, newPort,
                                              newPassword,
                                              self.__useQEMUWebsockets)

            string = xmlFile.generateConfigurationString()
            # Start the domain
            self.__libvirtConnection.startDomain(string)

            if (not self.__useQEMUWebsockets):
                websockifyPID = self.__childProcessManager.runCommandInBackground(
                    [
                        self.__websockifyPath,
                        self.__vncServerIP + ":" + str(newPort + 1),
                        self.__vncServerIP + ":" + str(newPort)
                    ])

            # Everything went OK => register the resources on the database

            self.__commandsDBConnector.registerVMResources(
                newName, imageID, newPort, newPassword, userID, websockifyPID,
                newOSDisk, newDataDisk, newMAC, newUUID)
            self.__commandsDBConnector.addVMBootCommand(newName, commandID)

        except Exception as e:
            print e
            # Free the allocated resources, generate an error packet and send it.
            if (imageFound and not isBootable):
                self.__commandsDBConnector.deleteImage(imageID)
            if (newUUID != None):
                self.__commandsDBConnector.freeMACAndUUID(newUUID, newMAC)
            if (diskImagesCreated):
                ChildProcessManager.runCommandInForeground(
                    "rm " + newOSDisk, None)
                ChildProcessManager.runCommandInForeground(
                    "rm " + newDataDisk, None)
                directoryName = path.dirname(newOSDisk)
                if (listdir(directoryName) == []):
                    ChildProcessManager.runCommandInForeground("rm -rf " +
                                                               directoryName)
            if (websockifyPID != -1):
                ChildProcessManager.runCommandInForeground(
                    "kill " + websockifyPID, None)
            p = self.__packetManager.createInternalErrorPacket(commandID)
            self.__networkManager.sendPacket('', self.__listenningPort, p)
    def startListenning(self, networkInterface, useSSL, certificatesDirectory,
                        commandsListenningPort, ftpListenningPort,
                        maxConnections, maxConnectionsPerIP,
                        uploadBandwidthRatio, downloadBandwidthRatio,
                        ftpUsername, ftpPasswordLength):
        """
        Boots up the FTP server and creates the control connection.
        Args:
            networkInterface: the network interface that will be used by the FTP server
            useSSL: indicates if SSL encryption must be used in the control connection or not
            certificatesDirectory: the directory where the files server.crt and server.key are
            commandsListenningPort: the control connection's port
            ftpListenningPort: the FTP server listenning port
            maxConnections: maximum FTP connections
            maxConnectionsPerIP: maximum FTP connections per IP address
            uploadBandwidthRatio: maximum download bandwidth fraction
            downloadBandwidthRatio: maximum upload bandwidth fraction
            ftpUsername: the FTP user that the virtual machine servers will use
            ftpPasswordLength: the random FTP password length
        Returns:
            Nothing
        @attention: The FTP password will be randomly generated at every boot.
        """
        try:
            self.__maxConnections = maxConnections
            self.__commandsListenningPort = commandsListenningPort
            self.__FTPListenningPort = ftpListenningPort
            self.__networkManager = NetworkManager(certificatesDirectory)
            self.__repositoryPacketHandler = ImageRepositoryPacketHandler(
                self.__networkManager)

            self.__commandsCallback = CommandsCallback(
                self.__networkManager, self.__repositoryPacketHandler,
                commandsListenningPort, self.__dbConnector,
                self.__retrieveQueue, self.__storeQueue,
                self.__diskImagesDirectory)

            self.__networkManager.startNetworkService()
            self.__networkManager.listenIn(commandsListenningPort,
                                           self.__commandsCallback, useSSL)

            dataCallback = FTPServerCallback(self.__slotCounter,
                                             self.__dbConnector)

            self.__ftpUsername = ftpUsername
            self.__ftpPassword = ChildProcessManager.runCommandInForeground(
                "openssl rand -base64 {0}".format(ftpPasswordLength),
                Exception)

            self.__ftpServer = ConfigurableFTPServer(
                "Image repository FTP Server")

            self.__ftpServer.startListenning(networkInterface,
                                             ftpListenningPort, maxConnections,
                                             maxConnectionsPerIP, dataCallback,
                                             downloadBandwidthRatio,
                                             uploadBandwidthRatio)
            self.__ftpServer.addUser(self.__ftpUsername, self.__ftpPassword,
                                     self.__diskImagesDirectory, "eramw")
        except Exception as e:
            print "Error: " + e.message
            self.__finish = True
    def initTransfers(self):
        """
        Initializes the upload and download transfers
        Args:
            None
        Returns:
            Nothing
        """
        store = False
        while not (self.__finish or self.__commandsCallback.haltReceived()):
            if (self.__slotCounter.read() == self.__maxConnections):
                # No free slots => sleep
                sleep(0.1)
            else:
                # There are slots => enable uploads and downloads in parallel
                self.__slotCounter.decrement()

                if (self.__retrieveQueue.isEmpty()
                        and self.__storeQueue.isEmpty()):
                    sleep(0.1)
                    continue
                if (not self.__retrieveQueue.isEmpty()
                        and self.__storeQueue.isEmpty()):
                    queue = self.__retrieveQueue
                    store = False
                elif (self.__retrieveQueue.isEmpty()
                      and not self.__storeQueue.isEmpty()):
                    queue = self.__storeQueue
                    store = True
                else:
                    if (store):
                        queue = self.__retrieveQueue
                        store = False
                    else:
                        queue = self.__storeQueue
                        store = True

                (imageID, clientIP, clientPort) = queue.pop(0)

                imageData = self.__dbConnector.getImageData(imageID)
                if (imageData == None):
                    if (store):
                        packet_type = PACKET_T.STOR_ERROR
                    else:
                        packet_type = PACKET_T.RETR_ERROR
                    p = self.__repositoryPacketHandler.createErrorPacket(
                        packet_type, ERROR_DESC_T.IR_IMAGE_DELETED)
                    self.__networkManager.sendPacket(
                        '', self.__commandsListenningPort, p, clientIP,
                        clientPort)
                else:
                    compressedFilePath = imageData["compressedFilePath"]

                    if (not "undefined" in compressedFilePath):
                        serverDirectory = path.relpath(
                            path.dirname(compressedFilePath),
                            self.__diskImagesDirectory)
                        compressedFileName = path.basename(compressedFilePath)
                    else:
                        serverDirectory = str(imageID)
                        compressedFileName = ""
                        serverDirectoryPath = path.join(
                            self.__diskImagesDirectory, serverDirectory)
                        if (path.exists(serverDirectoryPath)):
                            # The directory exists, and can store shit => clean it up!
                            ChildProcessManager.runCommandInForeground(
                                "rm -rf " + serverDirectoryPath, Exception)
                        mkdir(serverDirectoryPath)

                    if (store):
                        packet_type = PACKET_T.STOR_START
                    else:
                        packet_type = PACKET_T.RETR_START

                    p = self.__repositoryPacketHandler.createTransferEnabledPacket(
                        packet_type, imageID, self.__FTPListenningPort,
                        self.__ftpUsername, self.__ftpPassword,
                        serverDirectory, compressedFileName)

                    self.__networkManager.sendPacket(
                        '', self.__commandsListenningPort, p, clientIP,
                        clientPort)