xref: /openbmc/openbmc/poky/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py (revision f1e5d6968976c2341c6d554bfcc8895f1b33c26b)
1#
2# SPDX-License-Identifier: GPL-2.0-only
3#
4
5from django.core.management.base import BaseCommand
6
7from django.core.management import call_command
8from bldcontrol.models import BuildRequest, BuildEnvironment, BRError
9from orm.models import ToasterSetting, Build, Layer
10
11import os
12import traceback
13import warnings
14
15
16def DN(path):
17    if path is None:
18        return ""
19    else:
20        return os.path.dirname(path)
21
22
23class Command(BaseCommand):
24    args = ""
25    help = "Verifies that the configured settings are valid and usable, or prompts the user to fix the settings."
26
27    def __init__(self, *args, **kwargs):
28        super(Command, self).__init__(*args, **kwargs)
29        self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__)))))))
30
31    def _verify_build_environment(self):
32        # provide a local build env. This will be extended later to include non local
33        if BuildEnvironment.objects.count() == 0:
34            BuildEnvironment.objects.create(betype=BuildEnvironment.TYPE_LOCAL)
35
36        # we make sure we have builddir and sourcedir for all defined build envionments
37        for be in BuildEnvironment.objects.all():
38            be.needs_import = False
39            def _verify_be():
40                is_changed = False
41
42                def _update_sourcedir():
43                    be.sourcedir = os.environ.get('TOASTER_DIR')
44                    return True
45
46                if len(be.sourcedir) == 0:
47                    is_changed = _update_sourcedir()
48
49                if not be.sourcedir.startswith("/"):
50                    print("\n -- Validation: The layers checkout directory must be set to an absolute path.")
51                    is_changed = _update_sourcedir()
52
53                if is_changed:
54                    if be.betype == BuildEnvironment.TYPE_LOCAL:
55                        be.needs_import = True
56                    return True
57
58                def _update_builddir():
59                    be.builddir = os.environ.get('TOASTER_DIR')+"/build"
60                    return True
61
62                if len(be.builddir) == 0:
63                    is_changed = _update_builddir()
64
65                if not be.builddir.startswith("/"):
66                    print("\n -- Validation: The build directory must to be set to an absolute path.")
67                    is_changed = _update_builddir()
68
69                if is_changed:
70                    print("\nBuild configuration saved")
71                    be.save()
72                    return True
73
74                if be.needs_import:
75                    try:
76                        print("Loading default settings")
77                        call_command("loaddata", "settings")
78                        template_conf = os.environ.get("TEMPLATECONF", "")
79                        custom_xml_only = os.environ.get("CUSTOM_XML_ONLY")
80
81                        if ToasterSetting.objects.filter(name='CUSTOM_XML_ONLY').count() > 0 or custom_xml_only is not None:
82                            # only use the custom settings
83                            pass
84                        elif "poky" in template_conf:
85                            print("Loading poky configuration")
86                            call_command("loaddata", "poky")
87                        else:
88                            print("Loading OE-Core configuration")
89                            call_command("loaddata", "oe-core")
90                            if template_conf:
91                                oe_core_path = os.path.realpath(
92                                    template_conf +
93                                    "/../")
94                            else:
95                                print("TEMPLATECONF not found. You may have to"
96                                      " manually configure layer paths")
97                                oe_core_path = input("Please enter the path of"
98                                                     " your openembedded-core "
99                                                     "layer: ")
100                            # Update the layer instances of openemebedded-core
101                            for layer in Layer.objects.filter(
102                                    name="openembedded-core",
103                                    local_source_dir="OE-CORE-LAYER-DIR"):
104                                layer.local_path = oe_core_path
105                                layer.save()
106
107                        # Import the custom fixture if it's present
108                        with warnings.catch_warnings():
109                            warnings.filterwarnings(
110                                action="ignore",
111                                message="^.*No fixture named.*$")
112                            print("Importing custom settings if present")
113                            try:
114                                call_command("loaddata", "custom")
115                            except:
116                                print("NOTE: optional fixture 'custom' not found")
117
118                        # we run lsupdates after config update
119                        print("\nFetching information from the layer index, "
120                              "please wait.\nYou can re-update any time later "
121                              "by running bitbake/lib/toaster/manage.py "
122                              "lsupdates\n")
123                        call_command("lsupdates")
124
125                        # we don't look for any other config files
126                        return is_changed
127                    except Exception as e:
128                        print("Failure while trying to setup toaster: %s"
129                              % e)
130                        traceback.print_exc()
131
132                return is_changed
133
134            while _verify_be():
135                pass
136        return 0
137
138    def _verify_default_settings(self):
139        # verify that default settings are there
140        if ToasterSetting.objects.filter(name='DEFAULT_RELEASE').count() != 1:
141            ToasterSetting.objects.filter(name='DEFAULT_RELEASE').delete()
142            ToasterSetting.objects.get_or_create(name='DEFAULT_RELEASE', value='')
143        return 0
144
145    def _verify_builds_in_progress(self):
146        # we are just starting up. we must not have any builds in progress, or build environments taken
147        for b in BuildRequest.objects.filter(state=BuildRequest.REQ_INPROGRESS):
148            BRError.objects.create(req=b, errtype="toaster",
149                                   errmsg=
150                                   "Toaster found this build IN PROGRESS while Toaster started up. This is an inconsistent state, and the build was marked as failed")
151
152        BuildRequest.objects.filter(state=BuildRequest.REQ_INPROGRESS).update(state=BuildRequest.REQ_FAILED)
153
154        BuildEnvironment.objects.update(lock=BuildEnvironment.LOCK_FREE)
155
156        # also mark "In Progress builds as failures"
157        from django.utils import timezone
158        Build.objects.filter(outcome=Build.IN_PROGRESS).update(outcome=Build.FAILED, completed_on=timezone.now())
159
160        return 0
161
162
163
164    def handle(self, **options):
165        retval = 0
166        retval += self._verify_build_environment()
167        retval += self._verify_default_settings()
168        retval += self._verify_builds_in_progress()
169
170        return retval
171