def test_can_create_device(self):
     """Instantiate an actual device"""
     c = Configurator('test_configurator.conf')
     k, d = c.createDevice('dev1')
     assert hash(k)
     self.assertEqual(d.getDeviceType(), 'PseudoDevice')
     self.assertEqual(d.port, 9)
 def test_get_password(self):
     """Password gleaned correctly from config file"""
     
     c = Configurator()
     c.fromString(configdata)
     self.assertEqual(len(c), 2)
     self.assertEqual(c.getPassword(), 'password123')
    def test_case_insensitivity(self):
        """Authentication section name should be case insensitive"""
        
        c = Configurator()
        c.fromString(configdata2)

        self.assertEqual(len(c), 2)
        self.assertEqual(c.getPassword(), 'password123')
    def test_password(self):
        """Aggregator should have random password"""

        assert type(self.aggregator.getPassword()) == type("")

        # ensure a second instance has differing password ...
        conf = Configurator()
        conf.fromString('')
        other = Aggregator(conf)
        assert other.getPassword() != self.aggregator.getPassword()
    def setUpClass(self):
        """Start a DeviceServer in a child process to test against"""

        self.deviceserverprocess = SubProcessProtocol()
        self.deviceserverprocess.waitOnStartUp( ['server.py', 'deviceserver.conf', '-n'], \
                                                path=os.path.join(agdevicecontrol.path,'bin') )

        if self.deviceserverprocess.running is False:
            raise unittest.SkipTest, "DeviceServer didn't start correctly, skipping tests"

        #wait for slow single CPU buildbots to catch up
        import time
        time.sleep(1)

        # use the config above
        conf = Configurator()
        conf.fromString(configdata)

        # can be set by timeout
        self.failure = False


        # safety timeout
        self.timeout = reactor.callLater(10, self.failed, "Aggregator failed to connect to all deviceservers ... failing")
        
        self.aggregator = Aggregator(conf)
        self.done = False
        while not self.done:
            print "Waiting for aggregator to connect to deviceservers"
            reactor.iterate(0.1)
            if self.aggregator.connected:
                self.succeeded()

        if self.failure:
            raise unittest.SkipTest, "Aggregator didn't connect to all deviceservers ... skipping tests"



        # FIXME: we really should handle missing and newly appearing deviceservers.

        # safety timeout
        self.timeout = reactor.callLater(10, self.failed, "Aggregator failed to map all deviceservers ... failing")

        self.aggregator.notifyOnMapped(self.succeeded)

        self.done = False
        while not self.done:
            print "Waiting for aggregator to map deviceservers"
            reactor.iterate(0.1)


        if self.failure:
            raise unittest.SkipTest, "Aggregator didn't start correctly, skipping tests"
    def setUp(self):
        """I'm called at the very beginning of each test"""

        c = Configurator()
        c.fromString(configdata)
        self.ds = DeviceServer(c)

        self.finished = False
        self.failed = None
        self.pending_deferreds = []

        # safety timeout
        self.timeout = reactor.callLater(10, self.timedOut)
Example #7
0
 def loadConfig(self, config_file):
     self.config = Configurator(config_file)
Example #8
0
class Aggregator:

    implements(IDeviceServer,IAggregator)

    def __init__(self, config, testmode=False):

        self.servers = []

        # keyed by server, pbroot objects for RPC
        self.perspectives = {}

        # each server has a devicemap, each a dictionary keyed by devicetype
        # containing devices on the server
        self.devicemaps = {}

        # composite devicemap aggregating all deviceservers
        # by the devicetype, each a list of device names
        self.aggregatormap = {}

        # key by device name, corresponding server name containing the device
        self.devicedict = {}

        # becomes True only once we have perspectives on all DeviceServers
        self.connected = False

        # user can register to be informed when the Aggregator has completed
        # full connection to all constituent DeviceServers
        self._notifyonmappedcb = None

        # random password unless in testmode
        if not testmode:
            self.password = self._generatePassword()
        else:
            print "Test mode enabled with preconfigured password (shouldn't see this in normal use)"
            self.password = '******'  # hey, it had to be something ...

        # becomes True only once we have aggregatormap compiled
        self.mapped = False

        self.config = config
        if not isinstance(config,Configurator):
            self.loadConfig(config)

        self._connectAll()



    def _generatePassword(self, length=10):
        """http://mail.python.org/pipermail/python-list/2004-February/208169.html"""

        twoletters = [c+d for c in string.letters for d in string.letters]
        n = len(twoletters)
        l2 = length // 2
        lst = [None] * l2
        for i in xrange(l2):
             lst[i] = twoletters[int(random.random() * n)]
        if length & 1:
            lst.append(random.choice(string.letters))
        return "".join(lst)


    def getPassword(self):
        return self.password


    def notifyOnMapped(self, callback):
        self._notifyonmappedcb = callback


    def loadConfig(self, config_file):
        self.config = Configurator(config_file)


    def _connectAll(self):
        for server in self.config.sections():
            self._connect(server)


    def _connect(self, server):
        
        host = self.config.get(server,'host')
        port = int(self.config.get(server,'port'))

        factory = pb.PBClientFactory()
        reactor.connectTCP(host, port, factory)

        password = self.config.get(server,'password')
        d = factory.login(credentials.UsernamePassword(version.apiversion,password))

        d.addCallback(self._onConnectSuccess, server)
        d.addErrback(self._onConnectFailure, server)

        self.servers.append(server)


    def _onConnectSuccess(self, perspective, server):
        """I'm called on successful connection to each deviceserver 'server'"""

        self.perspectives[server] = perspective

        d = perspective.callRemote("getDeviceMap")
        d.addCallback(self._onDeviceMapSuccess, server)
        d.addErrback(self._onDeviceMapFailure, server)

        # have we got all the perspectives yet?
        if len(self.perspectives) == len(self.servers):
            self.connected = True
        

    def _onConnectFailure(self, failure, server):
        """Failed connection to a deviceserver"""

        # FIXME: notify of failure, have we finished getting perspectives?
        return failure



    def _onDeviceMapSuccess(self, devicemap, server):
        """I'm called on successful devicemap for every device server"""

        # paranioa check
        assert not server in self.devicemaps
	print server
    
        self.devicemaps[server] = devicemap

        for devicetype,devicelist in devicemap.items():
            if devicetype in self.aggregatormap:
                self.aggregatormap[devicetype].extend( devicelist )
            else:
                self.aggregatormap[devicetype] = devicelist

            # we'll need to discern server given a device name
            for device in devicelist:
		print " DEBUG:"
		print device.id
                assert not device in self.devicedict
                self.devicedict[device] = server

        # have we got all the devicemaps? (FIXME: can't complete if a
        # DeviceServer doesn't connect)
        if len(self.devicemaps) == len(self.servers):
            self.mapped = True
            if self._notifyonmappedcb:
                self._notifyonmappedcb(self)


    def _onDeviceMapFailure(self, failure, server):
        """Failed to retrieve a devicemap deviceserver"""
        return failure


    def getDeviceList(self):
        """Return aggregated devicelist (assumes built-up during connection chain"""
        return defer.succeed(self.devicedict.keys())


    def getDeviceMap(self):
        """Return aggregated devicemap (assumes built-up during connection chain"""
        return defer.succeed(self.aggregatormap)


    def deviceExecute(self, device, command, params=None):
	print 
	print "DEBUG:"
	print device
	print device.id
        server = self.devicedict[device]
        return self.perspectives[server].callRemote("deviceExecute", device, command, params)
