Ejemplo n.º 1
0
class ChirpServerProcessProtocol(protocol.ProcessProtocol):

    logger = logging.getLogger(support.discoverCaller())

    def __init__(self, aclFileName):
        self._aclFileName = aclFileName

    def connectionMade(self):
        self.transport.closeStdin()
        self.logger.debug("Process started!")

    def outReceived(self, data):
        self.logger.debug("Chirp Server stdout: %s" % data)

    def errReceived(self, data):
        self.logger.debug("Chirp Server stderr: %s" % data)

    def inConnectionLost(self):
        pass  #we don't care about stdin. We do in fact close it ourselves

    def outConnectionLost(self):
        self.logger.info("Chirp Server closed its stdout")

    def errConnectionLost(self):
        self.logger.info("Chirp Server closed its stderr")

    def processExited(self, reason):
        #This is called when the child process has been reaped
        os.remove(self._aclFileName)

    def processEnded(self, reason):
        #This is called when all the file descriptors associated with the child
        #process have been closed and the process has been reaped
        self.logger.warn("Process ended (code: %s) " % reason.value.exitCode)
Ejemplo n.º 2
0
class BaseStompEngine(stomper.Engine):
    """
  G{classtree BaseStompEngine}
  """

    logger = logging.getLogger(support.discoverCaller())

    @inject.param('msgInterpreter', MsgInterpreter, scope=inject.appscope)
    def __init__(self, msgInterpreter):
        super(BaseStompEngine, self).__init__()
        self._msgInterpreter = msgInterpreter

    def ack(self, msg):
        """Called when a MESSAGE message is received"""
        #msg is an unpacked frame
        self._msgInterpreter.interpret(msg)
        return stomper.NO_REPONSE_NEEDED

    def react(self, msg):
        """ Returns an iterable of responses """
        rxdFrame = stomper.unpack_frame(msg)
        cmd = rxdFrame['cmd']

        self.logger.info("Received a %s message." % cmd)
        self.logger.debug("Headers: %s ; Body: %s" %
                          (rxdFrame['headers'], rxdFrame['body']))
        try:
            res = list(stomper.Engine.react(self, msg))
        except Exception, e:
            self.logger.error(str(e))
            res = stomper.NO_REPONSE_NEEDED
        return res
Ejemplo n.º 3
0
def unpause(vm): 
  def impl():
    return _execProgressCmd(vm, 'unpause', None)

  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread( impl )
  return d
Ejemplo n.º 4
0
def getPerformanceData(vm):
    def impl():
        return _perf.query(["*"], [vm])

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 5
0
def restoreSnapshot(vm):
    def impl():
        return _execProgressCmd(vm, 'restoreSnapshot', (name, desc))

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 6
0
def getPerformanceData(vm):
  def impl():
    return _perf.query( ["*"], [vm] )
    
  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread(impl)
  return d
Ejemplo n.º 7
0
def restoreSnapshot(vm):
  def impl():
    return _execProgressCmd(vm, 'restoreSnapshot', (name, desc))

  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread( impl )
  return d
Ejemplo n.º 8
0
def pause(vm):
    def impl():
        return _execProgressCmd(vm, 'pause', None)

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 9
0
class CommandExecuter(object):

    logger = logging.getLogger(support.discoverCaller())

    def __init__(self, cmdId, parameters):
        #parameters is a dict
        self._cmdId = cmdId
        self._parameters = parameters

    def executeCommand(self):
        """ 
    Executes (or tries to) cmd.

    Runs cmd, returning a tuple (stdout, stderr) with the
    contents of the execution
    """
        res = None
        cmd = self._parameters.pop('cmd')
        fileForStdin = self._parameters.pop('fileForStdin')
        try:
            if fileForStdin:
                fileForStdin = file(fileForStdin, 'r')
        except Exception, e:
            res = defer.fail(('', str(e), -1))  #mimic process output
            self._execResUsage = resource.getrusage(resource.RUSAGE_CHILDREN)
        else:
