1"""
2Utilities for managing kickstart
3
4.. versionadded:: 2015.8.0
5"""
6
7import argparse
8import shlex
9
10import salt.utils.files
11import salt.utils.yaml
12
13
14def clean_args(args):
15    """
16    Cleans up the args that weren't passed in
17    """
18    for arg in list(args):
19        if not args[arg]:
20            del args[arg]
21    return args
22
23
24def parse_auth(rule):
25    """
26    Parses the auth/authconfig line
27    """
28    parser = argparse.ArgumentParser()
29    rules = shlex.split(rule)
30    rules.pop(0)
31    noargs = (
32        "back",
33        "test",
34        "nostart",
35        "kickstart",
36        "probe",
37        "enablecache",
38        "disablecache",
39        "disablenis",
40        "enableshadow",
41        "disableshadow",
42        "enablemd5",
43        "disablemd5",
44        "enableldap",
45        "enableldapauth",
46        "enableldaptls",
47        "disableldap",
48        "disableldapauth",
49        "enablekrb5kdcdns",
50        "disablekrb5kdcdns",
51        "enablekrb5realmdns",
52        "disablekrb5realmdns",
53        "disablekrb5",
54        "disablehe-siod",
55        "enablesmbauth",
56        "disablesmbauth",
57        "enablewinbind",
58        "enablewinbindauth",
59        "disablewinbind",
60        "disablewinbindauth",
61        "enablewinbindusedefaultdomain",
62        "disablewinbindusedefaultdomain",
63        "enablewins",
64        "disablewins",
65    )
66    for arg in noargs:
67        parser.add_argument("--{}".format(arg), dest=arg, action="store_true")
68
69    parser.add_argument("--enablenis", dest="enablenis", action="store")
70    parser.add_argument("--hesiodrhs", dest="hesiodrhs", action="store")
71    parser.add_argument("--krb5adminserver", dest="krb5adminserver", action="append")
72    parser.add_argument("--krb5kdc", dest="krb5kdc", action="append")
73    parser.add_argument("--ldapbasedn", dest="ldapbasedn", action="store")
74    parser.add_argument("--ldapserver", dest="ldapserver", action="append")
75    parser.add_argument("--nisserver", dest="nisserver", action="append")
76    parser.add_argument("--passalgo", dest="passalgo", action="store")
77    parser.add_argument("--smbidmapgid", dest="smbidmapgid", action="store")
78    parser.add_argument("--smbidmapuid", dest="smbidmapuid", action="store")
79    parser.add_argument("--smbrealm", dest="smbrealm", action="store")
80    parser.add_argument(
81        "--smbsecurity",
82        dest="smbsecurity",
83        action="store",
84        choices=["user", "server", "domain", "dns"],
85    )
86    parser.add_argument("--smbservers", dest="smbservers", action="store")
87    parser.add_argument("--smbworkgroup", dest="smbworkgroup", action="store")
88    parser.add_argument("--winbindjoin", dest="winbindjoin", action="store")
89    parser.add_argument("--winbindseparator", dest="winbindseparator", action="store")
90    parser.add_argument(
91        "--winbindtemplatehomedir", dest="winbindtemplatehomedir", action="store"
92    )
93    parser.add_argument(
94        "--winbindtemplateprimarygroup",
95        dest="winbindtemplateprimarygroup",
96        action="store",
97    )
98    parser.add_argument(
99        "--winbindtemplateshell", dest="winbindtemplateshell", action="store"
100    )
101
102    parser.add_argument("--enablekrb5", dest="enablekrb5", action="store_true")
103    if "--enablekrb5" in rules:
104        parser.add_argument(
105            "--krb5realm", dest="krb5realm", action="store", required=True
106        )
107    parser.add_argument("--enablehesiod", dest="enablehesiod", action="store_true")
108    if "--enablehesiod" in rules:
109        parser.add_argument(
110            "--hesiodlhs", dest="hesiodlhs", action="store", required=True
111        )
112
113    args = clean_args(vars(parser.parse_args(rules)))
114    parser = None
115    return args
116
117
118def parse_autopart(rule):
119    """
120    Parse the autopart line
121    """
122    parser = argparse.ArgumentParser()
123    rules = shlex.split(rule)
124    rules.pop(0)
125    parser.add_argument("--type", dest="type", action="store")
126    parser.add_argument("--encrypted", dest="encrypted", action="store_true")
127    parser.add_argument("--passphrase", dest="passphrase", action="store")
128    parser.add_argument("--escrowcert", dest="escrowcert", action="store")
129    parser.add_argument("--backuppassphrase", dest="backuppassphrase", action="store")
130
131    args = clean_args(vars(parser.parse_args(rules)))
132    parser = None
133    return args
134
135
136def parse_autostep(rule):
137    """
138    Parse the autostep line
139    """
140    parser = argparse.ArgumentParser()
141    rules = shlex.split(rule)
142    rules.pop(0)
143    parser.add_argument("--autoscreenshot", dest="autoscreenshot", action="store")
144
145    args = clean_args(vars(parser.parse_args(rules)))
146    parser = None
147    return args
148
149
150def parse_bootloader(rule):
151    """
152    Parse the bootloader line
153    """
154    parser = argparse.ArgumentParser()
155    rules = shlex.split(rule)
156    rules.pop(0)
157    parser.add_argument("--append", dest="append", action="store")
158    parser.add_argument("--driveorder", dest="driveorder", action="store")
159    parser.add_argument("--location", dest="location", action="store")
160    parser.add_argument("--password", dest="password", action="store")
161    parser.add_argument("--md5pass", dest="md5pass", action="store")
162    parser.add_argument("--upgrade", dest="upgrade", action="store_true")
163    parser.add_argument("--timeout", dest="timeout", action="store")
164    parser.add_argument("--boot-drive", dest="bootdrive", action="store")
165
166    args = clean_args(vars(parser.parse_args(rules)))
167    parser = None
168    return args
169
170
171def parse_btrfs(rule):
172    """
173    Parse the btrfs line
174
175    TODO: finish up the weird parsing on this one
176    http://fedoraproject.org/wiki/Anaconda/Kickstart#btrfs
177    """
178    parser = argparse.ArgumentParser()
179    rules = shlex.split(rule)
180    rules.pop(0)
181    parser.add_argument("--name", dest="name", action="store")
182    parser.add_argument("--data", dest="data", action="store")
183    parser.add_argument("--metadata", dest="metadata", action="store")
184    parser.add_argument("--label", dest="label", action="store")
185    parser.add_argument("--noformat", dest="noformat", action="store_true")
186    parser.add_argument("--useexisting", dest="useexisting", action="store_true")
187    parser.add_argument("--subvol", dest="subvol", action="store_true")
188
189    args = clean_args(vars(parser.parse_args(rules)))
190    parser = None
191    return args
192
193
194def parse_clearpart(rule):
195    """
196    Parse the clearpart line
197    """
198    parser = argparse.ArgumentParser()
199    rules = shlex.split(rule)
200    rules.pop(0)
201    parser.add_argument("--all", dest="all", action="store_true")
202    parser.add_argument("--drives", dest="drives", action="store")
203    parser.add_argument("--init_label", dest="init_label", action="store_true")
204    parser.add_argument("--linux", dest="linux", action="store_true")
205    parser.add_argument("--none", dest="none", action="store_true")
206    parser.add_argument("--initlabel", dest="init_label", action="store_true")
207    parser.add_argument("--list", dest="list", action="store")
208
209    args = clean_args(vars(parser.parse_args(rules)))
210    parser = None
211    return args
212
213
214def parse_device(rule):
215    """
216    Parse the device line
217    """
218    parser = argparse.ArgumentParser()
219    rules = shlex.split(rule)
220    rules.pop(0)
221    modulename = rules.pop(0)
222    parser.add_argument("--opts", dest="opts", action="store")
223
224    args = clean_args(vars(parser.parse_args(rules)))
225    args["modulename"] = modulename
226    parser = None
227    return args
228
229
230def parse_dmraid(rule):
231    """
232    Parse the dmraid line
233    """
234    parser = argparse.ArgumentParser()
235    rules = shlex.split(rule)
236    rules.pop(0)
237    parser.add_argument("--name", dest="name", action="store")
238    parser.add_argument("--dev", dest="dev", action="store")
239
240    args = clean_args(vars(parser.parse_args(rules)))
241    parser = None
242    return args
243
244
245def parse_driverdisk(rule):
246    """
247    Parse the driverdisk line
248    """
249    if "--" not in rule:
250        return {"partition": rule}
251
252    parser = argparse.ArgumentParser()
253    rules = shlex.split(rule)
254    rules.pop(0)
255    parser.add_argument("--source", dest="source", action="store")
256    parser.add_argument("--biospart", dest="biospart", action="store")
257
258    args = clean_args(vars(parser.parse_args(rules)))
259    parser = None
260    return args
261
262
263def parse_firewall(rule):
264    """
265    Parse the firewall line
266    """
267    parser = argparse.ArgumentParser()
268    rules = shlex.split(rule)
269    rules.pop(0)
270    parser.add_argument("--enable", "--enabled", dest="enable", action="store_true")
271    parser.add_argument("--disable", "--disabled", dest="disable", action="store_true")
272    parser.add_argument("--port", dest="port", action="store")
273    parser.add_argument("--service", dest="service", action="store")
274    parser.add_argument("--ssh", dest="ssh", action="store_true")
275    parser.add_argument("--smtp", dest="smtp", action="store_true")
276    parser.add_argument("--http", dest="http", action="store_true")
277    parser.add_argument("--ftp", dest="ftp", action="store_true")
278
279    args = clean_args(vars(parser.parse_args(rules)))
280    parser = None
281    return args
282
283
284def parse_firstboot(rule):
285    """
286    Parse the firstboot line
287    """
288    parser = argparse.ArgumentParser()
289    rules = shlex.split(rule)
290    rules.pop(0)
291    parser.add_argument("--enable", "--enabled", dest="enable", action="store_true")
292    parser.add_argument("--disable", "--disabled", dest="disable", action="store_true")
293    parser.add_argument("--reconfig", dest="reconfig", action="store_true")
294
295    args = clean_args(vars(parser.parse_args(rules)))
296    parser = None
297    return args
298
299
300def parse_group(rule):
301    """
302    Parse the group line
303    """
304    parser = argparse.ArgumentParser()
305    rules = shlex.split(rule)
306    rules.pop(0)
307    parser.add_argument("--name", dest="name", action="store")
308    parser.add_argument("--gid", dest="gid", action="store")
309
310    args = clean_args(vars(parser.parse_args(rules)))
311    parser = None
312    return args
313
314
315def parse_harddrive(rule):
316    """
317    Parse the harddrive line
318    """
319    parser = argparse.ArgumentParser()
320    rules = shlex.split(rule)
321    rules.pop(0)
322    parser.add_argument("--biospart", dest="biospart", action="store")
323    parser.add_argument("--partition", dest="partition", action="store")
324    parser.add_argument("--dir", dest="dir", action="store")
325
326    args = clean_args(vars(parser.parse_args(rules)))
327    parser = None
328    return args
329
330
331def parse_ignoredisk(rule):
332    """
333    Parse the ignoredisk line
334    """
335    parser = argparse.ArgumentParser()
336    rules = shlex.split(rule)
337    rules.pop(0)
338    parser.add_argument("--drives", dest="drives", action="store")
339    parser.add_argument("--only-use", dest="only-use", action="store")
340    parser.add_argument("--interactive", dest="interactive", action="store_true")
341
342    args = clean_args(vars(parser.parse_args(rules)))
343    parser = None
344    return args
345
346
347def parse_iscsi(rule):
348    """
349    Parse the iscsi line
350    """
351    parser = argparse.ArgumentParser()
352    rules = shlex.split(rule)
353    rules.pop(0)
354    parser.add_argument("--ipaddr", dest="ipaddr", action="store")
355    parser.add_argument("--port", dest="port", action="store")
356    parser.add_argument("--target", dest="target", action="store")
357    parser.add_argument("--iface", dest="iface", action="store")
358    parser.add_argument("--user", dest="user", action="store")
359    parser.add_argument("--password", dest="password", action="store")
360    parser.add_argument("--reverse-user", dest="reverse-user", action="store")
361    parser.add_argument("--reverse-password", dest="reverse-password", action="store")
362
363    args = clean_args(vars(parser.parse_args(rules)))
364    parser = None
365    return args
366
367
368def parse_iscsiname(rule):
369    """
370    Parse the iscsiname line
371    """
372    parser = argparse.ArgumentParser()
373    rules = shlex.split(rule)
374    rules.pop(0)
375    # parser.add_argument('iqn')
376
377    args = clean_args(vars(parser.parse_args(rules)))
378    parser = None
379    return args
380
381
382def parse_keyboard(rule):
383    """
384    Parse the keyboard line
385    """
386    parser = argparse.ArgumentParser()
387    rules = shlex.split(rule)
388    rules.pop(0)
389    parser.add_argument("--vckeymap", dest="vckeymap", action="store")
390    parser.add_argument("--xlayouts", dest="xlayouts", action="store")
391    parser.add_argument("--switch", dest="switch", action="store")
392    parser.add_argument("keyboard")
393
394    args = clean_args(vars(parser.parse_args(rules)))
395
396    if "keyboard" in args and "xlayouts" not in args:
397        args["xlayouts"] = args["keyboard"]
398
399    parser = None
400    return args
401
402
403def parse_lang(rule):
404    """
405    Parse the lang line
406    """
407    parser = argparse.ArgumentParser()
408    rules = shlex.split(rule)
409    rules.pop(0)
410    parser.add_argument("lang")
411
412    args = clean_args(vars(parser.parse_args(rules)))
413    parser = None
414    return args
415
416
417def parse_logvol(rule):
418    """
419    Parse the logvol line
420    """
421    parser = argparse.ArgumentParser()
422    rules = shlex.split(rule)
423    rules.pop(0)
424    parser.add_argument("mntpoint")
425    parser.add_argument("--noformat", dest="noformat", action="store_true")
426    parser.add_argument("--useexisting", dest="useexisting", action="store_true")
427    parser.add_argument("--fstype", dest="fstype", action="store")
428    parser.add_argument("--fsoptions", dest="fsoptions", action="store")
429    parser.add_argument("--grow", dest="grow", action="store_true")
430    parser.add_argument("--maxsize", dest="maxsize", action="store")
431    parser.add_argument("--recommended", dest="recommended", action="store_true")
432    parser.add_argument("--percent", dest="percent", action="store_true")
433    parser.add_argument("--encrypted", dest="encrypted", action="store_true")
434    parser.add_argument("--passphrase", dest="passphrase", action="store")
435    parser.add_argument("--escrowcert", dest="escrowcert", action="store")
436    parser.add_argument(
437        "--backuppassphrase", dest="backuppassphrase", action="store_true"
438    )
439    parser.add_argument("--name", dest="name", action="store")
440    parser.add_argument("--vgname", dest="vgname", action="store")
441    parser.add_argument("--size", dest="size", action="store")
442    parser.add_argument("--label", dest="label", action="store")
443
444    args = clean_args(vars(parser.parse_args(rules)))
445    parser = None
446    return args
447
448
449def parse_logging(rule):
450    """
451    Parse the logging line
452    """
453    parser = argparse.ArgumentParser()
454    rules = shlex.split(rule)
455    rules.pop(0)
456    parser.add_argument("--host", dest="host", action="store")
457    parser.add_argument("--port", dest="port", action="store")
458    parser.add_argument(
459        "--level",
460        dest="level",
461        action="store",
462        choices=["debug", "info", "warning", "error", "critical"],
463    )
464
465    args = clean_args(vars(parser.parse_args(rules)))
466    parser = None
467    return args
468
469
470def parse_monitor(rule):
471    """
472    Parse the monitor line
473    """
474    parser = argparse.ArgumentParser()
475    rules = shlex.split(rule)
476    rules.pop(0)
477    parser.add_argument("--hsync", dest="hsync", action="store")
478    parser.add_argument("--monitor", dest="monitor", action="store")
479    parser.add_argument("--noprobe", dest="noprobe", action="store_true")
480    parser.add_argument("--vsync", dest="vsync", action="store")
481
482    args = clean_args(vars(parser.parse_args(rules)))
483    parser = None
484    return args
485
486
487def parse_multipath(rule):
488    """
489    Parse the multipath line
490    """
491    parser = argparse.ArgumentParser()
492    rules = shlex.split(rule)
493    rules.pop(0)
494    parser.add_argument("--name", dest="name", action="store")
495    parser.add_argument("--device", dest="device", action="store")
496    parser.add_argument("--rule", dest="rule", action="store")
497
498    args = clean_args(vars(parser.parse_args(rules)))
499    parser = None
500    return args
501
502
503def parse_network(rule):
504    """
505    Parse the network line
506    """
507    parser = argparse.ArgumentParser()
508    rules = shlex.split(rule)
509    rules.pop(0)
510    parser.add_argument(
511        "--bootproto",
512        dest="bootproto",
513        action="store",
514        choices=["dhcp", "bootp", "static", "ibft"],
515    )
516    parser.add_argument("--device", dest="device", action="store")
517    parser.add_argument("--ip", dest="ip", action="store")
518    parser.add_argument("--ipv6", dest="ipv6", action="store")
519    parser.add_argument("--gateway", dest="gateway", action="store")
520    parser.add_argument("--nodefroute", dest="nodefroute", action="store_true")
521    parser.add_argument("--nameserver", dest="nameserver", action="store")
522    parser.add_argument("--nodns", dest="nodns", action="store_true")
523    parser.add_argument("--netmask", dest="netmask", action="store")
524    parser.add_argument("--hostname", dest="hostname", action="store")
525    parser.add_argument("--ethtool", dest="ethtool", action="store")
526    parser.add_argument("--essid", dest="essid", action="store")
527    parser.add_argument("--wepkey", dest="wepkey", action="store")
528    parser.add_argument("--wpakey", dest="wpakey", action="store")
529    parser.add_argument("--onboot", dest="onboot", action="store")
530    parser.add_argument("--dhcpclass", dest="dhcpclass", action="store")
531    parser.add_argument("--mtu", dest="mtu", action="store")
532    parser.add_argument("--noipv4", dest="noipv4", action="store_true")
533    parser.add_argument("--noipv6", dest="noipv6", action="store_true")
534    parser.add_argument("--activate", dest="activate", action="store_true")
535
536    args = clean_args(vars(parser.parse_args(rules)))
537    parser = None
538    return args
539
540
541def parse_nfs(rule):
542    """
543    Parse the nfs line
544    """
545    parser = argparse.ArgumentParser()
546    rules = shlex.split(rule)
547    rules.pop(0)
548    parser.add_argument("--server", dest="server", action="store")
549    parser.add_argument("--dir", dest="dir", action="store")
550    parser.add_argument("--opts", dest="opts", action="store")
551
552    args = clean_args(vars(parser.parse_args(rules)))
553    parser = None
554    return args
555
556
557def parse_partition(rule):
558    """
559    Parse the partition line
560    """
561    parser = argparse.ArgumentParser()
562    rules = shlex.split(rule)
563    rules.pop(0)
564    parser.add_argument("mntpoint")
565    parser.add_argument("--size", dest="size", action="store")
566    parser.add_argument("--grow", dest="grow", action="store_true")
567    parser.add_argument("--maxsize", dest="maxsize", action="store")
568    parser.add_argument("--noformat", dest="noformat", action="store_true")
569    parser.add_argument("--onpart", "--usepart", dest="onpart", action="store")
570    parser.add_argument("--ondisk", "--ondrive", dest="ondisk", action="store")
571    parser.add_argument("--asprimary", dest="asprimary", action="store_true")
572    parser.add_argument("--fsprofile", dest="fsprofile", action="store")
573    parser.add_argument("--fstype", dest="fstype", action="store")
574    parser.add_argument("--fsoptions", dest="fsoptions", action="store")
575    parser.add_argument("--label", dest="label", action="store")
576    parser.add_argument("--recommended", dest="recommended", action="store_true")
577    parser.add_argument("--onbiosdisk", dest="onbiosdisk", action="store")
578    parser.add_argument("--encrypted", dest="encrypted", action="store_true")
579    parser.add_argument("--passphrase", dest="passphrase", action="store")
580    parser.add_argument("--escrowcert", dest="escrowcert", action="store")
581    parser.add_argument("--backupphrase", dest="backupphrase", action="store")
582
583    args = clean_args(vars(parser.parse_args(rules)))
584    parser = None
585    return args
586
587
588def parse_raid(rule):
589    """
590    Parse the raid line
591    """
592    parser = argparse.ArgumentParser()
593    rules = shlex.split(rule)
594    rules.pop(0)
595
596    partitions = []
597    newrules = []
598    for count, rule in enumerate(rules):
599        if count == 0:
600            newrules.append(rule)
601            continue
602        elif rule.startswith("--"):
603            newrules.append(rule)
604            continue
605        else:
606            partitions.append(rule)
607    rules = newrules
608
609    parser.add_argument("mntpoint")
610    parser.add_argument("--level", dest="level", action="store")
611    parser.add_argument("--device", dest="device", action="store")
612    parser.add_argument("--spares", dest="spares", action="store")
613    parser.add_argument("--fstype", dest="fstype", action="store")
614    parser.add_argument("--fsoptions", dest="fsoptions", action="store")
615    parser.add_argument("--label", dest="label", action="store")
616    parser.add_argument("--noformat", dest="noformat", action="store_true")
617    parser.add_argument("--useexisting", dest="useexisting", action="store_true")
618    parser.add_argument("--encrypted", dest="encrypted", action="store_true")
619    parser.add_argument("--passphrase", dest="passphrase", action="store")
620    parser.add_argument("--escrowcert", dest="escrowcert", action="store")
621    parser.add_argument("--backuppassphrase", dest="backuppassphrase", action="store")
622
623    args = clean_args(vars(parser.parse_args(rules)))
624    if partitions:
625        args["partitions"] = partitions
626    parser = None
627    return args
628
629
630def parse_reboot(rule):
631    """
632    Parse the reboot line
633    """
634    parser = argparse.ArgumentParser()
635    rules = shlex.split(rule)
636    rules.pop(0)
637    parser.add_argument("--eject", dest="eject", action="store_true")
638
639    args = clean_args(vars(parser.parse_args(rules)))
640    parser = None
641    return args
642
643
644def parse_repo(rule):
645    """
646    Parse the repo line
647    """
648    parser = argparse.ArgumentParser()
649    rules = shlex.split(rule)
650    rules.pop(0)
651    parser.add_argument("--name", dest="name", action="store")
652    parser.add_argument("--baseurl", dest="baseurl", action="store")
653    parser.add_argument("--mirrorlist", dest="mirrorlist", action="store")
654    parser.add_argument("--cost", dest="cost", action="store")
655    parser.add_argument("--excludepkgs", dest="excludepkgs", action="store")
656    parser.add_argument("--includepkgs", dest="includepkgs", action="store")
657    parser.add_argument("--proxy", dest="proxy", action="store")
658    parser.add_argument("--ignoregroups", dest="ignoregroups", action="store")
659    parser.add_argument("--noverifyssl", dest="noverifyssl", action="store_true")
660
661    args = clean_args(vars(parser.parse_args(rules)))
662    parser = None
663    return args
664
665
666def parse_rescue(rule):
667    """
668    Parse the rescue line
669    """
670    parser = argparse.ArgumentParser()
671    rules = shlex.split(rule)
672    rules.pop(0)
673    parser.add_argument("--nomount", dest="nomount", action="store_true")
674    parser.add_argument("--romount", dest="romount", action="store_true")
675
676    args = clean_args(vars(parser.parse_args(rules)))
677    parser = None
678    return args
679
680
681def parse_rootpw(rule):
682    """
683    Parse the rootpw line
684    """
685    parser = argparse.ArgumentParser()
686    rules = shlex.split(rule)
687    rules.pop(0)
688    parser.add_argument("--iscrypted", dest="iscrypted", action="store_true")
689    parser.add_argument("--plaintext", dest="plaintext", action="store_true")
690    parser.add_argument("--lock", dest="lock", action="store_true")
691    parser.add_argument("password")
692
693    args = clean_args(vars(parser.parse_args(rules)))
694    parser = None
695    return args
696
697
698def parse_selinux(rule):
699    """
700    Parse the selinux line
701    """
702    parser = argparse.ArgumentParser()
703    rules = shlex.split(rule)
704    rules.pop(0)
705    parser.add_argument("--disabled", dest="disabled", action="store_true")
706    parser.add_argument("--enforcing", dest="enforcing", action="store_true")
707    parser.add_argument("--permissive", dest="permissive", action="store_true")
708
709    args = clean_args(vars(parser.parse_args(rules)))
710    parser = None
711    return args
712
713
714def parse_services(rule):
715    """
716    Parse the services line
717    """
718    parser = argparse.ArgumentParser()
719    rules = shlex.split(rule)
720    rules.pop(0)
721    parser.add_argument("--disabled", dest="disabled", action="store")
722    parser.add_argument("--enabled", dest="enabled", action="store")
723
724    args = clean_args(vars(parser.parse_args(rules)))
725    parser = None
726    return args
727
728
729def parse_sshpw(rule):
730    """
731    Parse the sshpw line
732    """
733    parser = argparse.ArgumentParser()
734    rules = shlex.split(rule)
735    rules.pop(0)
736    parser.add_argument("--username", dest="username", action="store")
737    parser.add_argument("--iscrypted", dest="iscrypted", action="store_true")
738    parser.add_argument("--plaintext", dest="plaintext", action="store_true")
739    parser.add_argument("--lock", dest="lock", action="store_true")
740
741    args = clean_args(vars(parser.parse_args(rules)))
742    parser = None
743    return args
744
745
746def parse_timezone(rule):
747    """
748    Parse the timezone line
749    """
750    parser = argparse.ArgumentParser()
751    rules = shlex.split(rule)
752    rules.pop(0)
753    parser.add_argument("--utc", dest="utc", action="store_true")
754    parser.add_argument("--nontp", dest="nontp", action="store_true")
755    parser.add_argument("--ntpservers", dest="ntpservers", action="store")
756    parser.add_argument("--isUtc", dest="isutc", action="store_true")
757    parser.add_argument("timezone")
758
759    args = clean_args(vars(parser.parse_args(rules)))
760    parser = None
761    return args
762
763
764def parse_updates(rule):
765    """
766    Parse the updates line
767    """
768    rules = shlex.split(rule)
769    rules.pop(0)
770    return {"url": rules[0]} if rules else True
771
772
773def parse_upgrade(rule):
774    """
775    Parse the upgrade line
776    """
777    parser = argparse.ArgumentParser()
778    rules = shlex.split(rule)
779    rules.pop(0)
780    parser.add_argument("--root-device", dest="root-device", action="store")
781
782    args = clean_args(vars(parser.parse_args(rules)))
783    parser = None
784    if args:
785        return args
786    return True
787
788
789def parse_url(rule):
790    """
791    Parse the url line
792    """
793    parser = argparse.ArgumentParser()
794    rules = shlex.split(rule)
795    rules.pop(0)
796    parser.add_argument("--url", dest="url", action="store")
797    parser.add_argument("--proxy", dest="proxy", action="store")
798    parser.add_argument("--noverifyssl", dest="noverifyssl", action="store_true")
799
800    args = clean_args(vars(parser.parse_args(rules)))
801    parser = None
802    return args
803
804
805def parse_user(rule):
806    """
807    Parse the user line
808    """
809    parser = argparse.ArgumentParser()
810    rules = shlex.split(rule)
811    rules.pop(0)
812    parser.add_argument("--name", dest="name", action="store")
813    parser.add_argument("--gecos", dest="gecos", action="store")
814    parser.add_argument("--groups", dest="groups", action="store")
815    parser.add_argument("--homedir", dest="homedir", action="store")
816    parser.add_argument("--lock", dest="lock", action="store_true")
817    parser.add_argument("--password", dest="password", action="store")
818    parser.add_argument("--iscrypted", dest="iscrypted", action="store_true")
819    parser.add_argument("--plaintext", dest="plaintext", action="store_true")
820    parser.add_argument("--shell", dest="shell", action="store")
821    parser.add_argument("--uid", dest="uid", action="store")
822
823    args = clean_args(vars(parser.parse_args(rules)))
824    parser = None
825    return args
826
827
828def parse_vnc(rule):
829    """
830    Parse the vnc line
831    """
832    parser = argparse.ArgumentParser()
833    rules = shlex.split(rule)
834    rules.pop(0)
835    parser.add_argument("--host", dest="host", action="store")
836    parser.add_argument("--port", dest="port", action="store")
837    parser.add_argument("--password", dest="password", action="store")
838
839    args = clean_args(vars(parser.parse_args(rules)))
840    parser = None
841    return args
842
843
844def parse_volgroup(rule):
845    """
846    Parse the volgroup line
847    """
848    parser = argparse.ArgumentParser()
849    rules = shlex.split(rule)
850    rules.pop(0)
851
852    partitions = []
853    newrules = []
854    for count, rule in enumerate(rules):
855        if count == 0:
856            newrules.append(rule)
857            continue
858        elif rule.startswith("--"):
859            newrules.append(rule)
860            continue
861        else:
862            partitions.append(rule)
863    rules = newrules
864
865    parser.add_argument("name")
866    parser.add_argument("--noformat", dest="noformat", action="store_true")
867    parser.add_argument("--useexisting", dest="useexisting", action="store_true")
868    parser.add_argument("--pesize", dest="pesize", action="store")
869    parser.add_argument("--reserved-space", dest="reserved-space", action="store")
870    parser.add_argument("--reserved-percent", dest="reserved-percent", action="store")
871
872    args = clean_args(vars(parser.parse_args(rules)))
873    if partitions:
874        args["partitions"] = partitions
875    parser = None
876    return args
877
878
879def parse_xconfig(rule):
880    """
881    Parse the xconfig line
882    """
883    parser = argparse.ArgumentParser()
884    rules = shlex.split(rule)
885    rules.pop(0)
886    parser.add_argument("--defaultdesktop", dest="defaultdesktop", action="store")
887    parser.add_argument("--startxonboot", dest="startxonboot", action="store_true")
888
889    args = clean_args(vars(parser.parse_args(rules)))
890    parser = None
891    return args
892
893
894def parse_zfcp(rule):
895    """
896    Parse the zfcp line
897    """
898    parser = argparse.ArgumentParser()
899    rules = shlex.split(rule)
900    rules.pop(0)
901    parser.add_argument("--devnum", dest="devnum", action="store")
902    parser.add_argument("--fcplun", dest="fcplun", action="store")
903    parser.add_argument("--wwpn", dest="wwpn", action="store")
904
905    args = clean_args(vars(parser.parse_args(rules)))
906    parser = None
907    return args
908
909
910def mksls(src, dst=None):
911    """
912    Convert a kickstart file to an SLS file
913    """
914    mode = "command"
915    sls = {}
916    ks_opts = {}
917    with salt.utils.files.fopen(src, "r") as fh_:
918        for line in fh_:
919            if line.startswith("#"):
920                continue
921
922            if mode == "command":
923                if line.startswith("auth ") or line.startswith("authconfig "):
924                    ks_opts["auth"] = parse_auth(line)
925                elif line.startswith("autopart"):
926                    ks_opts["autopath"] = parse_autopart(line)
927                elif line.startswith("autostep"):
928                    ks_opts["autostep"] = parse_autostep(line)
929                elif line.startswith("bootloader"):
930                    ks_opts["bootloader"] = parse_bootloader(line)
931                elif line.startswith("btrfs"):
932                    ks_opts["btrfs"] = parse_btrfs(line)
933                elif line.startswith("cdrom"):
934                    ks_opts["cdrom"] = True
935                elif line.startswith("clearpart"):
936                    ks_opts["clearpart"] = parse_clearpart(line)
937                elif line.startswith("cmdline"):
938                    ks_opts["cmdline"] = True
939                elif line.startswith("device"):
940                    ks_opts["device"] = parse_device(line)
941                elif line.startswith("dmraid"):
942                    ks_opts["dmraid"] = parse_dmraid(line)
943                elif line.startswith("driverdisk"):
944                    ks_opts["driverdisk"] = parse_driverdisk(line)
945                elif line.startswith("firewall"):
946                    ks_opts["firewall"] = parse_firewall(line)
947                elif line.startswith("firstboot"):
948                    ks_opts["firstboot"] = parse_firstboot(line)
949                elif line.startswith("group"):
950                    ks_opts["group"] = parse_group(line)
951                elif line.startswith("graphical"):
952                    ks_opts["graphical"] = True
953                elif line.startswith("halt"):
954                    ks_opts["halt"] = True
955                elif line.startswith("harddrive"):
956                    ks_opts["harddrive"] = True
957                elif line.startswith("ignoredisk"):
958                    ks_opts["ignoredisk"] = parse_ignoredisk(line)
959                elif line.startswith("install"):
960                    ks_opts["install"] = True
961                elif line.startswith("iscsi"):
962                    ks_opts["iscsi"] = parse_iscsi(line)
963                elif line.startswith("iscsiname"):
964                    ks_opts["iscsiname"] = parse_iscsiname(line)
965                elif line.startswith("keyboard"):
966                    ks_opts["keyboard"] = parse_keyboard(line)
967                elif line.startswith("lang"):
968                    ks_opts["lang"] = parse_lang(line)
969                elif line.startswith("logvol"):
970                    if "logvol" not in ks_opts:
971                        ks_opts["logvol"] = []
972                    ks_opts["logvol"].append(parse_logvol(line))
973                elif line.startswith("logging"):
974                    ks_opts["logging"] = parse_logging(line)
975                elif line.startswith("mediacheck"):
976                    ks_opts["mediacheck"] = True
977                elif line.startswith("monitor"):
978                    ks_opts["monitor"] = parse_monitor(line)
979                elif line.startswith("multipath"):
980                    ks_opts["multipath"] = parse_multipath(line)
981                elif line.startswith("network"):
982                    if "network" not in ks_opts:
983                        ks_opts["network"] = []
984                    ks_opts["network"].append(parse_network(line))
985                elif line.startswith("nfs"):
986                    ks_opts["nfs"] = True
987                elif line.startswith("part ") or line.startswith("partition"):
988                    if "part" not in ks_opts:
989                        ks_opts["part"] = []
990                    ks_opts["part"].append(parse_partition(line))
991                elif line.startswith("poweroff"):
992                    ks_opts["poweroff"] = True
993                elif line.startswith("raid"):
994                    if "raid" not in ks_opts:
995                        ks_opts["raid"] = []
996                    ks_opts["raid"].append(parse_raid(line))
997                elif line.startswith("reboot"):
998                    ks_opts["reboot"] = parse_reboot(line)
999                elif line.startswith("repo"):
1000                    ks_opts["repo"] = parse_repo(line)
1001                elif line.startswith("rescue"):
1002                    ks_opts["rescue"] = parse_rescue(line)
1003                elif line.startswith("rootpw"):
1004                    ks_opts["rootpw"] = parse_rootpw(line)
1005                elif line.startswith("selinux"):
1006                    ks_opts["selinux"] = parse_selinux(line)
1007                elif line.startswith("services"):
1008                    ks_opts["services"] = parse_services(line)
1009                elif line.startswith("shutdown"):
1010                    ks_opts["shutdown"] = True
1011                elif line.startswith("sshpw"):
1012                    ks_opts["sshpw"] = parse_sshpw(line)
1013                elif line.startswith("skipx"):
1014                    ks_opts["skipx"] = True
1015                elif line.startswith("text"):
1016                    ks_opts["text"] = True
1017                elif line.startswith("timezone"):
1018                    ks_opts["timezone"] = parse_timezone(line)
1019                elif line.startswith("updates"):
1020                    ks_opts["updates"] = parse_updates(line)
1021                elif line.startswith("upgrade"):
1022                    ks_opts["upgrade"] = parse_upgrade(line)
1023                elif line.startswith("url"):
1024                    ks_opts["url"] = True
1025                elif line.startswith("user"):
1026                    ks_opts["user"] = parse_user(line)
1027                elif line.startswith("vnc"):
1028                    ks_opts["vnc"] = parse_vnc(line)
1029                elif line.startswith("volgroup"):
1030                    ks_opts["volgroup"] = parse_volgroup(line)
1031                elif line.startswith("xconfig"):
1032                    ks_opts["xconfig"] = parse_xconfig(line)
1033                elif line.startswith("zerombr"):
1034                    ks_opts["zerombr"] = True
1035                elif line.startswith("zfcp"):
1036                    ks_opts["zfcp"] = parse_zfcp(line)
1037
1038            if line.startswith("%include"):
1039                rules = shlex.split(line)
1040                if not ks_opts["include"]:
1041                    ks_opts["include"] = []
1042                ks_opts["include"].append(rules[1])
1043
1044            if line.startswith("%ksappend"):
1045                rules = shlex.split(line)
1046                if not ks_opts["ksappend"]:
1047                    ks_opts["ksappend"] = []
1048                ks_opts["ksappend"].append(rules[1])
1049
1050            if line.startswith("%packages"):
1051                mode = "packages"
1052                if "packages" not in ks_opts:
1053                    ks_opts["packages"] = {"packages": {}}
1054
1055                parser = argparse.ArgumentParser()
1056                opts = shlex.split(line)
1057                opts.pop(0)
1058                parser.add_argument("--default", dest="default", action="store_true")
1059                parser.add_argument(
1060                    "--excludedocs", dest="excludedocs", action="store_true"
1061                )
1062                parser.add_argument(
1063                    "--ignoremissing", dest="ignoremissing", action="store_true"
1064                )
1065                parser.add_argument("--instLangs", dest="instLangs", action="store")
1066                parser.add_argument("--multilib", dest="multilib", action="store_true")
1067                parser.add_argument(
1068                    "--nodefaults", dest="nodefaults", action="store_true"
1069                )
1070                parser.add_argument("--optional", dest="optional", action="store_true")
1071                parser.add_argument("--nobase", dest="nobase", action="store_true")
1072                args = clean_args(vars(parser.parse_args(opts)))
1073                ks_opts["packages"]["options"] = args
1074
1075                continue
1076
1077            if line.startswith("%pre"):
1078                mode = "pre"
1079
1080                parser = argparse.ArgumentParser()
1081                opts = shlex.split(line)
1082                opts.pop(0)
1083                parser.add_argument("--interpreter", dest="interpreter", action="store")
1084                parser.add_argument(
1085                    "--erroronfail", dest="erroronfail", action="store_true"
1086                )
1087                parser.add_argument("--log", dest="log", action="store")
1088                args = clean_args(vars(parser.parse_args(opts)))
1089                ks_opts["pre"] = {"options": args, "script": ""}
1090
1091                continue
1092
1093            if line.startswith("%post"):
1094                mode = "post"
1095
1096                parser = argparse.ArgumentParser()
1097                opts = shlex.split(line)
1098                opts.pop(0)
1099                parser.add_argument("--nochroot", dest="nochroot", action="store_true")
1100                parser.add_argument("--interpreter", dest="interpreter", action="store")
1101                parser.add_argument(
1102                    "--erroronfail", dest="erroronfail", action="store_true"
1103                )
1104                parser.add_argument("--log", dest="log", action="store")
1105                args = clean_args(vars(parser.parse_args(opts)))
1106                ks_opts["post"] = {"options": args, "script": ""}
1107
1108                continue
1109
1110            if line.startswith("%end"):
1111                mode = None
1112
1113            if mode == "packages":
1114                if line.startswith("-"):
1115                    package = line.replace("-", "", 1).strip()
1116                    ks_opts["packages"]["packages"][package] = False
1117                else:
1118                    ks_opts["packages"]["packages"][line.strip()] = True
1119
1120            if mode == "pre":
1121                ks_opts["pre"]["script"] += line
1122
1123            if mode == "post":
1124                ks_opts["post"]["script"] += line
1125
1126    # Set language
1127    sls[ks_opts["lang"]["lang"]] = {"locale": ["system"]}
1128
1129    # Set keyboard
1130    sls[ks_opts["keyboard"]["xlayouts"]] = {"keyboard": ["system"]}
1131
1132    # Set timezone
1133    sls[ks_opts["timezone"]["timezone"]] = {"timezone": ["system"]}
1134    if "utc" in ks_opts["timezone"]:
1135        sls[ks_opts["timezone"]["timezone"]]["timezone"].append("utc")
1136
1137    # Set network
1138    if "network" in ks_opts:
1139        for interface in ks_opts["network"]:
1140            device = interface.get("device", None)
1141            if device is not None:
1142                del interface["device"]
1143                sls[device] = {"proto": interface["bootproto"]}
1144                del interface["bootproto"]
1145
1146                if "onboot" in interface:
1147                    if "no" in interface["onboot"]:
1148                        sls[device]["enabled"] = False
1149                    else:
1150                        sls[device]["enabled"] = True
1151                    del interface["onboot"]
1152
1153                if "noipv4" in interface:
1154                    sls[device]["ipv4"] = {"enabled": False}
1155                    del interface["noipv4"]
1156                if "noipv6" in interface:
1157                    sls[device]["ipv6"] = {"enabled": False}
1158                    del interface["noipv6"]
1159
1160                for option in interface:
1161                    if type(interface[option]) is bool:
1162                        sls[device][option] = {"enabled": [interface[option]]}
1163                    else:
1164                        sls[device][option] = interface[option]
1165            if "hostname" in interface:
1166                sls["system"] = {
1167                    "network.system": {
1168                        "enabled": True,
1169                        "hostname": interface["hostname"],
1170                        "apply_hostname": True,
1171                    }
1172                }
1173
1174    # Set selinux
1175    if "selinux" in ks_opts:
1176        for mode in ks_opts["selinux"]:
1177            sls[mode] = {"selinux": ["mode"]}
1178
1179    # Get package data together
1180    if "nobase" not in ks_opts["packages"]["options"]:
1181        sls["base"] = {"pkg_group": ["installed"]}
1182
1183    packages = ks_opts["packages"]["packages"]
1184    for package in packages:
1185        if not packages[package]:
1186            continue
1187        if package and packages[package] is True:
1188            if package.startswith("@"):
1189                pkg_group = package.replace("@", "", 1)
1190                sls[pkg_group] = {"pkg_group": ["installed"]}
1191            else:
1192                sls[package] = {"pkg": ["installed"]}
1193        elif packages[package] is False:
1194            sls[package] = {"pkg": ["absent"]}
1195
1196    if dst:
1197        with salt.utils.files.fopen(dst, "w") as fp_:
1198            salt.utils.yaml.safe_dump(sls, fp_, default_flow_style=False)
1199    else:
1200        return salt.utils.yaml.safe_dump(sls, default_flow_style=False)
1201