summaryrefslogtreecommitdiffstats
path: root/scripts/lib/mic/kickstart
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/mic/kickstart')
-rw-r--r--scripts/lib/mic/kickstart/__init__.py892
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/__init__.py17
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/desktop.py95
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/installerfw.py63
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/micboot.py49
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/micpartition.py57
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/micrepo.py127
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/partition.py482
-rw-r--r--scripts/lib/mic/kickstart/custom_commands/wicboot.py57
9 files changed, 1839 insertions, 0 deletions
diff --git a/scripts/lib/mic/kickstart/__init__.py b/scripts/lib/mic/kickstart/__init__.py
new file mode 100644
index 0000000000..72f3ca6849
--- /dev/null
+++ b/scripts/lib/mic/kickstart/__init__.py
@@ -0,0 +1,892 @@
1#!/usr/bin/python -tt
2#
3# Copyright (c) 2007 Red Hat, Inc.
4# Copyright (c) 2009, 2010, 2011 Intel, Inc.
5#
6# This program is free software; you can redistribute it and/or modify it
7# under the terms of the GNU General Public License as published by the Free
8# Software Foundation; version 2 of the License
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13# for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc., 59
17# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19import os, sys, re
20import shutil
21import subprocess
22import string
23
24import pykickstart.sections as kssections
25import pykickstart.commands as kscommands
26import pykickstart.constants as ksconstants
27import pykickstart.errors as kserrors
28import pykickstart.parser as ksparser
29import pykickstart.version as ksversion
30from pykickstart.handlers.control import commandMap
31from pykickstart.handlers.control import dataMap
32
33from mic import msger
34from mic.utils import errors, misc, runner, fs_related as fs
35from custom_commands import desktop, micrepo, wicboot, partition, installerfw
36
37
38AUTH_URL_PTN = r"(?P<scheme>.*)://(?P<username>.*)(:?P<password>.*)?@(?P<url>.*)"
39
40
41class PrepackageSection(kssections.Section):
42 sectionOpen = "%prepackages"
43
44 def handleLine(self, line):
45 if not self.handler:
46 return
47
48 (h, s, t) = line.partition('#')
49 line = h.rstrip()
50
51 self.handler.prepackages.add([line])
52
53 def handleHeader(self, lineno, args):
54 kssections.Section.handleHeader(self, lineno, args)
55
56class AttachmentSection(kssections.Section):
57 sectionOpen = "%attachment"
58
59 def handleLine(self, line):
60 if not self.handler:
61 return
62
63 (h, s, t) = line.partition('#')
64 line = h.rstrip()
65
66 self.handler.attachment.add([line])
67
68 def handleHeader(self, lineno, args):
69 kssections.Section.handleHeader(self, lineno, args)
70
71def apply_wrapper(func):
72 def wrapper(*kargs, **kwargs):
73 try:
74 func(*kargs, **kwargs)
75 except (OSError, IOError, errors.KsError), err:
76 cfgcls = kargs[0].__class__.__name__
77 if msger.ask("Failed to apply %s, skip and continue?" % cfgcls):
78 msger.warning("%s" % err)
79 pass
80 else:
81 # just throw out the exception
82 raise
83 return wrapper
84
85def read_kickstart(path):
86 """Parse a kickstart file and return a KickstartParser instance.
87
88 This is a simple utility function which takes a path to a kickstart file,
89 parses it and returns a pykickstart KickstartParser instance which can
90 be then passed to an ImageCreator constructor.
91
92 If an error occurs, a CreatorError exception is thrown.
93 """
94
95 #version = ksversion.makeVersion()
96 #ks = ksparser.KickstartParser(version)
97
98 using_version = ksversion.DEVEL
99 commandMap[using_version]["desktop"] = desktop.Mic_Desktop
100 commandMap[using_version]["repo"] = micrepo.Mic_Repo
101 commandMap[using_version]["bootloader"] = wicboot.Wic_Bootloader
102 commandMap[using_version]["part"] = partition.Wic_Partition
103 commandMap[using_version]["partition"] = partition.Wic_Partition
104 commandMap[using_version]["installerfw"] = installerfw.Mic_installerfw
105 dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
106 dataMap[using_version]["PartData"] = partition.Wic_PartData
107 superclass = ksversion.returnClassForVersion(version=using_version)
108
109 class KSHandlers(superclass):
110 def __init__(self):
111 superclass.__init__(self, mapping=commandMap[using_version])
112 self.prepackages = ksparser.Packages()
113 self.attachment = ksparser.Packages()
114
115 ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
116 ks.registerSection(PrepackageSection(ks.handler))
117 ks.registerSection(AttachmentSection(ks.handler))
118
119 try:
120 ks.readKickstart(path)
121 except (kserrors.KickstartParseError, kserrors.KickstartError), err:
122 if msger.ask("Errors occured on kickstart file, skip and continue?"):
123 msger.warning("%s" % err)
124 pass
125 else:
126 raise errors.KsError("%s" % err)
127
128 return ks
129
130class KickstartConfig(object):
131 """A base class for applying kickstart configurations to a system."""
132 def __init__(self, instroot):
133 self.instroot = instroot
134
135 def path(self, subpath):
136 return self.instroot + subpath
137
138 def _check_sysconfig(self):
139 if not os.path.exists(self.path("/etc/sysconfig")):
140 fs.makedirs(self.path("/etc/sysconfig"))
141
142 def chroot(self):
143 os.chroot(self.instroot)
144 os.chdir("/")
145
146 def call(self, args):
147 if not os.path.exists("%s/%s" %(self.instroot, args[0])):
148 raise errors.KsError("Can't find %s in chroot" % args[0])
149 subprocess.call(args, preexec_fn = self.chroot)
150
151 def apply(self):
152 pass
153
154class LanguageConfig(KickstartConfig):
155 """A class to apply a kickstart language configuration to a system."""
156 @apply_wrapper
157 def apply(self, kslang):
158 self._check_sysconfig()
159 if kslang.lang:
160 f = open(self.path("/etc/sysconfig/i18n"), "w+")
161 f.write("LANG=\"" + kslang.lang + "\"\n")
162 f.close()
163
164class KeyboardConfig(KickstartConfig):
165 """A class to apply a kickstart keyboard configuration to a system."""
166 @apply_wrapper
167 def apply(self, kskeyboard):
168 #
169 # FIXME:
170 # should this impact the X keyboard config too?
171 # or do we want to make X be able to do this mapping?
172 #
173 #k = rhpl.keyboard.Keyboard()
174 #if kskeyboard.keyboard:
175 # k.set(kskeyboard.keyboard)
176 #k.write(self.instroot)
177 pass
178
179class TimezoneConfig(KickstartConfig):
180 """A class to apply a kickstart timezone configuration to a system."""
181 @apply_wrapper
182 def apply(self, kstimezone):
183 self._check_sysconfig()
184 tz = kstimezone.timezone or "America/New_York"
185 utc = str(kstimezone.isUtc)
186
187 f = open(self.path("/etc/sysconfig/clock"), "w+")
188 f.write("ZONE=\"" + tz + "\"\n")
189 f.write("UTC=" + utc + "\n")
190 f.close()
191 tz_source = "/usr/share/zoneinfo/%s" % (tz)
192 tz_dest = "/etc/localtime"
193 try:
194 cpcmd = fs.find_binary_inchroot('cp', self.instroot)
195 if cpcmd:
196 self.call([cpcmd, "-f", tz_source, tz_dest])
197 else:
198 cpcmd = fs.find_binary_path('cp')
199 subprocess.call([cpcmd, "-f",
200 self.path(tz_source),
201 self.path(tz_dest)])
202 except (IOError, OSError), (errno, msg):
203 raise errors.KsError("Timezone setting error: %s" % msg)
204
205class AuthConfig(KickstartConfig):
206 """A class to apply a kickstart authconfig configuration to a system."""
207 @apply_wrapper
208 def apply(self, ksauthconfig):
209 auth = ksauthconfig.authconfig or "--useshadow --enablemd5"
210 args = ["/usr/share/authconfig/authconfig.py", "--update", "--nostart"]
211 self.call(args + auth.split())
212
213class FirewallConfig(KickstartConfig):
214 """A class to apply a kickstart firewall configuration to a system."""
215 @apply_wrapper
216 def apply(self, ksfirewall):
217 #
218 # FIXME: should handle the rest of the options
219 #
220 if not os.path.exists(self.path("/usr/sbin/lokkit")):
221 return
222 if ksfirewall.enabled:
223 status = "--enabled"
224 else:
225 status = "--disabled"
226
227 self.call(["/usr/sbin/lokkit",
228 "-f", "--quiet", "--nostart", status])
229
230class RootPasswordConfig(KickstartConfig):
231 """A class to apply a kickstart root password configuration to a system."""
232 def unset(self):
233 self.call(["/usr/bin/passwd", "-d", "root"])
234
235 def set_encrypted(self, password):
236 self.call(["/usr/sbin/usermod", "-p", password, "root"])
237
238 def set_unencrypted(self, password):
239 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
240 if not os.path.exists("%s/%s" %(self.instroot, p)):
241 raise errors.KsError("Unable to set unencrypted password due "
242 "to lack of %s" % p)
243
244 p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
245 stdout = subprocess.PIPE,
246 preexec_fn = self.chroot)
247 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
248 stdin = p1.stdout,
249 stdout = subprocess.PIPE,
250 preexec_fn = self.chroot)
251 p2.communicate()
252
253 @apply_wrapper
254 def apply(self, ksrootpw):
255 if ksrootpw.isCrypted:
256 self.set_encrypted(ksrootpw.password)
257 elif ksrootpw.password != "":
258 self.set_unencrypted(ksrootpw.password)
259 else:
260 self.unset()
261
262class UserConfig(KickstartConfig):
263 def set_empty_passwd(self, user):
264 self.call(["/usr/bin/passwd", "-d", user])
265
266 def set_encrypted_passwd(self, user, password):
267 self.call(["/usr/sbin/usermod", "-p", "%s" % password, user])
268
269 def set_unencrypted_passwd(self, user, password):
270 for p in ("/bin/echo", "/usr/sbin/chpasswd"):
271 if not os.path.exists("%s/%s" %(self.instroot, p)):
272 raise errors.KsError("Unable to set unencrypted password due "
273 "to lack of %s" % p)
274
275 p1 = subprocess.Popen(["/bin/echo", "%s:%s" %(user, password)],
276 stdout = subprocess.PIPE,
277 preexec_fn = self.chroot)
278 p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
279 stdin = p1.stdout,
280 stdout = subprocess.PIPE,
281 preexec_fn = self.chroot)
282 p2.communicate()
283
284 def addUser(self, userconfig):
285 args = [ "/usr/sbin/useradd" ]
286 if userconfig.groups:
287 args += [ "--groups", string.join(userconfig.groups, ",") ]
288 if userconfig.name:
289 args += [ "-m"]
290 args += [ "-d", "/home/%s" % userconfig.name ]
291 args.append(userconfig.name)
292 try:
293 dev_null = os.open("/dev/null", os.O_WRONLY)
294 msger.debug('adding user with %s' % args)
295 subprocess.call(args,
296 stdout = dev_null,
297 stderr = dev_null,
298 preexec_fn = self.chroot)
299 os.close(dev_null)
300 except:
301 msger.warning('Cannot add user using "useradd"')
302
303 if userconfig.password not in (None, ""):
304 if userconfig.isCrypted:
305 self.set_encrypted_passwd(userconfig.name,
306 userconfig.password)
307 else:
308 self.set_unencrypted_passwd(userconfig.name,
309 userconfig.password)
310 else:
311 self.set_empty_passwd(userconfig.name)
312 else:
313 raise errors.KsError("Invalid kickstart command: %s" \
314 % userconfig.__str__())
315
316 @apply_wrapper
317 def apply(self, user):
318 for userconfig in user.userList:
319 self.addUser(userconfig)
320
321class ServicesConfig(KickstartConfig):
322 """A class to apply a kickstart services configuration to a system."""
323 @apply_wrapper
324 def apply(self, ksservices):
325 if not os.path.exists(self.path("/sbin/chkconfig")):
326 return
327 for s in ksservices.enabled:
328 self.call(["/sbin/chkconfig", s, "on"])
329 for s in ksservices.disabled:
330 self.call(["/sbin/chkconfig", s, "off"])
331
332class XConfig(KickstartConfig):
333 """A class to apply a kickstart X configuration to a system."""
334 @apply_wrapper
335 def apply(self, ksxconfig):
336 if ksxconfig.startX and os.path.exists(self.path("/etc/inittab")):
337 f = open(self.path("/etc/inittab"), "rw+")
338 buf = f.read()
339 buf = buf.replace("id:3:initdefault", "id:5:initdefault")
340 f.seek(0)
341 f.write(buf)
342 f.close()
343 if ksxconfig.defaultdesktop:
344 self._check_sysconfig()
345 f = open(self.path("/etc/sysconfig/desktop"), "w")
346 f.write("DESKTOP="+ksxconfig.defaultdesktop+"\n")
347 f.close()
348
349class DesktopConfig(KickstartConfig):
350 """A class to apply a kickstart desktop configuration to a system."""
351 @apply_wrapper
352 def apply(self, ksdesktop):
353 if ksdesktop.defaultdesktop:
354 self._check_sysconfig()
355 f = open(self.path("/etc/sysconfig/desktop"), "w")
356 f.write("DESKTOP="+ksdesktop.defaultdesktop+"\n")
357 f.close()
358 if os.path.exists(self.path("/etc/gdm/custom.conf")):
359 f = open(self.path("/etc/skel/.dmrc"), "w")
360 f.write("[Desktop]\n")
361 f.write("Session="+ksdesktop.defaultdesktop.lower()+"\n")
362 f.close()
363 if ksdesktop.session:
364 if os.path.exists(self.path("/etc/sysconfig/uxlaunch")):
365 f = open(self.path("/etc/sysconfig/uxlaunch"), "a+")
366 f.write("session="+ksdesktop.session.lower()+"\n")
367 f.close()
368 if ksdesktop.autologinuser:
369 self._check_sysconfig()
370 f = open(self.path("/etc/sysconfig/desktop"), "a+")
371 f.write("AUTOLOGIN_USER=" + ksdesktop.autologinuser + "\n")
372 f.close()
373 if os.path.exists(self.path("/etc/gdm/custom.conf")):
374 f = open(self.path("/etc/gdm/custom.conf"), "w")
375 f.write("[daemon]\n")
376 f.write("AutomaticLoginEnable=true\n")
377 f.write("AutomaticLogin=" + ksdesktop.autologinuser + "\n")
378 f.close()
379
380class MoblinRepoConfig(KickstartConfig):
381 """A class to apply a kickstart desktop configuration to a system."""
382 def __create_repo_section(self, repo, type, fd):
383 baseurl = None
384 mirrorlist = None
385 reposuffix = {"base":"", "debuginfo":"-debuginfo", "source":"-source"}
386 reponame = repo.name + reposuffix[type]
387 if type == "base":
388 if repo.baseurl:
389 baseurl = repo.baseurl
390 if repo.mirrorlist:
391 mirrorlist = repo.mirrorlist
392
393 elif type == "debuginfo":
394 if repo.baseurl:
395 if repo.baseurl.endswith("/"):
396 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
397 else:
398 baseurl = os.path.dirname(repo.baseurl)
399 baseurl += "/debug"
400
401 if repo.mirrorlist:
402 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
403 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
404 mirrorlist += "debug" + "-" + variant
405
406 elif type == "source":
407 if repo.baseurl:
408 if repo.baseurl.endswith("/"):
409 baseurl = os.path.dirname(
410 os.path.dirname(
411 os.path.dirname(repo.baseurl)))
412 else:
413 baseurl = os.path.dirname(os.path.dirname(repo.baseurl))
414 baseurl += "/source"
415
416 if repo.mirrorlist:
417 variant = repo.mirrorlist[repo.mirrorlist.find("$"):]
418 mirrorlist = repo.mirrorlist[0:repo.mirrorlist.find("$")]
419 mirrorlist += "source" + "-" + variant
420
421 fd.write("[" + reponame + "]\n")
422 fd.write("name=" + reponame + "\n")
423 fd.write("failovermethod=priority\n")
424 if baseurl:
425 auth_url = re.compile(AUTH_URL_PTN)
426 m = auth_url.match(baseurl)
427 if m:
428 baseurl = "%s://%s" % (m.group('scheme'), m.group('url'))
429 fd.write("baseurl=" + baseurl + "\n")
430 if mirrorlist:
431 fd.write("mirrorlist=" + mirrorlist + "\n")
432 """ Skip saving proxy settings """
433 #if repo.proxy:
434 # fd.write("proxy=" + repo.proxy + "\n")
435 #if repo.proxy_username:
436 # fd.write("proxy_username=" + repo.proxy_username + "\n")
437 #if repo.proxy_password:
438 # fd.write("proxy_password=" + repo.proxy_password + "\n")
439 if repo.gpgkey:
440 fd.write("gpgkey=" + repo.gpgkey + "\n")
441 fd.write("gpgcheck=1\n")
442 else:
443 fd.write("gpgcheck=0\n")
444 if type == "source" or type == "debuginfo" or repo.disable:
445 fd.write("enabled=0\n")
446 else:
447 fd.write("enabled=1\n")
448 fd.write("\n")
449
450 def __create_repo_file(self, repo, repodir):
451 fs.makedirs(self.path(repodir))
452 f = open(self.path(repodir + "/" + repo.name + ".repo"), "w")
453 self.__create_repo_section(repo, "base", f)
454 if repo.debuginfo:
455 self.__create_repo_section(repo, "debuginfo", f)
456 if repo.source:
457 self.__create_repo_section(repo, "source", f)
458 f.close()
459
460 @apply_wrapper
461 def apply(self, ksrepo, repodata, repourl):
462 for repo in ksrepo.repoList:
463 if repo.name in repourl:
464 repo.baseurl = repourl[repo.name]
465 if repo.save:
466 #self.__create_repo_file(repo, "/etc/yum.repos.d")
467 self.__create_repo_file(repo, "/etc/zypp/repos.d")
468 """ Import repo gpg keys """
469 if repodata:
470 for repo in repodata:
471 if repo['repokey']:
472 runner.quiet(['rpm',
473 "--root=%s" % self.instroot,
474 "--import",
475 repo['repokey']])
476
477class RPMMacroConfig(KickstartConfig):
478 """A class to apply the specified rpm macros to the filesystem"""
479 @apply_wrapper
480 def apply(self, ks):
481 if not ks:
482 return
483 if not os.path.exists(self.path("/etc/rpm")):
484 os.mkdir(self.path("/etc/rpm"))
485 f = open(self.path("/etc/rpm/macros.imgcreate"), "w+")
486 if exclude_docs(ks):
487 f.write("%_excludedocs 1\n")
488 f.write("%__file_context_path %{nil}\n")
489 if inst_langs(ks) != None:
490 f.write("%_install_langs ")
491 f.write(inst_langs(ks))
492 f.write("\n")
493 f.close()
494
495class NetworkConfig(KickstartConfig):
496 """A class to apply a kickstart network configuration to a system."""
497 def write_ifcfg(self, network):
498 p = self.path("/etc/sysconfig/network-scripts/ifcfg-" + network.device)
499
500 f = file(p, "w+")
501 os.chmod(p, 0644)
502
503 f.write("DEVICE=%s\n" % network.device)
504 f.write("BOOTPROTO=%s\n" % network.bootProto)
505
506 if network.bootProto.lower() == "static":
507 if network.ip:
508 f.write("IPADDR=%s\n" % network.ip)
509 if network.netmask:
510 f.write("NETMASK=%s\n" % network.netmask)
511
512 if network.onboot:
513 f.write("ONBOOT=on\n")
514 else:
515 f.write("ONBOOT=off\n")
516
517 if network.essid:
518 f.write("ESSID=%s\n" % network.essid)
519
520 if network.ethtool:
521 if network.ethtool.find("autoneg") == -1:
522 network.ethtool = "autoneg off " + network.ethtool
523 f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
524
525 if network.bootProto.lower() == "dhcp":
526 if network.hostname:
527 f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
528 if network.dhcpclass:
529 f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
530
531 if network.mtu:
532 f.write("MTU=%s\n" % network.mtu)
533
534 f.close()
535
536 def write_wepkey(self, network):
537 if not network.wepkey:
538 return
539
540 p = self.path("/etc/sysconfig/network-scripts/keys-" + network.device)
541 f = file(p, "w+")
542 os.chmod(p, 0600)
543 f.write("KEY=%s\n" % network.wepkey)
544 f.close()
545
546 def write_sysconfig(self, useipv6, hostname, gateway):
547 path = self.path("/etc/sysconfig/network")
548 f = file(path, "w+")
549 os.chmod(path, 0644)
550
551 f.write("NETWORKING=yes\n")
552
553 if useipv6:
554 f.write("NETWORKING_IPV6=yes\n")
555 else:
556 f.write("NETWORKING_IPV6=no\n")
557
558 if hostname:
559 f.write("HOSTNAME=%s\n" % hostname)
560 else:
561 f.write("HOSTNAME=localhost.localdomain\n")
562
563 if gateway:
564 f.write("GATEWAY=%s\n" % gateway)
565
566 f.close()
567
568 def write_hosts(self, hostname):
569 localline = ""
570 if hostname and hostname != "localhost.localdomain":
571 localline += hostname + " "
572 l = hostname.split(".")
573 if len(l) > 1:
574 localline += l[0] + " "
575 localline += "localhost.localdomain localhost"
576
577 path = self.path("/etc/hosts")
578 f = file(path, "w+")
579 os.chmod(path, 0644)
580 f.write("127.0.0.1\t\t%s\n" % localline)
581 f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
582 f.close()
583
584 def write_resolv(self, nodns, nameservers):
585 if nodns or not nameservers:
586 return
587
588 path = self.path("/etc/resolv.conf")
589 f = file(path, "w+")
590 os.chmod(path, 0644)
591
592 for ns in (nameservers):
593 if ns:
594 f.write("nameserver %s\n" % ns)
595
596 f.close()
597
598 @apply_wrapper
599 def apply(self, ksnet):
600 fs.makedirs(self.path("/etc/sysconfig/network-scripts"))
601
602 useipv6 = False
603 nodns = False
604 hostname = None
605 gateway = None
606 nameservers = None
607
608 for network in ksnet.network:
609 if not network.device:
610 raise errors.KsError("No --device specified with "
611 "network kickstart command")
612
613 if (network.onboot and network.bootProto.lower() != "dhcp" and
614 not (network.ip and network.netmask)):
615 raise errors.KsError("No IP address and/or netmask "
616 "specified with static "
617 "configuration for '%s'" %
618 network.device)
619
620 self.write_ifcfg(network)
621 self.write_wepkey(network)
622
623 if network.ipv6:
624 useipv6 = True
625 if network.nodns:
626 nodns = True
627
628 if network.hostname:
629 hostname = network.hostname
630 if network.gateway:
631 gateway = network.gateway
632
633 if network.nameserver:
634 nameservers = network.nameserver.split(",")
635
636 self.write_sysconfig(useipv6, hostname, gateway)
637 self.write_hosts(hostname)
638 self.write_resolv(nodns, nameservers)
639
640def use_installerfw(ks, feature):
641 """ Check if the installer framework has to be used for a feature
642 "feature". """
643
644 features = ks.handler.installerfw.features
645 if features:
646 if feature in features or "all" in features:
647 return True
648 return False
649
650def get_image_size(ks, default = None):
651 __size = 0
652 for p in ks.handler.partition.partitions:
653 if p.mountpoint == "/" and p.size:
654 __size = p.size
655 if __size > 0:
656 return int(__size) * 1024L * 1024L
657 else:
658 return default
659
660def get_image_fstype(ks, default = None):
661 for p in ks.handler.partition.partitions:
662 if p.mountpoint == "/" and p.fstype:
663 return p.fstype
664 return default
665
666def get_image_fsopts(ks, default = None):
667 for p in ks.handler.partition.partitions:
668 if p.mountpoint == "/" and p.fsopts:
669 return p.fsopts
670 return default
671
672def get_modules(ks):
673 devices = []
674 if isinstance(ks.handler.device, kscommands.device.FC3_Device):
675 devices.append(ks.handler.device)
676 else:
677 devices.extend(ks.handler.device.deviceList)
678
679 modules = []
680 for device in devices:
681 if not device.moduleName:
682 continue
683 modules.extend(device.moduleName.split(":"))
684
685 return modules
686
687def get_timeout(ks, default = None):
688 if not hasattr(ks.handler.bootloader, "timeout"):
689 return default
690 if ks.handler.bootloader.timeout is None:
691 return default
692 return int(ks.handler.bootloader.timeout)
693
694def get_kernel_args(ks, default = "ro rd.live.image"):
695 if not hasattr(ks.handler.bootloader, "appendLine"):
696 return default
697 if ks.handler.bootloader.appendLine is None:
698 return default
699 return "%s %s" %(default, ks.handler.bootloader.appendLine)
700
701def get_menu_args(ks, default = ""):
702 if not hasattr(ks.handler.bootloader, "menus"):
703 return default
704 if ks.handler.bootloader.menus in (None, ""):
705 return default
706 return "%s" % ks.handler.bootloader.menus
707
708def get_default_kernel(ks, default = None):
709 if not hasattr(ks.handler.bootloader, "default"):
710 return default
711 if not ks.handler.bootloader.default:
712 return default
713 return ks.handler.bootloader.default
714
715def get_repos(ks, repo_urls=None):
716 repos = {}
717 for repo in ks.handler.repo.repoList:
718 inc = []
719 if hasattr(repo, "includepkgs"):
720 inc.extend(repo.includepkgs)
721
722 exc = []
723 if hasattr(repo, "excludepkgs"):
724 exc.extend(repo.excludepkgs)
725
726 baseurl = repo.baseurl
727 mirrorlist = repo.mirrorlist
728
729 if repo_urls and repo.name in repo_urls:
730 baseurl = repo_urls[repo.name]
731 mirrorlist = None
732
733 if repos.has_key(repo.name):
734 msger.warning("Overriding already specified repo %s" %(repo.name,))
735
736 proxy = None
737 if hasattr(repo, "proxy"):
738 proxy = repo.proxy
739 proxy_username = None
740 if hasattr(repo, "proxy_username"):
741 proxy_username = repo.proxy_username
742 proxy_password = None
743 if hasattr(repo, "proxy_password"):
744 proxy_password = repo.proxy_password
745 if hasattr(repo, "debuginfo"):
746 debuginfo = repo.debuginfo
747 if hasattr(repo, "source"):
748 source = repo.source
749 if hasattr(repo, "gpgkey"):
750 gpgkey = repo.gpgkey
751 if hasattr(repo, "disable"):
752 disable = repo.disable
753 ssl_verify = True
754 if hasattr(repo, "ssl_verify"):
755 ssl_verify = repo.ssl_verify == "yes"
756 nocache = False
757 if hasattr(repo, "nocache"):
758 nocache = repo.nocache
759 cost = None
760 if hasattr(repo, "cost"):
761 cost = repo.cost
762 priority = None
763 if hasattr(repo, "priority"):
764 priority = repo.priority
765
766 repos[repo.name] = (repo.name, baseurl, mirrorlist, inc, exc,
767 proxy, proxy_username, proxy_password, debuginfo,
768 source, gpgkey, disable, ssl_verify, nocache,
769 cost, priority)
770
771 return repos.values()
772
773def convert_method_to_repo(ks):
774 try:
775 ks.handler.repo.methodToRepo()
776 except (AttributeError, kserrors.KickstartError):
777 pass
778
779def get_attachment(ks, required=()):
780 return ks.handler.attachment.packageList + list(required)
781
782def get_pre_packages(ks, required=()):
783 return ks.handler.prepackages.packageList + list(required)
784
785def get_packages(ks, required=()):
786 return ks.handler.packages.packageList + list(required)
787
788def get_groups(ks, required=()):
789 return ks.handler.packages.groupList + list(required)
790
791def get_excluded(ks, required=()):
792 return ks.handler.packages.excludedList + list(required)
793
794def get_partitions(ks):
795 return ks.handler.partition.partitions
796
797def ignore_missing(ks):
798 return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE
799
800def exclude_docs(ks):
801 return ks.handler.packages.excludeDocs
802
803def inst_langs(ks):
804 if hasattr(ks.handler.packages, "instLange"):
805 return ks.handler.packages.instLange
806 elif hasattr(ks.handler.packages, "instLangs"):
807 return ks.handler.packages.instLangs
808 return ""
809
810def get_post_scripts(ks):
811 scripts = []
812 for s in ks.handler.scripts:
813 if s.type != ksparser.KS_SCRIPT_POST:
814 continue
815 scripts.append(s)
816 return scripts
817
818def add_repo(ks, repostr):
819 args = repostr.split()
820 repoobj = ks.handler.repo.parse(args[1:])
821 if repoobj and repoobj not in ks.handler.repo.repoList:
822 ks.handler.repo.repoList.append(repoobj)
823
824def remove_all_repos(ks):
825 while len(ks.handler.repo.repoList) != 0:
826 del ks.handler.repo.repoList[0]
827
828def remove_duplicate_repos(ks):
829 i = 0
830 j = i + 1
831 while True:
832 if len(ks.handler.repo.repoList) < 2:
833 break
834 if i >= len(ks.handler.repo.repoList) - 1:
835 break
836 name = ks.handler.repo.repoList[i].name
837 baseurl = ks.handler.repo.repoList[i].baseurl
838 if j < len(ks.handler.repo.repoList):
839 if (ks.handler.repo.repoList[j].name == name or \
840 ks.handler.repo.repoList[j].baseurl == baseurl):
841 del ks.handler.repo.repoList[j]
842 else:
843 j += 1
844 if j >= len(ks.handler.repo.repoList):
845 i += 1
846 j = i + 1
847 else:
848 i += 1
849 j = i + 1
850
851def resolve_groups(creatoropts, repometadata):
852 iszypp = False
853 if 'zypp' == creatoropts['pkgmgr']:
854 iszypp = True
855 ks = creatoropts['ks']
856
857 for repo in repometadata:
858 """ Mustn't replace group with package list if repo is ready for the
859 corresponding package manager.
860 """
861
862 if iszypp and repo["patterns"]:
863 continue
864 if not iszypp and repo["comps"]:
865 continue
866
867 # But we also must handle such cases, use zypp but repo only has comps,
868 # use yum but repo only has patterns, use zypp but use_comps is true,
869 # use yum but use_comps is false.
870 groupfile = None
871 if iszypp and repo["comps"]:
872 groupfile = repo["comps"]
873 get_pkglist_handler = misc.get_pkglist_in_comps
874 if not iszypp and repo["patterns"]:
875 groupfile = repo["patterns"]
876 get_pkglist_handler = misc.get_pkglist_in_patterns
877
878 if groupfile:
879 i = 0
880 while True:
881 if i >= len(ks.handler.packages.groupList):
882 break
883 pkglist = get_pkglist_handler(
884 ks.handler.packages.groupList[i].name,
885 groupfile)
886 if pkglist:
887 del ks.handler.packages.groupList[i]
888 for pkg in pkglist:
889 if pkg not in ks.handler.packages.packageList:
890 ks.handler.packages.packageList.append(pkg)
891 else:
892 i = i + 1
diff --git a/scripts/lib/mic/kickstart/custom_commands/__init__.py b/scripts/lib/mic/kickstart/custom_commands/__init__.py
new file mode 100644
index 0000000000..6aed0ff6fa
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/__init__.py
@@ -0,0 +1,17 @@
1from desktop import Mic_Desktop
2from micrepo import Mic_Repo, Mic_RepoData
3from micpartition import Mic_Partition
4from micpartition import Mic_PartData
5from installerfw import Mic_installerfw
6from partition import Wic_Partition
7
8__all__ = (
9 "Mic_Desktop",
10 "Mic_Repo",
11 "Mic_RepoData",
12 "Mic_Partition",
13 "Mic_PartData",
14 "Mic_installerfw",
15 "Wic_Partition",
16 "Wic_PartData",
17)
diff --git a/scripts/lib/mic/kickstart/custom_commands/desktop.py b/scripts/lib/mic/kickstart/custom_commands/desktop.py
new file mode 100644
index 0000000000..c8bd647ae3
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/desktop.py
@@ -0,0 +1,95 @@
1#!/usr/bin/python -tt
2#
3# Copyright (c) 2008, 2009, 2010 Intel, Inc.
4#
5# Yi Yang <yi.y.yang@intel.com>
6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by the Free
9# Software Foundation; version 2 of the License
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14# for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc., 59
18# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20from pykickstart.base import *
21from pykickstart.errors import *
22from pykickstart.options import *
23
24class Mic_Desktop(KickstartCommand):
25 def __init__(self, writePriority=0,
26 defaultdesktop=None,
27 defaultdm=None,
28 autologinuser=None,
29 session=None):
30
31 KickstartCommand.__init__(self, writePriority)
32
33 self.__new_version = False
34 self.op = self._getParser()
35
36 self.defaultdesktop = defaultdesktop
37 self.autologinuser = autologinuser
38 self.defaultdm = defaultdm
39 self.session = session
40
41 def __str__(self):
42 retval = ""
43
44 if self.defaultdesktop != None:
45 retval += " --defaultdesktop=%s" % self.defaultdesktop
46 if self.session != None:
47 retval += " --session=\"%s\"" % self.session
48 if self.autologinuser != None:
49 retval += " --autologinuser=%s" % self.autologinuser
50 if self.defaultdm != None:
51 retval += " --defaultdm=%s" % self.defaultdm
52
53 if retval != "":
54 retval = "# Default Desktop Settings\ndesktop %s\n" % retval
55
56 return retval
57
58 def _getParser(self):
59 try:
60 op = KSOptionParser(lineno=self.lineno)
61 except TypeError:
62 # the latest version has not lineno argument
63 op = KSOptionParser()
64 self.__new_version = True
65
66 op.add_option("--defaultdesktop", dest="defaultdesktop",
67 action="store",
68 type="string",
69 nargs=1)
70 op.add_option("--autologinuser", dest="autologinuser",
71 action="store",
72 type="string",
73 nargs=1)
74 op.add_option("--defaultdm", dest="defaultdm",
75 action="store",
76 type="string",
77 nargs=1)
78 op.add_option("--session", dest="session",
79 action="store",
80 type="string",
81 nargs=1)
82 return op
83
84 def parse(self, args):
85 if self.__new_version:
86 (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno)
87 else:
88 (opts, extra) = self.op.parse_args(args=args)
89
90 if extra:
91 m = _("Unexpected arguments to %(command)s command: %(options)s") \
92 % {"command": "desktop", "options": extra}
93 raise KickstartValueError, formatErrorMsg(self.lineno, msg=m)
94
95 self._setToSelf(self.op, opts)
diff --git a/scripts/lib/mic/kickstart/custom_commands/installerfw.py b/scripts/lib/mic/kickstart/custom_commands/installerfw.py
new file mode 100644
index 0000000000..2466f1dc07
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/installerfw.py
@@ -0,0 +1,63 @@
1#!/usr/bin/python -tt
2#
3# Copyright (c) 2013 Intel, Inc.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the Free
7# Software Foundation; version 2 of the License
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12# for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc., 59
16# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18from pykickstart.base import *
19from pykickstart.options import *
20
21class Mic_installerfw(KickstartCommand):
22 """ This class implements the "installerfw" KS option. The argument
23 of the option is a comman-separated list of MIC features which have to be
24 disabled and instead, will be done in the installer. For example,
25 "installerfw=extlinux" disables all the MIC code which installs extlinux to
26 the target images, and instead, the extlinux or whatever boot-loader will
27 be installed by the installer instead.
28
29 The installer is a tool which is external to MIC, it comes from the
30 installation repositories and can be executed by MIC in order to perform
31 various configuration actions. The main point here is to make sure MIC has
32 no hard-wired knoledge about the target OS configuration. """
33
34 removedKeywords = KickstartCommand.removedKeywords
35 removedAttrs = KickstartCommand.removedAttrs
36
37 def __init__(self, *args, **kwargs):
38 KickstartCommand.__init__(self, *args, **kwargs)
39 self.op = self._getParser()
40 self.features = kwargs.get("installerfw", None)
41
42 def __str__(self):
43 retval = KickstartCommand.__str__(self)
44
45 if self.features:
46 retval += "# Enable installer framework features\ninstallerfw\n"
47
48 return retval
49
50 def _getParser(self):
51 op = KSOptionParser()
52 return op
53
54 def parse(self, args):
55 (_, extra) = self.op.parse_args(args=args, lineno=self.lineno)
56
57 if len(extra) != 1:
58 msg = "Kickstart command \"installerfw\" requires one " \
59 "argumet - a list of legacy features to disable"
60 raise KickstartValueError, formatErrorMsg(self.lineno, msg = msg)
61
62 self.features = extra[0].split(",")
63 return self
diff --git a/scripts/lib/mic/kickstart/custom_commands/micboot.py b/scripts/lib/mic/kickstart/custom_commands/micboot.py
new file mode 100644
index 0000000000..66d1678aa7
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/micboot.py
@@ -0,0 +1,49 @@
1#!/usr/bin/python -tt
2#
3# Copyright (c) 2008, 2009, 2010 Intel, Inc.
4#
5# Anas Nashif
6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by the Free
9# Software Foundation; version 2 of the License
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14# for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc., 59
18# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20from pykickstart.base import *
21from pykickstart.errors import *
22from pykickstart.options import *
23from pykickstart.commands.bootloader import *
24
25class Mic_Bootloader(F8_Bootloader):
26 def __init__(self, writePriority=10, appendLine="", driveorder=None,
27 forceLBA=False, location="", md5pass="", password="",
28 upgrade=False, menus=""):
29 F8_Bootloader.__init__(self, writePriority, appendLine, driveorder,
30 forceLBA, location, md5pass, password, upgrade)
31
32 self.menus = ""
33 self.ptable = "msdos"
34
35 def _getArgsAsStr(self):
36 ret = F8_Bootloader._getArgsAsStr(self)
37
38 if self.menus == "":
39 ret += " --menus=%s" %(self.menus,)
40 if self.ptable:
41 ret += " --ptable=\"%s\"" %(self.ptable,)
42 return ret
43
44 def _getParser(self):
45 op = F8_Bootloader._getParser(self)
46 op.add_option("--menus", dest="menus")
47 op.add_option("--ptable", dest="ptable", type="string")
48 return op
49
diff --git a/scripts/lib/mic/kickstart/custom_commands/micpartition.py b/scripts/lib/mic/kickstart/custom_commands/micpartition.py
new file mode 100644
index 0000000000..59a87fb486
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/micpartition.py
@@ -0,0 +1,57 @@
1#!/usr/bin/python -tt
2#
3# Marko Saukko <marko.saukko@cybercom.com>
4#
5# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
6#
7# This copyrighted material is made available to anyone wishing to use, modify,
8# copy, or redistribute it subject to the terms and conditions of the GNU
9# General Public License v.2. This program is distributed in the hope that it
10# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
11# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12# See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# this program; if not, write to the Free Software Foundation, Inc., 51
16# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18from pykickstart.commands.partition import *
19
20class Mic_PartData(FC4_PartData):
21 removedKeywords = FC4_PartData.removedKeywords
22 removedAttrs = FC4_PartData.removedAttrs
23
24 def __init__(self, *args, **kwargs):
25 FC4_PartData.__init__(self, *args, **kwargs)
26 self.deleteRemovedAttrs()
27 self.align = kwargs.get("align", None)
28 self.extopts = kwargs.get("extopts", None)
29 self.part_type = kwargs.get("part_type", None)
30
31 def _getArgsAsStr(self):
32 retval = FC4_PartData._getArgsAsStr(self)
33
34 if self.align:
35 retval += " --align"
36 if self.extopts:
37 retval += " --extoptions=%s" % self.extopts
38 if self.part_type:
39 retval += " --part-type=%s" % self.part_type
40
41 return retval
42
43class Mic_Partition(FC4_Partition):
44 removedKeywords = FC4_Partition.removedKeywords
45 removedAttrs = FC4_Partition.removedAttrs
46
47 def _getParser(self):
48 op = FC4_Partition._getParser(self)
49 # The alignment value is given in kBytes. e.g., value 8 means that
50 # the partition is aligned to start from 8096 byte boundary.
51 op.add_option("--align", type="int", action="store", dest="align",
52 default=None)
53 op.add_option("--extoptions", type="string", action="store", dest="extopts",
54 default=None)
55 op.add_option("--part-type", type="string", action="store", dest="part_type",
56 default=None)
57 return op
diff --git a/scripts/lib/mic/kickstart/custom_commands/micrepo.py b/scripts/lib/mic/kickstart/custom_commands/micrepo.py
new file mode 100644
index 0000000000..b31576e400
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/micrepo.py
@@ -0,0 +1,127 @@
1#!/usr/bin/python -tt
2#
3# Copyright (c) 2008, 2009, 2010 Intel, Inc.
4#
5# Yi Yang <yi.y.yang@intel.com>
6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by the Free
9# Software Foundation; version 2 of the License
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14# for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc., 59
18# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20from pykickstart.base import *
21from pykickstart.errors import *
22from pykickstart.options import *
23from pykickstart.commands.repo import *
24
25class Mic_RepoData(F8_RepoData):
26
27 def __init__(self, baseurl="", mirrorlist=None, name="", priority=None,
28 includepkgs=(), excludepkgs=(), save=False, proxy=None,
29 proxy_username=None, proxy_password=None, debuginfo=False,
30 source=False, gpgkey=None, disable=False, ssl_verify="yes",
31 nocache=False):
32 kw = {}
33 # F8_RepoData keywords
34 if includepkgs:
35 kw['includepkgs'] = includepkgs
36 if excludepkgs:
37 kw['excludepkgs'] = excludepkgs
38
39 #FC6_RepoData keywords
40 if baseurl:
41 kw['baseurl'] = baseurl
42 if mirrorlist:
43 kw['mirrorlist'] = mirrorlist
44 if name:
45 kw['name'] = name
46
47 F8_RepoData.__init__(self, **kw)
48 self.save = save
49 self.proxy = proxy
50 self.proxy_username = proxy_username
51 self.proxy_password = proxy_password
52 self.debuginfo = debuginfo
53 self.disable = disable
54 self.source = source
55 self.gpgkey = gpgkey
56 self.ssl_verify = ssl_verify.lower()
57 self.priority = priority
58 self.nocache = nocache
59
60 def _getArgsAsStr(self):
61 retval = F8_RepoData._getArgsAsStr(self)
62
63 if self.save:
64 retval += " --save"
65 if self.proxy:
66 retval += " --proxy=%s" % self.proxy
67 if self.proxy_username:
68 retval += " --proxyuser=%s" % self.proxy_username
69 if self.proxy_password:
70 retval += " --proxypasswd=%s" % self.proxy_password
71 if self.debuginfo:
72 retval += " --debuginfo"
73 if self.source:
74 retval += " --source"
75 if self.gpgkey:
76 retval += " --gpgkey=%s" % self.gpgkey
77 if self.disable:
78 retval += " --disable"
79 if self.ssl_verify:
80 retval += " --ssl_verify=%s" % self.ssl_verify
81 if self.priority:
82 retval += " --priority=%s" % self.priority
83 if self.nocache:
84 retval += " --nocache"
85
86 return retval
87
88class Mic_Repo(F8_Repo):
89 def __init__(self, writePriority=0, repoList=None):
90 F8_Repo.__init__(self, writePriority, repoList)
91
92 def __str__(self):
93 retval = ""
94 for repo in self.repoList:
95 retval += repo.__str__()
96
97 return retval
98
99 def _getParser(self):
100 def list_cb (option, opt_str, value, parser):
101 for d in value.split(','):
102 parser.values.ensure_value(option.dest, []).append(d)
103
104 op = F8_Repo._getParser(self)
105 op.add_option("--save", action="store_true", dest="save",
106 default=False)
107 op.add_option("--proxy", type="string", action="store", dest="proxy",
108 default=None, nargs=1)
109 op.add_option("--proxyuser", type="string", action="store",
110 dest="proxy_username", default=None, nargs=1)
111 op.add_option("--proxypasswd", type="string", action="store",
112 dest="proxy_password", default=None, nargs=1)
113 op.add_option("--debuginfo", action="store_true", dest="debuginfo",
114 default=False)
115 op.add_option("--source", action="store_true", dest="source",
116 default=False)
117 op.add_option("--disable", action="store_true", dest="disable",
118 default=False)
119 op.add_option("--gpgkey", type="string", action="store", dest="gpgkey",
120 default=None, nargs=1)
121 op.add_option("--ssl_verify", type="string", action="store",
122 dest="ssl_verify", default="yes")
123 op.add_option("--priority", type="int", action="store", dest="priority",
124 default=None)
125 op.add_option("--nocache", action="store_true", dest="nocache",
126 default=False)
127 return op
diff --git a/scripts/lib/mic/kickstart/custom_commands/partition.py b/scripts/lib/mic/kickstart/custom_commands/partition.py
new file mode 100644
index 0000000000..450d2d492d
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/partition.py
@@ -0,0 +1,482 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# Copyright (c) 2013, Intel Corporation.
5# All rights reserved.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# DESCRIPTION
21# This module provides the OpenEmbedded partition object definitions.
22#
23# AUTHORS
24# Tom Zanussi <tom.zanussi (at] linux.intel.com>
25#
26
27import shutil
28
29from pykickstart.commands.partition import *
30from mic.utils.oe.misc import *
31from mic.kickstart.custom_commands import *
32from mic.plugin import pluginmgr
33
34import os
35from mic.utils.oe.package_manager import *
36
37partition_methods = {
38 "do_install_pkgs":None,
39 "do_stage_partition":None,
40 "do_prepare_partition":None,
41 "do_configure_partition":None,
42}
43
44class Wic_PartData(Mic_PartData):
45 removedKeywords = Mic_PartData.removedKeywords
46 removedAttrs = Mic_PartData.removedAttrs
47
48 def __init__(self, *args, **kwargs):
49 Mic_PartData.__init__(self, *args, **kwargs)
50 self.deleteRemovedAttrs()
51 self.source = kwargs.get("source", None)
52 self.rootfs = kwargs.get("rootfs-dir", None)
53 self.source_file = ""
54 self.size = 0
55
56 def _getArgsAsStr(self):
57 retval = Mic_PartData._getArgsAsStr(self)
58
59 if self.source:
60 retval += " --source=%s" % self.source
61 if self.rootfs:
62 retval += " --rootfs-dir=%s" % self.rootfs
63
64 return retval
65
66 def get_rootfs(self):
67 """
68 Acessor for rootfs dir
69 """
70 return self.rootfs
71
72 def set_rootfs(self, rootfs):
73 """
74 Acessor for actual rootfs dir, which must be set by source
75 plugins.
76 """
77 self.rootfs = rootfs
78
79 def get_size(self):
80 """
81 Accessor for partition size, 0 or --size before set_size().
82 """
83 return self.size
84
85 def set_size(self, size):
86 """
87 Accessor for actual partition size, which must be set by source
88 plugins.
89 """
90 self.size = size
91
92 def set_source_file(self, source_file):
93 """
94 Accessor for source_file, the location of the generated partition
95 image, which must be set by source plugins.
96 """
97 self.source_file = source_file
98
99 def get_extra_block_count(self, current_blocks):
100 """
101 The --size param is reflected in self.size (in MB), and we already
102 have current_blocks (1k) blocks, calculate and return the
103 number of (1k) blocks we need to add to get to --size, 0 if
104 we're already there or beyond.
105 """
106 msger.debug("Requested partition size for %s: %d" % \
107 (self.mountpoint, self.size))
108
109 if not self.size:
110 return 0
111
112 requested_blocks = self.size * 1024
113
114 msger.debug("Requested blocks %d, current_blocks %d" % \
115 (requested_blocks, current_blocks))
116
117 if requested_blocks > current_blocks:
118 return requested_blocks - current_blocks
119 else:
120 return 0
121
122 def install_pkgs(self, creator, cr_workdir, oe_builddir, rootfs_dir,
123 bootimg_dir, kernel_dir, native_sysroot):
124 """
125 Prepare content for individual partitions, installing packages.
126 """
127
128 if not self.source:
129 return
130
131 self._source_methods = pluginmgr.get_source_plugin_methods(self.source, partition_methods)
132 self._source_methods["do_install_pkgs"](self, creator,
133 cr_workdir,
134 oe_builddir,
135 rootfs_dir,
136 bootimg_dir,
137 kernel_dir,
138 native_sysroot)
139
140 def install_pkgs_ipk(self, cr_workdir, oe_builddir, rootfs_dir,
141 native_sysroot, packages, repourl):
142 """
143 Install packages specified into wks file using opkg package manager.
144 This method is dependend on bb module.
145 """
146
147 gVar = {}
148 gVar["DEPLOY_DIR_IPK"] = os.path.join(oe_builddir, "tmp/deploy/ipk")
149
150 # Run postinstall scripts even in offline mode
151 # Use the arch priority package rather than higher version one if more than one candidate is found.
152 #d.setVar("OPKG_ARGS", "--force_postinstall --prefer-arch-to-version")
153 gVar["OPKG_ARGS"] = "--force_postinstall"
154
155 # OPKG path relative to /output_path
156 gVar["OPKGLIBDIR"] = "var/lib"
157
158 source_url = repourl.split()
159
160 # Generate feed uri's names, it doesn't seem to matter what name they have
161 feed_uris = ""
162 cnt = 0
163 archs = ""
164 for url in source_url:
165 feed_uris += "cl_def_feed%d##%s\n" % (cnt, url)
166 cnt += 1
167 head, tail = os.path.split(url)
168 archs += " " + tail
169
170 # IPK_FEED_URIS with special formating defines the URI's used as source for packages
171 gVar['IPK_FEED_URIS'] = feed_uris
172
173 gVar['BUILD_IMAGES_FROM_FEEDS'] = "1"
174
175 # We need to provide sysroot for utilities
176 gVar['STAGING_DIR_NATIVE'] = native_sysroot
177
178 # Set WORKDIR for output
179 gVar['WORKDIR'] = cr_workdir
180
181 # Set TMPDIR for output
182 gVar['TMPDIR'] = os.path.join(cr_workdir, "tmp")
183
184 if 'ROOTFS_DIR' in rootfs_dir:
185 target_dir = rootfs_dir['ROOTFS_DIR']
186 elif os.path.isdir(rootfs_dir):
187 target_dir = rootfs_dir
188 else:
189 msg = "Couldn't find --rootfs-dir=%s connection"
190 msg += " or it is not a valid path, exiting"
191 msger.error(msg % rootfs_dir)
192
193 # Need native sysroot /usr/bin/ for opkg-cl
194 # chnage PATH var to avoid issues with host tools
195 defpath = os.environ['PATH']
196 os.environ['PATH'] = native_sysroot + "/usr/bin/" + ":/bin:/usr/bin:"
197
198 pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot
199 pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % target_dir
200 pseudo += "export PSEUDO_PASSWD=%s;" % target_dir
201 pseudo += "export PSEUDO_NOSYMLINKEXP=1;"
202 pseudo += "%s/usr/bin/pseudo " % native_sysroot
203
204 pm = WicOpkgPM(gVar,
205 target_dir,
206 'opkg.conf',
207 archs,
208 pseudo,
209 native_sysroot)
210
211 pm.update()
212
213 pm.install(packages)
214
215 os.environ['PATH'] += defpath + ":" + native_sysroot + "/usr/bin/"
216
217
218 def prepare(self, cr, cr_workdir, oe_builddir, rootfs_dir, bootimg_dir,
219 kernel_dir, native_sysroot):
220 """
221 Prepare content for individual partitions, depending on
222 partition command parameters.
223 """
224 if not self.source:
225 if self.fstype and self.fstype == "swap":
226 self.prepare_swap_partition(cr_workdir, oe_builddir,
227 native_sysroot)
228 elif self.fstype:
229 self.prepare_empty_partition(cr_workdir, oe_builddir,
230 native_sysroot)
231 return
232
233 self._source_methods = pluginmgr.get_source_plugin_methods(self.source, partition_methods)
234 self._source_methods["do_configure_partition"](self, cr, cr_workdir,
235 oe_builddir,
236 bootimg_dir,
237 kernel_dir,
238 native_sysroot)
239 self._source_methods["do_stage_partition"](self, cr, cr_workdir,
240 oe_builddir,
241 bootimg_dir, kernel_dir,
242 native_sysroot)
243 self._source_methods["do_prepare_partition"](self, cr, cr_workdir,
244 oe_builddir,
245 bootimg_dir, kernel_dir, rootfs_dir,
246 native_sysroot)
247
248 def prepare_rootfs_from_fs_image(self, cr_workdir, oe_builddir,
249 rootfs_dir):
250 """
251 Handle an already-created partition e.g. xxx.ext3
252 """
253 rootfs = oe_builddir
254 du_cmd = "du -Lbms %s" % rootfs
255 rc, out = exec_cmd(du_cmd)
256 rootfs_size = out.split()[0]
257
258 self.size = rootfs_size
259 self.source_file = rootfs
260
261 def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir,
262 native_sysroot):
263 """
264 Prepare content for a rootfs partition i.e. create a partition
265 and fill it from a /rootfs dir.
266
267 Currently handles ext2/3/4 and btrfs.
268 """
269 pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot
270 pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % rootfs_dir
271 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir
272 pseudo += "export PSEUDO_NOSYMLINKEXP=1;"
273 pseudo += "%s/usr/bin/pseudo " % native_sysroot
274
275 if self.fstype.startswith("ext"):
276 return self.prepare_rootfs_ext(cr_workdir, oe_builddir,
277 rootfs_dir, native_sysroot,
278 pseudo)
279 elif self.fstype.startswith("btrfs"):
280 return self.prepare_rootfs_btrfs(cr_workdir, oe_builddir,
281 rootfs_dir, native_sysroot,
282 pseudo)
283
284 def prepare_rootfs_ext(self, cr_workdir, oe_builddir, rootfs_dir,
285 native_sysroot, pseudo):
286 """
287 Prepare content for an ext2/3/4 rootfs partition.
288 """
289
290 image_rootfs = rootfs_dir
291 rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label ,self.fstype)
292
293 du_cmd = "du -ks %s" % image_rootfs
294 rc, out = exec_cmd(du_cmd)
295 actual_rootfs_size = int(out.split()[0])
296
297 extra_blocks = self.get_extra_block_count(actual_rootfs_size)
298
299 if extra_blocks < IMAGE_EXTRA_SPACE:
300 extra_blocks = IMAGE_EXTRA_SPACE
301
302 rootfs_size = actual_rootfs_size + extra_blocks
303
304 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
305 (extra_blocks, self.mountpoint, rootfs_size))
306
307 dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \
308 (rootfs, rootfs_size)
309 rc, out = exec_cmd(dd_cmd)
310
311 extra_imagecmd = "-i 8192"
312
313 mkfs_cmd = "mkfs.%s -F %s %s -d %s" % \
314 (self.fstype, extra_imagecmd, rootfs, image_rootfs)
315 rc, out = exec_native_cmd(pseudo + mkfs_cmd, native_sysroot)
316
317
318 # get the rootfs size in the right units for kickstart (Mb)
319 du_cmd = "du -Lbms %s" % rootfs
320 rc, out = exec_cmd(du_cmd)
321 rootfs_size = out.split()[0]
322
323 self.size = rootfs_size
324 self.source_file = rootfs
325
326 return 0
327
328 def prepare_for_uboot(self, arch, cr_workdir, oe_builddir, rootfs_dir,
329 native_sysroot):
330 """
331 Generates u-boot image from source_file( ext2/3/4 )
332
333 """
334 pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot
335 pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % rootfs_dir
336 pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir
337 pseudo += "export PSEUDO_NOSYMLINKEXP=1;"
338 pseudo += "%s/usr/bin/pseudo " % native_sysroot
339
340 # 1) compress image
341 rootfs = self.source_file
342 rootfs_gzip = "%s.gz" % rootfs
343 gzip_cmd = "gzip -f -9 -c %s > %s" % (rootfs, rootfs_gzip)
344 rc, out = exec_native_cmd(pseudo + gzip_cmd, native_sysroot)
345
346 # 2) image for U-Boot
347 rootfs_uboot = "%s.u-boot" % rootfs_gzip
348 mkimage_cmd = "mkimage -A %s -O linux -T ramdisk -C gzip -n %s -d %s %s" % \
349 (arch, self.label, rootfs_gzip, rootfs_uboot)
350 rc, out = exec_native_cmd(pseudo + mkimage_cmd, native_sysroot)
351
352 msger.info("\n\n\tThe new U-Boot ramdisk image can be found here:\n\t\t%s\n\n" % rootfs_uboot)
353
354 return 0
355
356 def prepare_rootfs_btrfs(self, cr_workdir, oe_builddir, rootfs_dir,
357 native_sysroot, pseudo):
358 """
359 Prepare content for a btrfs rootfs partition.
360
361 Currently handles ext2/3/4 and btrfs.
362 """
363 image_rootfs = rootfs_dir
364 rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label, self.fstype)
365
366 du_cmd = "du -ks %s" % image_rootfs
367 rc, out = exec_cmd(du_cmd)
368 actual_rootfs_size = int(out.split()[0])
369
370 extra_blocks = self.get_extra_block_count(actual_rootfs_size)
371
372 if extra_blocks < IMAGE_EXTRA_SPACE:
373 extra_blocks = IMAGE_EXTRA_SPACE
374
375 rootfs_size = actual_rootfs_size + extra_blocks
376
377 msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \
378 (extra_blocks, self.mountpoint, rootfs_size))
379
380 dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \
381 (rootfs, rootfs_size)
382 rc, out = exec_cmd(dd_cmd)
383
384 mkfs_cmd = "mkfs.%s -b %d -r %s %s" % \
385 (self.fstype, rootfs_size * 1024, image_rootfs, rootfs)
386 rc, out = exec_native_cmd(pseudo + mkfs_cmd, native_sysroot)
387
388 # get the rootfs size in the right units for kickstart (Mb)
389 du_cmd = "du -Lbms %s" % rootfs
390 rc, out = exec_cmd(du_cmd)
391 rootfs_size = out.split()[0]
392
393 self.size = rootfs_size
394 self.source_file = rootfs
395
396 def prepare_empty_partition(self, cr_workdir, oe_builddir, native_sysroot):
397 """
398 Prepare an empty partition.
399 """
400 if self.fstype.startswith("ext"):
401 return self.prepare_empty_partition_ext(cr_workdir, oe_builddir,
402 native_sysroot)
403 elif self.fstype.startswith("btrfs"):
404 return self.prepare_empty_partition_btrfs(cr_workdir, oe_builddir,
405 native_sysroot)
406
407 def prepare_empty_partition_ext(self, cr_workdir, oe_builddir,
408 native_sysroot):
409 """
410 Prepare an empty ext2/3/4 partition.
411 """
412 fs = "%s/fs.%s" % (cr_workdir, self.fstype)
413
414 dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \
415 (fs, self.size)
416 rc, out = exec_cmd(dd_cmd)
417
418 extra_imagecmd = "-i 8192"
419
420 mkfs_cmd = "mkfs.%s -F %s %s" % (self.fstype, extra_imagecmd, fs)
421 rc, out = exec_native_cmd(mkfs_cmd, native_sysroot)
422
423 self.source_file = fs
424
425 return 0
426
427 def prepare_empty_partition_btrfs(self, cr_workdir, oe_builddir,
428 native_sysroot):
429 """
430 Prepare an empty btrfs partition.
431 """
432 fs = "%s/fs.%s" % (cr_workdir, self.fstype)
433
434 dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \
435 (fs, self.size)
436 rc, out = exec_cmd(dd_cmd)
437
438 mkfs_cmd = "mkfs.%s -b %d %s" % (self.fstype, self.size * 1024, rootfs)
439 rc, out = exec_native_cmd(mkfs_cmd, native_sysroot)
440
441 mkfs_cmd = "mkfs.%s -F %s %s" % (self.fstype, extra_imagecmd, fs)
442 rc, out = exec_native_cmd(mkfs_cmd, native_sysroot)
443
444 self.source_file = fs
445
446 return 0
447
448 def prepare_swap_partition(self, cr_workdir, oe_builddir, native_sysroot):
449 """
450 Prepare a swap partition.
451 """
452 fs = "%s/fs.%s" % (cr_workdir, self.fstype)
453
454 dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \
455 (fs, self.size)
456 rc, out = exec_cmd(dd_cmd)
457
458 import uuid
459 label_str = ""
460 if self.label:
461 label_str = "-L %s" % self.label
462 mkswap_cmd = "mkswap %s -U %s %s" % (label_str, str(uuid.uuid1()), fs)
463 rc, out = exec_native_cmd(mkswap_cmd, native_sysroot)
464
465 self.source_file = fs
466
467 return 0
468
469class Wic_Partition(Mic_Partition):
470 removedKeywords = Mic_Partition.removedKeywords
471 removedAttrs = Mic_Partition.removedAttrs
472
473 def _getParser(self):
474 op = Mic_Partition._getParser(self)
475 # use specified source file to fill the partition
476 # and calculate partition size
477 op.add_option("--source", type="string", action="store",
478 dest="source", default=None)
479 # use specified rootfs path to fill the partition
480 op.add_option("--rootfs-dir", type="string", action="store",
481 dest="rootfs", default=None)
482 return op
diff --git a/scripts/lib/mic/kickstart/custom_commands/wicboot.py b/scripts/lib/mic/kickstart/custom_commands/wicboot.py
new file mode 100644
index 0000000000..ab8871de4e
--- /dev/null
+++ b/scripts/lib/mic/kickstart/custom_commands/wicboot.py
@@ -0,0 +1,57 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# Copyright (c) 2014, Intel Corporation.
5# All rights reserved.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# DESCRIPTION
21# This module provides the OpenEmbedded bootloader object definitions.
22#
23# AUTHORS
24# Tom Zanussi <tom.zanussi (at] linux.intel.com>
25#
26
27from pykickstart.base import *
28from pykickstart.errors import *
29from pykickstart.options import *
30from pykickstart.commands.bootloader import *
31
32from mic.kickstart.custom_commands.micboot import *
33
34class Wic_Bootloader(Mic_Bootloader):
35 def __init__(self, writePriority=10, appendLine="", driveorder=None,
36 forceLBA=False, location="", md5pass="", password="",
37 upgrade=False, menus=""):
38 Mic_Bootloader.__init__(self, writePriority, appendLine, driveorder,
39 forceLBA, location, md5pass, password, upgrade)
40
41 self.source = ""
42
43 def _getArgsAsStr(self):
44 retval = Mic_Bootloader._getArgsAsStr(self)
45
46 if self.source:
47 retval += " --source=%s" % self.source
48
49 return retval
50
51 def _getParser(self):
52 op = Mic_Bootloader._getParser(self)
53 # use specified source plugin to implement bootloader-specific methods
54 op.add_option("--source", type="string", action="store",
55 dest="source", default=None)
56 return op
57