Ejemplo n.º 10
0
class VMStompEngine(BaseStompEngine):
  """ This basically models a client (ie, VM instance)"""
  
  logger = logging.getLogger(support.discoverCaller())

  config = inject.attr("config")
  words = inject.attr("words")
  stompProtocol = inject.attr('stompProtocol', scope=inject.appscope)


  def __init__(self):
    super( VMStompEngine, self).__init__()
 
    networkInterface = self.config.get('VM', 'network_interface')

    networkInterfaceData = netifaces.ifaddresses(networkInterface)
    self._id, self._ip = [ networkInterfaceData[af][0]['addr'] for af in (netifaces.AF_LINK, netifaces.AF_INET) ]
    self._id = self._id.upper()
    self.logger.debug("VM instantiated with id/ip %s/%s" % (self._id, self._ip) )

    self._descriptor = EntityDescriptor(self._id, ip=self._ip)


  @property
  def descriptor(self):
    return self._descriptor

  def connected(self, msg):
    res = []
    #once connected, subscribe
    res.append(stomper.subscribe(destinations.CMD_REQ_DESTINATION))

    #announce ourselves
    res.append( self.words['HELLO']().howToSay() )
 
    return tuple(res)

  def pong(self, pingMsg):
    self.stompProtocol.sendMsg( self.words['PONG']().howToSay(pingMsg) )

  def dealWithExecutionResults(self, results):
    resultsFields = ('cmd-id', 'out', 'err', 'finished', 'exitCodeOrSignal', 'resources' )
    #see CommandExecuter.getExecutionResults

    resultsDict = dict( zip( resultsFields, results ) )
    #self.protocol got injected by StompProtocol
    self.stompProtocol.sendMsg( self.words['CMD_RESULT']().howToSay(resultsDict) )

  @property
  def id(self):
    return self._id

  @property
  def ip(self):
    return self._ip

  def __repr__(self):
    return "VM with ID/IP: %s/%s" % (self.id, self.ip)
Ejemplo n.º 11
0
def listAvailableVMs():
  def impl():
    vbox = _ctx['vbox']
    ms = _getMachines()
    msNames = [ str(m.name) for m in ms ]
    return msNames
  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread(impl)
  return d
Ejemplo n.º 12
0
def listAvailableVMs():
    def impl():
        vbox = _ctx['vbox']
        ms = _getMachines()
        msNames = [str(m.name) for m in ms]
        return msNames

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 13
0
def listVMsWithState():
  def impl():
    vbox = _ctx['vbox']
    ms = _getMachines()
    msNamesAndStates = [ (str(m.name), _getNameForMachineStateCode(m.state)) \
        for m in ms ]
    return dict(msNamesAndStates)
  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread(impl)
  return d
Ejemplo n.º 14
0
class HostStompEngine(BaseStompEngine):

    logger = logging.getLogger(support.discoverCaller())

    def __init__(self):
        super(HostStompEngine, self).__init__()

    def connected(self, msg):
        #once connected, subscribe
        return (stomper.subscribe(destinations.CONN_DESTINATION),
                stomper.subscribe(destinations.CMD_RES_DESTINATION))
Ejemplo n.º 15
0
def getState( vm): 
  def impl():
    m = _ctx['vbox'].findMachine(vm)
    stateCode = m.state
    stateName = _getNameForMachineStateCode(stateCode)
    return stateName

  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread(impl)
  
  return d
Ejemplo n.º 16
0
def getState(vm):
    def impl():
        m = _ctx['vbox'].findMachine(vm)
        stateCode = m.state
        stateName = _getNameForMachineStateCode(stateCode)
        return stateName

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)

    return d
