def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval): """ Establishes a connection with the cluster server. Args: certificatePath: the server.crt and server.key directory path. clusterServerIP: the cluster server's IPv4 address clusterServerListenningPort: the cluster server's listenning port. statusDBUpdateInterval: the status database update interval (in seconds) Returns: Nothing """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Connect to the main server self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady( clusterServerIP, clusterServerListenningPort)): sleep(0.1) # Create the packet handler self.__pHandler = ClusterServerPacketHandler(self.__manager) # Create the update thread self.__updateRequestThread = StatusDatabaseUpdateThread( _ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) # Start it self.__updateRequestThread.start()
def __sendUpdateRequestPackets(self): """ Sends the update request packets to the cluster server Args: None Returns: Nothing """ if (self.__commandsProcessor.finish()) : return p = self.__packetHandler.createDataRequestPacket(PACKET_T.QUERY_VM_SERVERS_STATUS) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine servers status", errorMessage) p = self.__packetHandler.createDataRequestPacket(PACKET_T.QUERY_VM_DISTRIBUTION) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine distribution", errorMessage) p = self.__packetHandler.createDataRequestPacket(PACKET_T.QUERY_ACTIVE_VM_VNC_DATA) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Active virtual machines data", errorMessage) p = self.__packetHandler.createDataRequestPacket(PACKET_T.QUERY_REPOSITORY_STATUS) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Image repository status", errorMessage) p = self.__packetHandler.createDataRequestPacket(PACKET_T.QUERY_VM_SERVERS_RESOURCE_USAGE) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine servers resource usage", errorMessage)
def disconnectFromClusterServer(self): """ Cierra la conexión con el servidor de cluster y borra las bases de datos de estado Argumentos: Ninguno Devuelve: Nada @attention: Este método debe llamarse desde el hilo principal para evitar cuelgues """ # Apagar el servidor de cluster p = self.__repositoryPacketHandler.createHaltPacket( self.__haltVMServers) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) # Dejar de actualizar las bases de datos self.__updateRequestThread.stop() # Dejar de monitorizar los comandos self.__commandMonitoringThread.stop() # Cerrar las conexiones con las bases de datos self.closeNetworkAndDBConnections()
def __requestVNCConnectionData(self): """ Processes a VNC connection data request packet Args: data: a dictionary containing the incoming packet's data Returns: Nothing """ p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.QUERY_ACTIVE_VM_DATA) connectionData = self.__commandsDBConnector.getActiveVMServersConnectionData() for cd in connectionData : errorMessage = self.__networkManager.sendPacket(cd["ServerIP"], cd["ServerPort"], p) NetworkManager.printConnectionWarningIfNecessary(cd["ServerIP"], cd["ServerPort"], "VNC connection data request", errorMessage)
def __sendStatusRequestToVMServer(self, vmServerIP, vmServerPort): """ Sends a status request packet to a virtual machine server Args: vmServerIP : the virtual machine server's IP address vmServerPort: the virtual machine server control connection's port Returns: Nothing """ p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) errorMessage = self.__networkManager.sendPacket(vmServerIP, vmServerPort, p) NetworkManager.printConnectionWarningIfNecessary(vmServerIP, vmServerPort, "status request", errorMessage) p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.QUERY_ACTIVE_DOMAIN_UIDS) errorMessage = self.__networkManager.sendPacket(vmServerIP, vmServerPort, p) NetworkManager.printConnectionWarningIfNecessary(vmServerIP, vmServerPort, "active domain UIDs request", errorMessage)
def connectToClusterServer(self, useSSL, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establishes a connection with the cluster server Args: certificatePath: the directory where the server.crt and server.key files are clusterServerIP: the cluster server's IP address clusterServerListenningPort: the cluster server commands connection's port statusDBUpdateInterval: the database update interval (in seconds) Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__packetHandler = ClusterServerPacketHandler( self.__networkManager) self.__commandsProcessor = CommandsProcessor( self.__commandsHandler, self.__packetHandler, self.__networkManager, self.__clusterServerIP, self.__clusterServerPort, self.__commandsDBConnector, self.__endpointDBConnector) packetReactor = ClusterEndpointPacketReactor( self.__codeTranslator, self.__commandsHandler, self.__packetHandler, self.__commandsProcessor, self.__endpointDBConnector, self.__commandsDBConnector) try: self.__networkManager.connectTo(clusterServerIP, clusterServerListenningPort, 5, packetReactor, useSSL) while (not self.__networkManager.isConnectionReady( clusterServerIP, clusterServerListenningPort)): sleep(0.1) self.__updateRequestThread = VMServerMonitoringThread( self.__packetHandler, self.__networkManager, self.__commandsProcessor, self.__clusterServerIP, self.__clusterServerPort, statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandExecutionThread = CommandsMonitoringThread( self.__commandsDBConnector, commandTimeout, self.__commandsHandler, commandTimeoutCheckInterval) self.__commandExecutionThread.start() except NetworkManagerException as e: raise Exception(e.message)
def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval): """ Establishes a connection with the cluster server. Args: certificatePath: the server.crt and server.key directory path. clusterServerIP: the cluster server's IPv4 address clusterServerListenningPort: the cluster server's listenning port. statusDBUpdateInterval: the status database update interval (in seconds) Returns: Nothing """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Connect to the main server self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady(clusterServerIP, clusterServerListenningPort)) : sleep(0.1) # Create the packet handler self.__pHandler = ClusterServerPacketHandler(self.__manager) # Create the update thread self.__updateRequestThread = StatusDatabaseUpdateThread(_ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) # Start it self.__updateRequestThread.start()
def connectToClusterServer(self, useSSL, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establishes a connection with the cluster server Args: certificatePath: the directory where the server.crt and server.key files are clusterServerIP: the cluster server's IP address clusterServerListenningPort: the cluster server commands connection's port statusDBUpdateInterval: the database update interval (in seconds) Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__packetHandler = ClusterServerPacketHandler(self.__networkManager) self.__commandsProcessor = CommandsProcessor(self.__commandsHandler, self.__packetHandler, self.__networkManager, self.__clusterServerIP, self.__clusterServerPort, self.__commandsDBConnector, self.__endpointDBConnector) packetReactor = ClusterEndpointPacketReactor(self.__codeTranslator, self.__commandsHandler, self.__packetHandler, self.__commandsProcessor, self.__endpointDBConnector, self.__commandsDBConnector) try : self.__networkManager.connectTo(clusterServerIP, clusterServerListenningPort, 5, packetReactor, useSSL) while (not self.__networkManager.isConnectionReady(clusterServerIP, clusterServerListenningPort)) : sleep(0.1) self.__updateRequestThread = VMServerMonitoringThread(self.__packetHandler, self.__networkManager, self.__commandsProcessor, self.__clusterServerIP, self.__clusterServerPort, statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandExecutionThread = CommandsMonitoringThread(self.__commandsDBConnector, commandTimeout, self.__commandsHandler, commandTimeoutCheckInterval) self.__commandExecutionThread.start() except NetworkManagerException as e : raise Exception(e.message)
def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establece la conexión con el servidor de cluster Argumentos: certificatePath: la ruta del directorio con los ficheros server.crt y server.key. clusterServerIP: la IP del servidor de cluster clusterServerListenningPort: el puerto en el que escucha el servidor de cluster statusDBUpdateInterval: el periodo de actualización de la base de datos (en segundos) Devuelve: Nada Lanza: EnpointException: se lanza cuando no se puede establecer una conexión con el servidor web """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Establecer la conexión self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort try : self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady(clusterServerIP, clusterServerListenningPort)) : sleep(0.1) # TODO: si esto falla, terminar. # Preparar la recepción de paquetes y la actualización automática de la base de datos de estado self.__repositoryPacketHandler = ClusterServerPacketHandler(self.__manager) self.__updateRequestThread = VMServerMonitoringThread(_ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandMonitoringThread = CommandMonitoringThread(self.__commandsDBConnector, commandTimeout, commandTimeoutCheckInterval) self.__commandMonitoringThread.start() except NetworkManagerException as e : raise EndpointException(e.message)
def disconnectFromClusterServer(self): """ Closes the connection with the cluster server Args: None Devuelve: Nada """ p = self.__packetHandler.createHaltPacket(self.__commandsProcessor.haltVMServers()) errorMessage = self.__networkManager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) self.__updateRequestThread.stop() self.__commandExecutionThread.stop() self.closeNetworkConnections()
def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establece la conexión con el servidor de cluster Argumentos: certificatePath: la ruta del directorio con los ficheros server.crt y server.key. clusterServerIP: la IP del servidor de cluster clusterServerListenningPort: el puerto en el que escucha el servidor de cluster statusDBUpdateInterval: el periodo de actualización de la base de datos (en segundos) Devuelve: Nada Lanza: EnpointException: se lanza cuando no se puede establecer una conexión con el servidor web """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Establecer la conexión self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort try: self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady( clusterServerIP, clusterServerListenningPort)): sleep(0.1) # TODO: si esto falla, terminar. # Preparar la recepción de paquetes y la actualización automática de la base de datos de estado self.__repositoryPacketHandler = ClusterServerPacketHandler( self.__manager) self.__updateRequestThread = VMServerMonitoringThread( _ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandMonitoringThread = CommandMonitoringThread( self.__commandsDBConnector, commandTimeout, commandTimeoutCheckInterval) self.__commandMonitoringThread.start() except NetworkManagerException as e: raise EndpointException(e.message)
def startListenning(self, certificatePath, port): """ Starts the network service and creates a server connection. Args: certificatePath: the server.crt and server.key files path port: the listenning port Returns: Nothing """ self.__loadBalancer = SimpleLoadBalancer(self.__dbConnector) self.__networkManager = NetworkManager(certificatePath) self.__webPort = port self.__networkManager.startNetworkService() self.__webPacketHandler = ClusterServerPacketHandler( self.__networkManager) self.__vmServerPacketHandler = VMServerPacketHandler( self.__networkManager) self.__networkManager.listenIn(port, self.__webCallback, True) self.__vmServerCallback = VMServerCallback(self)
def __requestVNCConnectionData(self): """ Processes a VNC connection data request packet Args: data: a dictionary containing the incoming packet's data Returns: Nothing """ p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.QUERY_ACTIVE_VM_DATA) connectionData = self.__commandsDBConnector.getActiveVMServersConnectionData( ) for cd in connectionData: errorMessage = self.__networkManager.sendPacket( cd["ServerIP"], cd["ServerPort"], p) NetworkManager.printConnectionWarningIfNecessary( cd["ServerIP"], cd["ServerPort"], "VNC connection data request", errorMessage)
def disconnectFromClusterServer(self): """ Closes the connection with the cluster server Args: None Devuelve: Nada """ p = self.__packetHandler.createHaltPacket( self.__commandsProcessor.haltVMServers()) errorMessage = self.__networkManager.sendPacket( self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) self.__updateRequestThread.stop() self.__commandExecutionThread.stop() self.closeNetworkConnections()
def startListenning(self, useSSL, certificatePath, listenningPort, repositoryIP, repositoryPort, vmServerStatusUpdateInterval): """ Creates the control connection Args: useSSL: indicates if SSL encryption must be used in the control connection or not certificatePath: the directory where the server.crt and server.key files are listenningPort: the control connection's port repositoryIP: the image repository IP address repositoryPort: the image repository's port vmServerStatusUpdateInterval: the virtual machine server status database interval Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__listenningPort = listenningPort self.__packetHandler = ClusterServerPacketHandler(self.__networkManager) self.__useSSL = useSSL imageRepositoryPacketHandler = ImageRepositoryPacketHandler(self.__networkManager) vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) networkEventsReactor = NetworkEventsReactor(self.__dbConnector, repositoryIP, repositoryPort) imageRepositoryPacketReactor = ImageRepositoryPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, repositoryIP, repositoryPort, self.__packetHandler, vmServerPacketHandler, imageRepositoryPacketHandler) try : imageRepositoryCallback = ImageRepositoryCallback(imageRepositoryPacketReactor, networkEventsReactor) self.__networkManager.connectTo(repositoryIP, repositoryPort, 10, imageRepositoryCallback, self.__useSSL, True) self.__dbConnector.addImageRepository(repositoryIP, repositoryPort, SERVER_STATE_T.READY) except Exception as e: print "Can't connect to the image repository: " + e.message self.__exit = True return vmServerPacketReactor = VMServerPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, vmServerPacketHandler, self.__packetHandler) self.__endpointPacketReactor = EndpointPacketReactor(self.__dbConnector, self.__networkManager, vmServerPacketHandler, self.__packetHandler, imageRepositoryPacketHandler, VMServerCallback(vmServerPacketReactor, networkEventsReactor), listenningPort, repositoryIP, repositoryPort, self.__loadBalancerSettings, self.__averageCompressionRatio, self.__useSSL) clusterEndpointCallback = ClusterEndpointCallback(self.__endpointPacketReactor) self.__networkManager.listenIn(listenningPort, clusterEndpointCallback, self.__useSSL) self.__statusMonitoringThread = ClusterStatusMonitoringThread(vmServerStatusUpdateInterval, self.__dbConnector, self.__networkManager, repositoryIP, repositoryPort, vmServerPacketHandler, imageRepositoryPacketHandler) self.__statusMonitoringThread.start()
def _sendUpdateRequestPackets(self): """ Solicita información de estado al serividor de cluster Argumentos: Ninguno Devuelve: Nada """ if (self.__stopped): return # Enviamos paquetes para obtener los tres tipos de información que necesitamos para actualizar la base de datos de estado p = self.__repositoryPacketHandler.createDataRequestPacket( PACKET_T.QUERY_VM_SERVERS_STATUS) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Virtual machine servers status", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket( PACKET_T.QUERY_VM_DISTRIBUTION) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Virtual machine distribution", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket( PACKET_T.QUERY_ACTIVE_VM_DATA) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Active virtual machines data", errorMessage)
def disconnectFromClusterServer(self): """ Cierra la conexión con el servidor de cluster y borra las bases de datos de estado Argumentos: Ninguno Devuelve: Nada @attention: Este método debe llamarse desde el hilo principal para evitar cuelgues """ # Apagar el servidor de cluster p = self.__repositoryPacketHandler.createHaltPacket(self.__haltVMServers) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) # Dejar de actualizar las bases de datos self.__updateRequestThread.stop() # Dejar de monitorizar los comandos self.__commandMonitoringThread.stop() # Cerrar las conexiones con las bases de datos self.closeNetworkAndDBConnections()
def __sendStatusRequestToVMServer(self, vmServerIP, vmServerPort): """ Sends a status request packet to a virtual machine server Args: vmServerIP : the virtual machine server's IP address vmServerPort: the virtual machine server control connection's port Returns: Nothing """ p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) errorMessage = self.__networkManager.sendPacket( vmServerIP, vmServerPort, p) NetworkManager.printConnectionWarningIfNecessary( vmServerIP, vmServerPort, "status request", errorMessage) p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.QUERY_ACTIVE_DOMAIN_UIDS) errorMessage = self.__networkManager.sendPacket( vmServerIP, vmServerPort, p) NetworkManager.printConnectionWarningIfNecessary( vmServerIP, vmServerPort, "active domain UIDs request", errorMessage)
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, certificatePath, port): """ Starts the network service and creates a server connection. Args: certificatePath: the server.crt and server.key files path port: the listenning port Returns: Nothing """ self.__loadBalancer = SimpleLoadBalancer(self.__dbConnector) self.__networkManager = NetworkManager(certificatePath) self.__webPort = port self.__networkManager.startNetworkService() self.__webPacketHandler = ClusterServerPacketHandler(self.__networkManager) self.__vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) self.__networkManager.listenIn(port, self.__webCallback, True) self.__vmServerCallback = VMServerCallback(self)
def __startListenning(self): """ Creates the control connection Args: None Returns: Nothing """ networkInterface = self.__parser.getConfigurationParameter("vncNetworkInterface") listenningPort = self.__parser.getConfigurationParameter("listenningPort") try : self.__vncServerIP = get_ip_address(networkInterface) except Exception : raise Exception("Error: the network interface '{0}' is not ready. Exiting now".format(networkInterface)) self.__ftpTimeout = self.__parser.getConfigurationParameter("FTPTimeout") self.__listenningPort = listenningPort self.__networkManager = NetworkManager(self.__parser.getConfigurationParameter("certificatePath")) self.__networkManager.startNetworkService() self.__useSSL = self.__parser.getConfigurationParameter("useSSL") self.__packetManager = VMServerPacketHandler(self.__networkManager) self.__connectToDatabases("VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__domainHandler = DomainHandler(self.__commandsDBConnector, self.__vncServerIP, self.__networkManager, self.__packetManager, self.__listenningPort, self.__parser.getConfigurationParameter("useQEMUWebsockets"), self.__parser.getConfigurationParameter("websockifyPath"), self.__parser.getConfigurationParameter("configFilePath"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("executionImagePath"), self.__parser.getConfigurationParameter("passwordLength")) self.__domainHandler.connectToLibvirt(self.__parser.getConfigurationParameter("vncNetworkInterface"), self.__parser.getConfigurationParameter("vnName"), self.__parser.getConfigurationParameter("gatewayIP"), self.__parser.getConfigurationParameter("netMask"), self.__parser.getConfigurationParameter("dhcpStartIP"), self.__parser.getConfigurationParameter("dhcpEndIP"), self.__parser.getConfigurationParameter("createVirtualNetworkAsRoot")) self.__domainHandler.doInitialCleanup() self.__deleteTemporaryZipFiles() self.__fileTransferThread = FileTransferThread(self.__networkManager, self.__listenningPort, self.__packetManager, self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("FTPTimeout"), self.__parser.getConfigurationParameter("MaxTransferAttempts"), self.__commandsDBConnector, self.__useSSL) self.__compressionThread = CompressionThread(self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("configFilePath"), self.__commandsDBConnector, self.__domainHandler, self.__networkManager, self.__listenningPort, self.__packetManager) self.__fileTransferThread.start() self.__compressionThread.start() self.__networkManager.listenIn(self.__listenningPort, self, self.__useSSL)
def _sendUpdateRequestPackets(self): """ Solicita información de estado al serividor de cluster Argumentos: Ninguno Devuelve: Nada """ if (self.__stopped) : return # Enviamos paquetes para obtener los tres tipos de información que necesitamos para actualizar la base de datos de estado p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_VM_SERVERS_STATUS) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine servers status", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_VM_DISTRIBUTION) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine distribution", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_ACTIVE_VM_DATA) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Active virtual machines data", errorMessage)
"\tautoDeployImage <imageID> <instances>: performs an auto-deployment operation" ) print("\tquit: closes this application") print("\thelp: prints this help message") if __name__ == "__main__": print('*' * 80) print('*' * 80) printLogo() print('Cluster Server tester') print('Version 7.0') print('*' * 80) print('*' * 80) print() networkManager = NetworkManager(".") networkManager.startNetworkService() pHandler = ClusterServerPacketHandler(networkManager) ip_address = raw_input("Cluster server IP address: ") port = raw_input("Cluster server control connection port: ") try: port = int(port) networkManager.connectTo(ip_address, port, 10, TesterCallback(pHandler), True) while not networkManager.isConnectionReady(ip_address, port): sleep(0.1) end = False while not end: command = raw_input('> ') tokens = command.split() end = process_command(tokens, networkManager, pHandler, ip_address,
def __startListenning(self): """ Creates the control connection Args: None Returns: Nothing """ networkInterface = self.__parser.getConfigurationParameter( "vncNetworkInterface") listenningPort = self.__parser.getConfigurationParameter( "listenningPort") try: self.__vncServerIP = get_ip_address(networkInterface) except Exception: raise Exception( "Error: the network interface '{0}' is not ready. Exiting now". format(networkInterface)) self.__ftpTimeout = self.__parser.getConfigurationParameter( "FTPTimeout") self.__listenningPort = listenningPort self.__networkManager = NetworkManager( self.__parser.getConfigurationParameter("certificatePath")) self.__networkManager.startNetworkService() self.__useSSL = self.__parser.getConfigurationParameter("useSSL") self.__packetManager = VMServerPacketHandler(self.__networkManager) self.__connectToDatabases( "VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__domainHandler = DomainHandler( self.__commandsDBConnector, self.__vncServerIP, self.__networkManager, self.__packetManager, self.__listenningPort, self.__parser.getConfigurationParameter("useQEMUWebsockets"), self.__parser.getConfigurationParameter("websockifyPath"), self.__parser.getConfigurationParameter("configFilePath"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("executionImagePath"), self.__parser.getConfigurationParameter("passwordLength")) self.__domainHandler.connectToLibvirt( self.__parser.getConfigurationParameter("vncNetworkInterface"), self.__parser.getConfigurationParameter("vnName"), self.__parser.getConfigurationParameter("gatewayIP"), self.__parser.getConfigurationParameter("netMask"), self.__parser.getConfigurationParameter("dhcpStartIP"), self.__parser.getConfigurationParameter("dhcpEndIP"), self.__parser.getConfigurationParameter( "createVirtualNetworkAsRoot")) self.__domainHandler.doInitialCleanup() self.__deleteTemporaryZipFiles() self.__fileTransferThread = FileTransferThread( self.__networkManager, self.__listenningPort, self.__packetManager, self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("FTPTimeout"), self.__parser.getConfigurationParameter("MaxTransferAttempts"), self.__commandsDBConnector, self.__useSSL) self.__compressionThread = CompressionThread( self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("configFilePath"), self.__commandsDBConnector, self.__domainHandler, self.__networkManager, self.__listenningPort, self.__packetManager) self.__fileTransferThread.start() self.__compressionThread.start() self.__networkManager.listenIn(self.__listenningPort, self, self.__useSSL)
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, DummyCallback()) print("The server is now ready") sleep(200) networkManager.stopNetworkService()
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)
Prueba 'Puente': Un cliente se conecta al servidor por el puerto 8080. Otro cliente se conecta a este mismo servidor por el puerto 8081. El primer cliente envia un paquete al servidor, este lo recibe y redirecciona su contenido al segundo cliente. Trascurrido 20 segundos el proceso se repite en sentido contrario Para llevar a cabo la prueba será necesario ejecutar: 1. ejecutar el serverWridge y esperar a que se informe de que la conexión está disponible 2. Ejecutar el clientReceptor. 3. Inmediatamente después ejecutar clientEmisor. Módulos necesarios: -serverWridge,clientEmisor,clientReceptor """ from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager() networkManager.startNetworkService() networkManager.connectTo("127.0.0.1", 8081, 20, DummyCallback()) sleep(20) p = networkManager.createPacket(0) p.writeString("Hello Client 1!") networkManager.sendPacket("127.0.0.1", 8081, p) sleep(100) networkManager.stopNetworkService()
# -*- coding: utf8 -*- ''' Test que simula un chat entre un cliente y un servidor Este test se ejecuta junto al módulo clientConversational y requiere del módulo ConvCallback ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__": listP = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, ConvCallback(listP)) print("The server is now ready") ans = "" while ans != "bye": #esperamos una respuesta while (len(listP) == 0): sleep(0.1) # Extraemos la contestacion ans = listP.pop() print("<<" + ans) if ans != "bye": p = networkManager.createPacket(0) print(">>") ans = raw_input() p.writeString(ans)
# -*- coding: utf8 -*- ''' Test que simula un chat entre un cliente y un servidor Este test se ejecuta junto al módulo serverConversational y requiere del módulo ConvCallback ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__": listP = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.connectTo('127.0.0.1', 8080, 20, ConvCallback(listP)) while not networkManager.isConnectionReady('127.0.0.1', 8080): sleep(0.1) #Creamos el string gordo ans = "" while ans != "bye": p = networkManager.createPacket(0) print(">>") ans = raw_input() p.writeString(ans) #enviamos el mensaje networkManager.sendPacket('127.0.0.1', 8080, p) #esperamos una respuesta while (len(listP) == 0): sleep(0.1) #Extraemos la contestación print("<<" + listP.pop())
''' Test que comprueba si el servidor es capaz de recibir un paquete con un String de 15000 caracteres. Testeado con server 03 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager() networkManager.startNetworkService() networkManager.connectTo('127.0.0.1', 8080, 20, DummyCallback()) p = networkManager.createPacket(0) #Creamos el string gordo bigS = "" for i in range(15000): bigS += 's' p.writeString(bigS) networkManager.sendPacket('127.0.0.1', 8080, p) sleep(100) networkManager.stopNetworkService()
class WebServerEndpoint(object): """ These objects communicate a cluster server and the web connectors. """ def __init__(self): """ Initializes the endpoint's state Args: None """ self.__stopped = False def connectToDatabases(self, mysqlRootsPassword, statusDBName, commandsDBName, statusdbSQLFilePath, commandsDBSQLFilePath, websiteUser, websiteUserPassword, endpointUser, endpointUserPassword): """ Establishes a connection with the system status database. Args: mysqlRootsPassword: MySQL root's password statusDBName: the status database name statusdbSQLFilePath: the database schema definition SQL file path websiteUser: the website user's name. websiteUserPassword: the website user's password endpointUser: the update user's name. This user will have ALL privileges on the status database. endpointUserPassword: the update user's password. """ # Create the status database self.__rootsPassword = mysqlRootsPassword self.__statusDatabaseName = statusDBName self.__commandsDatabaseName = commandsDBName configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(statusDBName, statusdbSQLFilePath) configurator.runSQLScript(commandsDBName, commandsDBSQLFilePath) # Register the website and the endpoint users configurator.addUser(websiteUser, websiteUserPassword, statusDBName, False) configurator.addUser(endpointUser, endpointUserPassword, statusDBName, True) configurator.addUser(websiteUser, websiteUserPassword, commandsDBName, True) configurator.addUser(endpointUser, endpointUserPassword, commandsDBName, True) # Create the database connectors self.__commandsDBConnector = CommandsDatabaseConnector( endpointUser, endpointUserPassword, commandsDBName, 1) self.__writer = SystemStatusDatabaseWriter(endpointUser, endpointUserPassword, statusDBName) # Connect to the database self.__writer.connect() self.__commandsDBConnector.connect() def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval): """ Establishes a connection with the cluster server. Args: certificatePath: the server.crt and server.key directory path. clusterServerIP: the cluster server's IPv4 address clusterServerListenningPort: the cluster server's listenning port. statusDBUpdateInterval: the status database update interval (in seconds) Returns: Nothing """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Connect to the main server self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady( clusterServerIP, clusterServerListenningPort)): sleep(0.1) # Create the packet handler self.__pHandler = ClusterServerPacketHandler(self.__manager) # Create the update thread self.__updateRequestThread = StatusDatabaseUpdateThread( _ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) # Start it self.__updateRequestThread.start() def disconnectFromClusterServer(self): """ Closes the connection with the cluster server and drops the databases. Args: haltVMServers: if True, the virtual machine servers will be halted immediately. If false, they will be halted until all their virtual machines have been shut down. Returns: Nothing @attention: DO NOT call this method inside a network thread (i.e. inside the web callback). If you do so, your application will hang. """ # Send a halt packet to the cluster server p = self.__pHandler.createHaltPacket(self.__haltVMServers) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) # Stop the update request thread self.__updateRequestThread.stop() # Close the database connections self.__commandsDBConnector.disconnect() self.__writer.disconnect() # Stop the network service self.__manager.stopNetworkService() # Delete the status database dbConfigurator = DBConfigurator(self.__rootsPassword) dbConfigurator.dropDatabase(self.__statusDatabaseName) dbConfigurator.dropDatabase(self.__commandsDatabaseName) def _processIncomingPacket(self, packet): """ Processes an incoming package (sent from the cluster server). Args: packet: the packet to process Returns: Nothing """ if (self.__stopped): return data = self.__pHandler.readPacket(packet) if (data["packet_type"] == PACKET_T.VM_SERVERS_STATUS_DATA): self.__writer.processVMServerSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.VM_DISTRIBUTION_DATA): self.__writer.processVMDistributionSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.ACTIVE_VM_DATA): self.__writer.processActiveVMSegment(data["Segment"], data["SequenceSize"], data["VMServerIP"], data["Data"]) else: l = data["CommandID"].split("|") commandID = (int(l[0]), float(l[1])) if (data["packet_type"] == PACKET_T.COMMAND_EXECUTED): self.__commandsDBConnector.removeExecutedCommand(commandID) else: # Command outputs => serialize and add them to the commands database if (data["packet_type"] == PACKET_T.VM_SERVER_BOOTUP_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_UNREGISTRATION_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_SHUTDOWN_ERROR): (outputType, outputContent ) = CommandsHandler.createVMServerGenericErrorOutput( data["packet_type"], data["ServerNameOrIPAddress"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_SERVER_REGISTRATION_ERROR): (outputType, outputContent ) = CommandsHandler.createVMServerRegistrationErrorOutput( data["VMServerIP"], data["VMServerPort"], data["VMServerName"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_BOOT_FAILURE): (outputType, outputContent ) = CommandsHandler.createVMBootFailureErrorOutput( data["VMID"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_CONNECTION_DATA): (outputType, outputContent ) = CommandsHandler.createVMConnectionDataOutput( data["VNCServerIPAddress"], data["VNCServerPort"], data["VNCServerPassword"]) self.__commandsDBConnector.addCommandOutput( commandID, outputType, outputContent) def processCommands(self): """ Processes the commands sent from the web connectors. Args: None Returns: Nothing @attention: This method will only finish after processing a halt command. """ while not self.__stopped: commandData = self.__commandsDBConnector.popCommand() if (commandData == None): sleep(0.1) else: (commandID, commandType, commandArgs) = commandData parsedArgs = CommandsHandler.deserializeCommandArgs( commandType, commandArgs) if (commandType != COMMAND_TYPE.HALT): serializedCommandID = "{0}|{1}".format( commandID[0], commandID[1]) if (commandType == COMMAND_TYPE.BOOTUP_VM_SERVER): packet = self.__pHandler.createVMServerBootUpPacket( parsedArgs["VMServerNameOrIP"], serializedCommandID) elif (commandType == COMMAND_TYPE.REGISTER_VM_SERVER): packet = self.__pHandler.createVMServerRegistrationPacket( parsedArgs["VMServerIP"], parsedArgs["VMServerPort"], parsedArgs["VMServerName"], serializedCommandID) elif (commandType == COMMAND_TYPE.UNREGISTER_OR_SHUTDOWN_VM_SERVER): packet = self.__pHandler.createVMServerUnregistrationOrShutdownPacket( parsedArgs["VMServerNameOrIP"], parsedArgs["Halt"], parsedArgs["Unregister"], serializedCommandID) elif (commandType == COMMAND_TYPE.VM_BOOT_REQUEST): packet = self.__pHandler.createVMBootRequestPacket( parsedArgs["VMID"], parsedArgs["UserID"], serializedCommandID) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, packet) else: self.__stopped = True self.__haltVMServers = parsedArgs["HaltVMServers"] def _sendUpdateRequestPackets(self): """ Sends the update request packets to the cluster server. Args: None Returns: Nothing """ if (self.__stopped): return # Send some update request packets to the cluster server p = self.__pHandler.createDataRequestPacket( PACKET_T.QUERY_VM_SERVERS_STATUS) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) p = self.__pHandler.createDataRequestPacket( PACKET_T.QUERY_VM_DISTRIBUTION) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) p = self.__pHandler.createDataRequestPacket( PACKET_T.QUERY_ACTIVE_VM_DATA) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p)
# -*- coding: utf8 -*- ''' Test que simula un chat entre un cliente y un servidor Este test se ejecuta junto al módulo serverConversational y requiere del módulo ConvCallback ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__" : listP = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.connectTo('127.0.0.1', 8080, 20, ConvCallback(listP)) while not networkManager.isConnectionReady('127.0.0.1', 8080): sleep(0.1) #Creamos el string gordo ans = "" while ans != "bye": p = networkManager.createPacket(0) print(">>") ans = raw_input() p.writeString(ans) #enviamos el mensaje networkManager.sendPacket('127.0.0.1', 8080, p) #esperamos una respuesta while(len(listP) == 0): sleep(0.1) #Extraemos la contestación print("<<" + listP.pop())
class WebServerEndpoint(object): """ These objects communicate a cluster server and the web connectors. """ def __init__(self): """ Initializes the endpoint's state Args: None """ self.__stopped = False def connectToDatabases(self, mysqlRootsPassword, statusDBName, commandsDBName, statusdbSQLFilePath, commandsDBSQLFilePath, websiteUser, websiteUserPassword, endpointUser, endpointUserPassword): """ Establishes a connection with the system status database. Args: mysqlRootsPassword: MySQL root's password statusDBName: the status database name statusdbSQLFilePath: the database schema definition SQL file path websiteUser: the website user's name. websiteUserPassword: the website user's password endpointUser: the update user's name. This user will have ALL privileges on the status database. endpointUserPassword: the update user's password. """ # Create the status database self.__rootsPassword = mysqlRootsPassword self.__statusDatabaseName = statusDBName self.__commandsDatabaseName = commandsDBName configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(statusDBName, statusdbSQLFilePath) configurator.runSQLScript(commandsDBName, commandsDBSQLFilePath) # Register the website and the endpoint users configurator.addUser(websiteUser, websiteUserPassword, statusDBName, False) configurator.addUser(endpointUser, endpointUserPassword, statusDBName, True) configurator.addUser(websiteUser, websiteUserPassword, commandsDBName, True) configurator.addUser(endpointUser, endpointUserPassword, commandsDBName, True) # Create the database connectors self.__commandsDBConnector = CommandsDatabaseConnector(endpointUser, endpointUserPassword, commandsDBName, 1) self.__writer = SystemStatusDatabaseWriter(endpointUser, endpointUserPassword, statusDBName) # Connect to the database self.__writer.connect() self.__commandsDBConnector.connect() def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval): """ Establishes a connection with the cluster server. Args: certificatePath: the server.crt and server.key directory path. clusterServerIP: the cluster server's IPv4 address clusterServerListenningPort: the cluster server's listenning port. statusDBUpdateInterval: the status database update interval (in seconds) Returns: Nothing """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Connect to the main server self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady(clusterServerIP, clusterServerListenningPort)) : sleep(0.1) # Create the packet handler self.__pHandler = ClusterServerPacketHandler(self.__manager) # Create the update thread self.__updateRequestThread = StatusDatabaseUpdateThread(_ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) # Start it self.__updateRequestThread.start() def disconnectFromClusterServer(self): """ Closes the connection with the cluster server and drops the databases. Args: haltVMServers: if True, the virtual machine servers will be halted immediately. If false, they will be halted until all their virtual machines have been shut down. Returns: Nothing @attention: DO NOT call this method inside a network thread (i.e. inside the web callback). If you do so, your application will hang. """ # Send a halt packet to the cluster server p = self.__pHandler.createHaltPacket(self.__haltVMServers) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) # Stop the update request thread self.__updateRequestThread.stop() # Close the database connections self.__commandsDBConnector.disconnect() self.__writer.disconnect() # Stop the network service self.__manager.stopNetworkService() # Delete the status database dbConfigurator = DBConfigurator(self.__rootsPassword) dbConfigurator.dropDatabase(self.__statusDatabaseName) dbConfigurator.dropDatabase(self.__commandsDatabaseName) def _processIncomingPacket(self, packet): """ Processes an incoming package (sent from the cluster server). Args: packet: the packet to process Returns: Nothing """ if (self.__stopped) : return data = self.__pHandler.readPacket(packet) if (data["packet_type"] == PACKET_T.VM_SERVERS_STATUS_DATA) : self.__writer.processVMServerSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.VM_DISTRIBUTION_DATA) : self.__writer.processVMDistributionSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.ACTIVE_VM_DATA) : self.__writer.processActiveVMSegment(data["Segment"], data["SequenceSize"], data["VMServerIP"], data["Data"]) else : l = data["CommandID"].split("|") commandID = (int(l[0]), float(l[1])) if (data["packet_type"] == PACKET_T.COMMAND_EXECUTED) : self.__commandsDBConnector.removeExecutedCommand(commandID) else : # Command outputs => serialize and add them to the commands database if (data["packet_type"] == PACKET_T.VM_SERVER_BOOTUP_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_UNREGISTRATION_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_SHUTDOWN_ERROR) : (outputType, outputContent) = CommandsHandler.createVMServerGenericErrorOutput( data["packet_type"], data["ServerNameOrIPAddress"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_SERVER_REGISTRATION_ERROR) : (outputType, outputContent) = CommandsHandler.createVMServerRegistrationErrorOutput( data["VMServerIP"], data["VMServerPort"], data["VMServerName"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_BOOT_FAILURE) : (outputType, outputContent) = CommandsHandler.createVMBootFailureErrorOutput( data["VMID"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_CONNECTION_DATA) : (outputType, outputContent) = CommandsHandler.createVMConnectionDataOutput( data["VNCServerIPAddress"], data["VNCServerPort"], data["VNCServerPassword"]) self.__commandsDBConnector.addCommandOutput(commandID, outputType, outputContent) def processCommands(self): """ Processes the commands sent from the web connectors. Args: None Returns: Nothing @attention: This method will only finish after processing a halt command. """ while not self.__stopped : commandData = self.__commandsDBConnector.popCommand() if (commandData == None) : sleep(0.1) else : (commandID, commandType, commandArgs) = commandData parsedArgs = CommandsHandler.deserializeCommandArgs(commandType, commandArgs) if (commandType != COMMAND_TYPE.HALT) : serializedCommandID = "{0}|{1}".format(commandID[0], commandID[1]) if (commandType == COMMAND_TYPE.BOOTUP_VM_SERVER) : packet = self.__pHandler.createVMServerBootUpPacket(parsedArgs["VMServerNameOrIP"], serializedCommandID) elif (commandType == COMMAND_TYPE.REGISTER_VM_SERVER) : packet = self.__pHandler.createVMServerRegistrationPacket(parsedArgs["VMServerIP"], parsedArgs["VMServerPort"], parsedArgs["VMServerName"], serializedCommandID) elif (commandType == COMMAND_TYPE.UNREGISTER_OR_SHUTDOWN_VM_SERVER) : packet = self.__pHandler.createVMServerUnregistrationOrShutdownPacket(parsedArgs["VMServerNameOrIP"], parsedArgs["Halt"], parsedArgs["Unregister"], serializedCommandID) elif (commandType == COMMAND_TYPE.VM_BOOT_REQUEST) : packet = self.__pHandler.createVMBootRequestPacket(parsedArgs["VMID"], parsedArgs["UserID"], serializedCommandID) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, packet) else : self.__stopped = True self.__haltVMServers = parsedArgs["HaltVMServers"] def _sendUpdateRequestPackets(self): """ Sends the update request packets to the cluster server. Args: None Returns: Nothing """ if (self.__stopped) : return # Send some update request packets to the cluster server p = self.__pHandler.createDataRequestPacket(PACKET_T.QUERY_VM_SERVERS_STATUS) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) p = self.__pHandler.createDataRequestPacket(PACKET_T.QUERY_VM_DISTRIBUTION) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) p = self.__pHandler.createDataRequestPacket(PACKET_T.QUERY_ACTIVE_VM_DATA) self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p)
# -*- coding: utf8 -*- ''' Test que simula un chat entre un cliente y un servidor Este test se ejecuta junto al módulo clientConversational y requiere del módulo ConvCallback ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__" : listP = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, ConvCallback(listP)) print("The server is now ready") ans = "" while ans != "bye": #esperamos una respuesta while(len(listP) == 0): sleep(0.1) # Extraemos la contestacion ans = listP.pop() print("<<" + ans) if ans != "bye" : p = networkManager.createPacket(0) print(">>") ans = raw_input() p.writeString(ans)
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() print "Creating server..." networkManager.listenIn(8080, DummyCallback(), True) print "The server is now ready" sleep(200) networkManager.stopNetworkService()
Test que comprueba si el servidor es capaz de recibir los paquetes enviados desde varios clientes. Para realizarse la prueba debe ejecutarse este módulo el número de clientes que se desee Testeado con server 03 ''' import time from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": # Fase 1 :Creamos y conectamos a los clientes #Cliente 1 client1 = NetworkManager() client1.startNetworkService() client1.connectTo('127.0.0.1', 8080, 20, DummyCallback()) while (not client1.isConnectionReady('127.0.0.1', 8080)): sleep(0.1) #Fase 2: Cada cliente envia su paquete #Cliente 1 p1 = client1.createPacket(0) p1.writeString("I am Client " + str(time.localtime()[3]) + ":" + str(time.localtime()[4]) + ":" + str(time.localtime()[5])) client1.sendPacket('127.0.0.1', 8080, p1) #Fase 3: Esperamos y cerramos las conexiones sleep(200) #Cliente 1
class ClusterServerMainReactor(object): ''' This class is associated with the cluster server main reactor. ''' def __init__(self, loadBalancerSettings, averageCompressionRatio, timeout): """ Initializes the reactor's state Args: loadBalancerSettings: a list containing the load balancing algorithm settings averageCompressionRation: the compression algorithm's average compression ratio timeout: the virtual machine boot commands timeout """ self.__exit = False self.__loadBalancerSettings = loadBalancerSettings self.__averageCompressionRatio = averageCompressionRatio self.__timeout = timeout self.__statusMonitoringThread = None def connectToDatabase(self, mysqlRootsPassword, dbName, dbUser, dbPassword, scriptPath): """ Establishes a connection with the cluster server database Args: mysqlRootsPassword: the MySQL root user's password dbName: a database name dbUser: a MySQL user name dbPassword: the user's password scriptPath: the schema definition script Returns: Nothing """ configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(dbName, scriptPath, "root", mysqlRootsPassword) configurator.addUser(dbUser, dbPassword, dbName, True) self.__dbConnector = ClusterServerDatabaseConnector(dbUser, dbPassword, dbName) self.__dbConnector.initializeVMServersStatus() def startListenning(self, useSSL, certificatePath, listenningPort, repositoryIP, repositoryPort, vmServerStatusUpdateInterval): """ Creates the control connection Args: useSSL: indicates if SSL encryption must be used in the control connection or not certificatePath: the directory where the server.crt and server.key files are listenningPort: the control connection's port repositoryIP: the image repository IP address repositoryPort: the image repository's port vmServerStatusUpdateInterval: the virtual machine server status database interval Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__listenningPort = listenningPort self.__packetHandler = ClusterServerPacketHandler(self.__networkManager) self.__useSSL = useSSL imageRepositoryPacketHandler = ImageRepositoryPacketHandler(self.__networkManager) vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) networkEventsReactor = NetworkEventsReactor(self.__dbConnector, repositoryIP, repositoryPort) imageRepositoryPacketReactor = ImageRepositoryPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, repositoryIP, repositoryPort, self.__packetHandler, vmServerPacketHandler, imageRepositoryPacketHandler) try : imageRepositoryCallback = ImageRepositoryCallback(imageRepositoryPacketReactor, networkEventsReactor) self.__networkManager.connectTo(repositoryIP, repositoryPort, 10, imageRepositoryCallback, self.__useSSL, True) self.__dbConnector.addImageRepository(repositoryIP, repositoryPort, SERVER_STATE_T.READY) except Exception as e: print "Can't connect to the image repository: " + e.message self.__exit = True return vmServerPacketReactor = VMServerPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, vmServerPacketHandler, self.__packetHandler) self.__endpointPacketReactor = EndpointPacketReactor(self.__dbConnector, self.__networkManager, vmServerPacketHandler, self.__packetHandler, imageRepositoryPacketHandler, VMServerCallback(vmServerPacketReactor, networkEventsReactor), listenningPort, repositoryIP, repositoryPort, self.__loadBalancerSettings, self.__averageCompressionRatio, self.__useSSL) clusterEndpointCallback = ClusterEndpointCallback(self.__endpointPacketReactor) self.__networkManager.listenIn(listenningPort, clusterEndpointCallback, self.__useSSL) self.__statusMonitoringThread = ClusterStatusMonitoringThread(vmServerStatusUpdateInterval, self.__dbConnector, self.__networkManager, repositoryIP, repositoryPort, vmServerPacketHandler, imageRepositoryPacketHandler) self.__statusMonitoringThread.start() def monitorVMBootCommands(self): """ Deletes the timed out virtual machine boot commands Args: None Returns: Nothing """ while not self.__exit and not self.__endpointPacketReactor.hasFinished(): data = self.__dbConnector.getOldVMBootCommandID(self.__timeout) if (data == None) : sleep(1) else : self.__dbConnector.deleteActiveVMLocation(data[0]) p = self.__packetHandler.createErrorPacket(CLUSTER_SERVER_PACKET_T.VM_BOOT_FAILURE, ERROR_DESC_T.CLSRVR_VM_BOOT_TIMEOUT, data[0]) self.__networkManager.sendPacket('', self.__listenningPort, p) def closeNetworkConnections(self): """ Closes the control connection Args: None Returns: Nothing """ if (self.__statusMonitoringThread != None) : self.__statusMonitoringThread.stop() self.__networkManager.stopNetworkService()
Test que comprueba si el servidor es capaz de recibir los paquetes enviados desde varios clientes. Para realizarse la prueba debe ejecutarse este módulo el número de clientes que se desee Testeado con server 03 ''' import time from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : # Fase 1 :Creamos y conectamos a los clientes #Cliente 1 client1 = NetworkManager() client1.startNetworkService() client1.connectTo('127.0.0.1', 8080, 20, DummyCallback()) while(not client1.isConnectionReady('127.0.0.1', 8080)): sleep(0.1) #Fase 2: Cada cliente envia su paquete #Cliente 1 p1 = client1.createPacket(0) p1.writeString("I am Client " + str(time.localtime()[3]) + ":" + str(time.localtime()[4]) + ":" + str(time.localtime()[5])) client1.sendPacket('127.0.0.1', 8080, p1) #Fase 3: Esperamos y cerramos las conexiones sleep(200) #Cliente 1
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() print "Creating server..." networkManager.listenIn(8080, DummyCallback(), True) print "The server is now ready" sleep(20) p = networkManager.createPacket(1) p.writeString("***") networkManager.sendPacket('', 8080, p) sleep(10) networkManager.stopNetworkService()
print("\thelp: prints the following help message") print("\tquit: closes this application") except Exception as e : print("Error: " + e.message) if __name__ == "__main__" : print('*' * 80) print('*' * 80) printLogo() print('Virtual Machine Server tester') print('Version 8.0') print('*' * 80) print('*' * 80) print() networkManager = NetworkManager(".") networkManager.startNetworkService() pHandler = VMServerPacketHandler(networkManager) ip_address = raw_input("VM Server IP address: ") port = raw_input("VM Server control connection port: ") try : port = int(port) networkManager.connectTo(ip_address, port, 10, TesterCallback(pHandler), True) while not networkManager.isConnectionReady(ip_address, port) : sleep(0.1) end = False while not end : command = raw_input('> ') tokens = command.split() end = process_command(tokens, networkManager, pHandler, ip_address, port)
class ClusterServerReactor(WebPacketReactor, VMServerPacketReactor): ''' These objects react to packages received from the website or from a virtual machine server. ''' def __init__(self, timeout): """ Initializes the reactor's state. Args: None """ self.__webCallback = WebCallback(self) self.__finished = False self.__timeout = timeout def connectToDatabase(self, mysqlRootsPassword, dbName, dbUser, dbPassword, scriptPath): """ Establishes a connection with the cluster server database. Args: mysqlRootsPassword: MySQL root's password dbName: the cluster server database's name dbUser: the cluster server database's user name dbPassword: the cluster server database's user password scriptPath: the cluster server database's initialization script path """ configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(dbName, scriptPath) configurator.addUser(dbUser, dbPassword, dbName, True) self.__dbConnector = ClusterServerDatabaseConnector( dbUser, dbPassword, dbName) self.__dbConnector.connect() self.__dbConnector.resetVMServersStatus() def startListenning(self, certificatePath, port): """ Starts the network service and creates a server connection. Args: certificatePath: the server.crt and server.key files path port: the listenning port Returns: Nothing """ self.__loadBalancer = SimpleLoadBalancer(self.__dbConnector) self.__networkManager = NetworkManager(certificatePath) self.__webPort = port self.__networkManager.startNetworkService() self.__webPacketHandler = ClusterServerPacketHandler( self.__networkManager) self.__vmServerPacketHandler = VMServerPacketHandler( self.__networkManager) self.__networkManager.listenIn(port, self.__webCallback, True) self.__vmServerCallback = VMServerCallback(self) def processWebIncomingPacket(self, packet): """ Processes a packet received from the web server. Args: packet: the packet to process Returns: Nothing """ data = self.__webPacketHandler.readPacket(packet) if (data["packet_type"] == WEB_PACKET_T.REGISTER_VM_SERVER): self.__registerVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.QUERY_VM_SERVERS_STATUS): self.__sendVMServerStatusData() elif (data["packet_type"] == WEB_PACKET_T.UNREGISTER_OR_SHUTDOWN_VM_SERVER): self.__unregisterOrShutdownVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.BOOTUP_VM_SERVER): self.__bootUpVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.VM_BOOT_REQUEST): self.__bootUpVM(data) elif (data["packet_type"] == WEB_PACKET_T.HALT): self.__halt(data) elif (data["packet_type"] == WEB_PACKET_T.QUERY_VM_DISTRIBUTION): self.__sendVMDistributionData() elif (data["packet_type"] == WEB_PACKET_T.QUERY_ACTIVE_VM_DATA): self.__requestVNCConnectionData() def __requestVNCConnectionData(self): """ Sends a VNC connection data request packet to all the active virtual machine servers Args: None Returns: Nothing """ # Create a VNC connection data packet p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.QUERY_ACTIVE_VM_DATA) # Fetch the active virtual machine server's IP addresses and ports connectionData = self.__dbConnector.getActiveVMServersConnectionData() for cd in connectionData: self.__networkManager.sendPacket(cd["ServerIP"], cd["ServerPort"], p) def __halt(self, data): """ Shuts down the cluster (including the virtual machine servers). Args: haltVMServers: if True, all the active virtual machines will be destroyed and the virtual machine servers will be shut down. If false, the virtual machine servers will wait until there are no active virtual machines, and then they'll be shut down. """ vmServersConnectionData = self.__dbConnector.getActiveVMServersConnectionData( ) if (vmServersConnectionData != None): args = dict() args["Halt"] = data["HaltVMServers"] args["Unregister"] = False for connectionData in vmServersConnectionData: args["ServerNameOrIPAddress"] = connectionData["ServerIP"] self.__unregisterOrShutdownVMServer(args) self.__finished = True def __registerVMServer(self, data): """ Processes a virtual machine server registration packet. Args: data: the received virtual machine server registration packet. Returns: Nothing """ try: # Check if the IP address is assigned to another virtual machine server server_id = self.__dbConnector.getVMServerID(data["VMServerIP"]) if (server_id != None): raise Exception("The IP address " + data["VMServerIP"] + " is assigned to another VM server") # Check if the name is assigned to another virtual machine server server_id = self.__dbConnector.getVMServerID(data["VMServerName"]) if (server_id != None): raise Exception("The name " + data["VMServerName"] + " is assigned to another VM server") # Establish a connection self.__networkManager.connectTo(data["VMServerIP"], data["VMServerPort"], 20, self.__vmServerCallback, True, True) while not self.__networkManager.isConnectionReady( data["VMServerIP"], data["VMServerPort"]): sleep(0.1) # Register the server on the database self.__dbConnector.registerVMServer(data["VMServerName"], data["VMServerIP"], data["VMServerPort"]) # Command the virtual machine server to tell us its state p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) self.__networkManager.sendPacket(data["VMServerIP"], data["VMServerPort"], p) # Everything went fine p = self.__webPacketHandler.createCommandExecutedPacket( data["CommandID"]) except Exception as e: p = self.__webPacketHandler.createVMServerRegistrationErrorPacket( data["VMServerIP"], data["VMServerPort"], data["VMServerName"], str(e), data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def __unregisterOrShutdownVMServer(self, data): """ Processes a virtual machine server unregistration or shutdown packet. Args: key: the virtual machine server's IPv4 address or its name. halt: if True, the virtual machine server will be shut down immediately. If false, it'll wait until all the virtual machines are shut down, and then it will finally be shut down. unregister: if True, the virtual machine server will be deleted from the cluster server's database. """ key = data["ServerNameOrIPAddress"] halt = data["Halt"] unregister = data["Unregister"] if data.has_key("CommandID"): useCommandID = True commandID = data["CommandID"] else: useCommandID = False # Shut down the server (if necessary) serverId = self.__dbConnector.getVMServerID(key) if (serverId != None): serverData = self.__dbConnector.getVMServerBasicData(serverId) status = serverData["ServerStatus"] if (status == SERVER_STATE_T.READY or status == SERVER_STATE_T.BOOTING): if not halt: p = self.__vmServerPacketHandler.createVMServerShutdownPacket( ) else: p = self.__vmServerPacketHandler.createVMServerHaltPacket() self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Close the network connection self.__networkManager.closeConnection(serverData["ServerIP"], serverData["ServerPort"]) if (not unregister): self.__dbConnector.updateVMServerStatus( serverId, SERVER_STATE_T.SHUT_DOWN) self.__dbConnector.deleteVMServerStatistics(serverId) else: # Update the virtual machine server's state self.__dbConnector.deleteVMServer(key) if (useCommandID): # Create a command executed packet and send it to the website p = self.__webPacketHandler.createCommandExecutedPacket( commandID) self.__networkManager.sendPacket('', self.__webPort, p) else: # Error if (unregister): packet_type = WEB_PACKET_T.VM_SERVER_UNREGISTRATION_ERROR else: packet_type = WEB_PACKET_T.VM_SERVER_SHUTDOWN_ERROR errorMessage = "The virtual machine server with name or IP address <<{0}>> is not registered".format( key) p = self.__webPacketHandler.createVMServerGenericErrorPacket( packet_type, key, errorMessage, commandID) self.__networkManager.sendPacket('', self.__webPort, p) def __updateVMServerStatus(self, data): """ Processes a virtual machine server's status packet. Args: data: the received packet Returns: Nothing """ # Fetch the virtual machine server's ID serverID = None while (serverID == None): serverID = self.__dbConnector.getVMServerID(data["VMServerIP"]) if (serverID == None): sleep(0.1) # Change its status self.__dbConnector.updateVMServerStatus(serverID, SERVER_STATE_T.READY) self.__dbConnector.setVMServerStatistics(serverID, data["ActiveDomains"]) def __bootUpVMServer(self, data): """ Processes a virtual machine server boot packet. Args: serverNameOrIPAddress: the virtual machine server's name or IPv4 address. Returns: Nothing """ try: serverNameOrIPAddress = data["ServerNameOrIPAddress"] serverId = self.__dbConnector.getVMServerID(serverNameOrIPAddress) if (serverId == None): raise Exception("The virtual machine server is not registered") serverData = self.__dbConnector.getVMServerBasicData(serverId) # Connect to the virtual machine server self.__networkManager.connectTo(serverData["ServerIP"], serverData["ServerPort"], 20, self.__vmServerCallback, True, True) while not self.__networkManager.isConnectionReady( serverData["ServerIP"], serverData["ServerPort"]): sleep(0.1) # Change its status self.__dbConnector.updateVMServerStatus(serverId, SERVER_STATE_T.BOOTING) # Send the status request p = self.__vmServerPacketHandler.createVMServerDataRequestPacket( VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Everything went fine p = self.__webPacketHandler.createCommandExecutedPacket( data["CommandID"]) except Exception as e: p = self.__webPacketHandler.createVMServerGenericErrorPacket( WEB_PACKET_T.VM_SERVER_BOOTUP_ERROR, serverNameOrIPAddress, str(e), data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def __sendVMServerStatusData(self): """ Processes a virtual machine server data request packet. Args: None Returns: Nothing """ self.__sendStatusData( self.__dbConnector.getVMServerBasicData, self.__webPacketHandler.createVMServerStatusPacket) def __sendVMDistributionData(self): """ Processes a virtual machine distribution data packet Args: None Returns: Nothing """ self.__sendStatusData( self.__dbConnector.getHostedImages, self.__webPacketHandler.createVMDistributionPacket) def __sendStatusData(self, queryMethod, packetCreationMethod): """ Processes a data request packet. Args: queryMethod: the method that extracts the data from the database packetCreationMethod: the method that creates the packet Returns: Nothing """ segmentSize = 5 outgoingData = [] serverIDs = self.__dbConnector.getVMServerIDs() if (len(serverIDs) == 0): segmentCounter = 0 segmentNumber = 0 sendLastSegment = True else: segmentCounter = 1 segmentNumber = (len(serverIDs) / segmentSize) if (len(serverIDs) % segmentSize != 0): segmentNumber += 1 sendLastSegment = True else: sendLastSegment = False for serverID in serverIDs: row = queryMethod(serverID) if (isinstance(row, dict)): outgoingData.append(row) else: outgoingData += row if (len(outgoingData) >= segmentSize): # Flush packet = packetCreationMethod(segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__webPort, packet) outgoingData = [] segmentCounter += 1 # Send the last segment if (sendLastSegment): packet = packetCreationMethod(segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__webPort, packet) def __bootUpVM(self, data): """ Processes a virtual machine boot request packet. Args: vmName: the virtual machine's ID userID: the user's unique identifier Returns: Nothing """ vmID = data["VMID"] userID = data["UserID"] # Choose the virtual machine server that will host the image (serverID, errorMessage) = self.__loadBalancer.assignVMServer(vmID) if (errorMessage != None): # Something went wrong => warn the user p = self.__webPacketHandler.createVMBootFailurePacket( vmID, errorMessage, data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) else: # Ask the virtual machine server to boot up the VM p = self.__vmServerPacketHandler.createVMBootPacket( vmID, userID, data["CommandID"]) serverData = self.__dbConnector.getVMServerBasicData(serverID) self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Register the boot command self.__dbConnector.registerVMBootCommand(data["CommandID"], data["VMID"]) # Everything went fine #p = self.__webPacketHandler.createCommandExecutedPacket(data["CommandID"]) #self.__networkManager.sendPacket('', self.__webPort, p) def processVMServerIncomingPacket(self, packet): """ Processes a packet sent from a virtual machine server. Args: packet: the packet to process Returns: Nothing """ data = self.__vmServerPacketHandler.readPacket(packet) if (data["packet_type"] == VMSRVR_PACKET_T.SERVER_STATUS): self.__updateVMServerStatus(data) elif (data["packet_type"] == VMSRVR_PACKET_T.DOMAIN_CONNECTION_DATA): self.__sendVMConnectionData(data) elif (data["packet_type"] == VMSRVR_PACKET_T.ACTIVE_VM_DATA): self.__sendVNCConnectionData(packet) def processServerReconnectionData(self, ipAddress, reconnection_status): """ Processes a reconnection status event Args: ipAddress: the connection's IPv4 address port: the connection's port reconnection_status: the reconnection process' status Returns: Nothing """ if (reconnection_status == RECONNECTION_T.RECONNECTING): status = SERVER_STATE_T.RECONNECTING elif (reconnection_status == RECONNECTION_T.REESTABLISHED): status = SERVER_STATE_T.READY else: status = SERVER_STATE_T.CONNECTION_TIMED_OUT serverID = self.__dbConnector.getVMServerID(ipAddress) self.__dbConnector.updateVMServerStatus(serverID, status) def __sendVNCConnectionData(self, packet): """ Processes a VNC connection data packet Args: packet: the packet to process Returns: Nothing """ p = self.__webPacketHandler.createActiveVMsDataPacket(packet) self.__networkManager.sendPacket('', self.__webPort, p) def __sendVMConnectionData(self, data): """ Processes a virtual machine connection data packet. Args: data: the packet to process' data. Returns: Nothing """ # Delete the boot command from the database self.__dbConnector.removeVMBootCommand(data["CommandID"]) p = self.__webPacketHandler.createVMConnectionDataPacket( data["VNCServerIP"], data["VNCServerPort"], data["VNCServerPassword"], data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def monitorVMBootCommands(self): errorMessage = "Could not boot up virtual machine (timeout error)" while not self.__finished: data = self.__dbConnector.getOldVMBootCommandID(self.__timeout) if (not self.__finished and data == None): # Be careful with this: if MySQL server receives too many queries per second, # the reactor's database connection will be closed. sleep(1) else: # Create a virtual machine boot error packet p = self.__webPacketHandler.createVMBootFailurePacket( data[1], errorMessage, data[0]) self.__networkManager.sendPacket('', self.__webPort, p) def hasFinished(self): """ Indicates if the cluster server has finished or not. """ return self.__finished def shutdown(self): """ Shuts down the cluster server. Args: None Returns: Nothing @attention: this method MUST NOT be called from a network thread. If you do so, the application will hang! """ self.__networkManager.stopNetworkService()
# -*- coding: utf8 -*- """ A simple server test @author: Luis Barrios Hernández @version: 1.0 """ from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() print "Creating server..." networkManager.listenIn(8080, DummyCallback(), True) networkManager.listenIn(8081, DummyCallback(), True) print "The server is now ready" sleep(30) print networkManager.isConnectionReady("", 8080) p = networkManager.createPacket(10) p.writeString("Hello, Client!") networkManager.sendPacket("", 8080, p) p = networkManager.createPacket(10) sleep(10) p.writeString("Hello, Client 1!") networkManager.sendPacket("", 8081, p) print "Packet sent from server" networkManager.stopNetworkService()
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() print "Creating server..." networkManager.listenIn(8080, DummyCallback(), True) networkManager.listenIn(8081, DummyCallback(), True) print "The server is now ready" sleep(30) print networkManager.isConnectionReady('', 8080) p = networkManager.createPacket(10) p.writeString("Hello, Client!") networkManager.sendPacket('', 8080, p) p = networkManager.createPacket(10) sleep(10) p.writeString("Hello, Client 1!") networkManager.sendPacket('', 8081, p) print "Packet sent from server" networkManager.stopNetworkService()
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() print "Creating server..." networkManager.listenIn(8080, DummyCallback(), True) print "The server is now ready" sleep(20) p = networkManager.createPacket(1) p.writeString("***") networkManager.sendPacket('', 8080, p) sleep(10) networkManager.stopNetworkService()
class ClusterServerMainReactor(object): ''' This class is associated with the cluster server main reactor. ''' def __init__(self, loadBalancerSettings, averageCompressionRatio, timeout): """ Initializes the reactor's state Args: loadBalancerSettings: a list containing the load balancing algorithm settings averageCompressionRation: the compression algorithm's average compression ratio timeout: the virtual machine boot commands timeout """ self.__exit = False self.__loadBalancerSettings = loadBalancerSettings self.__averageCompressionRatio = averageCompressionRatio self.__timeout = timeout self.__statusMonitoringThread = None def connectToDatabase(self, mysqlRootsPassword, dbName, dbUser, dbPassword, scriptPath): """ Establishes a connection with the cluster server database Args: mysqlRootsPassword: the MySQL root user's password dbName: a database name dbUser: a MySQL user name dbPassword: the user's password scriptPath: the schema definition script Returns: Nothing """ configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(dbName, scriptPath, "root", mysqlRootsPassword) configurator.addUser(dbUser, dbPassword, dbName, True) self.__dbConnector = ClusterServerDatabaseConnector( dbUser, dbPassword, dbName) self.__dbConnector.initializeVMServersStatus() def startListenning(self, useSSL, certificatePath, listenningPort, repositoryIP, repositoryPort, vmServerStatusUpdateInterval): """ Creates the control connection Args: useSSL: indicates if SSL encryption must be used in the control connection or not certificatePath: the directory where the server.crt and server.key files are listenningPort: the control connection's port repositoryIP: the image repository IP address repositoryPort: the image repository's port vmServerStatusUpdateInterval: the virtual machine server status database interval Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__listenningPort = listenningPort self.__packetHandler = ClusterServerPacketHandler( self.__networkManager) self.__useSSL = useSSL imageRepositoryPacketHandler = ImageRepositoryPacketHandler( self.__networkManager) vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) networkEventsReactor = NetworkEventsReactor(self.__dbConnector, repositoryIP, repositoryPort) imageRepositoryPacketReactor = ImageRepositoryPacketReactor( self.__dbConnector, self.__networkManager, listenningPort, repositoryIP, repositoryPort, self.__packetHandler, vmServerPacketHandler, imageRepositoryPacketHandler) try: imageRepositoryCallback = ImageRepositoryCallback( imageRepositoryPacketReactor, networkEventsReactor) self.__networkManager.connectTo(repositoryIP, repositoryPort, 10, imageRepositoryCallback, self.__useSSL, True) self.__dbConnector.addImageRepository(repositoryIP, repositoryPort, SERVER_STATE_T.READY) except Exception as e: print "Can't connect to the image repository: " + e.message self.__exit = True return vmServerPacketReactor = VMServerPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, vmServerPacketHandler, self.__packetHandler) self.__endpointPacketReactor = EndpointPacketReactor( self.__dbConnector, self.__networkManager, vmServerPacketHandler, self.__packetHandler, imageRepositoryPacketHandler, VMServerCallback(vmServerPacketReactor, networkEventsReactor), listenningPort, repositoryIP, repositoryPort, self.__loadBalancerSettings, self.__averageCompressionRatio, self.__useSSL) clusterEndpointCallback = ClusterEndpointCallback( self.__endpointPacketReactor) self.__networkManager.listenIn(listenningPort, clusterEndpointCallback, self.__useSSL) self.__statusMonitoringThread = ClusterStatusMonitoringThread( vmServerStatusUpdateInterval, self.__dbConnector, self.__networkManager, repositoryIP, repositoryPort, vmServerPacketHandler, imageRepositoryPacketHandler) self.__statusMonitoringThread.start() def monitorVMBootCommands(self): """ Deletes the timed out virtual machine boot commands Args: None Returns: Nothing """ while not self.__exit and not self.__endpointPacketReactor.hasFinished( ): data = self.__dbConnector.getOldVMBootCommandID(self.__timeout) if (data == None): sleep(1) else: self.__dbConnector.deleteActiveVMLocation(data[0]) p = self.__packetHandler.createErrorPacket( CLUSTER_SERVER_PACKET_T.VM_BOOT_FAILURE, ERROR_DESC_T.CLSRVR_VM_BOOT_TIMEOUT, data[0]) self.__networkManager.sendPacket('', self.__listenningPort, p) def closeNetworkConnections(self): """ Closes the control connection Args: None Returns: Nothing """ if (self.__statusMonitoringThread != None): self.__statusMonitoringThread.stop() self.__networkManager.stopNetworkService()
1. ejecutar el serverWridge y esperar a que se informe de que la conexión está disponible 2. Ejecutar el clientReceptor. 3. Inmediatamente después ejecutar clientEmisor. Módulos necesarios: -serverWridge,clientEmisor,clientReceptor ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__": listP = [] listP1 = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, ConvCallback(listP)) networkManager.listenIn(8081, ConvCallback(listP1)) print("The server is now ready") #esperamos una respuesta while (len(listP) == 0): sleep(0.1) # Extraemos la contestacion ans = listP[0] #Se la enviamos al otro cliente p = networkManager.createPacket(0) p.writeString(ans) networkManager.sendPacket('', 8081, p) #Esperamos al de regreso while (len(listP1) == 0):
# -*- coding: utf8 -*- ''' A simple client test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : port = 8080 networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() networkManager.connectTo('127.0.0.1', port, 5, DummyCallback(), True) sleep(2) p = networkManager.createPacket(0) p.writeString("Greetings from a client") networkManager.sendPacket('127.0.0.1', port, p) p = networkManager.createPacket(0) p.writeString("Greetings from a client 1") networkManager.sendPacket('127.0.0.1', port, p) sleep(60) networkManager.stopNetworkService()
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 WebServerEndpoint(object): """ Estos objetos comunican un servidor de cluster con la web """ def __init__(self): """ Inicializa el estado del endpoint Argumentos: Ninguno """ self.__stopped = False def connectToDatabases(self, mysqlRootsPassword, statusDBName, commandsDBName, statusdbSQLFilePath, commandsDBSQLFilePath, websiteUser, websiteUserPassword, endpointUser, endpointUserPassword, minCommandInterval): """ Establece la conexión con la base de datos de estado y con la base de datos de comandos. Argumentos: mysqlRootsPassword: la contraseña de root de MySQL statusDBName: el nombre de la base de datos de estado statusdbSQLFilePath: la ruta del script que crea la base de datos de estado websiteUser: nombre de usuario que usará la web para manipular las bases de datos websiteUserPassword: contraseña del usuario de la web endpointUser: usuario que utilizará en eldpoint para manipular las bases de datos de estado. Será el único que puede escribir en la base de datos de estado. endpointUserPassword: contraseña del usuario del endpoint """ # Crear las bases de datos self.__rootsPassword = mysqlRootsPassword self.__statusDatabaseName = statusDBName self.__commandsDatabaseName = commandsDBName configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(statusDBName, statusdbSQLFilePath) configurator.runSQLScript(commandsDBName, commandsDBSQLFilePath) # Registrar en ellas los usuarios configurator.addUser(websiteUser, websiteUserPassword, statusDBName, False) configurator.addUser(endpointUser, endpointUserPassword, statusDBName, True) configurator.addUser(websiteUser, websiteUserPassword, commandsDBName, True) configurator.addUser(endpointUser, endpointUserPassword, commandsDBName, True) # Crear los conectores self.__commandsDBConnector = CommandsDatabaseConnector(endpointUser, endpointUserPassword, commandsDBName, minCommandInterval) self.__endpointDBConnector = ClusterEndpointDBConnector(endpointUser, endpointUserPassword, statusDBName) def connectToClusterServer(self, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establece la conexión con el servidor de cluster Argumentos: certificatePath: la ruta del directorio con los ficheros server.crt y server.key. clusterServerIP: la IP del servidor de cluster clusterServerListenningPort: el puerto en el que escucha el servidor de cluster statusDBUpdateInterval: el periodo de actualización de la base de datos (en segundos) Devuelve: Nada Lanza: EnpointException: se lanza cuando no se puede establecer una conexión con el servidor web """ self.__manager = NetworkManager(certificatePath) self.__manager.startNetworkService() callback = _ClusterServerEndpointCallback(self) # Establecer la conexión self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort try : self.__manager.connectTo(clusterServerIP, clusterServerListenningPort, 5, callback, True) while (not self.__manager.isConnectionReady(clusterServerIP, clusterServerListenningPort)) : sleep(0.1) # TODO: si esto falla, terminar. # Preparar la recepción de paquetes y la actualización automática de la base de datos de estado self.__repositoryPacketHandler = ClusterServerPacketHandler(self.__manager) self.__updateRequestThread = VMServerMonitoringThread(_ClusterServerEndpointUpdateHandler(self), statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandMonitoringThread = CommandMonitoringThread(self.__commandsDBConnector, commandTimeout, commandTimeoutCheckInterval) self.__commandMonitoringThread.start() except NetworkManagerException as e : raise EndpointException(e.message) def disconnectFromClusterServer(self): """ Cierra la conexión con el servidor de cluster y borra las bases de datos de estado Argumentos: Ninguno Devuelve: Nada @attention: Este método debe llamarse desde el hilo principal para evitar cuelgues """ # Apagar el servidor de cluster p = self.__repositoryPacketHandler.createHaltPacket(self.__haltVMServers) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) # Dejar de actualizar las bases de datos self.__updateRequestThread.stop() # Dejar de monitorizar los comandos self.__commandMonitoringThread.stop() # Cerrar las conexiones con las bases de datos self.closeNetworkAndDBConnections() def closeNetworkAndDBConnections(self): """ Cierra las conexiones con las bases de datos Argumentos: Ninguno Devuelve: Nada """ # Detener el servicio de red self.__manager.stopNetworkService() # Borrar las bases de datos de comandos y de estado dbConfigurator = DBConfigurator(self.__rootsPassword) dbConfigurator.dropDatabase(self.__commandsDatabaseName) def _processIncomingPacket(self, packet): """ Procesa un paquete enviado desde el servidor de cluster Argumentos: packet: el paquete a procesar Devuelve: Nada """ if (self.__stopped) : return data = self.__repositoryPacketHandler.readPacket(packet) if (data["packet_type"] == PACKET_T.VM_SERVERS_STATUS_DATA) : self.__endpointDBConnector.processVMServerSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.VM_DISTRIBUTION_DATA) : self.__endpointDBConnector.processVMDistributionSegment(data["Segment"], data["SequenceSize"], data["Data"]) elif (data["packet_type"] == PACKET_T.ACTIVE_VM_DATA) : self.__endpointDBConnector.processActiveVMSegment(data["Segment"], data["SequenceSize"], data["VMServerIP"], data["Data"]) else : l = data["CommandID"].split("|") commandID = (int(l[0]), float(l[1])) if (data["packet_type"] == PACKET_T.COMMAND_EXECUTED) : self.__commandsDBConnector.removeExecutedCommand(commandID) else : # El resto de paquetes contienen el resultado de ejecutar comandos => los serializamos y los añadimos # a la base de datos de comandos para que los conectores se enteren if (data["packet_type"] == PACKET_T.VM_SERVER_BOOTUP_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_UNREGISTRATION_ERROR or data["packet_type"] == PACKET_T.VM_SERVER_SHUTDOWN_ERROR) : (outputType, outputContent) = CommandsHandler.createVMServerGenericErrorOutput( data["packet_type"], data["ServerNameOrIPAddress"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_SERVER_REGISTRATION_ERROR) : (outputType, outputContent) = CommandsHandler.createVMServerRegistrationErrorOutput( data["VMServerIP"], data["VMServerPort"], data["VMServerName"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_BOOT_FAILURE) : (outputType, outputContent) = CommandsHandler.createVMBootFailureErrorOutput( data["VMID"], data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_CONNECTION_DATA) : (outputType, outputContent) = CommandsHandler.createVMConnectionDataOutput( data["VNCServerIPAddress"], data["VNCServerPort"], data["VNCServerPassword"]) elif (data["packet_type"] == PACKET_T.DOMAIN_DESTRUCTION_ERROR): (outputType, outputContent) = CommandsHandler.createDomainDestructionErrorOutput(data["ErrorMessage"]) elif (data["packet_type"] == PACKET_T.VM_SERVER_CONFIGURATION_CHANGE_ERROR) : (outputType, outputContent) = CommandsHandler.createVMServerConfigurationChangeErrorOutput(data["ErrorMessage"]) self.__commandsDBConnector.addCommandOutput(commandID, outputType, outputContent) def processCommands(self): """ Procesa los comandos enviados desde los conectores Argumentos: Ninguno Devuelve: Nada """ while not self.__stopped : commandData = self.__commandsDBConnector.popCommand() if (commandData == None) : sleep(0.1) else : (commandID, commandType, commandArgs) = commandData parsedArgs = CommandsHandler.deserializeCommandArgs(commandType, commandArgs) if (commandType != COMMAND_TYPE.HALT) : serializedCommandID = "{0}|{1}".format(commandID[0], commandID[1]) if (commandType == COMMAND_TYPE.BOOTUP_VM_SERVER) : packet = self.__repositoryPacketHandler.createVMServerBootUpPacket(parsedArgs["VMServerNameOrIP"], serializedCommandID) elif (commandType == COMMAND_TYPE.REGISTER_VM_SERVER) : packet = self.__repositoryPacketHandler.createVMServerRegistrationPacket(parsedArgs["VMServerIP"], parsedArgs["VMServerPort"], parsedArgs["VMServerName"], parsedArgs["IsVanillaServer"], serializedCommandID) elif (commandType == COMMAND_TYPE.UNREGISTER_OR_SHUTDOWN_VM_SERVER) : packet = self.__repositoryPacketHandler.createVMServerUnregistrationOrShutdownPacket(parsedArgs["VMServerNameOrIP"], parsedArgs["Halt"], parsedArgs["Unregister"], serializedCommandID) elif (commandType == COMMAND_TYPE.VM_BOOT_REQUEST) : packet = self.__repositoryPacketHandler.createVMBootRequestPacket(parsedArgs["VMID"], parsedArgs["UserID"], serializedCommandID) elif (commandType == COMMAND_TYPE.DESTROY_DOMAIN): packet = self.__repositoryPacketHandler.createDomainDestructionPacket(parsedArgs["DomainID"], serializedCommandID) elif (commandType == COMMAND_TYPE.VM_SERVER_CONFIGURATION_CHANGE) : packet = self.__repositoryPacketHandler.createVMServerConfigurationChangePacket(parsedArgs["VMServerNameOrIPAddress"], parsedArgs["NewServerName"], parsedArgs["NewServerIPAddress"], parsedArgs["NewServerPort"], parsedArgs["NewVanillaImageEditionBehavior"], serializedCommandID) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, packet) if (errorMessage != None) : # Error al enviar el paquete => el comando no se podrá ejecutar => avisar a la web (outputType, outputContent) = CommandsHandler.createConnectionErrorOutput() self.__commandsDBConnector.addCommandOutput(commandID, outputType, outputContent) else : self.__stopped = True self.__haltVMServers = parsedArgs["HaltVMServers"] def _sendUpdateRequestPackets(self): """ Solicita información de estado al serividor de cluster Argumentos: Ninguno Devuelve: Nada """ if (self.__stopped) : return # Enviamos paquetes para obtener los tres tipos de información que necesitamos para actualizar la base de datos de estado p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_VM_SERVERS_STATUS) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine servers status", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_VM_DISTRIBUTION) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Virtual machine distribution", errorMessage) p = self.__repositoryPacketHandler.createDataRequestPacket(PACKET_T.QUERY_ACTIVE_VM_DATA) errorMessage = self.__manager.sendPacket(self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary(self.__clusterServerIP, self.__clusterServerPort, "Active virtual machines data", errorMessage)
class VMServerReactor(NetworkCallback): """ Virtual machine server packet reactor """ def __init__(self, configurationFileParser): """ Initializes the reactor's state, establishes the connection with the database and creates the control connection Args: configurationFileParser: the virtual machine server's configuration file parser """ self.__finished = False self.__emergencyStop = False self.__fileTransferThread = None self.__compressionThread = None self.__networkManager = None self.__parser = configurationFileParser self.__domainHandler = None self.__domainTimeout = 0 try: self.__connectToDatabases( "VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__startListenning() except Exception as e: print e.message self.__emergencyStop = True self.__finished = True def __connectToDatabases(self, databaseName, user, password): """ Establishes the connection with the database Args: databaseName: a database name user: a SQL username password: the user's password Returns: Nothing """ self.__commandsDBConnector = VMServerDBConnector( user, password, databaseName) def __startListenning(self): """ Creates the control connection Args: None Returns: Nothing """ networkInterface = self.__parser.getConfigurationParameter( "vncNetworkInterface") listenningPort = self.__parser.getConfigurationParameter( "listenningPort") try: self.__vncServerIP = get_ip_address(networkInterface) except Exception: raise Exception( "Error: the network interface '{0}' is not ready. Exiting now". format(networkInterface)) self.__ftpTimeout = self.__parser.getConfigurationParameter( "FTPTimeout") self.__listenningPort = listenningPort self.__networkManager = NetworkManager( self.__parser.getConfigurationParameter("certificatePath")) self.__networkManager.startNetworkService() self.__useSSL = self.__parser.getConfigurationParameter("useSSL") self.__packetManager = VMServerPacketHandler(self.__networkManager) self.__connectToDatabases( "VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__domainHandler = DomainHandler( self.__commandsDBConnector, self.__vncServerIP, self.__networkManager, self.__packetManager, self.__listenningPort, self.__parser.getConfigurationParameter("useQEMUWebsockets"), self.__parser.getConfigurationParameter("websockifyPath"), self.__parser.getConfigurationParameter("configFilePath"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("executionImagePath"), self.__parser.getConfigurationParameter("passwordLength")) self.__domainHandler.connectToLibvirt( self.__parser.getConfigurationParameter("vncNetworkInterface"), self.__parser.getConfigurationParameter("vnName"), self.__parser.getConfigurationParameter("gatewayIP"), self.__parser.getConfigurationParameter("netMask"), self.__parser.getConfigurationParameter("dhcpStartIP"), self.__parser.getConfigurationParameter("dhcpEndIP"), self.__parser.getConfigurationParameter( "createVirtualNetworkAsRoot")) self.__domainHandler.doInitialCleanup() self.__deleteTemporaryZipFiles() self.__fileTransferThread = FileTransferThread( self.__networkManager, self.__listenningPort, self.__packetManager, self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("FTPTimeout"), self.__parser.getConfigurationParameter("MaxTransferAttempts"), self.__commandsDBConnector, self.__useSSL) self.__compressionThread = CompressionThread( self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("configFilePath"), self.__commandsDBConnector, self.__domainHandler, self.__networkManager, self.__listenningPort, self.__packetManager) self.__fileTransferThread.start() self.__compressionThread.start() self.__networkManager.listenIn(self.__listenningPort, self, self.__useSSL) def __deleteTemporaryZipFiles(self): """ Deletes the temporary zip files Args: None Returns: Nothing """ transfer_dir_path = self.__parser.getConfigurationParameter( "TransferDirectory") for filePath in os.listdir(transfer_dir_path): fileName = os.path.splitext(filePath)[0] if re.match("[^0-9]", fileName): # The non-temporary zip files only have numbers on their names os.remove(os.path.join(transfer_dir_path, filePath)) def shutdown(self): """ Shuts down the virtual machine server Args: None Returns: Nothing """ if (self.__emergencyStop): self.__domainTimeout = 0 self.__domainHandler.shutdown(self.__domainTimeout) if (self.__fileTransferThread != None): self.__fileTransferThread.stop() self.__fileTransferThread.join() if (self.__compressionThread != None): self.__compressionThread.stop() self.__compressionThread.join() if (self.__networkManager != None): self.__networkManager.stopNetworkService( ) # Dejar de atender peticiones inmediatamente sys.exit() def processPacket(self, packet): """ Processes a packet sent from the cluster server Args: packet: the packet to process Returns: Nothing """ data = self.__packetManager.readPacket(packet) if (data["packet_type"] == VM_SERVER_PACKET_T.CREATE_DOMAIN): self.__domainHandler.createDomain(data["MachineID"], data["UserID"], data["CommandID"]) elif (data["packet_type"] == VM_SERVER_PACKET_T.SERVER_STATUS_REQUEST): self.__sendStatusData() elif (data["packet_type"] == VM_SERVER_PACKET_T.USER_FRIENDLY_SHUTDOWN ): self.__domainTimeout = data["Timeout"] self.__finished = True elif (data["packet_type"] == VM_SERVER_PACKET_T.HALT): self.__domainTimeout = 0 self.__finished = True elif (data['packet_type'] == VM_SERVER_PACKET_T.QUERY_ACTIVE_VM_DATA): self.__sendDomainsVNCConnectionData() elif (data['packet_type'] == VM_SERVER_PACKET_T.DESTROY_DOMAIN): self.__domainHandler.destroyDomain(data["DomainID"]) elif (data['packet_type'] == VM_SERVER_PACKET_T.REBOOT_DOMAIN): self.__domainHandler.rebootDomain(data["DomainID"]) elif (data['packet_type'] == VM_SERVER_PACKET_T.QUERY_ACTIVE_DOMAIN_UIDS): self.__sendActiveDomainUIDs() elif (data['packet_type'] == VM_SERVER_PACKET_T.IMAGE_EDITION): self.__processImageEditionPacket(data) elif (data['packet_type'] == VM_SERVER_PACKET_T.DEPLOY_IMAGE): self.__processDeployImagePacket(data) elif (data['packet_type'] == VM_SERVER_PACKET_T.DELETE_IMAGE): self.__processDeleteImagePacket(data) def __processDeployImagePacket(self, data): """ Processes an image deployment packet Args: data: a dictionary containing the packet to process' data Returns: Nothing """ data.pop("packet_type") data["Transfer_Type"] = TRANSFER_T.DEPLOY_IMAGE self.__commandsDBConnector.addToTransferQueue(data) 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 __processImageEditionPacket(self, data): """ Processes an image edition packet Args: data: a dictionary containing the packet to process' data Returns: Nothing """ data.pop("packet_type") if (data["Modify"]): data["Transfer_Type"] = TRANSFER_T.EDIT_IMAGE else: data["Transfer_Type"] = TRANSFER_T.CREATE_IMAGE data.pop("Modify") self.__commandsDBConnector.addToTransferQueue(data) def __sendDomainsVNCConnectionData(self): ''' Sends the domains' VNC connection data to the cluster server Args: None Returns: Nothing ''' vncConnectionData = self.__commandsDBConnector.getDomainsConnectionData( ) segmentSize = 150 segmentCounter = 1 outgoingData = [] if (len(vncConnectionData) == 0): segmentCounter = 0 segmentNumber = (len(vncConnectionData) / segmentSize) if (len(vncConnectionData) % segmentSize != 0): segmentNumber += 1 sendLastSegment = True else: sendLastSegment = segmentNumber == 0 for connectionParameters in vncConnectionData: outgoingData.append(connectionParameters) if (len(outgoingData) >= segmentSize): # Flush packet = self.__packetManager.createActiveVMsVNCDataPacket( self.__vncServerIP, segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__listenningPort, packet) outgoingData = [] segmentCounter += 1 # Send the last segment if (sendLastSegment): packet = self.__packetManager.createActiveVMsVNCDataPacket( self.__vncServerIP, segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__listenningPort, packet) 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 __generateDiskStats(self): """ Generates the hard disk usage statistics Args: None Returns: the free and available storage and temporary space """ diskStats_storage = os.statvfs( self.__parser.getConfigurationParameter("sourceImagePath")) diskStats_temporaryData = os.statvfs( self.__parser.getConfigurationParameter("executionImagePath")) allocatedStorageSpace, allocatedTemporaryStorageSpace = self.__checkDiskImagesSpace( ) freeStorageSpace = diskStats_storage.f_bfree * diskStats_storage.f_frsize / 1024 - allocatedStorageSpace availableStorageSpace = diskStats_storage.f_blocks * diskStats_storage.f_frsize / 1024 freeTemporaryStorageSpace = diskStats_temporaryData.f_bfree * diskStats_temporaryData.f_frsize / 1024 - allocatedTemporaryStorageSpace availableTemporaryStorageSpace = diskStats_temporaryData.f_blocks * diskStats_temporaryData.f_frsize / 1024 return freeStorageSpace, availableStorageSpace, freeTemporaryStorageSpace, availableTemporaryStorageSpace def __checkDiskImagesSpace(self): """ Checks how much disk space must be allocated for the active virtual machines' disk images Args: None Returns: the storage and temporary storage space that must be allocated. """ activeDomainNames = self.__commandsDBConnector.getRegisteredDomainNames( ) allocatedStorageSpace = 0 allocatedTemporaryStorageSpace = 0 for domainName in activeDomainNames: imageID = self.__commandsDBConnector.getDomainImageID(domainName) if (imageID == None): return 0, 0 dataImagePath = self.__commandsDBConnector.getDomainDataImagePath( domainName) if (dataImagePath == None): return 0, 0 osImagePath = self.__commandsDBConnector.getDomainOSImagePath( domainName) if (osImagePath == None): return 0, 0 isEditedImage = self.__commandsDBConnector.getBootableFlag(imageID) if (isEditedImage == None): return 0, 0 dataSpace = self.__getAllocatedSpace(dataImagePath) if (isEditedImage): osSpace = self.__getAllocatedSpace(osImagePath) allocatedStorageSpace += osSpace + dataSpace else: allocatedTemporaryStorageSpace += dataSpace return allocatedStorageSpace, allocatedTemporaryStorageSpace 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 @staticmethod def __extractImageSize(string): """ Extracts an image size from a quemu-img command output. Args: string: the qemu-img command's image size Returns: the disk image size (in kilobytes) """ if ("G" in string): power = 2 elif ("M" in string): power = 1 else: power = 0 string = string.replace("G", "") string = string.replace("M", "") string = string.replace("K", "") return int(ceil(float(string))) * 1024**power def __sendActiveDomainUIDs(self): """ Sends domains' UUIDs to the cluster server Args: None Returns: Nothing """ activeDomainUIDs = self.__commandsDBConnector.getActiveDomainUIDs() packet = self.__packetManager.createActiveDomainUIDsPacket( self.__vncServerIP, activeDomainUIDs) self.__networkManager.sendPacket('', self.__listenningPort, packet) def has_finished(self): """ Checks if the virtual machine server has been shut down or not Args: None Returns: Nothing """ return self.__finished
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__": networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, DummyCallback()) print("The server is now ready") sleep(200) networkManager.stopNetworkService()
class ClusterServerReactor(WebPacketReactor, VMServerPacketReactor): ''' These objects react to packages received from the website or from a virtual machine server. ''' def __init__(self, timeout): """ Initializes the reactor's state. Args: None """ self.__webCallback = WebCallback(self) self.__finished = False self.__timeout = timeout def connectToDatabase(self, mysqlRootsPassword, dbName, dbUser, dbPassword, scriptPath): """ Establishes a connection with the cluster server database. Args: mysqlRootsPassword: MySQL root's password dbName: the cluster server database's name dbUser: the cluster server database's user name dbPassword: the cluster server database's user password scriptPath: the cluster server database's initialization script path """ configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(dbName, scriptPath) configurator.addUser(dbUser, dbPassword, dbName, True) self.__dbConnector = ClusterServerDatabaseConnector(dbUser, dbPassword, dbName) self.__dbConnector.connect() self.__dbConnector.resetVMServersStatus() def startListenning(self, certificatePath, port): """ Starts the network service and creates a server connection. Args: certificatePath: the server.crt and server.key files path port: the listenning port Returns: Nothing """ self.__loadBalancer = SimpleLoadBalancer(self.__dbConnector) self.__networkManager = NetworkManager(certificatePath) self.__webPort = port self.__networkManager.startNetworkService() self.__webPacketHandler = ClusterServerPacketHandler(self.__networkManager) self.__vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) self.__networkManager.listenIn(port, self.__webCallback, True) self.__vmServerCallback = VMServerCallback(self) def processWebIncomingPacket(self, packet): """ Processes a packet received from the web server. Args: packet: the packet to process Returns: Nothing """ data = self.__webPacketHandler.readPacket(packet) if (data["packet_type"] == WEB_PACKET_T.REGISTER_VM_SERVER) : self.__registerVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.QUERY_VM_SERVERS_STATUS) : self.__sendVMServerStatusData() elif (data["packet_type"] == WEB_PACKET_T.UNREGISTER_OR_SHUTDOWN_VM_SERVER) : self.__unregisterOrShutdownVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.BOOTUP_VM_SERVER) : self.__bootUpVMServer(data) elif (data["packet_type"] == WEB_PACKET_T.VM_BOOT_REQUEST): self.__bootUpVM(data) elif (data["packet_type"] == WEB_PACKET_T.HALT) : self.__halt(data) elif (data["packet_type"] == WEB_PACKET_T.QUERY_VM_DISTRIBUTION) : self.__sendVMDistributionData() elif (data["packet_type"] == WEB_PACKET_T.QUERY_ACTIVE_VM_DATA) : self.__requestVNCConnectionData() def __requestVNCConnectionData(self): """ Sends a VNC connection data request packet to all the active virtual machine servers Args: None Returns: Nothing """ # Create a VNC connection data packet p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.QUERY_ACTIVE_VM_DATA) # Fetch the active virtual machine server's IP addresses and ports connectionData = self.__dbConnector.getActiveVMServersConnectionData() for cd in connectionData : self.__networkManager.sendPacket(cd["ServerIP"], cd["ServerPort"], p) def __halt(self, data): """ Shuts down the cluster (including the virtual machine servers). Args: haltVMServers: if True, all the active virtual machines will be destroyed and the virtual machine servers will be shut down. If false, the virtual machine servers will wait until there are no active virtual machines, and then they'll be shut down. """ vmServersConnectionData = self.__dbConnector.getActiveVMServersConnectionData() if (vmServersConnectionData != None) : args = dict() args["Halt"] = data["HaltVMServers"] args["Unregister"] = False for connectionData in vmServersConnectionData : args["ServerNameOrIPAddress"] = connectionData["ServerIP"] self.__unregisterOrShutdownVMServer(args) self.__finished = True def __registerVMServer(self, data): """ Processes a virtual machine server registration packet. Args: data: the received virtual machine server registration packet. Returns: Nothing """ try : # Check if the IP address is assigned to another virtual machine server server_id = self.__dbConnector.getVMServerID(data["VMServerIP"]) if (server_id != None) : raise Exception("The IP address " + data["VMServerIP"] + " is assigned to another VM server") # Check if the name is assigned to another virtual machine server server_id = self.__dbConnector.getVMServerID(data["VMServerName"]) if (server_id != None) : raise Exception("The name " + data["VMServerName"] + " is assigned to another VM server") # Establish a connection self.__networkManager.connectTo(data["VMServerIP"], data["VMServerPort"], 20, self.__vmServerCallback, True, True) while not self.__networkManager.isConnectionReady(data["VMServerIP"], data["VMServerPort"]) : sleep(0.1) # Register the server on the database self.__dbConnector.registerVMServer(data["VMServerName"], data["VMServerIP"], data["VMServerPort"]) # Command the virtual machine server to tell us its state p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) self.__networkManager.sendPacket(data["VMServerIP"], data["VMServerPort"], p) # Everything went fine p = self.__webPacketHandler.createCommandExecutedPacket(data["CommandID"]) except Exception as e: p = self.__webPacketHandler.createVMServerRegistrationErrorPacket(data["VMServerIP"], data["VMServerPort"], data["VMServerName"], str(e), data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def __unregisterOrShutdownVMServer(self, data): """ Processes a virtual machine server unregistration or shutdown packet. Args: key: the virtual machine server's IPv4 address or its name. halt: if True, the virtual machine server will be shut down immediately. If false, it'll wait until all the virtual machines are shut down, and then it will finally be shut down. unregister: if True, the virtual machine server will be deleted from the cluster server's database. """ key = data["ServerNameOrIPAddress"] halt = data["Halt"] unregister = data["Unregister"] if data.has_key("CommandID") : useCommandID = True commandID = data["CommandID"] else : useCommandID = False # Shut down the server (if necessary) serverId = self.__dbConnector.getVMServerID(key) if (serverId != None) : serverData = self.__dbConnector.getVMServerBasicData(serverId) status = serverData["ServerStatus"] if (status == SERVER_STATE_T.READY or status == SERVER_STATE_T.BOOTING) : if not halt : p = self.__vmServerPacketHandler.createVMServerShutdownPacket() else : p = self.__vmServerPacketHandler.createVMServerHaltPacket() self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Close the network connection self.__networkManager.closeConnection(serverData["ServerIP"], serverData["ServerPort"]) if (not unregister) : self.__dbConnector.updateVMServerStatus(serverId, SERVER_STATE_T.SHUT_DOWN) self.__dbConnector.deleteVMServerStatistics(serverId) else : # Update the virtual machine server's state self.__dbConnector.deleteVMServer(key) if (useCommandID) : # Create a command executed packet and send it to the website p = self.__webPacketHandler.createCommandExecutedPacket(commandID) self.__networkManager.sendPacket('', self.__webPort, p) else : # Error if (unregister) : packet_type = WEB_PACKET_T.VM_SERVER_UNREGISTRATION_ERROR else : packet_type = WEB_PACKET_T.VM_SERVER_SHUTDOWN_ERROR errorMessage = "The virtual machine server with name or IP address <<{0}>> is not registered".format(key) p = self.__webPacketHandler.createVMServerGenericErrorPacket(packet_type, key, errorMessage, commandID) self.__networkManager.sendPacket('', self.__webPort, p) def __updateVMServerStatus(self, data): """ Processes a virtual machine server's status packet. Args: data: the received packet Returns: Nothing """ # Fetch the virtual machine server's ID serverID = None while (serverID == None) : serverID = self.__dbConnector.getVMServerID(data["VMServerIP"]) if (serverID == None) : sleep(0.1) # Change its status self.__dbConnector.updateVMServerStatus(serverID, SERVER_STATE_T.READY) self.__dbConnector.setVMServerStatistics(serverID, data["ActiveDomains"]) def __bootUpVMServer(self, data): """ Processes a virtual machine server boot packet. Args: serverNameOrIPAddress: the virtual machine server's name or IPv4 address. Returns: Nothing """ try : serverNameOrIPAddress = data["ServerNameOrIPAddress"] serverId = self.__dbConnector.getVMServerID(serverNameOrIPAddress) if (serverId == None) : raise Exception("The virtual machine server is not registered") serverData = self.__dbConnector.getVMServerBasicData(serverId) # Connect to the virtual machine server self.__networkManager.connectTo(serverData["ServerIP"], serverData["ServerPort"], 20, self.__vmServerCallback, True, True) while not self.__networkManager.isConnectionReady(serverData["ServerIP"], serverData["ServerPort"]) : sleep(0.1) # Change its status self.__dbConnector.updateVMServerStatus(serverId, SERVER_STATE_T.BOOTING) # Send the status request p = self.__vmServerPacketHandler.createVMServerDataRequestPacket(VMSRVR_PACKET_T.SERVER_STATUS_REQUEST) self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Everything went fine p = self.__webPacketHandler.createCommandExecutedPacket(data["CommandID"]) except Exception as e: p = self.__webPacketHandler.createVMServerGenericErrorPacket(WEB_PACKET_T.VM_SERVER_BOOTUP_ERROR, serverNameOrIPAddress, str(e), data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def __sendVMServerStatusData(self): """ Processes a virtual machine server data request packet. Args: None Returns: Nothing """ self.__sendStatusData(self.__dbConnector.getVMServerBasicData, self.__webPacketHandler.createVMServerStatusPacket) def __sendVMDistributionData(self): """ Processes a virtual machine distribution data packet Args: None Returns: Nothing """ self.__sendStatusData(self.__dbConnector.getHostedImages, self.__webPacketHandler.createVMDistributionPacket) def __sendStatusData(self, queryMethod, packetCreationMethod): """ Processes a data request packet. Args: queryMethod: the method that extracts the data from the database packetCreationMethod: the method that creates the packet Returns: Nothing """ segmentSize = 5 outgoingData = [] serverIDs = self.__dbConnector.getVMServerIDs() if (len(serverIDs) == 0) : segmentCounter = 0 segmentNumber = 0 sendLastSegment = True else : segmentCounter = 1 segmentNumber = (len(serverIDs) / segmentSize) if (len(serverIDs) % segmentSize != 0) : segmentNumber += 1 sendLastSegment = True else : sendLastSegment = False for serverID in serverIDs : row = queryMethod(serverID) if (isinstance(row, dict)) : outgoingData.append(row) else : outgoingData += row if (len(outgoingData) >= segmentSize) : # Flush packet = packetCreationMethod(segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__webPort, packet) outgoingData = [] segmentCounter += 1 # Send the last segment if (sendLastSegment) : packet = packetCreationMethod(segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__webPort, packet) def __bootUpVM(self, data): """ Processes a virtual machine boot request packet. Args: vmName: the virtual machine's ID userID: the user's unique identifier Returns: Nothing """ vmID = data["VMID"] userID = data["UserID"] # Choose the virtual machine server that will host the image (serverID, errorMessage) = self.__loadBalancer.assignVMServer(vmID) if (errorMessage != None) : # Something went wrong => warn the user p = self.__webPacketHandler.createVMBootFailurePacket(vmID, errorMessage, data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) else : # Ask the virtual machine server to boot up the VM p = self.__vmServerPacketHandler.createVMBootPacket(vmID, userID, data["CommandID"]) serverData = self.__dbConnector.getVMServerBasicData(serverID) self.__networkManager.sendPacket(serverData["ServerIP"], serverData["ServerPort"], p) # Register the boot command self.__dbConnector.registerVMBootCommand(data["CommandID"], data["VMID"]) # Everything went fine #p = self.__webPacketHandler.createCommandExecutedPacket(data["CommandID"]) #self.__networkManager.sendPacket('', self.__webPort, p) def processVMServerIncomingPacket(self, packet): """ Processes a packet sent from a virtual machine server. Args: packet: the packet to process Returns: Nothing """ data = self.__vmServerPacketHandler.readPacket(packet) if (data["packet_type"] == VMSRVR_PACKET_T.SERVER_STATUS) : self.__updateVMServerStatus(data) elif (data["packet_type"] == VMSRVR_PACKET_T.DOMAIN_CONNECTION_DATA) : self.__sendVMConnectionData(data) elif (data["packet_type"] == VMSRVR_PACKET_T.ACTIVE_VM_DATA) : self.__sendVNCConnectionData(packet) def processServerReconnectionData(self, ipAddress, reconnection_status) : """ Processes a reconnection status event Args: ipAddress: the connection's IPv4 address port: the connection's port reconnection_status: the reconnection process' status Returns: Nothing """ if (reconnection_status == RECONNECTION_T.RECONNECTING) : status = SERVER_STATE_T.RECONNECTING elif (reconnection_status == RECONNECTION_T.REESTABLISHED) : status = SERVER_STATE_T.READY else : status = SERVER_STATE_T.CONNECTION_TIMED_OUT serverID = self.__dbConnector.getVMServerID(ipAddress) self.__dbConnector.updateVMServerStatus(serverID, status) def __sendVNCConnectionData(self, packet): """ Processes a VNC connection data packet Args: packet: the packet to process Returns: Nothing """ p = self.__webPacketHandler.createActiveVMsDataPacket(packet) self.__networkManager.sendPacket('', self.__webPort, p) def __sendVMConnectionData(self, data): """ Processes a virtual machine connection data packet. Args: data: the packet to process' data. Returns: Nothing """ # Delete the boot command from the database self.__dbConnector.removeVMBootCommand(data["CommandID"]) p = self.__webPacketHandler.createVMConnectionDataPacket(data["VNCServerIP"], data["VNCServerPort"], data["VNCServerPassword"], data["CommandID"]) self.__networkManager.sendPacket('', self.__webPort, p) def monitorVMBootCommands(self): errorMessage = "Could not boot up virtual machine (timeout error)" while not self.__finished : data = self.__dbConnector.getOldVMBootCommandID(self.__timeout) if (not self.__finished and data == None) : # Be careful with this: if MySQL server receives too many queries per second, # the reactor's database connection will be closed. sleep(1) else : # Create a virtual machine boot error packet p = self.__webPacketHandler.createVMBootFailurePacket(data[1], errorMessage, data[0]) self.__networkManager.sendPacket('', self.__webPort, p) def hasFinished(self): """ Indicates if the cluster server has finished or not. """ return self.__finished def shutdown(self): """ Shuts down the cluster server. Args: None Returns: Nothing @attention: this method MUST NOT be called from a network thread. If you do so, the application will hang! """ self.__networkManager.stopNetworkService()
# -*- coding: utf8 -*- ''' A simple client test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : networkManager = NetworkManager() networkManager.startNetworkService() networkManager.connectTo('192.168.0.5', 8080, 20, DummyCallback()) p = networkManager.createPacket(0) p.writeString("Greetings from a client") networkManager.sendPacket('192.168.0.5', 8080, p) sleep(100) networkManager.stopNetworkService()
1. ejecutar el serverWridge y esperar a que se informe de que la conexión está disponible 2. Ejecutar el clientReceptor. 3. Inmediatamente después ejecutar clientEmisor. Módulos necesarios: -serverWridge,clientEmisor,clientReceptor ''' from network.manager.networkManager import NetworkManager from network.tests.ConvCallback import ConvCallback from time import sleep if __name__ == "__main__" : listP = [] listP1 = [] networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, ConvCallback(listP)) networkManager.listenIn(8081, ConvCallback(listP1)) print("The server is now ready") #esperamos una respuesta while(len(listP) == 0): sleep(0.1) # Extraemos la contestacion ans = listP[0] #Se la enviamos al otro cliente p = networkManager.createPacket(0) p.writeString(ans) networkManager.sendPacket('', 8081, p) #Esperamos al de regreso while(len(listP1) == 0):
def startListenning(self, useSSL, certificatePath, listenningPort, repositoryIP, repositoryPort, vmServerStatusUpdateInterval): """ Creates the control connection Args: useSSL: indicates if SSL encryption must be used in the control connection or not certificatePath: the directory where the server.crt and server.key files are listenningPort: the control connection's port repositoryIP: the image repository IP address repositoryPort: the image repository's port vmServerStatusUpdateInterval: the virtual machine server status database interval Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__listenningPort = listenningPort self.__packetHandler = ClusterServerPacketHandler( self.__networkManager) self.__useSSL = useSSL imageRepositoryPacketHandler = ImageRepositoryPacketHandler( self.__networkManager) vmServerPacketHandler = VMServerPacketHandler(self.__networkManager) networkEventsReactor = NetworkEventsReactor(self.__dbConnector, repositoryIP, repositoryPort) imageRepositoryPacketReactor = ImageRepositoryPacketReactor( self.__dbConnector, self.__networkManager, listenningPort, repositoryIP, repositoryPort, self.__packetHandler, vmServerPacketHandler, imageRepositoryPacketHandler) try: imageRepositoryCallback = ImageRepositoryCallback( imageRepositoryPacketReactor, networkEventsReactor) self.__networkManager.connectTo(repositoryIP, repositoryPort, 10, imageRepositoryCallback, self.__useSSL, True) self.__dbConnector.addImageRepository(repositoryIP, repositoryPort, SERVER_STATE_T.READY) except Exception as e: print "Can't connect to the image repository: " + e.message self.__exit = True return vmServerPacketReactor = VMServerPacketReactor(self.__dbConnector, self.__networkManager, listenningPort, vmServerPacketHandler, self.__packetHandler) self.__endpointPacketReactor = EndpointPacketReactor( self.__dbConnector, self.__networkManager, vmServerPacketHandler, self.__packetHandler, imageRepositoryPacketHandler, VMServerCallback(vmServerPacketReactor, networkEventsReactor), listenningPort, repositoryIP, repositoryPort, self.__loadBalancerSettings, self.__averageCompressionRatio, self.__useSSL) clusterEndpointCallback = ClusterEndpointCallback( self.__endpointPacketReactor) self.__networkManager.listenIn(listenningPort, clusterEndpointCallback, self.__useSSL) self.__statusMonitoringThread = ClusterStatusMonitoringThread( vmServerStatusUpdateInterval, self.__dbConnector, self.__networkManager, repositoryIP, repositoryPort, vmServerPacketHandler, imageRepositoryPacketHandler) self.__statusMonitoringThread.start()
class VMServerReactor(NetworkCallback): """ Virtual machine server packet reactor """ def __init__(self, configurationFileParser): """ Initializes the reactor's state, establishes the connection with the database and creates the control connection Args: configurationFileParser: the virtual machine server's configuration file parser """ self.__finished = False self.__emergencyStop = False self.__fileTransferThread = None self.__compressionThread = None self.__networkManager = None self.__parser = configurationFileParser self.__domainHandler = None self.__domainTimeout = 0 try : self.__connectToDatabases("VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__startListenning() except Exception as e: print e.message self.__emergencyStop = True self.__finished = True def __connectToDatabases(self, databaseName, user, password) : """ Establishes the connection with the database Args: databaseName: a database name user: a SQL username password: the user's password Returns: Nothing """ self.__commandsDBConnector = VMServerDBConnector(user, password, databaseName) def __startListenning(self): """ Creates the control connection Args: None Returns: Nothing """ networkInterface = self.__parser.getConfigurationParameter("vncNetworkInterface") listenningPort = self.__parser.getConfigurationParameter("listenningPort") try : self.__vncServerIP = get_ip_address(networkInterface) except Exception : raise Exception("Error: the network interface '{0}' is not ready. Exiting now".format(networkInterface)) self.__ftpTimeout = self.__parser.getConfigurationParameter("FTPTimeout") self.__listenningPort = listenningPort self.__networkManager = NetworkManager(self.__parser.getConfigurationParameter("certificatePath")) self.__networkManager.startNetworkService() self.__useSSL = self.__parser.getConfigurationParameter("useSSL") self.__packetManager = VMServerPacketHandler(self.__networkManager) self.__connectToDatabases("VMServerDB", self.__parser.getConfigurationParameter("databaseUserName"), self.__parser.getConfigurationParameter("databasePassword")) self.__domainHandler = DomainHandler(self.__commandsDBConnector, self.__vncServerIP, self.__networkManager, self.__packetManager, self.__listenningPort, self.__parser.getConfigurationParameter("useQEMUWebsockets"), self.__parser.getConfigurationParameter("websockifyPath"), self.__parser.getConfigurationParameter("configFilePath"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("executionImagePath"), self.__parser.getConfigurationParameter("passwordLength")) self.__domainHandler.connectToLibvirt(self.__parser.getConfigurationParameter("vncNetworkInterface"), self.__parser.getConfigurationParameter("vnName"), self.__parser.getConfigurationParameter("gatewayIP"), self.__parser.getConfigurationParameter("netMask"), self.__parser.getConfigurationParameter("dhcpStartIP"), self.__parser.getConfigurationParameter("dhcpEndIP"), self.__parser.getConfigurationParameter("createVirtualNetworkAsRoot")) self.__domainHandler.doInitialCleanup() self.__deleteTemporaryZipFiles() self.__fileTransferThread = FileTransferThread(self.__networkManager, self.__listenningPort, self.__packetManager, self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("FTPTimeout"), self.__parser.getConfigurationParameter("MaxTransferAttempts"), self.__commandsDBConnector, self.__useSSL) self.__compressionThread = CompressionThread(self.__parser.getConfigurationParameter("TransferDirectory"), self.__parser.getConfigurationParameter("sourceImagePath"), self.__parser.getConfigurationParameter("configFilePath"), self.__commandsDBConnector, self.__domainHandler, self.__networkManager, self.__listenningPort, self.__packetManager) self.__fileTransferThread.start() self.__compressionThread.start() self.__networkManager.listenIn(self.__listenningPort, self, self.__useSSL) def __deleteTemporaryZipFiles(self): """ Deletes the temporary zip files Args: None Returns: Nothing """ transfer_dir_path = self.__parser.getConfigurationParameter("TransferDirectory") for filePath in os.listdir(transfer_dir_path) : fileName = os.path.splitext(filePath)[0] if re.match("[^0-9]", fileName): # The non-temporary zip files only have numbers on their names os.remove(os.path.join(transfer_dir_path, filePath)) def shutdown(self): """ Shuts down the virtual machine server Args: None Returns: Nothing """ if (self.__emergencyStop) : self.__domainTimeout = 0 self.__domainHandler.shutdown(self.__domainTimeout) if (self.__fileTransferThread != None) : self.__fileTransferThread.stop() self.__fileTransferThread.join() if (self.__compressionThread != None) : self.__compressionThread.stop() self.__compressionThread.join() if (self.__networkManager != None) : self.__networkManager.stopNetworkService() # Dejar de atender peticiones inmediatamente sys.exit() def processPacket(self, packet): """ Processes a packet sent from the cluster server Args: packet: the packet to process Returns: Nothing """ data = self.__packetManager.readPacket(packet) if (data["packet_type"] == VM_SERVER_PACKET_T.CREATE_DOMAIN) : self.__domainHandler.createDomain(data["MachineID"], data["UserID"], data["CommandID"]) elif (data["packet_type"] == VM_SERVER_PACKET_T.SERVER_STATUS_REQUEST) : self.__sendStatusData() elif (data["packet_type"] == VM_SERVER_PACKET_T.USER_FRIENDLY_SHUTDOWN) : self.__domainTimeout = data["Timeout"] self.__finished = True elif (data["packet_type"] == VM_SERVER_PACKET_T.HALT) : self.__domainTimeout = 0 self.__finished = True elif (data['packet_type'] == VM_SERVER_PACKET_T.QUERY_ACTIVE_VM_DATA) : self.__sendDomainsVNCConnectionData() elif (data['packet_type'] == VM_SERVER_PACKET_T.DESTROY_DOMAIN) : self.__domainHandler.destroyDomain(data["DomainID"]) elif (data['packet_type'] == VM_SERVER_PACKET_T.REBOOT_DOMAIN) : self.__domainHandler.rebootDomain(data["DomainID"]) elif (data['packet_type'] == VM_SERVER_PACKET_T.QUERY_ACTIVE_DOMAIN_UIDS) : self.__sendActiveDomainUIDs() elif (data['packet_type'] == VM_SERVER_PACKET_T.IMAGE_EDITION) : self.__processImageEditionPacket(data) elif (data['packet_type'] == VM_SERVER_PACKET_T.DEPLOY_IMAGE) : self.__processDeployImagePacket(data) elif (data['packet_type'] == VM_SERVER_PACKET_T.DELETE_IMAGE) : self.__processDeleteImagePacket(data) def __processDeployImagePacket(self, data): """ Processes an image deployment packet Args: data: a dictionary containing the packet to process' data Returns: Nothing """ data.pop("packet_type") data["Transfer_Type"] = TRANSFER_T.DEPLOY_IMAGE self.__commandsDBConnector.addToTransferQueue(data) 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 __processImageEditionPacket(self, data): """ Processes an image edition packet Args: data: a dictionary containing the packet to process' data Returns: Nothing """ data.pop("packet_type") if (data["Modify"]) : data["Transfer_Type"] = TRANSFER_T.EDIT_IMAGE else : data["Transfer_Type"] = TRANSFER_T.CREATE_IMAGE data.pop("Modify") self.__commandsDBConnector.addToTransferQueue(data) def __sendDomainsVNCConnectionData(self): ''' Sends the domains' VNC connection data to the cluster server Args: None Returns: Nothing ''' vncConnectionData = self.__commandsDBConnector.getDomainsConnectionData() segmentSize = 150 segmentCounter = 1 outgoingData = [] if (len(vncConnectionData) == 0): segmentCounter = 0 segmentNumber = (len(vncConnectionData) / segmentSize) if (len(vncConnectionData) % segmentSize != 0) : segmentNumber += 1 sendLastSegment = True else : sendLastSegment = segmentNumber == 0 for connectionParameters in vncConnectionData : outgoingData.append(connectionParameters) if (len(outgoingData) >= segmentSize) : # Flush packet = self.__packetManager.createActiveVMsVNCDataPacket(self.__vncServerIP, segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__listenningPort, packet) outgoingData = [] segmentCounter += 1 # Send the last segment if (sendLastSegment) : packet = self.__packetManager.createActiveVMsVNCDataPacket(self.__vncServerIP, segmentCounter, segmentNumber, outgoingData) self.__networkManager.sendPacket('', self.__listenningPort, packet) 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 __generateDiskStats(self): """ Generates the hard disk usage statistics Args: None Returns: the free and available storage and temporary space """ diskStats_storage = os.statvfs(self.__parser.getConfigurationParameter("sourceImagePath")) diskStats_temporaryData = os.statvfs(self.__parser.getConfigurationParameter("executionImagePath")) allocatedStorageSpace, allocatedTemporaryStorageSpace = self.__checkDiskImagesSpace() freeStorageSpace = diskStats_storage.f_bfree * diskStats_storage.f_frsize / 1024 - allocatedStorageSpace availableStorageSpace = diskStats_storage.f_blocks * diskStats_storage.f_frsize / 1024 freeTemporaryStorageSpace = diskStats_temporaryData.f_bfree * diskStats_temporaryData.f_frsize / 1024 - allocatedTemporaryStorageSpace availableTemporaryStorageSpace = diskStats_temporaryData.f_blocks * diskStats_temporaryData.f_frsize / 1024 return freeStorageSpace, availableStorageSpace, freeTemporaryStorageSpace, availableTemporaryStorageSpace def __checkDiskImagesSpace(self): """ Checks how much disk space must be allocated for the active virtual machines' disk images Args: None Returns: the storage and temporary storage space that must be allocated. """ activeDomainNames = self.__commandsDBConnector.getRegisteredDomainNames() allocatedStorageSpace = 0 allocatedTemporaryStorageSpace = 0 for domainName in activeDomainNames: imageID = self.__commandsDBConnector.getDomainImageID(domainName) if (imageID == None) : return 0, 0 dataImagePath = self.__commandsDBConnector.getDomainDataImagePath(domainName) if (dataImagePath == None) : return 0, 0 osImagePath = self.__commandsDBConnector.getDomainOSImagePath(domainName) if (osImagePath == None): return 0, 0 isEditedImage = self.__commandsDBConnector.getBootableFlag(imageID) if (isEditedImage == None): return 0, 0 dataSpace = self.__getAllocatedSpace(dataImagePath) if (isEditedImage) : osSpace = self.__getAllocatedSpace(osImagePath) allocatedStorageSpace += osSpace + dataSpace else : allocatedTemporaryStorageSpace += dataSpace return allocatedStorageSpace, allocatedTemporaryStorageSpace 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 @staticmethod def __extractImageSize(string): """ Extracts an image size from a quemu-img command output. Args: string: the qemu-img command's image size Returns: the disk image size (in kilobytes) """ if ("G" in string) : power = 2 elif ("M" in string): power = 1 else: power = 0 string = string.replace("G", "") string = string.replace("M", "") string = string.replace("K", "") return int(ceil(float(string))) * 1024 ** power def __sendActiveDomainUIDs(self): """ Sends domains' UUIDs to the cluster server Args: None Returns: Nothing """ activeDomainUIDs = self.__commandsDBConnector.getActiveDomainUIDs() packet = self.__packetManager.createActiveDomainUIDsPacket(self.__vncServerIP, activeDomainUIDs) self.__networkManager.sendPacket('', self.__listenningPort, packet) def has_finished(self): """ Checks if the virtual machine server has been shut down or not Args: None Returns: Nothing """ return self.__finished
# -*- coding: utf8 -*- ''' A simple server test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : networkManager = NetworkManager() networkManager.startNetworkService() networkManager.listenIn(8080, DummyCallback()) networkManager.closeConnection('', 8080) sleep(5) try : networkManager.listenIn(8080, DummyCallback()) except Exception as e: print e print 'Finising' networkManager.stopNetworkService()
# -*- coding: utf8 -*- ''' A simple client test @author: Luis Barrios Hernández @version: 1.0 ''' from network.manager.networkManager import NetworkManager from network.tests.dummyCallback import DummyCallback from time import sleep if __name__ == "__main__" : networkManager = NetworkManager("/home/luis/Certificates") networkManager.startNetworkService() networkManager.connectTo('127.0.0.1', 8080, 20, DummyCallback(), True, True) sleep(2) p = networkManager.createPacket(0) p.writeString("Greetings from a client") networkManager.sendPacket('127.0.0.1', 8080, p) sleep(60) p = networkManager.createPacket(0) p.writeString("Greetings from a client 1") networkManager.sendPacket('127.0.0.1', 8080, p) sleep(200) networkManager.stopNetworkService()
class ClusterEndpointEntryPoint(object): """ These objects create, run and stop the cluster endpoint daemons. """ def __init__(self): """ Initializes the daemon's state Args: None """ self.__commandExecutionThread = None self.__updateRequestThread = None self.__codeTranslator = SpanishCodesTranslator() self.__commandsHandler = CommandsHandler(self.__codeTranslator) def connectToDatabases(self, mysqlRootsPassword, endpointDBName, commandsDBName, endpointdbSQLFilePath, commandsDBSQLFilePath, websiteUser, websiteUserPassword, endpointUser, endpointUserPassword, minCommandInterval): """ Establishes the connection with the two databases Args: mysqlRootsPassword: the MySQL root's password endpointDBName: the endpoint database's name endpointdbSQLFilePath: the endpoint database's schema definition file path websiteUser: the web application's username websiteUserPassword: the web application's username endpointUser: the endpoint daemon user's name endpointUserPassword: the endpoint daemon user's password """ self.__rootsPassword = mysqlRootsPassword self.__statusDatabaseName = endpointDBName self.__commandsDatabaseName = commandsDBName configurator = DBConfigurator(mysqlRootsPassword) configurator.runSQLScript(endpointDBName, endpointdbSQLFilePath, "root", mysqlRootsPassword) configurator.runSQLScript(commandsDBName, commandsDBSQLFilePath, "root", mysqlRootsPassword) configurator.addUser(websiteUser, websiteUserPassword, endpointDBName, False) configurator.addUser(endpointUser, endpointUserPassword, endpointDBName, True) configurator.addUser(websiteUser, websiteUserPassword, commandsDBName, True) configurator.addUser(endpointUser, endpointUserPassword, commandsDBName, True) self.__commandsDBConnector = CommandsDatabaseConnector( endpointUser, endpointUserPassword, commandsDBName, minCommandInterval) self.__endpointDBConnector = ClusterEndpointDBConnector( endpointUser, endpointUserPassword, endpointDBName) def connectToClusterServer(self, useSSL, certificatePath, clusterServerIP, clusterServerListenningPort, statusDBUpdateInterval, commandTimeout, commandTimeoutCheckInterval): """ Establishes a connection with the cluster server Args: certificatePath: the directory where the server.crt and server.key files are clusterServerIP: the cluster server's IP address clusterServerListenningPort: the cluster server commands connection's port statusDBUpdateInterval: the database update interval (in seconds) Returns: Nothing """ self.__networkManager = NetworkManager(certificatePath) self.__networkManager.startNetworkService() self.__clusterServerIP = clusterServerIP self.__clusterServerPort = clusterServerListenningPort self.__packetHandler = ClusterServerPacketHandler( self.__networkManager) self.__commandsProcessor = CommandsProcessor( self.__commandsHandler, self.__packetHandler, self.__networkManager, self.__clusterServerIP, self.__clusterServerPort, self.__commandsDBConnector, self.__endpointDBConnector) packetReactor = ClusterEndpointPacketReactor( self.__codeTranslator, self.__commandsHandler, self.__packetHandler, self.__commandsProcessor, self.__endpointDBConnector, self.__commandsDBConnector) try: self.__networkManager.connectTo(clusterServerIP, clusterServerListenningPort, 5, packetReactor, useSSL) while (not self.__networkManager.isConnectionReady( clusterServerIP, clusterServerListenningPort)): sleep(0.1) self.__updateRequestThread = VMServerMonitoringThread( self.__packetHandler, self.__networkManager, self.__commandsProcessor, self.__clusterServerIP, self.__clusterServerPort, statusDBUpdateInterval) self.__updateRequestThread.start() self.__commandExecutionThread = CommandsMonitoringThread( self.__commandsDBConnector, commandTimeout, self.__commandsHandler, commandTimeoutCheckInterval) self.__commandExecutionThread.start() except NetworkManagerException as e: raise Exception(e.message) def doEmergencyStop(self): """ Stops the endpoint daemon immediately Args: None Returns: Nothing """ self.__networkManager.stopNetworkService() if (self.__updateRequestThread != None): self.__updateRequestThread.stop() if (self.__commandExecutionThread != None): self.__commandExecutionThread.stop() def disconnectFromClusterServer(self): """ Closes the connection with the cluster server Args: None Devuelve: Nada """ p = self.__packetHandler.createHaltPacket( self.__commandsProcessor.haltVMServers()) errorMessage = self.__networkManager.sendPacket( self.__clusterServerIP, self.__clusterServerPort, p) NetworkManager.printConnectionWarningIfNecessary( self.__clusterServerIP, self.__clusterServerPort, "Cluster server halt", errorMessage) self.__updateRequestThread.stop() self.__commandExecutionThread.stop() self.closeNetworkConnections() def closeNetworkConnections(self): """ Closes the network connections Args: None Returns: Nothing """ self.__networkManager.stopNetworkService() def processCommands(self): """ Processes the users' requests Args: None Returns: Nothing """ self.__commandsProcessor.processCommands()