← Back to team overview

canonical-hw-cert team mailing list archive

[Merge] ~kevinyeh/cc-lab-manager:job_generator into cc-lab-manager:master

 

Kevin Yeh has proposed merging ~kevinyeh/cc-lab-manager:job_generator into cc-lab-manager:master.

Commit message:
add a script for generating jenkins jobs.
this version only targets on generic and oem kernel.

Requested reviews:
  Canonical Hardware Certification (canonical-hw-cert)

For more details, see:
https://code.launchpad.net/~kevinyeh/cc-lab-manager/+git/cc-lab-manager/+merge/425997
-- 
Your team Canonical Hardware Certification is requested to review the proposed merge of ~kevinyeh/cc-lab-manager:job_generator into cc-lab-manager:master.
diff --git a/cc_lab_manager/job_generator/__init__.py b/cc_lab_manager/job_generator/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cc_lab_manager/job_generator/__init__.py
diff --git a/cc_lab_manager/job_generator/job_generator.py b/cc_lab_manager/job_generator/job_generator.py
new file mode 100644
index 0000000..7f12976
--- /dev/null
+++ b/cc_lab_manager/job_generator/job_generator.py
@@ -0,0 +1,273 @@
+import sqlite3
+import logging
+import argparse
+import os
+import yaml
+import copy
+import sys
+import requests
+import re
+from cc_lab_manager.cc_lab_manager_maptable import release_image_mapping, kernel_to_check_table, oem_to_hwe_kerenl, test_cmds_pre_upgrade_actions_device, test_cmds_pre_test_actions_device, test_cmds_on_test_actions_device
+
+logger = logging.getLogger('cc-lab-manager')
+
+
+
+def read_data_from_db(path_to_db):
+    db = sqlite3.connect(path_to_db)
+    db.row_factory = sqlite3.Row
+    col_in_db = ["CID", "Provision","Device_ID", "Certified_OEM_Image", "SRU_Pool", "Provision", "IP","Project",
+                 "Controller_IP", "Lab", "Frame", "Shelf", "Partition", "CanonicalLabel"]
+    sqlcmd = 'select {} from lab_hw where CID not like \'dummy-%\' order by MAAS_Server'.format(",".join(col_in_db[0:]))
+    db_row_objs = db.execute(sqlcmd).fetchall()
+    db.close()
+    db_dict_list = []
+    for row_obj in db_row_objs:
+        db_dict_list.append({k: row_obj[k] for k in row_obj.keys()})
+    return db_row_objs
+
+def read_exclude_test_from_db(path_to_db):
+    
+    db = sqlite3.connect(path_to_db)
+    db.row_factory = sqlite3.Row
+    sqlcmd = 'select * from extra_option'
+    db_row_objs = db.execute(sqlcmd).fetchall()
+    db.close()
+    db_dict_list = []
+    for row_obj in db_row_objs:
+        db_dict_list.append({k: row_obj[k] for k in row_obj.keys()})
+
+    return db_row_objs
+
+def environ_or_required(key):
+    if os.environ.get(key):
+        return {'default': os.environ.get(key)}
+    else:
+        return {'required': True}
+
+def search_list_of_dict(slist, key):
+    
+    res = next((sub for sub in slist if sub['CID'] == key), None)
+    return dict(res)
+
+def selective_representer(dumper, data):
+    return dumper.represent_scalar(u"tag:yaml.org,2002:str", data,
+                                   style="|" if "\n" in data else None)
+
+
+def generate_generic_job_yaml(machine_list, exclude_test_list):
+    
+    sru_job_arch = [
+        {
+            "project":{
+                "name":None,
+                "srutype":None,
+                "series":None,
+                "image":None,
+                "flavor":None,
+                "kernel-to-check":None,
+                "jobs":[]
+            }
+        }
+    ]
+    
+    job_title = "{prefix}-{srutype}-sru-{series}-{flavor}-{system-id}"
+
+    job_list = {}
+    for machine in machine_list:
+        if machine["SRU_Pool"]:
+            release_list = machine["SRU_Pool"].split(",")
+            if release_list:
+                for rlist in release_list:
+                    if "oem" in rlist:
+                        continue
+                    if rlist not in job_list:
+                        if "oem" not in rlist:
+                            job_list[rlist] = []
+                    if machine["Provision"] == "maas_uefi":
+                        job_list[rlist].append({"cid":machine["CID"]})
+                    elif machine["Provision"] == "maas_legacy":
+                        job_list[rlist].append({"cid":machine["CID"],"image":release_image_mapping[rlist].format("legacy")})
+                    
+    for key in job_list:
+        if job_list[key]:
+            job_arch_tmp = copy.deepcopy(sru_job_arch)
+            job_arch_tmp[0]["project"]["name"] = key + "-desktop"
+            job_arch_tmp[0]["project"]["image"] = release_image_mapping[key].format("uefi")
+            job_arch_tmp[0]["project"]["kernel-to-check"] = kernel_to_check_table[key]
+            job_arch_tmp[0]["project"]["srutype"] = "stock"
+            job_arch_tmp[0]["project"]["series"] = key
+            if key in test_cmds_pre_upgrade_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_pre_upgrade_actions_device"] = test_cmds_pre_upgrade_actions_device[key]
+            if key in test_cmds_pre_test_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_pre_test_actions_device"] = test_cmds_pre_test_actions_device[key]
+            if key in test_cmds_on_test_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_on_test_actions_device"] = test_cmds_on_test_actions_device[key]
+            
+            if not job_arch_tmp[0]["project"]["flavor"]:
+                del job_arch_tmp[0]["project"]["flavor"]
+            
+            for job in job_list[key]:
+                machine = search_list_of_dict(machine_list,job["cid"])
+                extra_option = search_list_of_dict(exclude_test_list, job["cid"])
+                
+                tmp_dict = dict()
+                tmp_dict[job_title] = {}
+                tmp_dict[job_title]["system-id"] = machine["Device_ID"]
+                tmp_dict[job_title]["queue"] = machine["CID"]
+                if "image" in tmp_dict:
+                    tmp_dict[job_title]["image"] = job["image"]
+                if "kernel-to-check" in tmp_dict:
+                    tmp_dict[job_title]["kernel-to-check"] = job["kernel-to-check"]
+                if extra_option["Exclude_test"]:
+                    tmp_dict[job_title]["exclude_test"] = extra_option["Exclude_test"]
+                if extra_option["test_cmds_pre_upgrade_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_pre_upgrade_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_pre_upgrade_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_pre_upgrade_actions_device:
+                            tmp_dict[job_title]["test_cmds_pre_upgrade_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_pre_upgrade_actions_device[key]
+                if extra_option["test_cmds_pre_test_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_pre_test_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_pre_test_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_pre_test_actions_device:
+                            tmp_dict[job_title]["test_cmds_pre_test_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_pre_test_actions_device[key]
+                if extra_option["test_cmds_on_test_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_on_test_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_on_test_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_on_test_actions_device:
+                            tmp_dict[job_title]["test_cmds_on_test_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_on_test_actions_device[key]
+                job_arch_tmp[0]["project"]["jobs"].append(tmp_dict)
+            with open(key+".yaml", "w") as file:
+                yaml.add_representer(str, selective_representer)
+                yaml.dump(job_arch_tmp, file, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False, width=200)
+            
+def get_launchpad_tag(cid):
+    '''
+    this part we may need a new C3 API that can get the Launchpad tag for searching dependency of oem-meta package.
+    '''
+            
+def find_oem_meta_dependency(machine_list):
+    
+    for machine in machine_list:
+        if  "focal-oem" in machine["SRU_Pool"]:
+            lptag = get_launchpad_tag(machine["CID"])
+            if machine["Project"] == "Somerville":
+                url = "http://dell.archive.canonical.com/dists/focal-somerville-{}/public/binary-amd64/Packages".format(lptag)
+                re_pattern = 'oem-smoerville-(?:(?!factory)).*-meta'
+            elif machine["Project"] == "Stella":
+                url = "http://hp.archive.canonical.com/dists/focal-stella.cmit/public/binary-amd64/Packages";
+                re_pattern = 'oem-stella.cmit-(?:(?!factory)).*-meta'
+            
+            res = requests.get(url)
+            package_data = res.text.split("\n\n")
+            for data in package_data:
+                if data :
+                    data_yaml = yaml.safe_load(data)
+                    if re.match(re_pattern, data_yaml["Package"]):
+                        depend = data_yaml["Depends"].replace(" ","").split(",")
+                        for pkg in depend:
+                            if "linux-generic-hwe" in pkg:
+                                oem_to_hwe_kerenl["focal-oem"].append(machine["CID"])
+                
+def generate_oem_job_yaml(machine_list, exclude_test_list):
+    
+    sru_job_arch = [
+        {
+            "project":{
+                "name":None,
+                "srutype":None,
+                "series":None,
+                "image":None,
+                "flavor":None,
+                "kernel-to-check":None,
+                "jobs":[]
+            }
+        }
+    ]
+    
+    oem_job_list = {"focal-oem":[],"bionic-oem":[],"jammy-oem":[]}
+    job_title = "{prefix}-{srutype}-sru-{series}-{flavor}-{system-id}"
+    for machine in machine_list:
+        if machine["Certified_OEM_Image"]:
+            image_list = machine["Certified_OEM_Image"].split(",")
+            if image_list:
+                for ilist in image_list:
+                    if machine["Provision"] == "noprovision":
+                        image_name = ""
+                    else:
+                        image_name  = ilist.split('/')[-1].split('.')[0]
+                    if "focal" in ilist:
+                        if machine["CID"] in oem_to_hwe_kerenl["focal-oem"]:
+                            oem_job_list["focal-oem"].append({"cid":machine["CID"],"image":image_name,"kernel-to-check":"linux-generic_hwe-20_04"})
+                        else: 
+                            oem_job_list["focal-oem"].append({"cid":machine["CID"],"image":image_name,"kernel-to-check":"linux-oem-20_04"})
+                    elif "bionic" in ilist:
+                        oem_job_list["bionic-oem"].append({"cid":machine["CID"],"image":image_name,"kernel-to-check":"linux-oem"})
+    
+    for key in oem_job_list:
+        if oem_job_list[key]:
+            job_arch_tmp = copy.deepcopy(sru_job_arch)
+            job_arch_tmp[0]["project"]["name"] = key
+            job_arch_tmp[0]["project"]["srutype"] = "oem"
+            job_arch_tmp[0]["project"]["series"] = key.split("-")[0]
+            if key in test_cmds_pre_upgrade_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_pre_upgrade_actions_device"] = test_cmds_pre_upgrade_actions_device[key]
+            if key in test_cmds_pre_test_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_pre_test_actions_device"] = test_cmds_pre_test_actions_device[key]
+            if key in test_cmds_on_test_actions_device:
+                job_arch_tmp[0]["project"]["test_cmds_on_test_actions_device"] = test_cmds_on_test_actions_device[key]
+            for job in oem_job_list[key]:
+                machine = search_list_of_dict(machine_list,job["cid"])
+                extra_option = search_list_of_dict(exclude_test_list,job["cid"])
+                tmp_dict = dict()
+                tmp_dict[job_title] = {}
+                tmp_dict[job_title]["system-id"] = machine["Device_ID"]
+                tmp_dict[job_title]["image"] = job["image"]
+                tmp_dict[job_title]["kernel-to-check"] = job["kernel-to-check"]
+                if extra_option["Exclude_test"]:
+                    tmp_dict[job_title]["exclude_test"] = extra_option["Exclude_test"]
+                if extra_option["test_cmds_pre_upgrade_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_pre_upgrade_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_pre_upgrade_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_pre_upgrade_actions_device:
+                            tmp_dict[job_title]["test_cmds_pre_upgrade_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_pre_upgrade_actions_device[key]
+                if extra_option["test_cmds_pre_test_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_pre_test_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_pre_test_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_pre_test_actions_device:
+                            tmp_dict[job_title]["test_cmds_pre_test_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_pre_test_actions_device[key]
+                if extra_option["test_cmds_on_test_actions_device"]:
+                    extra_cmd = eval(extra_option["test_cmds_on_test_actions_device"])
+                    if key in extra_cmd:
+                        tmp_dict[job_title]["test_cmds_on_test_actions_device"] = extra_cmd[key]
+                        if key in test_cmds_on_test_actions_device:
+                            tmp_dict[job_title]["test_cmds_on_test_actions_device"] = extra_cmd[key]+"\n"+ test_cmds_on_test_actions_device[key]
+                job_arch_tmp[0]["project"]["jobs"].append(tmp_dict)
+            
+            for keys in job_arch_tmp[0]["project"].copy():
+                if not job_arch_tmp[0]["project"][keys]:
+                    job_arch_tmp[0]["project"].pop(keys)
+                    
+            with open(key+".yaml", "w") as file:
+                yaml.add_representer(str, selective_representer)
+                yaml.dump(job_arch_tmp, file, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False, width=200)
+
+
+def main():
+    
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--hwdb', help="Hardware db to read ip mapping", **environ_or_required('CCLM_HARDWARE_DB'))
+    args = parser.parse_args()
+    machine_list = read_data_from_db(args.hwdb)
+    exclude_test_list = read_exclude_test_from_db(args.hwdb)
+    generate_generic_job_yaml(machine_list, exclude_test_list)
+    # find_oem_meta_dependency(machine_list) # this funtciont is not completed
+    generate_oem_job_yaml(machine_list, exclude_test_list)
+
+if __name__ == '__main__':
+    main()