Ejemplo n.º 17
0
def listVMsWithState():
    def impl():
        vbox = _ctx['vbox']
        ms = _getMachines()
        msNamesAndStates = [ (str(m.name), _getNameForMachineStateCode(m.state)) \
            for m in ms ]
        return dict(msNamesAndStates)

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 18
0
def createVM(name, hddImagePath):
    vbox = _ctx['vbox']
    mgr = _ctx['mgr']

    def impl():
        ms = _getMachines()
        for m in ms:
            if m.name == name:
                raise ValueError("VM '%s' already exists" % name)
        guestType = vbox.getGuestOSType('Linux26')
        newMachine = vbox.createMachine(
            name, guestType.id, "", "00000000-0000-0000-0000-000000000000",
            False)
        if not os.path.isfile(hddImagePath):
            raise IOError("HDD image path doesn't point to a valid file: %s" %
                          hddImagePath)

        try:
            newMachine.saveSettings()
            #register the machine with VB (ie, make it visible)
            vbox.registerMachine(newMachine)

            session = mgr.getSessionObject(vbox)
            vbox.openSession(session, newMachine.id)
            mutableM = session.machine
            _attachNICs(mutableM)
            _addSCSIStorageController(mutableM)
            _attachHDToMachine(mutableM, hddImagePath)
        except:
            if session.state == _ctx['ifaces'].SessionState_Open:
                session.close()

            m = vbox.unregisterMachine(newMachine.id)
            m.deleteSettings()
            msg = "Rolled back creation of VM '%s'" % m.name
            logger.debug(msg)

            #the following two lines should go in a finally:,
            #but that's not supported by python 2.4
            if session.state == _ctx['ifaces'].SessionState_Open:
                session.close()

            raise

        #the following two lines should go in a finally:,
        #but that's not supported by python 2.4
        if session.state == _ctx['ifaces'].SessionState_Open:
            session.close()

        return (True, name)

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 19
0
def listRunningVMs():
  def impl():
    vbox = _ctx['vbox']
    ms = _getMachines()
    isRunning = lambda m: m.state ==  _ctx['ifaces'].MachineState_Running
    res = filter( isRunning, ms )
    res = [ str(m.name) for m in res ]
    return res
  
  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread(impl)
  return d
Ejemplo n.º 20
0
def listRunningVMs():
    def impl():
        vbox = _ctx['vbox']
        ms = _getMachines()
        isRunning = lambda m: m.state == _ctx['ifaces'].MachineState_Running
        res = filter(isRunning, ms)
        res = [str(m.name) for m in res]
        return res

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    d = threads.deferToThread(impl)
    return d
Ejemplo n.º 21
0
class FileTxs(object):
    """ 
  Handles the file transmission (to and from).
  """
    logger = logging.getLogger(support.discoverCaller())
    vmRegistry = inject.attr('VMRegistry', VMRegistry)

    def __init__(self):
        pass

    def cpFileToVM(self, vmId, pathToLocalFileName, pathToRemoteFileName=None):
        """
    @param pathToRemoteFileName where to store the file, relative to the root of the server.
    If None, the basename of the source will be stored in the / of the server.
    """
        #this returns a deferred whose callbacks take care of returning the result
        if not self.vmRegistry.isValid(vmId):
            msg = "Invalid VM Id: '%s'" % vmId
            self.logger.error(msg)
            dres = defer.fail(msg)
        else:
            vmIp = self.vmRegistry[vmId].ip
            if not pathToRemoteFileName:
                pathToRemoteFileName = basename(pathToLocalFileName)
            #chirp_put [options] <local-file> <hostname[:port]> <remote-file>
            args = ('-t 10', pathToLocalFileName, vmIp, pathToRemoteFileName
                    )  #FIXME: magic numbers
            chirp_cmd = join(self._chirpPath, 'chirp_put')
            dres = utils.getProcessOutputAndValue(chirp_cmd, args)

        return dres

    def cpFileFromVM(self,
                     vmId,
                     pathToRemoteFileName,
                     pathToLocalFileName=None):
        #this returns a deferred whose callbacks take care of returning the result
        if not self.vmRegistry.isValid(vmId):
            msg = "Invalid VM Id: '%s'" % vmId
            self.logger.error(msg)
            dres = defer.fail(msg)
        else:
            vmIp = self._vms[vmId].ip
            if not pathToLocalFileName:
                pathToLocalFileName = pathToRemoteFileName
            #chirp_get [options] <hostname[:port]> <remote-file> <local-file>
            args = ('-t 10', vmIp, pathToRemoteFileName, pathToLocalFileName
                    )  #FIXME: magic numbers
            chirp_cmd = join(self._chirpPath, 'chirp_get')
            dres = utils.getProcessOutputAndValue(chirp_cmd, args)
        return dres
