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