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 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
class ImageRepositoryReactor(object): """ Image repository packet reactor """ def __init__(self, diskImagesDirectory): """ Initializes the reactor's state Args: diskImagesDirectory: the FTP server's root directory """ self.__diskImagesDirectory = diskImagesDirectory self.__slotCounter = MultithreadingCounter() self.__retrieveQueue = GenericThreadSafeList() self.__storeQueue = GenericThreadSafeList() self.__finish = False self.__networkManager = None self.__ftpServer = None def connectToDatabase(self, repositoryDBName, repositoryDBUser, repositoryDBPassword): """ Establishes the connection with the image repository's database. Args: repositoryDBName: a database name repositoryDBUser: an user name repositoryDBPassword: a password Returns: Nothing """ self.__dbConnector = ImageRepositoryDBConnector( repositoryDBUser, repositoryDBPassword, repositoryDBName) 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 stopListenning(self): """ Stops the FTP server and closes the control connection. Args: None Returns: Nothing """ if (self.__ftpServer != None): try: self.__ftpServer.stopListenning() except Exception: pass if (self.__networkManager != None): self.__networkManager.stopNetworkService() 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 ImageRepositoryReactor(object): """ Image repository packet reactor """ def __init__(self, diskImagesDirectory): """ Initializes the reactor's state Args: diskImagesDirectory: the FTP server's root directory """ self.__diskImagesDirectory = diskImagesDirectory self.__slotCounter = MultithreadingCounter() self.__retrieveQueue = GenericThreadSafeList() self.__storeQueue = GenericThreadSafeList() self.__finish = False self.__networkManager = None self.__ftpServer = None def connectToDatabase(self, repositoryDBName, repositoryDBUser, repositoryDBPassword): """ Establishes the connection with the image repository's database. Args: repositoryDBName: a database name repositoryDBUser: an user name repositoryDBPassword: a password Returns: Nothing """ self.__dbConnector = ImageRepositoryDBConnector(repositoryDBUser, repositoryDBPassword, repositoryDBName) 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 stopListenning(self): """ Stops the FTP server and closes the control connection. Args: None Returns: Nothing """ if (self.__ftpServer != None) : try : self.__ftpServer.stopListenning() except Exception : pass if (self.__networkManager != None) : self.__networkManager.stopNetworkService() 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)