Ejemplo n.º 22
0
def createVM(name, hddImagePath):
  vbox = _ctx['vbox']
  mgr = _ctx['mgr']
  def impl():
    ms = _getMachines()
    for m in ms:
      if m.name == name:
        raise ValueError("VM '%s' already exists" % name)
    guestType = vbox.getGuestOSType('Linux26') 
    newMachine = vbox.createMachine(name, guestType.id, "", "00000000-0000-0000-0000-000000000000", False)
    if not os.path.isfile( hddImagePath ):
      raise IOError("HDD image path doesn't point to a valid file: %s" % hddImagePath )
      
    try:
      newMachine.saveSettings()
      #register the machine with VB (ie, make it visible)
      vbox.registerMachine( newMachine )
      
      session = mgr.getSessionObject(vbox)
      vbox.openSession( session, newMachine.id )
      mutableM = session.machine
      _attachNICs( mutableM )
      _addSCSIStorageController( mutableM )
      _attachHDToMachine( mutableM, hddImagePath )
    except: 
      if session.state == _ctx['ifaces'].SessionState_Open :
        session.close()

      m = vbox.unregisterMachine(newMachine.id)
      m.deleteSettings()
      msg = "Rolled back creation of VM '%s'" % m.name
      logger.debug(msg)

      #the following two lines should go in a finally:,
      #but that's not supported by python 2.4
      if session.state == _ctx['ifaces'].SessionState_Open:
        session.close()

      raise

    #the following two lines should go in a finally:,
    #but that's not supported by python 2.4
    if session.state == _ctx['ifaces'].SessionState_Open:
      session.close()

    return (True, name)

  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  d = threads.deferToThread( impl )
  return d
Ejemplo n.º 23
0
def start(vm):
    #what an ugly hack this is...
    if platform.system() != "Windows":

        def impl():
            session = _ctx['mgr'].getSessionObject(_ctx['vbox'])
            mach = _findMachineByNameOrId(vm)

            logger.info("Starting VM for machine %s" % mach.name)

            progress = _ctx['vbox'].openRemoteSession(session, mach.id, "vrdp",
                                                      "")
            progress.waitForCompletion(WAITING_GRACE_MS)
            completed = progress.completed
            if completed and (progress.resultCode == 0):
                logger.info("Startup of machine %s completed: %s" %
                            (mach.name, str(completed)))
            else:
                _reportError(progress)
                return False

            session.close()
            return True

        d = threads.deferToThread(impl)

    else:
        m = _findMachineByNameOrId(vm)
        mName = str(m.name)
        processProtocol = VBoxHeadlessProcessProtocol()
        pseudoCWD = os.path.dirname(sys.modules[__name__].__file__)
        vboxBinariesPath = None  #TODO: use VBOX_INSTALL_PATH
        cmdWithPath = os.path.join(pseudoCWD, 'scripts', 'vboxstart.bat')
        cmdWithArgs = ("vboxstart.bat", vboxBinariesPath, mName)
        cmdPath = os.path.join(pseudoCWD, 'scripts')
        newProc = lambda: reactor.spawnProcess(processProtocol,
                                               cmdWithPath,
                                               args=cmdWithArgs,
                                               env=None,
                                               path=cmdPath)
        reactor.callWhenRunning(newProc)
        d = True  #in order to have a unique return

    try:
        _startCollectingPerfData(vm)
    except:
        pass  #TODO: loggging

    logger.debug("Controller method %s invoked" % support.discoverCaller())
    return d
