aboutsummaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/orm/management/commands/lsupdates.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/orm/management/commands/lsupdates.py')
-rw-r--r--bitbake/lib/toaster/orm/management/commands/lsupdates.py251
1 files changed, 245 insertions, 6 deletions
diff --git a/bitbake/lib/toaster/orm/management/commands/lsupdates.py b/bitbake/lib/toaster/orm/management/commands/lsupdates.py
index 75e9513fca..89ee53e3dd 100644
--- a/bitbake/lib/toaster/orm/management/commands/lsupdates.py
+++ b/bitbake/lib/toaster/orm/management/commands/lsupdates.py
@@ -1,12 +1,251 @@
-from django.core.management.base import NoArgsCommand, CommandError
-from orm.models import LayerSource
+#
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.management.base import NoArgsCommand
+
+from orm.models import LayerSource, Layer, Release, Layer_Version
+from orm.models import LayerVersionDependency, Machine, Recipe
+
import os
+import json
+import logging
+logger = logging.getLogger("toaster")
+
+DEFAULT_LAYERINDEX_SERVER = "http://layers.openembedded.org/layerindex/api/"
+
class Command(NoArgsCommand):
- args = ""
- help = "Updates locally cached information from all LayerSources"
+ args = ""
+ help = "Updates locally cached information from a layerindex server"
+
+ def update(self):
+ """
+ Fetches layer, recipe and machine information from a layerindex
+ server
+ """
+
+ self.apiurl = DEFAULT_LAYERINDEX_SERVER
+
+ assert self.apiurl is not None
+ try:
+ from urllib.request import urlopen, URLError
+ from urllib.parse import urlparse
+ except ImportError:
+ from urllib2 import urlopen, URLError
+ from urlparse import urlparse
+
+ proxy_settings = os.environ.get("http_proxy", None)
+ oe_core_layer = 'openembedded-core'
+
+ def _get_json_response(apiurl=DEFAULT_LAYERINDEX_SERVER):
+ _parsedurl = urlparse(apiurl)
+ path = _parsedurl.path
+
+ # logger.debug("Fetching %s", apiurl)
+ try:
+ res = urlopen(apiurl)
+ except URLError as e:
+ raise Exception("Failed to read %s: %s" % (path, e.reason))
+
+ return json.loads(res.read().decode('utf-8'))
+
+ # verify we can get the basic api
+ try:
+ apilinks = _get_json_response()
+ except Exception as e:
+ import traceback
+ if proxy_settings is not None:
+ logger.info("EE: Using proxy %s" % proxy_settings)
+ logger.warning("EE: could not connect to %s, skipping update:"
+ "%s\n%s" % (self.apiurl, e, traceback.format_exc()))
+ return
+
+ # update branches; only those that we already have names listed in the
+ # Releases table
+ whitelist_branch_names = [rel.branch_name
+ for rel in Release.objects.all()]
+ if len(whitelist_branch_names) == 0:
+ raise Exception("Failed to make list of branches to fetch")
+
+ logger.debug("Fetching branches")
+
+ # keep a track of the id mappings so that layer_versions can be created
+ # for these layers later on
+ li_layer_id_to_toaster_layer_id = {}
+
+ # We may need this? TODO
+ #branches_info = _get_json_response(apilinks['branches'] +
+ # "?filter=name:%s"
+ # % "OR".join(whitelist_branch_names))
+
+ # update layers
+ layers_info = _get_json_response(apilinks['layerItems'])
+
+ for li in layers_info:
+ # Special case for the openembedded-core layer
+ if li['name'] == oe_core_layer:
+ try:
+ # If we have an existing openembedded-core for example
+ # from the toasterconf.json augment the info using the
+ # layerindex rather than duplicate it
+ oe_core_l = Layer.objects.get(name=oe_core_layer)
+ # Take ownership of the layer as now coming from the
+ # layerindex
+ oe_core_l.summary = li['summary']
+ oe_core_l.description = li['description']
+ oe_core_l.save()
+ li_layer_id_to_toaster_layer_id[li['id']] = oe_core_l.pk
+ continue
+
+ except Layer.DoesNotExist:
+ pass
+
+ l, created = Layer.objects.get_or_create(name=li['name'])
+ l.up_date = li['updated']
+ l.vcs_url = li['vcs_url']
+ l.vcs_web_url = li['vcs_web_url']
+ l.vcs_web_tree_base_url = li['vcs_web_tree_base_url']
+ l.vcs_web_file_base_url = li['vcs_web_file_base_url']
+ l.summary = li['summary']
+ l.description = li['description']
+ l.save()
+
+ li_layer_id_to_toaster_layer_id[li['id']] = l.pk
+
+ # update layerbranches/layer_versions
+ logger.debug("Fetching layer information")
+ layerbranches_info = _get_json_response(
+ apilinks['layerBranches'] + "?filter=branch__name:%s" %
+ "OR".join(whitelist_branch_names))
+
+ # Map Layer index layer_branch object id to
+ # layer_version toaster object id
+ li_layer_branch_id_to_toaster_lv_id = {}
+
+ for lbi in layerbranches_info:
+
+ try:
+ lv, created = Layer_Version.objects.get_or_create(
+ layer_source=LayerSource.TYPE_LAYERINDEX,
+ layer=Layer.objects.get(
+ pk=li_layer_id_to_toaster_layer_id[lbi['layer']])
+ )
+ except KeyError:
+ print("No such layerindex layer referenced by layerbranch %d" %
+ lbi['layer'])
+ continue
+
+ lv.up_date = lbi['updated']
+ lv.commit = lbi['actual_branch']
+ lv.dirpath = lbi['vcs_subdir']
+ lv.save()
+
+ li_layer_branch_id_to_toaster_lv_id[lbi['id']] =\
+ lv.pk
+
+ # update layer dependencies
+ layerdependencies_info = _get_json_response(
+ apilinks['layerDependencies'] +
+ "?filter=layerbranch__branch__name:%s" %
+ "OR".join(whitelist_branch_names))
+
+ dependlist = {}
+ for ldi in layerdependencies_info:
+ try:
+ lv = Layer_Version.objects.get(
+ pk=li_layer_branch_id_to_toaster_lv_id[ldi['layerbranch']])
+ except Layer_Version.DoesNotExist as e:
+ continue
+
+ if lv not in dependlist:
+ dependlist[lv] = []
+ try:
+ layer_id = li_layer_id_to_toaster_layer_id[ldi['dependency']]
+
+ dependlist[lv].append(
+ Layer_Version.objects.get(
+ layer_source=LayerSource.TYPE_LAYERINDEX,
+ layer__pk=layer_id))
+
+ except Layer_Version.DoesNotExist:
+ logger.warning("Cannot find layer version (ls:%s),"
+ "up_id:%s lv:%s" %
+ (self, ldi['dependency'], lv))
+
+ for lv in dependlist:
+ LayerVersionDependency.objects.filter(layer_version=lv).delete()
+ for lvd in dependlist[lv]:
+ LayerVersionDependency.objects.get_or_create(layer_version=lv,
+ depends_on=lvd)
+
+ # update machines
+ logger.debug("Fetching machine information")
+ machines_info = _get_json_response(
+ apilinks['machines'] + "?filter=layerbranch__branch__name:%s" %
+ "OR".join(whitelist_branch_names))
+
+ for mi in machines_info:
+ mo, created = Machine.objects.get_or_create(
+ name=mi['name'],
+ layer_version=Layer_Version.objects.get(
+ pk=li_layer_branch_id_to_toaster_lv_id[mi['layerbranch']]))
+ mo.up_date = mi['updated']
+ mo.name = mi['name']
+ mo.description = mi['description']
+ mo.save()
+
+ # update recipes; paginate by layer version / layer branch
+ logger.debug("Fetching target information")
+ recipes_info = _get_json_response(
+ apilinks['recipes'] + "?filter=layerbranch__branch__name:%s" %
+ "OR".join(whitelist_branch_names))
+
+ for ri in recipes_info:
+ try:
+ lv_id = li_layer_branch_id_to_toaster_lv_id[ri['layerbranch']]
+ lv = Layer_Version.objects.get(pk=lv_id)
+
+ ro, created = Recipe.objects.get_or_create(
+ layer_version=lv,
+ name=ri['pn']
+ )
+ ro.layer_version = lv
+ ro.up_date = ri['updated']
+ ro.name = ri['pn']
+ ro.version = ri['pv']
+ ro.summary = ri['summary']
+ ro.description = ri['description']
+ ro.section = ri['section']
+ ro.license = ri['license']
+ ro.homepage = ri['homepage']
+ ro.bugtracker = ri['bugtracker']
+ ro.file_path = ri['filepath'] + "/" + ri['filename']
+ if 'inherits' in ri:
+ ro.is_image = 'image' in ri['inherits'].split()
+ else: # workaround for old style layer index
+ ro.is_image = "-image-" in ri['pn']
+ ro.save()
+ except Exception as e:
+ logger.debug("Failed saving recipe %s", e)
def handle_noargs(self, **options):
- for ls in LayerSource.objects.all():
- ls.update()
+ self.update()