def __init__(self, inventoryFile):
        super(RainMoveServer, self).__init__()
        
        self.numparams = 7   
        
        self.user = ''
        self.element = ''
        self.operation = ''
        self.arguments = None
        self.forcemove = False
        
        
        #load from config file
        self._rainConf = RainMoveServerConf()
        self._rainConf.load_moveServerConfig() 
                
        self.port = self._rainConf.getMovePort()
        self.authorizedusers = self._rainConf.getMoveAuthorizedUsers()
        self.log_filename = self._rainConf.getMoveLog()
        self.logLevel = self._rainConf.getMoveLogLevel()
        
        self.protectedMachines=self._rainConf.getMovesProtectedMachines()
        
        self.proc_max = self._rainConf.getMoveProcMax()
        self.refresh_status = self._rainConf.getMoveRefreshStatus()
        
        self._ca_certs = self._rainConf.getMoveServerCaCerts()
        self._certfile = self._rainConf.getMoveServerCertFile()
        self._keyfile = self._rainConf.getMoveServerKeyFile()
        
        self.dbaddress = self._rainConf.getMoveDbAddress() 
        self.dbport = self._rainConf.getMoveDbPort()
        self.dbname = self._rainConf.getMoveDbName()
        
        print "\nReading Configuration file from " + self._rainConf.getConfigFile() + "\n"
        
        self.logger = self.setup_logger()
        
        self.fgfabric = Fabric(self._rainConf, self.logger, False)  #Fabric object
        
        if inventoryFile != None:
            fginventoryFile = InventoryFile(inventoryFile)
            nodesFile, servicesFile = self.fgfabric.loadGetNodesServices(fginventoryFile)

        fginventory = InventoryMongoDB(self.dbaddress, self.dbport, self.dbname)
        if fginventory.mongoConnection():
            if inventoryFile != None: #if we have this file we write it on DB
                fginventory.fromMemory2DB(nodesFile, servicesFile)
            self.fgfabric.load(fginventory)
        else:
            print "ERROR: connection with the database failed"
            sys.exit(-1)
        
        """
class RainMoveServer(object):

    def __init__(self, inventoryFile):
        super(RainMoveServer, self).__init__()
        
        self.numparams = 7   
        
        self.user = ''
        self.element = ''
        self.operation = ''
        self.arguments = None
        self.forcemove = False
        
        
        #load from config file
        self._rainConf = RainMoveServerConf()
        self._rainConf.load_moveServerConfig() 
                
        self.port = self._rainConf.getMovePort()
        self.authorizedusers = self._rainConf.getMoveAuthorizedUsers()
        self.log_filename = self._rainConf.getMoveLog()
        self.logLevel = self._rainConf.getMoveLogLevel()
        
        self.protectedMachines=self._rainConf.getMovesProtectedMachines()
        
        self.proc_max = self._rainConf.getMoveProcMax()
        self.refresh_status = self._rainConf.getMoveRefreshStatus()
        
        self._ca_certs = self._rainConf.getMoveServerCaCerts()
        self._certfile = self._rainConf.getMoveServerCertFile()
        self._keyfile = self._rainConf.getMoveServerKeyFile()
        
        self.dbaddress = self._rainConf.getMoveDbAddress() 
        self.dbport = self._rainConf.getMoveDbPort()
        self.dbname = self._rainConf.getMoveDbName()
        
        print "\nReading Configuration file from " + self._rainConf.getConfigFile() + "\n"
        
        self.logger = self.setup_logger()
        
        self.fgfabric = Fabric(self._rainConf, self.logger, False)  #Fabric object
        
        if inventoryFile != None:
            fginventoryFile = InventoryFile(inventoryFile)
            nodesFile, servicesFile = self.fgfabric.loadGetNodesServices(fginventoryFile)

        fginventory = InventoryMongoDB(self.dbaddress, self.dbport, self.dbname)
        if fginventory.mongoConnection():
            if inventoryFile != None: #if we have this file we write it on DB
                fginventory.fromMemory2DB(nodesFile, servicesFile)
            self.fgfabric.load(fginventory)
        else:
            print "ERROR: connection with the database failed"
            sys.exit(-1)
        
        """
        if inventoryfile != None:
            fginventory = InventoryFile(inventoryfile)
            self.fgfabric.load(fginventory)
        """
    """       
    def load(self, inventoryfile):
        fginventory = InventoryFile(inventoryfile)
        self.fgfabric.load(fginventory)
    """
    def setup_logger(self):
        #Setup logging
        logger = logging.getLogger("RainMoveServer")
        logger.setLevel(self.logLevel)    
        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        handler = logging.FileHandler(self.log_filename)
        handler.setLevel(self.logLevel)
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.propagate = False #Do not propagate to others
        
        return logger
    
    def auth(self, userCred):
        return FGAuth.auth(self.user, userCred)
    
    def start(self):  
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('', self.port))
        sock.listen(1)
        self.logger.info('Starting Server on port ' + str(self.port))
        while True:
            newsocket, fromaddr = sock.accept()
            connstream = None
            try:
                connstream = ssl.wrap_socket(newsocket,
                              server_side=True,
                              ca_certs=self._ca_certs,
                              cert_reqs=ssl.CERT_REQUIRED,
                              certfile=self._certfile,
                              keyfile=self._keyfile,
                              ssl_version=ssl.PROTOCOL_TLSv1)
                self.process_client(connstream)
            except ssl.SSLError:
                self.logger.error("Unsuccessful connection attempt from: " + repr(fromaddr))
            except socket.error:
                self.logger.error("Error with the socket connection")
            #except:
            #    self.logger.error("Uncontrolled Error: " + str(sys.exc_info()))
            finally:
                if type(connstream) is ssl.SSLSocket:
                    try: 
                        connstream.shutdown(socket.SHUT_RDWR)
                        connstream.close()
                    except:
                        pass
                    

    def process_client(self, connstream):
        self.logger.info('Accepted new connection')
        #receive the message
        data = connstream.read(2048)
        self.logger.debug("received data: " + data)
        params = data.split('|')
        #params[0] is user
        #params[1] is passwd
        #params[2] is passwd type
        #params[3] is resource (cluster, node, service)
        #params[4] is operation (add, remove, create, list...)
        #params[5] is arguments. This can be a list or a string. We can use eval() if it is a list.
        #params[6] is foce. THis is to force remove/move node from service
        if len(params) != self.numparams:
            msg = "ERROR: incorrect message"
            self.errormsg(connstream, msg)
            return
        
        self.user = params[0]
        passwd = params[1]
        passwdtype = params[2]
        self.resource = params[3]
        self.operation = params[4]
        try:
            value = eval(params[5]) #try to convert in list or None.
            if value:
                self.arguments = value
            else:
                self.arguments = [None]
        except:
            self.arguments = [params[5]]  #here means the argument was an string
        
        try:
            self.forcemove = eval(params[6].strip())
        except:
            self.forcemove = False

        #FORCE MOVE, identify where to put that and decide if eveyone is sending this parameter or not (i think I should send it)

        retry = 0
        maxretry = 3
        endloop = False
        while (not endloop):            
            userCred = FGCredential(passwdtype, passwd)          
            if self.user in self.authorizedusers:
                if (self.auth(userCred)):
                    connstream.write("OK")                                        
                    endloop = True
                else:
                    retry += 1
                    if retry < maxretry:
                        connstream.write("TryAuthAgain")
                        passwd = connstream.read(2048)
                    else:
                        msg = "ERROR: authentication failed"
                        endloop = True
                        self.errormsg(connstream, msg)
                        return
            else:
                msg = "ERROR: authentication failed. User is not allowed to use this service."
                endloop = True
                self.errormsg(connstream, msg)
                return

        #load protected machines just in case it changed
        self.protectedMachines = self._rainConf.load_moveServerConfigCheckProtected()
        #print self.protectedMachines
        if self.resource == 'service' and (self.operation == "add" or self.operation == "remove" or self.operation == "move"
                                           or self.operation == "info"):

            nodelist = self.arguments[:len(self.arguments)-1]
            if self.operation == "move":
                nodelist = self.arguments[:len(self.arguments)-2]
                          
            full=False
            proc_list = []
            joinstatus = []            
            for node in nodelist:         
                if len(proc_list) == self.proc_max:
                    full = True
                    while full:
                        for i in range(len(proc_list) - 1, -1, -1):
                            #self.logger.debug(str(proc_list[i]))
                            if not proc_list[i].is_alive():
                                #print "dead"                      
                                proc_list.pop(i)
                                full = False
                        if full:
                            time.sleep(self.refresh_status)
                try:
                    if self.operation == "move":
                        new_arguments=[node,self.arguments[len(self.arguments)-2],self.arguments[len(self.arguments)-1]]
                    else:                    
                        new_arguments=[node,self.arguments[len(self.arguments)-1]]
                    
                        
                    proc_list.append(Thread(target=eval("self.wrap_" + self.operation), args=(joinstatus,new_arguments)))            
                    proc_list[len(proc_list) - 1].start()
                except:
                    status = "ERROR: Node with "+node+" in FG Move server process. " + str(sys.exc_info())
                    #self.errormsg(connstream, msg)
                    
            for i in proc_list:
                i.join()
            
            status = ""
            for i in joinstatus:
                status += i + "\n"
                if re.search("^ERROR", i):
                    self.logger.error(i)
                    
            self.okmsg(connstream, status)
            
            if self.operation != "info":
                #Put in the logs the current status of the services
                self.printCurrentStatus()
            
        else:
            
            try:
                
                status = eval("self." + self.operation + "("+str(self.arguments)+")")
                
            except:
                msg = "ERROR: incorrect operation " + str(sys.exc_info())
                self.errormsg(connstream, msg)
                return
            
            
            if re.search("^ERROR", status):
                #sends ERROR: ... 
                self.errormsg(connstream, status)
                #return
            else:
                
                #sends OK
                self.okmsg(connstream, status)
                
        
        self.logger.info("Rain Move Server DONE")
    
    def create(self, arguments):
        '''create empty clusters or services'''
        status = 'OK'
        
        if self.resource == 'cluster':
            if self.fgfabric.getCluster(self.arguments[0]) == None:
                self.fgfabric.addCluster(Cluster(self.arguments[0]))
                status = "The cluster has been successfully created."
            else:
                status = "ERROR: the Cluster already exists"
        elif self.resource == 'service':
            if self.fgfabric.getService(self.arguments[0]) == None:                
                if self.arguments[1].lower() == 'hpc':
                    success, msg = self.fgfabric.addService(HPCService(self.arguments[0]))
                elif self.arguments[1].lower() == 'eucalyptus':
                    success, msg = self.fgfabric.addService(EucaService(self.arguments[0]))
                elif self.arguments[1].lower() == 'openstack':
                    success, msg = self.fgfabric.addService(OpenStackService(self.arguments[0]))
                elif self.arguments[1].lower() == 'nimbus':
                    success, msg = self.fgfabric.addService(NimbusService(self.arguments[0]))
                elif self.arguments[1].lower() == 'opennebula':
                    success, msg = self.fgfabric.addService(OpenNebulaService(self.arguments[0]))
                if success:
                    status = "The service has been successfully created."
                else:
                    status = "ERROR: " + msg
            else:
                status = "ERROR: the Service already exists"
        
        return status
    
    def wrap_add(self, joinstatus, arguments):
        
        joinstatus.append(self.add(arguments))
    
    
    def add(self, arguments):
        '''add new node; existing node to a cluster; existing node to a service, etc.
        '''
        status = 'OK'
        # add a new node
        if self.resource == 'node':
            
            if arguments[0] in self.protectedMachines or arguments[1] in self.protectedMachines or arguments[2] in self.protectedMachines:
                status = "ERROR: the machine is protected"
            else:
                #construcing a node from args
                #accepting format of: id,name,ip,cluster
                newnode = Node(arguments[0], arguments[1], arguments[2], arguments[3])
    
                #ADD node to the node list
                if self.fgfabric.getNode(arguments[0]) == None:
                    cluster = self.fgfabric.getCluster(arguments[3])
                    if cluster != None:
                        self.fgfabric.addNode(newnode)
                        if not cluster.add(newnode):
                            status = 'ERROR: adding the cluster'
                    else:
                        status = "ERROR: the Node cannot be added because the Cluster does not exists"
                else:
                    status = "ERROR: the Node already exists"    
             
        # add a node to a service. This internally invokes the implementations for specific service types.    
        elif self.resource == 'service':
            existingnode = self.fgfabric.getNode(arguments[0])
            if existingnode != None:
                if arguments[0] in self.protectedMachines or existingnode.ip in self.protectedMachines or existingnode.name in self.protectedMachines:
                    status = "ERROR: the machine is protected"
                else:                    
                    service = self.fgfabric.getService(arguments[1])
                    if service != None:
                        success, restatus = service.add(existingnode)
                        if not success:
                            status = "ERROR: adding the node " + arguments[0] + " to the service " + arguments[1] + ". " + str(restatus)
                        else:
                            status = "The node " + arguments[0] + " have been successfully integrated into the service. " + arguments[1] + ". " + str(restatus)
                            try:      
                                self.fgfabric.addNode2Service(arguments[0],service)
                            except:
                                status = "ERROR: adding the node " + arguments[0] + ". Storing information in the persistent data in the Fabric. " + str(sys.exc_info())
                                                
                    else:
                        status = "ERROR: the Node " + arguments[0] + " cannot be added because the Service does not exists"
            else:
                status = "ERROR: the Node " + arguments[0] + " does not exists"

        return status
    
    def wrap_remove(self,joinstatus, arguments):
        
        joinstatus.append(self.remove(arguments))
    
    def remove(self, arguments):
        status = 'OK'
        if self.resource == 'node':
            #if arguments[0] in self.protectedMachines or arguments[1] in self.protectedMachines or arguments[2] in self.protectedMachines:
            #    status = "ERROR: the machine is protected"
            #else:
            status = "ERROR: Not supported yet"
        elif self.resource == 'cluster':
            status = "ERROR: Not supported yet"
        elif self.resource == 'service':  #Remove a node from a service
            if arguments[0] in self.protectedMachines:
                status = "ERROR: the machine is protected"
            else:
                service = self.fgfabric.getService(arguments[1])
                if service != None:
                    success, restatus = service.remove(arguments[0], self.forcemove)
                    if not success:
                        status = "ERROR: removing the node " + arguments[0] + " from the service " + arguments[1] + ". " + str(restatus)
                    else:
                        status = "The node " + arguments[0] + " have been successfully deleted from the service " + arguments[1] + ". " + str(restatus)
                        try:
                            self.fgfabric.removeNodeFromService(arguments[0],service)
                        except:
                            status = "ERROR: removing the node " + arguments[0] + ". Storing information in the persistent data in the Fabric. " + str(sys.exc_info())
                    
                else:
                    status = "ERROR: the Node " + arguments[0] + " cannot be deleted because the Service does not exists"
                        
        return status
    
    def wrap_move(self,joinstatus, arguments):
        
        joinstatus.append(self.move(arguments))
    
    def move(self, arguments):
        status = 'ERROR: Wrong resource.'
        if self.resource == 'service':
            status = self.remove(arguments)
            if not re.search("^ERROR",status):
                arguments[1] = arguments[2]
                status = self.add(arguments)           
                        
        return status
    
    def wrap_info(self,joinstatus, arguments):
        
        joinstatus.append(self.info(arguments))
    
    def info(self, arguments):
        if self.resource == 'node':
            if arguments[0] in self.fgfabric.getNode().keys():
                status = str(self.fgfabric.getNode()[arguments[0]])
            else:
                status = "ERROR: The node " + arguments[0] + " does not exists."
            
        elif self.resource == 'service':
            existingnode = self.fgfabric.getNode(arguments[0])
            if existingnode != None:
                service = self.fgfabric.getService(arguments[1])
                if service != None:
                    success, restatus = service.info(existingnode)
                    if not success:
                        status = "ERROR: Getting information of the node " + arguments[0] + " from the service " + arguments[1] + ". " + str(restatus)
                    else:
                        status = "Status of the node " + arguments[0] + ": " + str(restatus)
                else:
                    status = "ERROR: the Service " + arguments[1] + " does not exists"
            else:
                status = "ERROR: the Node " + arguments[0] + " does not exists"
                
        return status
    
    def lists(self, arguments):
        status = 'ERROR: Wrong resource.'
        if self.resource == 'cluster':
            if not arguments[0]: #print
                cluster = self.fgfabric.getCluster()
                status = "The list of clusters is: " + str(cluster.keys())                
            else:
                cluster = self.fgfabric.getCluster(arguments[0])
                if cluster != None:
                    status = "Details of cluster " + str(arguments[0]) + " cluster: " + str(cluster.list().keys())

        elif self.resource == 'service':
            if not arguments[0]: #print
                service = self.fgfabric.getService()
                status = "The list of services is: " + str(service.keys())
            else:
                service = self.fgfabric.getService(arguments[0])
                if service != None:
                    status = "Details of service " + str(arguments[0]) + " service: " + str(service.list().keys())
            
        return status

    def listfreenodes(self, arguments):
        status = "ERROR: getting the list of free nodes"
        
        dictfree={}
        
        if not arguments[0]: #print
            listcluster = self.fgfabric.getCluster()
            for i in listcluster:                
                dictfree[i]=[]
                cluster = self.fgfabric.getCluster(i)
                listnodes=cluster.list()
                for j in listnodes:
                    if listnodes[j].allocated == 'FREE':
                        dictfree[i].append(listnodes[j].identifier)
            status = str(dictfree)
        else:
            cluster = self.fgfabric.getCluster(arguments[0])
            dictfree[arguments[0]]=[]
            listnodes=cluster.list()
            for j in listnodes:
                if listnodes[j].allocated == 'FREE':
                    dictfree[i].append(listnodes[j].identifier)
                    
            status = str(dictfree)
        
        return status

    def printCurrentStatus(self):
        services_details={}
        services = self.fgfabric.getService()
        #print services
        
        for i in services.keys(): 
            serv = self.fgfabric.getService(i)
            services_details[i]=serv.list().keys()
            #"Details of service " + str(arguments[0]) + " service: " + str(service.list().keys())
            
        services_details['freenodes']=self.listfreenodes([None])
        self.logger.debug( "CURRENT_STATUS=" + str(services_details))
        
    def okmsg(self, connstream, msg):
        connstream.write(msg)
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()

    def errormsg(self, connstream, msg):
        self.logger.error(msg)
        try:
            connstream.write(msg)
            connstream.shutdown(socket.SHUT_RDWR)
            connstream.close()
        except:
            self.logger.debug("In errormsg: " + str(sys.exc_info()))
        self.logger.info("Rain Move Server DONE")