Ejemplo n.º 24
0
class CommandRegistry(object):
    """ 
  For all command-execution related. 

  Keeps track of requests made, served and retired
  """
    logger = logging.getLogger(support.discoverCaller())

    words = inject.attr('words')
    vmRegistry = inject.attr('vmRegistry', VMRegistry)

    def __init__(self):
        self._cmdReqsSent = {
        }  #cmdId: dict with keys (timestamp, to, cmd, args, env, path)
        self._cmdReqsRetired = {}  #finished cmdReqsSent
        self._cmdReqsRcvd = {}

    def addCmdRequest(self, cmdId, requestInfoDict):
        self._cmdReqsSent[cmdId] = requestInfoDict

    def processCmdResult(self, resultsMsg):
        serializedResults = resultsMsg['body'].split(None, 1)[1]
        #serializeded data: dict with keys (cmd-id, out, err, finished?, code/signal, resources)
        results = support.deserialize(serializedResults)
        self.logger.debug("Deserialized results: %s" % results)
        cmdId = results.pop('cmd-id')
        #this comes from a word.CMD_RESULT.listenAndAct
        #note down for which cmd we are getting the result back
        assert cmdId in self._cmdReqsSent
        self._cmdReqsRcvd[cmdId] = results
        self._cmdReqsRetired[cmdId] = self._cmdReqsSent.pop(cmdId)
        self.logger.info("Received command results for cmd-id '%s'", cmdId)

    def popCmdResults(self, cmdId):
        # for invalid cmdIds, returning None could
        # result in problems with xml-rpc. Thus we
        # resource to an empty string, which likewise
        # fails a boolean test
        return self._cmdReqsRcvd.pop(cmdId, "")

    def listFinishedCmds(self):
        return self._cmdReqsRcvd.keys()

    def getCmdDetails(self, cmdId):
        details = self._cmdReqsSent.get(cmdId)
        if not details:
            details = self._cmdReqsRetired.get(cmdId)
        return support.serialize(details)
Ejemplo n.º 25
0
def start(vm):
  #what an ugly hack this is...
  if platform.system() != "Windows":
    def impl():
      session = _ctx['mgr'].getSessionObject(_ctx['vbox'])
      mach = _findMachineByNameOrId(vm)

      logger.info("Starting VM for machine %s" % mach.name)

      progress = _ctx['vbox'].openRemoteSession(session, mach.id, "vrdp", "")
      progress.waitForCompletion(WAITING_GRACE_MS) 
      completed = progress.completed
      if completed and (progress.resultCode == 0):
        logger.info("Startup of machine %s completed: %s" % (mach.name, str(completed)))
      else:
        _reportError(progress)
        return False

      session.close() 
      return True 

    d = threads.deferToThread(impl)
    
  else: 
    m = _findMachineByNameOrId(vm)
    mName = str(m.name)
    processProtocol = VBoxHeadlessProcessProtocol()
    pseudoCWD = os.path.dirname(sys.modules[__name__].__file__)
    vboxBinariesPath = None #TODO: use VBOX_INSTALL_PATH
    cmdWithPath = os.path.join(pseudoCWD, 'scripts', 'vboxstart.bat')
    cmdWithArgs = ("vboxstart.bat", vboxBinariesPath, mName)
    cmdPath = os.path.join(pseudoCWD, 'scripts')
    newProc = lambda: reactor.spawnProcess( processProtocol, cmdWithPath, args=cmdWithArgs, env=None, path=cmdPath )
    reactor.callWhenRunning(newProc)
    d = True #in order to have a unique return 

  try:
    _startCollectingPerfData(vm)
  except:
    pass #TODO: loggging
  
  logger.debug("Controller method %s invoked" % support.discoverCaller() )
  return d
Ejemplo n.º 26
0
class StompProtocol(Protocol):

    #transport available at self.transport, as set by BaseProtocol.makeConnection
    #factory available at self.factory, as set by Factory.buildProtocol

    logger = logging.getLogger(support.discoverCaller())

    stompEngine = inject.attr('stompEngine')
    config = inject.attr('config')

    def __init__(self):
        self._username = self.config.get('Broker', 'username')
        self._password = self.config.get('Broker', 'password')

    def sendMsg(self, msg):
        self.logger.debug("Sending msg '%s'" % msg)
        self.transport.write(msg)

    def connectionMade(self):
        """
    Called when a connection is made. 
    Protocol initialization happens here
    """
        self.logger.info("Connection with the broker made")
        stompConnectMsg = stomper.connect(self._username, self._password)
        self.sendMsg(stompConnectMsg)

        try:
            self.factory.resetDelay()
        except:
            pass

    def connectionLost(self, reason):
        """Called when the connection is shut down"""
        self.logger.info("Connection with the broker lost")

    def dataReceived(self, data):
        """Called whenever data is received"""
        reactions = self.stompEngine.react(data)
        if reactions:
            for reaction in filter(None, reactions):
                self.sendMsg(reaction)