Example #9
0
class DeviceServer:

    implements(IDeviceServer)

    def __init__(self, config):

        self.config = config
        if not isinstance(config,Configurator):
            self.loadConfig(config)

	#dictionary of devices, keyed by a Container with relevant info in it.
        self.devices = {}

        # each device has a command queue
        self.queues = {}

	# dictionary of device containers, keyed by type.
        self._devicemap = {}

        for device in self.config.sections():
	    con = Container()

	    key, instance = self.config.createDevice(device)
	    
	    con.name = key
	    con.type = instance.getDeviceType()

            try:
                self._devicemap[instance.getDeviceType()].append(con)
            except KeyError:
                self._devicemap[instance.getDeviceType()] = [con]
            self.devices[con] = instance
            self.queues[con] = DeviceQueue()



    def loadConfig(self, config):
        self.config = Configurator(config)


    def getPassword(self):
        return self.config.getPassword()


    def deviceExecute(self, device, command, param=None):
        if device in self.getDeviceList():
            if command in self.getCommandList(device):
                # bound method of desired device
                device_method = getattr(self.devices[device], command)

                # convenient reference
                queue = self.queues[device]

                # add to device queue
                d = queue.submit(device_method, param)

                return d



    def getDeviceList(self):
        return self.devices.keys()


    def getDeviceType(self, device):
        return self.devices[device].getDeviceType()


    def getCommandList(self, device):
        return self.devices[device].getCommandList()


    def getDeviceMap(self):
        return self._devicemap
 def test_load_from_string(self):
     """Create a config file from string data"""
     c = Configurator()
     c.fromString(configdata)
     self.assertIn('dev1', c)
 def test_no_password(self):
     """Anonymous password gleaned correctly from config file"""
     
     c = Configurator()
     self.assertEqual(c.getPassword(), '')
Example #12
0
class DeviceServer:

    implements(IDeviceServer)

    def __init__(self, config):

        self.config = config
        if not isinstance(config,Configurator):
            self.loadConfig(config)

        # dictionary of device instances keyed by name
        self.devices = {}

        # each device has a command queue
        self.queues = {}

        self._devicemap = {}

        for device in self.config.sections():

            key, instance = self.config.createDevice(device)

            try:
                self._devicemap[instance.getDeviceType()].append(device)
            except KeyError:
                self._devicemap[instance.getDeviceType()] = [device]
            self.devices[key] = instance
            self.queues[key] = DeviceQueue()

        self.message = "MESSAGE::TO::PASS"


    def loadConfig(self, config):
        self.config = Configurator(config)

    def setMessage(self, message):
        self.message = message


    def getPassword(self):
        return self.config.getPassword()


    def deviceExecute(self, device, command, param=None):
        if device in self.getDeviceList():
            if command in self.getCommandList(device):
                # bound method of desired device
                device_method = getattr(self.devices[device], command)

                # convenient reference
                queue = self.queues[device]

                # add to device queue
                d = queue.submit(device_method, param)

                return d



    def getDeviceList(self):
        return self.devices.keys()


    def getDeviceType(self, device):
        return self.devices[device].getDeviceType()


    def getCommandList(self, device):
        return self.devices[device].getCommandList()


    def getDeviceMap(self):
        return self._devicemap