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