Ejemplo n.º 27
0
class StompProtocolFactory(ReconnectingClientFactory):
    """ Responsible for creating an instance of L{StompProtocol} """

    logger = logging.getLogger(support.discoverCaller())

    __stompProtocol = inject.attr('stompProtocol')
    initialDelay = delay = 5.0
    factor = 1.0
    jitter = 0.0

    def __init__(self):
        #retry every 5 seconds, with no back-off
        self.protocol = lambda: self.__stompProtocol  #sigh... self.protocol must be callable

    def clientConnectionLost(self, connector, reason):
        self.logger.info("Connection with the broker lost: %s" % reason)
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

    def clientConnectionFailed(self, connector, reason):
        self.logger.error("Connection with the broker failed: %s" % reason)
        ReconnectingClientFactory.clientConnectionFailed(
            self, connector, reason)
Ejemplo n.º 28
0
class MsgInterpreter(object):

    logger = logging.getLogger(support.discoverCaller())

    @inject.param('words')
    def __init__(self, words):
        """ 
    @param words a list of "words" (ie, commands represented as classes)
    
    """
        self._words = words

    def interpret(self, msg):
        #msg is an unpacked STOMP frame
        firstWord = msg['body'].split(None,
                                      1)[0]  #only interested in the 1st word

        self.logger.debug("Trying to interpret %s" % (firstWord, ))
        try:
            word = self._words[firstWord]()
        except KeyError:
            raise NameError("Word '%s' unknown" % firstWord)

        word.listenAndAct(msg)
Ejemplo n.º 29
0
import CommandExecuter
from boincvm.common import support

import logging
import time
import stomper
import fnmatch

logger = logging.getLogger(support.discoverCaller())

CMD_REQ_DESTINATION = "/topic/cmd_requests"
CMD_RES_DESTINATION = "/topic/cmd_responses"
CONN_DESTINATION = "/topic/connections"


class BaseWord(object):
    """ Initializes the Frame object with the inheriting class' name """
    def __init__(self, src, dst):
        """
    @param invoker instance of the element (host, vm) receiving/sending the word.
    """
        self._frame = stomper.Frame()
        self._frame.body = self.__name__
        headers = {}
        headers['from'] = src
        headers['to'] = dst
        headers['timestamp'] = str(time.time())
        self._frame.headers = headers
        self._frame.cmd = 'SEND'
Ejemplo n.º 30
0
from boincvm.common import support

import logging
import time
import stomper
import inject
import pdb

logger = logging.getLogger(support.discoverCaller())


class BaseWord(object):
    """ Initializes the Frame object with the inheriting class' name """

    @inject.param("subject")
    def __init__(self, subject):
        self.subject = subject

        self.frame = stomper.Frame()
        self.frame.cmd = "SEND"
        self.frame.body = self.name

        headers = {}
        headers["from"] = subject.descriptor.id
        headers["timestamp"] = str(time.time())
        self.frame.headers = headers

    @property
    def name(self):
        """ Get the word's name """
        return self.__class__.__name__
