def __init__(self, transferDirectory, diskImagesDirectory,
              definitionFileDirectory, dbConnector, domainHandler,
              networkManager, serverListenningPort, packetHandler):
     """
     Initializes the compression thread's state
     Args:
         transferDirectory: the transfers directory
         diskImagesDirectory: the directory where the disk images are stored
         definitionFileDirectory: the directory where the definition files are stored
         dbConnector: the database connector
         domainHandler: the domain handler to use
         networkManger: the network manager to use
         serverListenningPort: the virtual machine server's control connection port.
         packetHandler: the packet handler to use
     """
     BasicThread.__init__(self, "File compression thread")
     self.__diskImagesDirectory = diskImagesDirectory
     self.__transferDirectory = transferDirectory
     self.__definitionFileDirectory = definitionFileDirectory
     self.__dbConnector = dbConnector
     self.__domainHandler = domainHandler
     self.__compressor = ZipBasedCompressor()
     self.__networkManager = networkManager
     self.__serverListenningPort = serverListenningPort
     self.__packetHandler = packetHandler
 def __init__(self, transferDirectory, diskImagesDirectory, definitionFileDirectory, dbConnector, domainHandler,
              networkManager, serverListenningPort, packetHandler):
     """
     Initializes the compression thread's state
     Args:
         transferDirectory: the transfers directory
         diskImagesDirectory: the directory where the disk images are stored
         definitionFileDirectory: the directory where the definition files are stored
         dbConnector: the database connector
         domainHandler: the domain handler to use
         networkManger: the network manager to use
         serverListenningPort: the virtual machine server's control connection port.
         packetHandler: the packet handler to use
     """
     BasicThread.__init__(self, "File compression thread")
     self.__diskImagesDirectory = diskImagesDirectory
     self.__transferDirectory = transferDirectory
     self.__definitionFileDirectory = definitionFileDirectory
     self.__dbConnector = dbConnector
     self.__domainHandler = domainHandler
     self.__compressor = ZipBasedCompressor()
     self.__networkManager = networkManager
     self.__serverListenningPort = serverListenningPort
     self.__packetHandler = packetHandler
class CompressionThread(BasicThread):
    """
    This thread class is associated with the compression thread
    """
    
    def __init__(self, transferDirectory, diskImagesDirectory, definitionFileDirectory, dbConnector, domainHandler,
                 networkManager, serverListenningPort, packetHandler):
        """
        Initializes the compression thread's state
        Args:
            transferDirectory: the transfers directory
            diskImagesDirectory: the directory where the disk images are stored
            definitionFileDirectory: the directory where the definition files are stored
            dbConnector: the database connector
            domainHandler: the domain handler to use
            networkManger: the network manager to use
            serverListenningPort: the virtual machine server's control connection port.
            packetHandler: the packet handler to use
        """
        BasicThread.__init__(self, "File compression thread")
        self.__diskImagesDirectory = diskImagesDirectory
        self.__transferDirectory = transferDirectory
        self.__definitionFileDirectory = definitionFileDirectory
        self.__dbConnector = dbConnector
        self.__domainHandler = domainHandler
        self.__compressor = ZipBasedCompressor()
        self.__networkManager = networkManager
        self.__serverListenningPort = serverListenningPort
        self.__packetHandler = packetHandler
        
    def run(self):
        while not self.finish() :
            data = self.__dbConnector.peekFromCompressionQueue()
            if (data == None):
                sleep(0.5)
            else:
                self.__processElement(data)
                self.__dbConnector.removeFirstElementFromCompressionQueue()

        
    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)
class CompressionThread(BasicThread):
    """
    This thread class is associated with the compression thread
    """
    def __init__(self, transferDirectory, diskImagesDirectory,
                 definitionFileDirectory, dbConnector, domainHandler,
                 networkManager, serverListenningPort, packetHandler):
        """
        Initializes the compression thread's state
        Args:
            transferDirectory: the transfers directory
            diskImagesDirectory: the directory where the disk images are stored
            definitionFileDirectory: the directory where the definition files are stored
            dbConnector: the database connector
            domainHandler: the domain handler to use
            networkManger: the network manager to use
            serverListenningPort: the virtual machine server's control connection port.
            packetHandler: the packet handler to use
        """
        BasicThread.__init__(self, "File compression thread")
        self.__diskImagesDirectory = diskImagesDirectory
        self.__transferDirectory = transferDirectory
        self.__definitionFileDirectory = definitionFileDirectory
        self.__dbConnector = dbConnector
        self.__domainHandler = domainHandler
        self.__compressor = ZipBasedCompressor()
        self.__networkManager = networkManager
        self.__serverListenningPort = serverListenningPort
        self.__packetHandler = packetHandler

    def run(self):
        while not self.finish():
            data = self.__dbConnector.peekFromCompressionQueue()
            if (data == None):
                sleep(0.5)
            else:
                self.__processElement(data)
                self.__dbConnector.removeFirstElementFromCompressionQueue()

    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)