diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2014-08-12 15:45:48 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-08-29 13:56:50 +0100 |
commit | 95df54238b6013c374215905b1937fbac72cdd63 (patch) | |
tree | 42f1f2061f9583c3906bb3f8674534d496792210 /bitbake/lib/toaster/bldcontrol | |
parent | 565f69205f130644dee136c8296dd0dc979e492b (diff) | |
download | poky-95df54238b6013c374215905b1937fbac72cdd63.tar.gz |
bitbake: toaster: update checksettings command for auto-detection
We enhance the checksettings command to try to automatically
detect settings for running on localhost.
The checksettings will look for a nearby poky layer source,
for a nearby build directory, and will try to import settings
from "toasterconf.json" files found in the local layer.
On new configuration, it will also perform updates from the
layer source.
(Bitbake rev: 2aab77dfccb538e2b09829841ea6c464d40cafb1)
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/bldcontrol')
-rw-r--r-- | bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py | 190 |
1 files changed, 182 insertions, 8 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py b/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py index a91dd150ef..4f6a66e711 100644 --- a/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py +++ b/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py | |||
@@ -1,38 +1,212 @@ | |||
1 | from django.core.management.base import NoArgsCommand, CommandError | 1 | from django.core.management.base import NoArgsCommand, CommandError |
2 | from django.db import transaction | 2 | from django.db import transaction |
3 | from orm.models import Build | 3 | from orm.models import LayerSource, ToasterSetting, Branch, Layer, Layer_Version |
4 | from orm.models import BitbakeVersion, Release, ReleaseDefaultLayer | ||
4 | from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException | 5 | from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException |
5 | from bldcontrol.models import BuildRequest, BuildEnvironment | 6 | from bldcontrol.models import BuildRequest, BuildEnvironment |
6 | import os | 7 | import os |
7 | 8 | ||
9 | def DN(path): | ||
10 | if path is None: | ||
11 | return "" | ||
12 | else: | ||
13 | return os.path.dirname(path) | ||
14 | |||
15 | |||
8 | class Command(NoArgsCommand): | 16 | class Command(NoArgsCommand): |
9 | args = "" | 17 | args = "" |
10 | help = "Verifies thid %dthe configured settings are valid and usable, or prompts the user to fix the settings." | 18 | help = "Verifies that the configured settings are valid and usable, or prompts the user to fix the settings." |
19 | |||
20 | def _reduce_canon_path(self, path): | ||
21 | components = [] | ||
22 | for c in path.split("/"): | ||
23 | if c == "..": | ||
24 | del components[-1] | ||
25 | elif c == ".": | ||
26 | pass | ||
27 | else: | ||
28 | components.append(c) | ||
29 | return "/".join(components) | ||
30 | |||
31 | def _find_first_path_for_file(self, startdirectory, filename, level = 0): | ||
32 | if level < 0: | ||
33 | return None | ||
34 | dirs = [] | ||
35 | for i in os.listdir(startdirectory): | ||
36 | j = os.path.join(startdirectory, i) | ||
37 | if os.path.isfile(j): | ||
38 | if i == filename: | ||
39 | return startdirectory | ||
40 | elif os.path.isdir(j): | ||
41 | dirs.append(j) | ||
42 | for j in dirs: | ||
43 | ret = self._find_first_path_for_file(j, filename, level - 1) | ||
44 | if ret is not None: | ||
45 | return ret | ||
46 | return None | ||
47 | |||
48 | def _get_suggested_sourcedir(self, be): | ||
49 | if be.betype != BuildEnvironment.TYPE_LOCAL: | ||
50 | return "" | ||
51 | return DN(DN(DN(self._find_first_path_for_file(self.guesspath, "toasterconf.json", 4)))) | ||
52 | |||
53 | def _get_suggested_builddir(self, be): | ||
54 | if be.betype != BuildEnvironment.TYPE_LOCAL: | ||
55 | return "" | ||
56 | return DN(self._find_first_path_for_file(self.guesspath, "bblayers.conf", 3)) | ||
57 | |||
58 | def _import_layer_config(self, baselayerdir): | ||
59 | filepath = os.path.join(baselayerdir, "meta/conf/toasterconf.json") | ||
60 | if not os.path.exists(filepath) or not os.path.isfile(filepath): | ||
61 | raise Exception("Failed to find toaster config file %s ." % filepath) | ||
62 | |||
63 | import json, pprint | ||
64 | data = json.loads(open(filepath, "r").read()) | ||
65 | |||
66 | # verify config file validity before updating settings | ||
67 | for i in ['bitbake', 'releases', 'defaultrelease', 'config', 'layersources']: | ||
68 | assert i in data | ||
69 | |||
70 | # import bitbake data | ||
71 | for bvi in data['bitbake']: | ||
72 | bvo, created = BitbakeVersion.objects.get_or_create(name=bvi['name']) | ||
73 | bvo.giturl = bvi['giturl'] | ||
74 | bvo.branch = bvi['branch'] | ||
75 | bvo.dirpath = bvi['dirpath'] | ||
76 | bvo.save() | ||
77 | |||
78 | # set the layer sources | ||
79 | for lsi in data['layersources']: | ||
80 | assert 'sourcetype' in lsi | ||
81 | assert 'apiurl' in lsi | ||
82 | assert 'name' in lsi | ||
83 | assert 'branches' in lsi | ||
84 | |||
85 | if lsi['sourcetype'] == LayerSource.TYPE_LAYERINDEX or lsi['apiurl'].startswith("/"): | ||
86 | apiurl = lsi['apiurl'] | ||
87 | else: | ||
88 | apiurl = self._reduce_canon_path(os.path.join(DN(filepath), lsi['apiurl'])) | ||
89 | |||
90 | try: | ||
91 | ls = LayerSource.objects.get(sourcetype = lsi['sourcetype'], apiurl = apiurl) | ||
92 | except LayerSource.DoesNotExist: | ||
93 | ls = LayerSource.objects.create( | ||
94 | name = lsi['name'], | ||
95 | sourcetype = lsi['sourcetype'], | ||
96 | apiurl = apiurl | ||
97 | ) | ||
98 | |||
99 | layerbranches = [] | ||
100 | for branchname in lsi['branches']: | ||
101 | bo, created = Branch.objects.get_or_create(layer_source = ls, name = branchname) | ||
102 | layerbranches.append(bo) | ||
103 | |||
104 | if 'layers' in lsi: | ||
105 | for layerinfo in lsi['layers']: | ||
106 | lo, created = Layer.objects.get_or_create(layer_source = ls, name = layerinfo['name']) | ||
107 | if layerinfo['local_path'].startswith("/"): | ||
108 | lo.local_path = layerinfo['local_path'] | ||
109 | else: | ||
110 | lo.local_path = self._reduce_canon_path(os.path.join(DN(filepath), layerinfo['local_path'])) | ||
111 | lo.layer_index_url = layerinfo['layer_index_url'] | ||
112 | if 'vcs_url' in layerinfo: | ||
113 | lo.vcs_url = layerinfo['vcs_url'] | ||
114 | lo.save() | ||
115 | |||
116 | for branch in layerbranches: | ||
117 | lvo, created = Layer_Version.objects.get_or_create(layer_source = ls, | ||
118 | up_branch = branch, | ||
119 | commit = branch.name, | ||
120 | layer = lo) | ||
121 | lvo.dirpath = layerinfo['dirpath'] | ||
122 | lvo.save() | ||
123 | # set releases | ||
124 | for ri in data['releases']: | ||
125 | bvo = BitbakeVersion.objects.get(name = ri['bitbake']) | ||
126 | assert bvo is not None | ||
127 | |||
128 | ro, created = Release.objects.get_or_create(name = ri['name'], bitbake_version = bvo) | ||
129 | ro.description = ri['description'] | ||
130 | ro.branch = ri['branch'] | ||
131 | ro.save() | ||
132 | |||
133 | for dli in ri['defaultlayers']: | ||
134 | lsi, layername = dli.split(":") | ||
135 | layer, created = Layer.objects.get_or_create( | ||
136 | layer_source = LayerSource.objects.get(name = lsi), | ||
137 | name = layername | ||
138 | ) | ||
139 | ReleaseDefaultLayer.objects.get_or_create( release = ro, layer = layer) | ||
140 | |||
141 | # set default release | ||
142 | if ToasterSetting.objects.filter(name = "DEFAULT_RELEASE").count() > 0: | ||
143 | ToasterSetting.objects.filter(name = "DEFAULT_RELEASE").update(value = data['defaultrelease']) | ||
144 | else: | ||
145 | ToasterSetting.objects.create(name = "DEFAULT_RELEASE", value = data['defaultrelease']) | ||
146 | |||
147 | # set default config variables | ||
148 | for configname in data['config']: | ||
149 | if ToasterSetting.objects.filter(name = "DEFCONF_" + configname).count() > 0: | ||
150 | ToasterSetting.objects.filter(name = "DEFCONF_" + configname).update(value = data['config'][configname]) | ||
151 | else: | ||
152 | ToasterSetting.objects.create(name = "DEFCONF_" + configname, value = data['config'][configname]) | ||
11 | 153 | ||
12 | def handle(self, **options): | 154 | def handle(self, **options): |
155 | self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__))))))) | ||
156 | |||
13 | # we make sure we have builddir and sourcedir for all defined build envionments | 157 | # we make sure we have builddir and sourcedir for all defined build envionments |
14 | for be in BuildEnvironment.objects.all(): | 158 | for be in BuildEnvironment.objects.all(): |
15 | def _verify_be(): | 159 | def _verify_be(): |
16 | is_changed = False | 160 | is_changed = False |
17 | print("Verifying the Build Environment type %s id %d." % (be.get_betype_display(), be.pk)) | 161 | print("Verifying the Build Environment type %s id %d." % (be.get_betype_display(), be.pk)) |
18 | if len(be.sourcedir) == 0: | 162 | if len(be.sourcedir) == 0: |
19 | be.sourcedir = raw_input(" -- sourcedir may not be empty:") | 163 | suggesteddir = self._get_suggested_sourcedir(be) |
164 | be.sourcedir = raw_input(" -- Layer sources checkout directory may not be empty [guessed \"%s\"]:" % suggesteddir) | ||
165 | if len(be.sourcedir) == 0 and len(suggesteddir) > 0: | ||
166 | be.sourcedir = suggesteddir | ||
20 | is_changed = True | 167 | is_changed = True |
168 | |||
21 | if not be.sourcedir.startswith("/"): | 169 | if not be.sourcedir.startswith("/"): |
22 | be.sourcedir = raw_input(" -- sourcedir must be an absolute path:") | 170 | be.sourcedir = raw_input(" -- Layer sources checkout directory must be an absolute path:") |
23 | is_changed = True | 171 | is_changed = True |
172 | |||
24 | if len(be.builddir) == 0: | 173 | if len(be.builddir) == 0: |
25 | be.builddir = raw_input(" -- builddir may not be empty:") | 174 | suggesteddir = self._get_suggested_builddir(be) |
175 | be.builddir = raw_input(" -- Build directory may not be empty [guessed \"%s\"]:" % suggesteddir) | ||
176 | if len(be.builddir) == 0 and len(suggesteddir) > 0: | ||
177 | be.builddir = suggesteddir | ||
26 | is_changed = True | 178 | is_changed = True |
179 | |||
27 | if not be.builddir.startswith("/"): | 180 | if not be.builddir.startswith("/"): |
28 | be.builddir = raw_input(" -- builddir must be an absolute path:") | 181 | be.builddir = raw_input(" -- Build directory must be an absolute path:") |
29 | is_changed = True | 182 | is_changed = True |
183 | |||
184 | |||
185 | |||
30 | if is_changed: | 186 | if is_changed: |
31 | print "saved" | 187 | print "Build configuration saved" |
32 | be.save() | 188 | be.save() |
189 | |||
190 | if is_changed and be.betype == BuildEnvironment.TYPE_LOCAL: | ||
191 | baselayerdir = DN(DN(self._find_first_path_for_file(be.sourcedir, "toasterconf.json", 3))) | ||
192 | if baselayerdir: | ||
193 | i = raw_input(" -- Do you want to import basic layer configuration from \"%s\" ? (y/N):" % baselayerdir) | ||
194 | if len(i) and i.upper()[0] == 'Y': | ||
195 | self._import_layer_config(baselayerdir) | ||
196 | # we run lsupdates after config update | ||
197 | print "Updating information from the layer source, please wait." | ||
198 | from django.core.management import call_command | ||
199 | call_command("lsupdates") | ||
200 | pass | ||
201 | |||
33 | return is_changed | 202 | return is_changed |
34 | 203 | ||
35 | while (_verify_be()): | 204 | while (_verify_be()): |
36 | pass | 205 | pass |
37 | 206 | ||
38 | return 0 | 207 | # verify that default settings are there |
208 | if ToasterSetting.objects.filter(name = 'DEFAULT_RELEASE').count() != 1: | ||
209 | ToasterSetting.objects.filter(name = 'DEFAULT_RELEASE').delete() | ||
210 | ToasterSetting.objects.get_or_create(name = 'DEFAULT_RELEASE', value = '') | ||
211 | |||
212 | return 0 | ||