Ejemplo n.º 31
0
class VMRegistry(object):
    """
  Keeps track of the registered virtual machines.
  """
    logger = logging.getLogger(support.discoverCaller())

    #PING/PONG
    #HELLO/BYE
    #STILL_ALIVE

    @inject.param('hvController')
    def __init__(self, hvController):
        self._vms = {}
        self._hvController = hvController
        self._idsToNames = self._getIdsToNamesMapping()
        self._namesToIds = dict(
            (v, k) for k, v in self._idsToNames.iteritems())

    def addVM(self, vmDescriptor):
        """
    @param vmDescriptor an instance of L{EntityDescriptor}
    """

        name = self.getNameForId(vmDescriptor.id)
        vmDescriptor.name = name
        self._vms[vmDescriptor.id] = vmDescriptor
        self.logger.info("VM '%s' has joined the party" %
                         self._vms[vmDescriptor.id].name)

    def removeVM(self, vmId):
        """ Removes a VM from the party """
        vmDescriptor = self._vms.pop(vmId)
        self.logger.info("VM '%s' has left the party" % vmDescriptor.name)

    def isValid(self, vmId):
        return vmId in self._vms

    def __getitem__(self, vmId):
        return self._vms[vmId]

    def getRegisteredVMs(self):
        """ Returns a list of the registered VMs """
        return self._vms.keys()

    def getNameForId(self, vmId):
        name = self._idsToNames.get(vmId)
        if not name:
            self.logger.error(
                "Unable to match VM ID '%s' to any registered VM (is \
          the VM controller really running from within a VM?)", str(vmId))
            raise Exceptions.NoSuchVirtualMachine(str(vmId))
        else:
            return name

    def getIdForName(self, vmName):
        id_ = self._namesToIds.get(vmName)
        if not id_:
            self.logger.error(
                "Unable to match VM name '%s' to any registered VM (is \
          the VM controller really running from within a VM?)", vmName)
            raise Exceptions.NoSuchVirtualMachine(vmName)
        else:
            return id_

    def _getIdsToNamesMapping(self):
        def holder():
            pass

        holder.res = None

        @defer.inlineCallbacks
        def _initializeIdsToNamesMapping():
            idsToNamesMap = yield self._hvController.getIdsToNamesMapping()
            self.logger.debug("Ids -> Names table initialized: %s" %
                              idsToNamesMap)
            holder.res = idsToNamesMap

        _initializeIdsToNamesMapping()
        return holder.res
Ejemplo n.º 32
0
class HostXMLRPCService(xmlrpc.XMLRPC, object):

    logger = logging.getLogger(support.discoverCaller())

    @inject.param('config')
    @inject.param('hvController')
    @inject.param('subject')
    def __init__(self, config, hvController, subject):
        xmlrpc.XMLRPC.__init__(self)
        self._config = config

        self._hvController = hvController
        self._createHVControllerMethods()

        self._host = subject

    #from xmlrpc.XMLRPC
    def _getFunction(self, functionPath):
        f = super(HostXMLRPCService, self)._getFunction(functionPath)

        # f is an xmlrpc_ method

        def wrapWithCallbacks(*args, **kw):
            return defer.maybeDeferred(f, *args,
                                       **kw).addCallbacks(_success, _fail)

        return wrapWithCallbacks

    def makeEngineAccesible(self):
        siteRoot = resource.Resource()
        siteRoot.putChild('RPC2', self)
        port = int(self._config.get('Host', 'xmlrpc_port'))
        listen_on = self._config.get('Host', 'xmlrpc_listen_on')
        reactor.listenTCP(port, server.Site(siteRoot), interface=listen_on)

    ###########################
    ## Operation on the VMs  ##
    ###########################
    def xmlrpc_listRegisteredVMs(self):
        registeredVMIds = self._host.getRegisteredVMs()
        return map(self._getNameForId, registeredVMIds)

    def xmlrpc_runCmd(self,
                      toVmName,
                      cmd,
                      args=(),
                      env={},
                      path=None,
                      fileForStdin=''):
        cmdId = self._host.sendCmdRequest(toVmName, cmd, args, env, path,
                                          fileForStdin)
        return cmdId

    def xmlrpc_ping(self,
                    toVmName,
                    timeout_secs=5.0):  #FIXME: magic number of seconds
        vmId = self._getIdForName(toVmName)
        return self._host.ping(vmId, timeout_secs)

    def xmlrpc_listFinishedCmds(self):
        return self._host.listFinishedCmds()

    def xmlrpc_getCmdResults(self, cmdId):
        return self._host.getCmdResults(cmdId)

    def xmlrpc_getCmdDetails(self, cmdId):
        return self._host.getCmdDetails(cmdId)

    def xmlrpc_cpFileToVM(self,
                          vmName,
                          pathToLocalFileName,
                          pathToRemoteFileName=None):
        vmId = self._getIdForName(vmName)
        return self._host.cpFileToVM(vmId, pathToLocalFileName,
                                     pathToRemoteFileName)

    def xmlrpc_cpFileFromVM(self,
                            vmName,
                            pathToRemoteFileName,
                            pathToLocalFileName=None):
        vmId = self._getIdForName(vmName)
        return self._host.cpFileFromVM(vmId, pathToRemoteFileName,
                                       pathToLocalFileName)

    ################################################
    ## Hypervisor controller dependent operations ##
    ################################################
    def _inspectHVControllerMethods(self):
        allMethods = inspect.getmembers(self._hvController, inspect.isfunction)
        publicMethods = filter(lambda method: method[0][0] != '_', allMethods)
        return publicMethods

    def _addMethod(self, method):
        name = 'xmlrpc_' + method.func_name
        setattr(self, name, method)

    def _createHVControllerMethods(self):
        self.hvControllerMethods = self._inspectHVControllerMethods()
        for method in self.hvControllerMethods:
            self._addMethod(method[1])
            self.logger.debug("Controler method %s dynamically added" %
                              method[0])

    def xmlrpc_help(self, methodName=None):
        if not methodName:
            allMethods = inspect.getmembers(self)
            xmlrpcMethods = filter(
                lambda method: method[0].startswith('xmlrpc_'), allMethods)
            methodNames = map(lambda m: m[0][len('xmlrpc_'):], xmlrpcMethods)
            resList = map(lambda mName: "%s" % self.xmlrpc_help(mName),
                          methodNames)
            res = '\n\n'.join(resList)

        else:
            f = getattr(self, 'xmlrpc_' + methodName, None)
            if not f:
                raise ValueError('No such method: %s' % methodName)
            else:
                signature = _getPrintableFunctionSignature(f)
                res = '%s%s:\n%s' % (
                    methodName,
                    signature,
                    f.__doc__ or '<No Docstring>',
                )

        return res
