blob: 2fbd7be3d2fa50349b66db42ab83ee5cfe151632 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#
Patrick Williamsc0f7c042017-02-23 20:41:17 -06002# BitBake Toaster Implementation
3#
Brad Bishopd7bf8c12018-02-25 22:55:05 -05004# Copyright (C) 2016-2017 Intel Corporation
Patrick Williamsc0f7c042017-02-23 20:41:17 -06005#
Brad Bishopc342db32019-05-15 21:57:59 -04006# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc0f7c042017-02-23 20:41:17 -06007#
Patrick Williamsc0f7c042017-02-23 20:41:17 -06008
Brad Bishopd7bf8c12018-02-25 22:55:05 -05009from django.core.management.base import BaseCommand
Patrick Williamsc0f7c042017-02-23 20:41:17 -060010
Andrew Geissler82c905d2020-04-13 13:39:40 -050011from orm.models import Layer, Release, Layer_Version
Patrick Williamsc0f7c042017-02-23 20:41:17 -060012from orm.models import LayerVersionDependency, Machine, Recipe
Brad Bishopd7bf8c12018-02-25 22:55:05 -050013from orm.models import Distro
14from orm.models import ToasterSetting
Patrick Williamsc0f7c042017-02-23 20:41:17 -060015
Patrick Williamsc124f4f2015-09-15 14:41:29 -050016import os
Patrick Williamsc0f7c042017-02-23 20:41:17 -060017import sys
18
Patrick Williamsc0f7c042017-02-23 20:41:17 -060019import logging
20import threading
21import time
22logger = logging.getLogger("toaster")
23
24DEFAULT_LAYERINDEX_SERVER = "http://layers.openembedded.org/layerindex/api/"
25
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080026# Add path to bitbake modules for layerindexlib
27# lib/toaster/orm/management/commands/lsupdates.py (abspath)
28# lib/toaster/orm/management/commands (dirname)
29# lib/toaster/orm/management (dirname)
30# lib/toaster/orm (dirname)
31# lib/toaster/ (dirname)
32# lib/ (dirname)
33path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
34sys.path.insert(0, path)
35
36import layerindexlib
37
Patrick Williamsc0f7c042017-02-23 20:41:17 -060038
39class Spinner(threading.Thread):
40 """ A simple progress spinner to indicate download/parsing is happening"""
41 def __init__(self, *args, **kwargs):
42 super(Spinner, self).__init__(*args, **kwargs)
43 self.setDaemon(True)
44 self.signal = True
45
46 def run(self):
47 os.system('setterm -cursor off')
48 while self.signal:
49 for char in ["/", "-", "\\", "|"]:
50 sys.stdout.write("\r" + char)
51 sys.stdout.flush()
52 time.sleep(0.25)
53 os.system('setterm -cursor on')
54
55 def stop(self):
56 self.signal = False
57
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
Brad Bishopd7bf8c12018-02-25 22:55:05 -050059class Command(BaseCommand):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060060 args = ""
61 help = "Updates locally cached information from a layerindex server"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050062
Patrick Williamsc0f7c042017-02-23 20:41:17 -060063 def mini_progress(self, what, i, total):
64 i = i + 1
65 pec = (float(i)/float(total))*100
66
67 sys.stdout.write("\rUpdating %s %d%%" %
68 (what,
69 pec))
70 sys.stdout.flush()
Andrew Geissler4b740dc2020-05-05 08:54:39 -050071 if int(pec) == 100:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060072 sys.stdout.write("\n")
73 sys.stdout.flush()
74
75 def update(self):
76 """
77 Fetches layer, recipe and machine information from a layerindex
78 server
79 """
80 os.system('setterm -cursor off')
81
82 self.apiurl = DEFAULT_LAYERINDEX_SERVER
Brad Bishopd7bf8c12018-02-25 22:55:05 -050083 if ToasterSetting.objects.filter(name='CUSTOM_LAYERINDEX_SERVER').count() == 1:
84 self.apiurl = ToasterSetting.objects.get(name = 'CUSTOM_LAYERINDEX_SERVER').value
Patrick Williamsc0f7c042017-02-23 20:41:17 -060085
86 assert self.apiurl is not None
Patrick Williamsc0f7c042017-02-23 20:41:17 -060087
88 # update branches; only those that we already have names listed in the
89 # Releases table
90 whitelist_branch_names = [rel.branch_name
91 for rel in Release.objects.all()]
92 if len(whitelist_branch_names) == 0:
93 raise Exception("Failed to make list of branches to fetch")
94
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080095 logger.info("Fetching metadata for %s",
Patrick Williamsc0f7c042017-02-23 20:41:17 -060096 " ".join(whitelist_branch_names))
97
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080098 # We require a non-empty bb.data, but we can fake it with a dictionary
99 layerindex = layerindexlib.LayerIndex({"DUMMY" : "VALUE"})
100
101 http_progress = Spinner()
102 http_progress.start()
103
104 if whitelist_branch_names:
105 url_branches = ";branch=%s" % ','.join(whitelist_branch_names)
106 else:
107 url_branches = ""
108 layerindex.load_layerindex("%s%s" % (self.apiurl, url_branches))
109
110 http_progress.stop()
111
112 # We know we're only processing one entry, so we reference it here
113 # (this is cheating...)
114 index = layerindex.indexes[0]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600115
116 # Map the layer index branches to toaster releases
117 li_branch_id_to_toaster_release = {}
118
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800119 logger.info("Processing releases")
120
121 total = len(index.branches)
122 for i, id in enumerate(index.branches):
123 li_branch_id_to_toaster_release[id] = \
124 Release.objects.get(name=index.branches[id].name)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600125 self.mini_progress("Releases", i, total)
126
127 # keep a track of the layerindex (li) id mappings so that
128 # layer_versions can be created for these layers later on
129 li_layer_id_to_toaster_layer_id = {}
130
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800131 logger.info("Processing layers")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600132
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800133 total = len(index.layerItems)
134 for i, id in enumerate(index.layerItems):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600135 try:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800136 l, created = Layer.objects.get_or_create(name=index.layerItems[id].name)
137 l.up_date = index.layerItems[id].updated
138 l.summary = index.layerItems[id].summary
139 l.description = index.layerItems[id].description
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500140
141 if created:
142 # predefined layers in the fixtures (for example poky.xml)
143 # always preempt the Layer Index for these values
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800144 l.vcs_url = index.layerItems[id].vcs_url
145 l.vcs_web_url = index.layerItems[id].vcs_web_url
146 l.vcs_web_tree_base_url = index.layerItems[id].vcs_web_tree_base_url
147 l.vcs_web_file_base_url = index.layerItems[id].vcs_web_file_base_url
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600148 l.save()
149 except Layer.MultipleObjectsReturned:
150 logger.info("Skipped %s as we found multiple layers and "
151 "don't know which to update" %
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800152 index.layerItems[id].name)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600153
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800154 li_layer_id_to_toaster_layer_id[id] = l.pk
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600155
156 self.mini_progress("layers", i, total)
157
158 # update layer_versions
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800159 logger.info("Processing layer versions")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600160
161 # Map Layer index layer_branch object id to
162 # layer_version toaster object id
163 li_layer_branch_id_to_toaster_lv_id = {}
164
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800165 total = len(index.layerBranches)
166 for i, id in enumerate(index.layerBranches):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500167 # release as defined by toaster map to layerindex branch
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800168 release = li_branch_id_to_toaster_release[index.layerBranches[id].branch_id]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600169
170 try:
171 lv, created = Layer_Version.objects.get_or_create(
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600172 layer=Layer.objects.get(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800173 pk=li_layer_id_to_toaster_layer_id[index.layerBranches[id].layer_id]),
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174 release=release
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600175 )
176 except KeyError:
177 logger.warning(
178 "No such layerindex layer referenced by layerbranch %d" %
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800179 index.layerBranches[id].layer_id)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600180 continue
181
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500182 if created:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800183 lv.release = li_branch_id_to_toaster_release[index.layerBranches[id].branch_id]
184 lv.up_date = index.layerBranches[id].updated
185 lv.commit = index.layerBranches[id].actual_branch
186 lv.dirpath = index.layerBranches[id].vcs_subdir
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187 lv.save()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600188
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800189 li_layer_branch_id_to_toaster_lv_id[index.layerBranches[id].id] =\
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600190 lv.pk
191 self.mini_progress("layer versions", i, total)
192
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800193 logger.info("Processing layer version dependencies")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600194
195 dependlist = {}
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800196 for id in index.layerDependencies:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600197 try:
198 lv = Layer_Version.objects.get(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800199 pk=li_layer_branch_id_to_toaster_lv_id[index.layerDependencies[id].layerbranch_id])
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600200 except Layer_Version.DoesNotExist as e:
201 continue
202
203 if lv not in dependlist:
204 dependlist[lv] = []
205 try:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800206 layer_id = li_layer_id_to_toaster_layer_id[index.layerDependencies[id].dependency_id]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600207
208 dependlist[lv].append(
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500209 Layer_Version.objects.get(layer__pk=layer_id,
210 release=lv.release))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600211
212 except Layer_Version.DoesNotExist:
213 logger.warning("Cannot find layer version (ls:%s),"
214 "up_id:%s lv:%s" %
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800215 (self, index.layerDependencies[id].dependency_id, lv))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600216
217 total = len(dependlist)
218 for i, lv in enumerate(dependlist):
219 LayerVersionDependency.objects.filter(layer_version=lv).delete()
220 for lvd in dependlist[lv]:
221 LayerVersionDependency.objects.get_or_create(layer_version=lv,
222 depends_on=lvd)
223 self.mini_progress("Layer version dependencies", i, total)
224
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500225 # update Distros
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800226 logger.info("Processing distro information")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500227
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800228 total = len(index.distros)
229 for i, id in enumerate(index.distros):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500230 distro, created = Distro.objects.get_or_create(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800231 name=index.distros[id].name,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500232 layer_version=Layer_Version.objects.get(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800233 pk=li_layer_branch_id_to_toaster_lv_id[index.distros[id].layerbranch_id]))
234 distro.up_date = index.distros[id].updated
235 distro.name = index.distros[id].name
236 distro.description = index.distros[id].description
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500237 distro.save()
238 self.mini_progress("distros", i, total)
239
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600240 # update machines
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800241 logger.info("Processing machine information")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600242
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800243 total = len(index.machines)
244 for i, id in enumerate(index.machines):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600245 mo, created = Machine.objects.get_or_create(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800246 name=index.machines[id].name,
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600247 layer_version=Layer_Version.objects.get(
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800248 pk=li_layer_branch_id_to_toaster_lv_id[index.machines[id].layerbranch_id]))
249 mo.up_date = index.machines[id].updated
250 mo.name = index.machines[id].name
251 mo.description = index.machines[id].description
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600252 mo.save()
253 self.mini_progress("machines", i, total)
254
255 # update recipes; paginate by layer version / layer branch
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800256 logger.info("Processing recipe information")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600257
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800258 total = len(index.recipes)
259 for i, id in enumerate(index.recipes):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600260 try:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800261 lv_id = li_layer_branch_id_to_toaster_lv_id[index.recipes[id].layerbranch_id]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600262 lv = Layer_Version.objects.get(pk=lv_id)
263
264 ro, created = Recipe.objects.get_or_create(
265 layer_version=lv,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800266 name=index.recipes[id].pn
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600267 )
268
269 ro.layer_version = lv
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800270 ro.up_date = index.recipes[id].updated
271 ro.name = index.recipes[id].pn
272 ro.version = index.recipes[id].pv
273 ro.summary = index.recipes[id].summary
274 ro.description = index.recipes[id].description
275 ro.section = index.recipes[id].section
276 ro.license = index.recipes[id].license
277 ro.homepage = index.recipes[id].homepage
278 ro.bugtracker = index.recipes[id].bugtracker
279 ro.file_path = index.recipes[id].fullpath
280 ro.is_image = 'image' in index.recipes[id].inherits.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600281 ro.save()
282 except Exception as e:
283 logger.warning("Failed saving recipe %s", e)
284
285 self.mini_progress("recipes", i, total)
286
287 os.system('setterm -cursor on')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500289 def handle(self, **options):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600290 self.update()