[yocto] [yocto-autobuilder][PATCH 3/5] autobuilder/buildsteps: Add DaftGetDevices step

Aníbal Limón anibal.limon at linux.intel.com
Fri Jun 2 10:13:03 PDT 2017


This buildstep will copy the devices configuration from the
worker and read it, in order to get daft ip an ssh port, to
use later in RunSanityTests

[YOCTO #10604]

Signed-off-by: Aníbal Limón <anibal.limon at linux.intel.com>
Signed-off-by: Monserrat Sedeno <monserratx.sedeno.bustos.intel.com>
Signed-off-by: Edwin Plauchu <edwin.plauchu.camacho at linux.intel.com>
---
 config/autobuilder.conf.example                    |   3 +
 .../autobuilder/buildsteps/DaftGetDevices.py       |  44 ++++++++
 lib/python2.7/site-packages/autobuilder/config.py  |   1 +
 .../site-packages/autobuilder/lib/daft.py          | 115 +++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 lib/python2.7/site-packages/autobuilder/buildsteps/DaftGetDevices.py
 create mode 100644 lib/python2.7/site-packages/autobuilder/lib/daft.py

diff --git a/config/autobuilder.conf.example b/config/autobuilder.conf.example
index 2ee11e6..e5ec16b 100644
--- a/config/autobuilder.conf.example
+++ b/config/autobuilder.conf.example
@@ -95,3 +95,6 @@ PERFORMANCE_MAIL_TO = "root at localhost otherperson at localhost"
 PERFORMANCE_MAIL_CC = "buildcc at localhost"
 PERFORMANCE_MAIL_BCC = "buildbcc at localhost"
 PERFORMANCE_MAIL_SIG = "Multiline\nSig\nLine"
+
+[Daft]
+DAFT_WORKER_DEVICES_CFG = "/etc/daft/devices.cfg"
diff --git a/lib/python2.7/site-packages/autobuilder/buildsteps/DaftGetDevices.py b/lib/python2.7/site-packages/autobuilder/buildsteps/DaftGetDevices.py
new file mode 100644
index 0000000..133a4d6
--- /dev/null
+++ b/lib/python2.7/site-packages/autobuilder/buildsteps/DaftGetDevices.py
@@ -0,0 +1,44 @@
+import os
+from buildbot.steps.transfer import FileUpload
+from buildbot.process.buildstep import BuildStep
+
+from lib.daft import DeployScanner
+from autobuilder.config import DAFT_WORKER_DEVICES_CFG
+
+class DaftGetDevices(FileUpload):
+    haltOnFailure = True
+
+    name = "DaftGetDevices"
+
+    def __init__(self, factory, argdict=None, **kwargs):
+        self.tests = None
+        self.factory = factory
+        for k, v in argdict.iteritems():
+            setattr(self, k, v)
+        self.description = "Getting devices configuration"
+        self.timeout = 100000
+        kwargs['timeout']=self.timeout
+
+        super(DaftGetDevices, self).__init__(DAFT_WORKER_DEVICES_CFG,
+                os.path.join('/tmp', 'devices.cfg'))
+
+    def finished(self, result):
+        if self.cmd:
+            ds = DeployScanner(devsconf_file = self.masterdest)
+            devices = ds()
+
+            found = False
+            dut_label = self.getProperty('custom_dut')
+            for d in devices:
+                if d['dut_label'] == dut_label:
+                    self.setProperty('dut_name', d['dut_label'], 'DaftGetDevices')
+                    self.setProperty('server_ip', d['server_address'], 'DaftGetDevices')
+                    target_ip = "%s:%s" % (d['ctrl_address'], d['dut_sshport'])
+                    self.setProperty('target_ip', target_ip, 'DaftGetDevices')
+
+                    found = True
+
+            if not found:
+                 return BuildStep.finished(self, FAILURE)
+
+        return super(DaftGetDevices, self).finished(result)
diff --git a/lib/python2.7/site-packages/autobuilder/config.py b/lib/python2.7/site-packages/autobuilder/config.py
index 9d945b1..5bcf6c6 100644
--- a/lib/python2.7/site-packages/autobuilder/config.py
+++ b/lib/python2.7/site-packages/autobuilder/config.py
@@ -23,3 +23,4 @@ RPM_PUBLISH_DIR = os.environ.get("RPM_PUBLISH_DIR")
 IPK_PUBLISH_DIR = os.environ.get("IPK_PUBLISH_DIR")
 DEB_PUBLISH_DIR = os.environ.get("DEB_PUBLISH_DIR")
 PERFORMANCE_PUBLISH_DIR = os.environ.get("PERFORMANCE_PUBLISH_DIR")
+DAFT_WORKER_DEVICES_CFG = os.environ.get("DAFT_WORKER_DEVICES_CFG")
diff --git a/lib/python2.7/site-packages/autobuilder/lib/daft.py b/lib/python2.7/site-packages/autobuilder/lib/daft.py
new file mode 100644
index 0000000..eef4bab
--- /dev/null
+++ b/lib/python2.7/site-packages/autobuilder/lib/daft.py
@@ -0,0 +1,115 @@
+import os
+import ConfigParser as configparser
+
+class DeployScanner(object):
+    '''
+    In charge of scanning deployed daft bbb devices
+    '''
+
+    __MAGIC_SERVER_ADDRESS = '192.168.30.1' # DAFT uses this address for this internal network
+    __MAGIC_SSH_PORT = 2233 # it is hardcoded as per DAFT implementation manual
+
+    def  __init__(self, *args, **kwargs):
+        self.devsconf_fp = kwargs.get('devsconf_file', None)
+        if not self.devsconf_fp:
+            raise Exception('not fed devsconf file')
+        self.ign_leases = kwargs.get('ign_leases', True)
+        if not self.ign_leases:
+            self.leases_file_path =  kwargs.get('leases_file', None)
+            if not self.leases_file_path:
+                raise Exception('not fed leases file')
+
+    def __call__(self):
+        '''
+        Creates relation of deployed devices
+        Returns:
+            List of dictionaries containing info about devices deployed.
+        '''
+        def create_relation(i,j):
+            r = []
+            for conf in i:
+                for active in j:
+                    if conf['bb_ip'] == active['ip']:
+                        r.append({
+                            'dut_label': conf['device'].lower(),
+                            'dut_family': conf['device_type'].lower(),
+                            'dut_sshport': str(self.__MAGIC_SSH_PORT),
+                            'ctrl_address': conf['bb_ip'],
+                            'server_address': self.__MAGIC_SERVER_ADDRESS
+                        })
+            return r
+
+        def slack_relation(i):
+            r = []
+            for conf in i:
+                r.append({
+                    'dut_label': conf['device'],
+                    'dut_family': conf['device_type'],
+                    'dut_sshport': str(self.__MAGIC_SSH_PORT),
+                    'ctrl_address': conf['bb_ip'],
+                    'server_address': self.__MAGIC_SERVER_ADDRESS
+                })
+            return r
+
+        fc = self.__fetch_confs()
+        if not fc:
+            raise Exception('There are no configurations as per BBB devices')
+
+        if self.ign_leases:
+            # Devices that nobody knows if were deployed
+            return slack_relation(fc)
+
+        als = self.__active_leases()
+        if not als:
+            raise Exception('DHCP server has not registered any host yet')
+
+        return create_relation(fc, als)
+
+    def __fetch_confs(self):
+        '''
+        Read and parse BBB configuration file and return result as dictionary
+        '''
+        config = configparser.SafeConfigParser()
+        config.read(self.devsconf_fp)
+        configurations = []
+        for device in config.sections():
+            device_config = dict(config.items(device))
+            device_config["device"] = device
+            device_config["device_type"] = device.rstrip('1234567890_')
+            configurations.append(device_config)
+        return configurations
+
+    def __active_leases(self):
+        """
+        Read the active leases from dnsmasq leases file and return a list of
+        active leases as dictionaries.
+        Args:
+            file_name (str): Path to leases file, e.g. /path/to/file/dnsmasq.leases
+        Returns:
+            List of dictionaries containing the active leases.
+            The dictionaries have the following format:
+            {
+                "mac": "device_mac_address",
+                "ip": "device_ip_address",
+                "hostname": "device_host_name",
+                "client_id": "client_id_or_*_if_unset"
+            }
+        """
+        with open(self.leases_file_path) as lease_file:
+            leases = lease_file.readlines()
+
+        leases_list = []
+
+        # dnsmasq.leases contains rows with the following format:
+        # <lease_expiry_time_as_epoch_format> <mac> <ip> <hostname> <domain>
+        # See:
+        #http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2005q1/000143.html
+        for lease in leases:
+            lease = lease.split()
+            leases_list.append({
+                "mac": lease[1],
+                "ip": lease[2],
+                "hostname": lease[3],
+                "client_id": lease[4],
+            })
+        return leases_list
-- 
2.1.4




More information about the yocto mailing list