Ejemplo n.º 33
0
class Host(object):
    logger = logging.getLogger(support.discoverCaller())

    #we use injection so that we can do things lazily
    cmdRegistry = inject.attr('cmdRegistry', CommandRegistry)
    vmRegistry = inject.attr('vmRegistry', VMRegistry)
    fileTxs = inject.attr('fileTxs', FileTxs)

    words = inject.attr('words')
    stompProtocol = inject.attr('stompProtocol')

    def __init__(self):
        self._descriptor = EntityDescriptor('Host-ID')

    @property
    def descriptor(self):
        return self._descriptor

    def sendCmdRequest(self,
                       toVmName,
                       cmd,
                       args=(),
                       env={},
                       path=None,
                       fileForStdin=''):
        #get id for name
        toVmId = self.vmRegistry.getIdForName(toVmName)
        cmdId = str(uuid.uuid4())

        toSend = self.words['CMD_RUN']().  \
                 howToSay(toVmId, \
                     cmdId, cmd, args, \
                     env, path, fileForStdin )

        requestKeys = ('timestamp', 'toVmName', 'toVmId', 'cmd', 'args', 'env',
                       'path', 'fileForStdin')
        requestValues = (time.time(), toVmName, toVmId, cmd, args, env, path,
                         fileForStdin)

        self.stompProtocol.sendMsg(toSend)
        self.logger.info(
            "Requested execution of command '%s' with cmd-id '%s'" %
            (cmd, cmdId))

        self.cmdRegistry.addCmdRequest(cmdId,
                                       dict(zip(requestKeys, requestValues)))
        return cmdId

    def processCmdResult(self, resultsMsg):
        self.cmdRegistry.processCmdResult(resultsMsg)

    #XXX: make it possible to be blocking?
    def getCmdResults(self, cmdId):
        return self.cmdRegistry.popCmdResults(cmdId)

################################

    def addVM(self, vmDescriptor):
        self.vmRegistry.addVM(vmDescriptor)

    def removeVM():
        self.vmRegistry.removeVM(vmId)


################################

    def cpFileToVM(self, vmId, pathToLocalFileName, pathToRemoteFileName=None):
        self.fileTxs.cpFileToVM(vmId, pathToLocalFileName,
                                pathToRemoteFileName)

    def cpFileFromVM(self,
                     vmId,
                     pathToRemoteFileName,
                     pathToLocalFileName=None):
        self.fileTxs.cpFileFromVM(vmId, pathToRemoteFileName,
                                  pathToLocalFileName)