#based on "pc" configuration # Accepted kernel parameters: # part=root=4,vg=LVM_VG_NAME,swap=4,var=20,home=max # disks=vda,vdb # zerombr !!!USE WITH CAUTION!!! # lang=en_US # pkgs=desktop,salpack # config=http://boot.salstar.sk/ks/custom # text # # System authorization information and root password auth --useshadow --enablemd5 rootpw --iscrypted $1$Nd.xn29E$ZyPRpRorSV06piZyARGxy/ # System bootloader configuration bootloader --append="" --location=mbr --timeout=1 # Firewall configuration (ssh is enabled by default) firewall --enabled # Run the Setup Agent on first boot firstboot --enable # System keyboard keyboard us # System language lang sk_SK.UTF-8 #lang en_US.UTF-8 # Installation logging level #logging info # Network information network --bootproto=dhcp --onboot=on #vnc --host=158.197.240.41 --port=5500 # Reboot after installation reboot # Accept EULA #eula --agreed # SELinux configuration selinux --permissive # System timezone timezone --utc Europe/Bratislava # Install OS instead of upgrade install # Services #services --disabled=netfs --enabled=network # iSCSI #ignoredisk --interactive #iscsiname iqn.2012-09.test #iscsi --ipaddr=158.197.16.70 --target=iqn.2012-09.sk.upjs.ftp:fedora # Disk partitioning information #part / --bytes-per-inode=4096 --fstype="ext4" --grow --size=1 %packages --ignoremissing -@Base dhclient openssh-clients openssh-server #screen wget rsync which iptables #joe #mc parted -sendmail %end %pre --interpreter /bin/bash # SAL's fedora/centos kickstart script # Fedora 25 has only python3 if [ -x /usr/bin/python ]; then PYTHON=/usr/bin/python else PYTHON=/usr/bin/python3 fi $PYTHON << PYTHON_EOF from __future__ import print_function import sys, os, re, socket if sys.version_info[0]>2: from urllib.request import urlopen, HTTPError else: from urllib2 import urlopen, HTTPError part_names = dict( swap='swap', boot='/boot', var='/var', home='/home', tmp='/tmp', www='/var/www', backuppc='/var/lib/BackupPC', mysql='/var/lib/mysql', pgsql='/var/lib/pgsql', mongodb='/var/lib/mongodb', redis='/var/lib/redis', squid='/var/spool/squid', opt='/opt' ) sys.stdout = open('/tmp/salstar.ks', 'wt') spare = 2 # check distribution (el6 or fc20) distro, arch = os.popen('uname -r').read().strip().split('.')[-2:] if arch.endswith('86'): arch = "i386" # boot command line cmd_line = {} for cmd in open('/proc/cmdline').read().strip().split(' '): arg = None if '=' in cmd: cmd, arg = cmd.split('=', 1) cmd_line[cmd] = arg def disksize(*disks): ds = [ int(open('/sys/class/block/%s/size' % x).read().strip())/2048 for x in disks ] print("# disksizes: %s = %s" % (disks, ds)) return min(ds) def size(s, disks=None, sum=0): if s in ['', 'max']: if disks is None: return "1 --grow" else: print("# sum=%d kB" % sum) return disksize(*disks)-sum if s.endswith('m') or s.endswith('M'): return int(s[:-1]) else: return int(float(s.strip('gG'))*1024) class mk_raid: cntr = -1 def __init__(self, disks): self.disks = disks def add(self, s): raids = [] self.cntr += 1 for i in 0, 1: if self.disks[i]: args = "" if self.cntr==0: args += " --asprimary" print("part raid.%d%d --size=%s --ondisk=%s%s" \ % (self.cntr, i+1, s, self.disks[i], args)) raids.append("raid.%d%d" % (self.cntr, i+1)) return raids def add_raid1(self, name, s, fstype=""): raids = self.add(s) print("raid %s --level=1 --device=md%d %s %s" \ % (name, self.cntr, fstype, " ".join(raids))) def add_vg(self, vg, s): self.add_raid1("pv.01", s) print("volgroup %s pv.01" % vg) def add_part(self, mp, s, fstype='--fstype=ext4'): self.add_raid1(mp, s, fstype) def not_cdrom_or_lun(hd): try: media = open('/sys/block/%s/device/media' % hd, 'r').read().strip() if media=='cdrom': return False except IOError: pass try: model = open('/sys/block/%s/device/model' % hd, 'r').read().strip() if model=='LUNZ': return False except IOError: pass return True def detect_disks(): return [x for x in os.listdir('/sys/block') if (x[0:2] in ['sd','vd','hd']) and not_cdrom_or_lun(x)] def initdisks(disks): if 'zerombr' in cmd_line: print("zerombr") if disks: print("clearpart --all --initlabel --drives=%s" \ % ','.join([x for x in disks if x])) else: print("clearpart --all --initlabel") def autopartition(disks, parts): if distro.startswith("fc"): biosboot = 2 else: biosboot = 0 if disks and disks.startswith("iscsi:"): #print("ignoredisk --interactive") print("iscsiname iqn.2012-09.test") print("iscsi --ipaddr=%s --target=%s --user=%s --password=%s" \ % tuple(disks[6:].split(";", 3))) return if not parts: return if disks: print("ignoredisk --only-use=%s" % disks.strip(',')) disks = disks.split(',') else: disks = detect_disks() parts = [x.split('=', 1) for x in parts.split(',')] vg = None if len(disks)==1: # one disk partition scheme disk0 = disks[0] for key, value in parts: if ':' in value: fstype = "--fstype=%s" % value.split(':', 1)[1] value = value.split(':', 1)[0] elif key=='swap': fstype = '' elif distro=='el7': fstype = '--fstype=xfs' else: fstype = '--fstype=ext4' if key=='vg': vg = value print("part pv.01 --ondisk=%s --size=1 --grow" % disk0) print("volgroup %s pv.01" % vg) elif key=='biosboot': biosboot = size(value) elif key=='root': initdisks(disks) if biosboot>0: print("part biosboot --fstype=biosboot --ondisk=%s --size=%d" \ % (disk0, biosboot)) print("part / --ondisk=%s %s --size=%d" \ % (disk0, fstype, size(value))) elif key in part_names: if vg: print("logvol %s --vgname=%s --size=%s --name=%s %s" \ % (part_names[key], vg, size(value), key, fstype)) else: print("part %s --ondisk=%s %s --size=%d" \ % (part_names[key], disk0, fstype, size(value))) elif len(disks)==2: # raid 1 partition scheme sum = spare # 1 disk0 = disks[0] disk1 = disks[1] raid = mk_raid(disks) for key, value in parts: if ':' in value: fstype = "--fstype=%s" %value.split(':', 1)[1] value = value.split(':', 1)[0] elif key=='swap': fstype = '' elif distro=='el7': fstype = '--fstype=xfs' else: fstype = '--fstype=ext4' print("# key, value, fstype:", key, value, fstype) if key=='vg': vg = value # calculate pv size #s = 0 #for k, v in parts: # if k=='vg': # s = 1 # elif s>0: # if v.isdigit(): # s += int(v)*1024 # else: # s += 1 # add pv # --grow disabled in F14 for raid partitions :-( #raid.add_vg(vg, "%d --grow" % s) print("# disk size: %d-%d" % (disksize(*disks), sum)) raid.add_vg(vg, "%d" % (disksize(*disks)-sum)) elif key=='biosboot': biosboot = size(value) elif key=='root': initdisks(disks) if biosboot>0: print("part biosboot --fstype=biosboot --ondisk=%s --size=%d" \ % (disk0, biosboot)) print("part biosboot --fstype=biosboot --ondisk=%s --size=%d" \ % (disk1, biosboot)) sum += biosboot s = size(value, disks, sum) raid.add_part("/", s, fstype) sum += s elif key in part_names: if vg: print("logvol %s --vgname=%s --size=%s --name=%s %s" \ % (part_names[key], vg, size(value), key, fstype)) else: s = size(value, disks, sum) raid.add_part(part_names[key], s, fstype) sum += s print("# sum=%d kB" % sum) class repocfg_class: fc = dict( base = [ 'url --url=%(mirror)s/fedora/linux/%(dir)s/%(ver)d/Fedora/%(arch)s/os/', 'repo --name=Updates --baseurl=%(mirror)s/fedora/linux/updates/%(ver)d/Everything/%(arch)s/' ], other = [ 'repo --name=Everything --baseurl=%(mirror)s/fedora/linux/%(dir)s/%(ver)d/Everything/%(arch)s/os/', 'repo --name=SALstar.sk --baseurl=https://www.salstar.sk/pub/fedora/%(ver)d/%(arch)s/' ], testing = [ 'repo --name=Updates-testing --baseurl=%(mirror)s/fedora/linux/updates/testing/%(ver)d/Everything/%(arch)s/' ] ) el = dict( base = [ 'url --url=%(mirror)s/centos/%(ver)d/os/%(arch)s/', 'repo --name=Updates --baseurl=%(mirror)s/centos/%(ver)d/updates/%(arch)s/', 'repo --name=EPEL --baseurl=%(mirror)s/mirrors/epel/%(ver)d/%(arch)s/' ], epel = [ 'repo --name=EPEL --baseurl=%(mirror)s/mirrors/epel/%(ver)d/%(arch)s/' ], cr = [ 'repo --name=CR --baseurl=%(mirror)/centos/%(ver)/cr/%(arch)/', ], other = [ 'repo --name=SALstar.sk --baseurl=https://www.salstar.sk/pub/epel/%(ver)d/%(arch)s/' ], testing = [ 'repo --name=EPEL-testing --baseurl=%(mirror)s/mirrors/epel/testing/%(ver)d/%(arch)s/' ] ) extra_pkgs = ('pkgs' in cmd_line) or ('packages' in cmd_line) cmd_line_testing = 'testing' in cmd_line cmd_line_repo = cmd_line.get('repo') cmd_line_pkgrepo = cmd_line.get('pkgrepo', '').split(',') cmd_line_packages = cmd_line.get('pkgs') or cmd_line.get('packages') def get(self, distro): grps = getattr(self, distro) ret = grps['base'] for pkgrepo in self.cmd_line_pkgrepo: if pkgrepo=='none': ret = [] elif grps.get(pkgrepo): ret.extend(grps[pkgrepo]) if self.cmd_line_testing: ret.extend(grps['testing']) if self.extra_pkgs: ret.extend(grps['epel']) ret.extend(grps['other']) return ret def repo_update(self, distro, version, arch): for repo in self.get(distro): if repo.startswith("url") and self.cmd_line_repo: print("url --url=%s" % self.cmd_line_repo) else: print(repo % dict( mirror="http://ftp.upjs.sk/pub", dir="releases", ver=version, arch=arch )) def geturl(self, url): if "://" not in url: url = os.path.join(os.path.dirname(cmd_line['ks']), url) #return urlopen(url).read() return '%include ' + url def package_update(self, distro, version): distro_packages = dict( fc = ["gdisk"], el = ["epel-release"] ) group_packages = dict( desktop = 'desktop.pkgs' ) print("%packages --ignoremissing") print("\n".join(distro_packages.get(distro))) if self.cmd_line_packages: for pkg in self.cmd_line_packages.split(','): if pkg in group_packages: print(self.geturl(group_packages[pkg])) else: print(pkg) print("%end") def lang(lang): if not lang: return langs = dict( en = "en_US", sk = "sk_SK", cs = "cs_CZ" ) if "_" not in lang and lang in langs: lang = langs[lang] if "." not in lang: lang += ".UTF-8" print("lang", lang) def url_get(src, dst=None): if cmd_line.get('config').startswith('https://'): import pycurl content = [] c = pycurl.Curl() c.setopt(pycurl.WRITEFUNCTION, content.append) c.setopt(pycurl.URL, os.path.join(cmd_line.get('config'), src)) try: c.perform() c.close() except pycurl.error as err: sys.stderr.write('Download error: %s [%s]' % (err[1], src)) return '' script = ''.join(content) else: try: script = urlopen( os.path.join(cmd_line.get('config'), src) ).read() except HTTPError as err: sys.stderr.write('Download error: %s [%s]' % (err, src)) return '' if dst: open(dst, 'wt').write(script) os.chmod(dst, 0o755) return script if "text" in cmd_line: print("text") if "passwd" in cmd_line: if cmd_line["passwd"].startswith("$"): print("rootpw --iscrypted %s" % cmd_line["passwd"]) else: print("rootpw %s" % cmd_line["passwd"]) autopartition( cmd_line.get('disk') or cmd_line.get('disks'), cmd_line.get('part') ) repocfg = repocfg_class() repocfg.repo_update(distro[:2], int(distro[2:]), arch) repocfg.package_update(distro[:2], int(distro[2:])) lang(cmd_line.get('lang')) # custom configuration if 'config' in cmd_line: exec(url_get('pre.py')) if url_get('pre.sh', '/tmp/salstar-custom-pre.sh'): os.system('/tmp/salstar-custom-pre.sh') url_get('post.sh', '/tmp/salstar-custom-post.sh') PYTHON_EOF %end %post --nochroot --interpreter /bin/bash # Fedora 25 has only python3 if [ -x /usr/bin/python ]; then PYTHON=/usr/bin/python else PYTHON=/usr/bin/python3 fi $PYTHON << PYTHON_EOF from __future__ import print_function import sys, os, re chroot = '/mnt/sysimage' repo_conf = '''\ [salstar.sk] name=SALstar.sk \$releasever - \$basearch - Base #baseurl=http://ftp.upjs.sk/pub/users/sal/Fedora/\$releasever/ mirrorlist=https://www.salstar.sk/download/mm/%(DISTRO)s/salstar/\$releasever/\$basearch gpgkey=https://www.salstar.sk/pub/sagator/SAGATOR-GPG-KEY gpgcheck=1 enabled=1 metadata_expire=1 [salstar.sk-testing] name=SALstar.sk \$releasever - \$basearch - Testing mirrorlist=https://www.salstar.sk/download/mm/%(DISTRO)s/salstar-testing/\$releasever/\$basearch gpgkey=https://www.salstar.sk/pub/sagator/SAGATOR-GPG-KEY gpgcheck=1 enabled=0 metadata_expire=1 [salstar.sk-builder] name=builder.salstar.sk baseurl=http://builder.salstar.sk/local/$releasever/$basearch/ gpgkey=https://www.salstar.sk/pub/sagator/SAGATOR-GPG-KEY gpgcheck=0 enabled=0 metadata_expire=1 ''' repo_key = '''\ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.6 (GNU/Linux) mQGiBEWSfqgRBADu/silyFvlgwCzsu8Ha/llSd4MidiYIeWO8vLszSJn6kVo+xbF hDlj/UXHQVwp/Q6pqrrNxucJSFaE/qWi6KuZ4XqN2xWyUAjSCJ0BiUJyoTD9NOg3 yXyzXVLRklHaeOUdNF7e376Vfwsgix1wsehBh66vtyX1znDfWPcqfAZkpwCgsw95 2f/9qBYhCM61Nd/jFe6HbW0EANmlw/CIS+QNCQQPntXbL2rGD80VLXK6W+yIMuPu bkSn1PJpeO4BBjOynVqAuW4bERm5gSPDxBqE5vD9Ef8pqsoUHRIVTyj1Z2I1JbXn OjbUZmFcLdqVNNHNRu3Bkb8YLD3qdtG6CHG6CfowYXZfdaTVgyYIcLiStGNNKaXI omJQA/9YFv2xvP82xykZvHqx0hnn/NXFrSn+9TJGdDKOo/6/6AA6BwXRBwjHG1x2 1CCIbnTOmoDeBw5+hpVtLnACannT6VnNvZ+Zm+qoMBZ/E+2m6MkkywyP7oUIsxLp 7FnZHd/e6FGpgzup55mZboAgth/l4+w1ztF1aCGHu6ATsR3VWLQpSmFuIE9ORFJF SiAoU0FHQVRPUikgPG9uZHJlampAc2Fsc3Rhci5zaz6IYAQTEQIAIAUCRZJ+qAIb AwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEAiqUAZrgi/nW/QAoJfsGDX8h6WH JqwZbPlWrR9FRP8ZAJ94pSLvMM6rfXlMbeOejfvFcdwc8w== =R77L -----END PGP PUBLIC KEY BLOCK----- ''' # add access from gateway, if behind NAT gwaccess="" gwip=os.popen( """/sbin/ip route get to 1.1.1.1 | awk '\$2=="via" { print \$3 }'""" ).read().strip() if re.search('^(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.', gwip): gwaccess=","+gwip ssh_authorized_keys='''\ from="work.salstar.sk,158.197.240.41,work6.salstar.sk,2001:4118:400:1::/64%s" \ ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAORxvbaG3OX99nkgSkVCPbptyfeBUUdlOtz5wPkN/EZozVQ56ZsKMHLXpHiBb973/PCrVQz1B4+n+D7Ud/UMSZIgGBThb2+Mh46qqrgPu1QhbvzcK1W4qEOsDWu4KQgCpxfFEaaF6a7V7MOrtXdSZmauMmSpSHO7BWM7Aq3PTVXH0Hvg== ondrejj@work.salstar.sk ''' % gwaccess # detect distribution rh_release = open(chroot+'/etc/redhat-release').read() if re.compile('^(CentOS|Red Hat|Scientific)').search(rh_release): os.environ['DISTRO'] = 'epel' else: os.environ['DISTRO'] = 'fedora' os.environ['CHROOT'] = chroot # add yum repository open(chroot+'/etc/yum.repos.d/salstar.repo', 'wt').write( repo_conf % os.environ ) open(chroot+'/etc/pki/rpm-gpg/SAGATOR-GPG-KEY', 'wt').write(repo_key) # add ssh key if not os.path.isdir(chroot+'/root/.ssh'): os.mkdir(chroot+'/root/.ssh') open(chroot+'/root/.ssh/authorized_keys', 'wt').write(ssh_authorized_keys) # custom configuration if os.path.exists('/tmp/salstar-custom-post.py'): exec(open('/tmp/salstar-custom-post.py').read()) if os.path.exists('/tmp/salstar-custom-post.sh'): os.system('/tmp/salstar-custom-post.sh') os.system('sync') PYTHON_EOF %end %include /tmp/salstar.ks