$ sudo python cobbler_distro_import.py -h usage: cobbler_distro_import.py [-h] -p PATH -a ARCH [-n NICKNAME] Import new distro into Cobbler optional arguments: -h, --help show this help message and exit -p PATH, --path PATH [ HTTP(s) | NFS ] path of an ISO -a ARCH, --arch ARCH Distro architecture, supported are: i386, x86_64, arm -n NICKNAME, --nickname NICKNAME Nickname for distribution
$ mount -o loop /tmp/<iso file> /mnt $ cobbler import --path=/mnt --name=<distro_name> \ --arch=<architecture> \ --kickstart=/var/lib/cobbler/kickstarts/<ks_file> $ cobbler distro list # verify work $ cobbler distro report $ umount /mnt $ rm /sascratch/iso/<iso file> # cleanup $ cobbler sync # if you import on master Cobbler
$ sudo cobbler_distro_import.py -p http://mysite.yu/OracleLinux/OL6/U10/i386/OracleLinux-R6-U10-Server-i386-dvd.iso -a i386 Check if Cobbler app is installed Check if OracleLinux-R6-U10-Server-i386-dvd is present. Wget downloading OracleLinux-R6-U10-Server-i386-dvd.iso 100% [........................................................] 3315597312 / 3315597312 OracleLinux-R6-U10-Server-i386-dvd.iso is downloaded Creating temp mount point /mnt/OracleLinux-R6-U10-Server-i386-dvd mount: /dev/loop0 is write-protected, mounting read-only /tmp/OracleLinux-R6-U10-Server-i386-dvd.iso is loop mounted to /mnt/OracleLinux-R6-U10-Server-i386-dvd task started: 2019-01-28_132905_import task started (id=Media import, time=Mon Jan 28 13:29:05 2019) ...shortened ... *** TASK COMPLETE *** OracleLinux-R6-U10-Server-i386-dvd was imported into Cobbler, still it's good to check import logs in /var/log/cobbler/tasks/ Unmount /mnt/OracleLinux-R6-U10-Server-i386-dvd Remove directory /mnt/OracleLinux-R6-U10-Server-i386-dvd Remove /tmp/OracleLinux-R6-U10-Server-i386-dvd.iso task started: 2019-01-28_132956_sync task started (id=Sync, time=Mon Jan 28 13:29:56 2019) ... *** TASK COMPLETE *** Run cobbler sync command
while true; do du -sh /var/www/cobbler/ks_mirror/; sleep 10; done
#!/bin/env python import os from time import gmtime, strftime import datetime import getpass import distutils.spawn # check if cobbler is installed import subprocess import wget import sys import re # regex import argparse import logging, logging.handlers import smtplib # sending email, plain text from email.mime.text import MIMEText # --- define colors class color: PURPLE = '\033[95m' CYAN = '\033[96m' DARKCYAN = '\033[36m' BLUE = '\033[94m' GREEN = '\033[92m' YELLOW = '\033[93m' RED = '\033[91m' BOLD = '\033[1m' UNDERLINE = '\033[4m' END = '\033[0m' # -- Does root run this? def i_am_root(): """ Exit if root doesn't run the script """ i_am=getpass.getuser() return True if i_am == "root" else False if not i_am_root(): sys.exit(color.RED + "Only root can run this script." + color.END ) # -- argument work parser = argparse.ArgumentParser(description='Import new distro into Cobbler') parser.add_argument("-p", "--path", help="[ HTTP(s) | NFS ] path of an ISO", required=True) parser.add_argument("-a", "--arch", help="Distro architecture, supported are: i386, x86_64, arm", required=True) parser.add_argument("-n", "--nickname", help="Nickname for distribution") args = parser.parse_args() iso_source_path=args.path distro_arch=args.arch nickname=args.nickname # -- define LOGGING PROGRAM = os.path.basename(sys.argv[0]) # name of this script LOG_PATH = ("/var/log/" + PROGRAM) # put together "/var/log/script_name" if not os.path.exists(LOG_PATH): # create LOG_PATH if doesn't exists os.makedirs(LOG_PATH) os.chown(LOG_PATH,-1,580) # root(-1 means no change):crm DSEE group #os.chown(LOG_PATH,-1,485400023) # root(-1 means no change):userg_sa IPA group os.chmod(LOG_PATH,0775) # drwxrwxr-x LOG_FILE = (LOG_PATH + "/" + datetime.datetime.now().strftime("%m-%d-%Y_%Hh%Mm%Ss")) formatter = logging.Formatter('%(asctime)s:%(levelname)s: %(message)s') handler = logging.handlers.TimedRotatingFileHandler(LOG_FILE, when='MIDNIGHT', backupCount=50, utc=False) handler.setFormatter(formatter) # Set up a specific logger with our desired output level logger = logging.getLogger(__name__) logger.addHandler(handler) logger.setLevel(logging.DEBUG) logger.debug("") logger.debug(color.GREEN + "START AT : " + strftime("%a, %d %b %Y %H:%M:%S", gmtime()) + color.END) KS_FILE = "/var/lib/cobbler/kickstarts/default.ks" # default ks, for attended installation VALID_ARCH = re.compile('[iI]386$|[xX]86_64$|[aA][rR][mM]$') NEW_DISTRO_NAME = subprocess.check_output(['basename %s .iso' % iso_source_path], shell=True).rstrip() # rstrip() remove \n ISO_NAME = subprocess.check_output(['basename %s' % iso_source_path], shell=True).rstrip() def find_download_location(location = "/.sascratch/iso/"): """ Function has one argument, if it's not provided, then it's /sascratch/iso/, which is default download place for IPA client, and for DSEE clients it's /tmp/. But, during testing, /sascratch/iso/ (nfs share) wasn't reliable, import times out, hence using /tmp/ all the time maybe better. So I just add . in front of sascratch. """ global DOWNLOAD_PLACE if os.path.isdir(location): DOWNLOAD_PLACE = location else: DOWNLOAD_PLACE = "/tmp/" def is_cobbler_installed(): """ Check if Cobbler is present """ logger.debug("Check if Cobbler app is installed") print ("Check if Cobbler app is installed") if not distutils.spawn.find_executable("cobbler"): logger.debug(color.RED + "Cobbler is not installed on this system." + color.END) sys.exit(color.RED + "Cobbler is not installed on this system." + color.END) def is_distro_present(): """ Check if distro already exists """ logger.debug("Check if " + NEW_DISTRO_NAME + " is present.") print ("Check if " + NEW_DISTRO_NAME + " is present.") #NEW_DISTRO_STATUS = subprocess.call(['basename %s .iso' % iso_source_path], shell=True) # returns $? #print ("exit status :" + str(NEW_DISTRO_STATUS)) #NEW_DISTRO_NAME = subprocess.check_output(['basename %s .iso' % iso_source_path], shell=True) # return output #print ("command's output :" + NEW_DISTRO_NAME) LIST_DISTRO = subprocess.check_output(['cobbler distro list'], shell=True) # this is string if LIST_DISTRO.find(NEW_DISTRO_NAME) != -1: #.find returs index if found, and -1 otherwize logger.debug("Distro " + NEW_DISTRO_NAME + " is already present.") # rstrip() remove \n sys.exit("Distro " + NEW_DISTRO_NAME + " is already present.") def get_http_iso(): """ Get ISO image from HTTP server using wget """ if not os.path.exists(DOWNLOAD_PLACE): logger.debug("Directory " + DOWNLOAD_PLACE + " doesn't exist, check why?") sys.exit("Directory " + DOWNLOAD_PLACE + " doesn't exist, check why?") try: logger.debug("Wget downloading %s " % ISO_NAME) print ("Wget downloading %s " % ISO_NAME) os.chdir(DOWNLOAD_PLACE) file=wget.download(iso_source_path) logger.debug("%s is downloaded" % ISO_NAME) print ("\n %s is downloaded" % ISO_NAME) except: logger.debug("Can't wget %s " % ISO_NAME) sys.exit("Can't wget %s " % ISO_NAME) def get_nfs_iso(): """ Get ISO image from NFS server using rsync """ if not os.path.exists(DOWNLOAD_PLACE): logger.debug("Directory " + DOWNLOAD_PLACE + " doesn't exist, check why?") sys.exit("Directory " + DOWNLOAD_PLACE + " doesn't exist, check why?") try: logger.debug("Rsync-ing %s " % ISO_NAME) print ("Rsync-ing %s " % ISO_NAME) os.chdir(DOWNLOAD_PLACE) subprocess.call(['rsync --progress -avH %s %s%s' % (iso_source_path, DOWNLOAD_PLACE, ISO_NAME)], shell=True) logger.debug("%s is rsync-ed" % ISO_NAME) print ("\n %s is rsync-ed" % ISO_NAME) except: logger.debug("Can't rsync %s from NFS server" % ISO_NAME) sys.exit("Can't rsync %s from NFS server" % ISO_NAME) def find_iso_path_type_and_get_iso(): """ Find if an ISO path is http or nfs location, then get an ISO """ if os.path.isfile(iso_source_path): # get iso via nfs get_nfs_iso() else: # get iso via http get_http_iso() def create_mount_location(): """ Create mount location """ try: if not os.path.exists("/mnt/%s" % NEW_DISTRO_NAME): logger.debug("Creating temp mount point /mnt/%s " % NEW_DISTRO_NAME) print ("Creating temp mount point /mnt/%s " % NEW_DISTRO_NAME) os.makedirs("/mnt/%s" % NEW_DISTRO_NAME) except: logger.debug("Can't create temp mount point /mnt/%s" % NEW_DISTRO_NAME) sys.exit("Can't create temp mount point /mnt/%s" % NEW_DISTRO_NAME) def mount_iso(): """ Mount ISO """ try: subprocess.call(['mount -o loop %s%s /mnt/%s' % (DOWNLOAD_PLACE, ISO_NAME, NEW_DISTRO_NAME)], shell=True) logger.debug("%s%s is loop mounted to /mnt/%s" % (DOWNLOAD_PLACE, ISO_NAME, NEW_DISTRO_NAME)) print ("%s%s is loop mounted to /mnt/%s" % (DOWNLOAD_PLACE, ISO_NAME, NEW_DISTRO_NAME)) except: logger.debug("Can't mount %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) sys.exit("Can't mount %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) def import_distro(nickname = NEW_DISTRO_NAME): """ Import distro into Cobbler, nickname has default values (if user doesn't provide info for them) """ try: subprocess.call(['cobbler import --path=/mnt/%s --name=%s --arch=%s --kickstart=%s' % (NEW_DISTRO_NAME, nickname, distro_arch, KS_FILE)], shell=True) logger.debug("%s was imported into Cobbler, still it's good to check import logs in /var/log/cobbler/tasks/" % NEW_DISTRO_NAME) print ("%s was imported into Cobbler, still it's good to check import logs in /var/log/cobbler/tasks/" % NEW_DISTRO_NAME) except: logger.debug("Can't import %s into Cobbler" % NEW_DISTRO_NAME) sys.exit("Can't import %s into Cobbler" % NEW_DISTRO_NAME) def cleanup(): """ Cleanup: unmount /mnt/NEW_DISTRO_NAME, remove directory and downloaded ISO """ try: subprocess.call(['umount /mnt/%s' % NEW_DISTRO_NAME], shell=True) logger.debug("Unmount /mnt/%s" % NEW_DISTRO_NAME) print ("Unmount /mnt/%s" % NEW_DISTRO_NAME) except: logger.debug("Can't umount /mnt/%s" % NEW_DISTRO_NAME) sys.exit("Can't umount /mnt/%s" % NEW_DISTRO_NAME) try: subprocess.call(['rmdir /mnt/%s' % NEW_DISTRO_NAME], shell=True) logger.debug("Remove directory /mnt/%s" % NEW_DISTRO_NAME) print ("Remove directory /mnt/%s" % NEW_DISTRO_NAME) except: logger.debug("Can't remove directory /mnt/%s" % NEW_DISTRO_NAME) sys.exit("Can't remove directory /mnt/%s" % NEW_DISTRO_NAME) try: subprocess.call(['rm -f %s%s' % (DOWNLOAD_PLACE, ISO_NAME)], shell=True) logger.debug("Remove %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) print ("Remove %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) except: logger.debug("Can't remove %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) sys.exit("Can't remove %s%s" % (DOWNLOAD_PLACE, ISO_NAME)) def cobbler_sync(): """ The command 'cobbler sync' has to be run so /etc/rsyncd.conf is updated. This is important on Master Cobbler since a distro will be replicated. """ try: subprocess.call(['cobbler sync'], shell=True) logger.debug("Run cobbler sync command") print ("Run cobbler sync command") except: logger.debug("Can't run cobbler sync command") sys.exit("Can't run cobbler sync command") # ----- MAIN -------------- if __name__ == '__main__': # print 'This program is being run by itself' if not VALID_ARCH.match(distro_arch): sys.exit("%s is not valid architecture" % distro_arch ) else: find_download_location() is_cobbler_installed() is_distro_present() find_iso_path_type_and_get_iso() create_mount_location() mount_iso() if nickname: import_distro(nickname) else: import_distro() cleanup() cobbler_sync() #else: # print 'I am being imported from another module' #logger.debug("\n") sys.exit(0)
#!/bin/env bash # Import cobbler disto # arguments: # $1 = http path to iso # $2 = arch # ks file is hardcoded # supports IPA clients, must be able to access /sascratch/iso # --------------------------- PROGNAME=`basename $0| sed 's/^9//'` LOGDATE=`date +%Y-%m-%d_%H_%M` LOG_PATH="/var/log/`basename ${PROGNAME}`" [ -d /var/log/`basename ${PROGNAME}` ] || mkdir /var/log/`basename ${PROGNAME}` LOGFILE=${LOG_PATH}/${LOGDATE}.log readonly loggerinfo="logger -t "${PROGNAME}" Info:" readonly loggerwarning="logger -t "${PROGNAME}" Warning:" readonly loggerproblem="logger -t "${PROGNAME}" Problem:" who_cares=" zarko.dudic@yu.yu \ " err() { echo ; echo "Problem: $*" ; echo ${loggerproblem} "$*" echo "$*" | mail -s "Problem from `hostname`:${PROGNAME}" ${who_cares} exit 1 } usage() { echo " Usage: ${PROGNAME} <http://iso-path> <arch> (Cobbler supported) arch: i386, x86_64, arm " exit 1 } # must be two arguments if [ $# -ne 2 ]; then usage ; exit 1 fi readonly distro_name=`basename $1 .iso` readonly arch=$2 ks_file="/var/lib/cobbler/kickstarts/default.ks" cleaning() { [ -d /mnt/${distro_name} ] && rmdir /mnt/${distro_name} [ -f /sascratch/iso/${distro_name}.iso ] && rm -f /sascratch/iso/${distro_name}.iso } # cleaning in case of script termination and regular exit trap cleaning HUP INT QUIT ABRT EXIT # ---------- MAIN ( ls /sascratch/iso/ > /dev/null if [ $? -ne 0 ]; then err "Can't access /sascratch/iso/, is this legit Cobbler server, plus IPA client?" fi if [ ${arch} != x86_64 -a ${arch} != arm -a ${arch} != i386 ]; then err "${arch} is not supported architecture, it has to be i386 OR x86_64 OR arm" fi # is this cobbler server which cobbler > /dev/null if [ $? -ne 0 ]; then err "Cobbler is not installed" fi # check if distro exist cobbler distro list | grep ${distro_name} > /dev/null if [ $? -eq 0 ]; then err " Distro ${distro_name} import has failed. Looks like it is already present (or similar one), please check this. " fi # get the ISO wget -O /sascratch/iso/${distro_name}.iso $1 || \ ( ( [ -f /sascratch/iso/${distro_name}.iso ] && \ rm -f /sascratch/iso/${distro_name}.iso ) && \ err "Can't wget $1" ) # create mount location [ -d /mnt/${distro_name} ] || ( mkdir /mnt/${distro_name} || err "Can't mkdir /mnt/${distro_name}" ) # mount ISO mount -o loop /sascratch/iso/${distro_name}.iso /mnt/${distro_name} || \ err "Can't mount /mnt/${distro_name}" # finally cobbler import cobbler import \ --path=/mnt/${distro_name} --name=${distro_name} --arch=$2 \ --kickstart=${ks_file} || \ ( cleaning ; err "Cobbler import has failed" ) [ -d /mnt/${distro_name} ] && ( umount /mnt/${distro_name} || err "Can't umount /mnt/${distro_name}" ) [ -d /mnt/${distro_name} ] && ( rmdir /mnt/${distro_name} || err "Can't rmdir /mnt/${distro_name}" ) [ -f /sascratch/iso/${distro_name}.iso ] && \ ( rm /sascratch/iso/${distro_name}.iso || err "Can't remove /sascratch/iso/${distro_name}.iso" ) echo "${distro_name} import has been successful!" | \ mail -s "`hostname`:${PROGNAME}" ${who_cares} || \ err "Can't send email about successful import" ) > ${LOGFILE} 2>&1 exit 0
set pager=1 if [ -s $prefix/grubenv ]; then load_env fi if [ "${next_entry}" ] ; then set default="${next_entry}" set next_entry= save_env next_entry set boot_once=true else set default="${saved_entry}" fi if [ x"${feature_menuentry_id}" = xy ]; then menuentry_id_option="--id" else menuentry_id_option="" fi export menuentry_id_option if [ "${prev_saved_entry}" ]; then set saved_entry="${prev_saved_entry}" save_env saved_entry set prev_saved_entry= save_env prev_saved_entry set boot_once=true fi function savedefault { if [ -z "${boot_once}" ]; then saved_entry="${chosen}" save_env saved_entry fi } function load_video { if [ x$feature_all_video_module = xy ]; then insmod all_video else insmod efi_gop insmod efi_uga insmod ieee1275_fb insmod vbe insmod vga insmod video_bochs insmod video_cirrus fi } terminal_output console set timeout=200 if [ x$feature_timeout_style = xy ] ; then set timeout_style=menu set timeout=600 # Fallback normal timeout code in case the timeout_style feature is # unavailable. else set timeout=600 fi load_video set gfxpayload=keep insmod gzio insmod part_gpt insmod ext2 menuentry 'OL7.6 aarch64. Text install.' --class red --class gnu-linux --class gnu --class os { linux (http)http://ca-cobbler-master/tftpboot/images/OL-R7-U6_aarch64-arm-arm/vmlinuz \ ks=http://ca-cobbler-master/cblr/svc/op/ks/profile/OL-R7-U6_aarch64-arm-arm \ inst.repo=http://ca-cobbler-master/cobbler/ks_mirror/OL-R7-U6_aarch64-arm \ inst.ks=http://ca-cobbler-master/cblr/svc/op/ks/profile/OL-R7-U6_aarch64-arm-arm \ nomodeset inst.text initrd (http)http://ca-cobbler-master/tftpboot/images/OL-R7-U6_aarch64-arm-arm/initrd.img } menuentry 'Boot OL7.6 aarch64 in RESCUE' --class red --class gnu-linux --class gnu --class os { linux (tftp)/images/OL-R7-U6_aarch64-arm-arm/vmlinuz nomodeset rescue initrd (tftp)/images/OL-R7-U6_aarch64-arm-arm/initrd.img } menuentry 'OL8.1 aarch64. Text install.' --class red --class gnu-linux --class gnu --class os { linux (http)http://ca-cobbler-master/tftpboot/images/OL-R8-U1-aarch64-arm-arm/vmlinuz \ ks=http://ca-cobbler-master/cblr/svc/op/ks/profile/OL-R8-U1-aarch64-arm-arm \ inst.repo=http://ca-cobbler-master/cobbler/ks_mirror/OL-R8-U1-aarch64-arm \ inst.ks=http://ca-cobbler-master/cblr/svc/op/ks/profile/OL-R8-U1-aarch64-arm-arm \ nomodeset inst.text initrd (http)http://ca-cobbler-master/tftpboot/images/OL-R8-U1-aarch64-arm-arm/initrd.img } menuentry 'OL8.1 aarch64 in RESCUE' --class red --class gnu-linux --class gnu --class os { linux (tftp)/images/OL-R8-U1-aarch64-arm-arm/vmlinuz nomodeset rescue initrd (tftp)/images/OL-R8-U1-aarch64-arm-arm/initrd.img }
# x7-2 host dev111.domain.com { hardware ethernet 00:10:e0:da:c6:31; option routers 10.x.x.1; fixed-address 10.x.x.62; next-server 10.x.x.61; filename "grub2/grubx64-ol8_u0.efi"; }
# dev111.domain.com set default=0 set timeout=15 menuentry 'OL-R8-U1-x86_64 UEFI grub2 dev111' { echo "Loading vmlinuz" linuxefi images/OL-R8-U1-x86_64/vmlinuz ksdevice=bootif ks=http://cobbler.domain.com/cblr/svc/op/ks/profile/OL-R8-U1-x86_64 text console=ttyS0,9600 echo "Loading initrd.img" initrdefi images/OL-R8-U1-x86_64/initrd.img echo "Booting kernel" }