Exemple #1
0
 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, 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()
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)
Exemple #4
0
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)