def install_files(): list_files_to_install = get_from_config("images", "list_files_to_install", dist) if not os.path.isfile(list_files_to_install): clean_and_exit("Error reading file " + list_files_to_install) dir_origin = get_from_config("images", "dir_files_to_install", dist) if not os.path.isdir(dir_origin): clean_and_exit("Error reading directory " + dir_origin) with open(list_files_to_install, "r") as file_to_read: for line in file_to_read: orig, dest, perm = line.rstrip().split() path_orig = dir_origin + "/" + orig path_dest = work_dir + "/" + dest file_perm = int(perm, 8) # tell int to use base 8 final_file = path_dest + orig if not os.path.isfile(path_orig): clean_and_exit("Error reading file " + path_orig) if not os.path.isdir(path_dest): os.makedirs(path_dest) shutil.copy(path_orig, path_dest) os.chmod(final_file, file_perm) if ("etc/init.d" in dest): run_chroot(["chroot", work_dir, "update-rc.d", orig, "defaults"]) # Empty hostname os.remove(work_dir + "/etc/hostname") run_chroot(["chroot", work_dir, "touch", "/etc/hostname"])
def do_ssh(hosts, command): hosts_l = [ full_hostname(host) for host in ClusterShell.NodeSet.NodeSet(hosts) ] hosts = ClusterShell.NodeSet.NodeSet('') hosts.updaten(hosts_l) os.environ["SSHPASS"] = \ value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") imm_user = \ value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") task = ClusterShell.Task.task_self() task.set_info("ssh_user", imm_user) task.set_info("ssh_path", "/usr/bin/sshpass -e /usr/bin/ssh") task.set_info("ssh_options", "-oBatchMode=no") task.shell(command, nodes=hosts.__str__()) task.resume() for buf, nodes in task.iter_buffers(): print "---\n%s:\n---\n %s" \ % (ClusterShell.NodeSet.fold(",".join(nodes)), buf)
def getmac(hosts): install_cfg() imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file(get_from_config("common", "master_passwd_file"), "PASSWD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) for host in nodeset: print "%s: " % host cmd = ["ipmitool", "-I", "lanplus", "-H", "imm" + host, "-U", imm_user, "-E", "fru", "print", "0"] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) # The data we want is in line 15 line = proc.stdout.readlines()[14] full_mac = line.split(":")[1].strip().upper() mac_address1 = "{0}:{1}:{2}:{3}:{4}:{5}".format(full_mac[0:2], full_mac[2:4], full_mac[4:6], full_mac[6:8], full_mac[8:10], full_mac[10:12]) mac_address2 = "{0}:{1}:{2}:{3}:{4}:{5}".format(full_mac[12:14], full_mac[14:16], full_mac[16:18], full_mac[18:20], full_mac[20:22], full_mac[22:24]) print "ETH0's MAC address is {0}\n" \ "ETH1's MAC address is {1}\n".format(mac_address1, mac_address2)
def install_files(): list_files_to_install = get_from_config("images", "list_files_to_install", dist) if not os.path.isfile(list_files_to_install): logging.warning("{0} is not a file!".format(list_files_to_install)) else: dir_origin = get_from_config("images", "dir_files_to_install", dist) if not os.path.isdir(dir_origin): logging.warning("{0} is not a directory!".format(dir_origin)) with open(list_files_to_install, "r") as file_to_read: for line in file_to_read: orig, dest, perm = line.rstrip().split() path_orig = dir_origin + "/" + orig path_dest = work_dir + "/" + dest file_perm = int(perm, 8) # tell int to use base 8 final_file = path_dest + orig if not os.path.isfile(path_orig): logging.warning("{0} is not a file!".format(path_orig)) if not os.path.isdir(path_dest): os.makedirs(path_dest) shutil.copy(path_orig, path_dest) os.chmod(final_file, file_perm) if ("etc/init.d" in dest): run_chroot( ["chroot", work_dir, "update-rc.d", orig, "defaults"]) # Empty hostname os.remove(work_dir + "/etc/hostname") run_chroot(["chroot", work_dir, "touch", "/etc/hostname"])
def do_connect(host, j=False, f=False): nodeset = ClusterShell.NodeSet.NodeSet(host) if (len(nodeset) != 1): clara_exit('Only one host allowed for this command') pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if pat.match(host): logging.debug( "The host is an IP adddres: {0}. Using ipmitool without conman.". format(host)) do_connect_ipmi(host) else: conmand = get_from_config("ipmi", "conmand") port = int(get_from_config("ipmi", "port")) if (len(conmand) == 0): clara_exit("You must set the configuration paramenter 'conmand'") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((conmand, port)) os.environ["CONMAN_ESCAPE"] = '!' cmd = ["conman"] if j: cmd = cmd + ["-j"] if f: cmd = cmd + ["-f"] cmd = cmd + ["-d", conmand, host] run(cmd) except socket.error as e: logging.debug( "Conman not running. Message on connect: Errno {0} - {1}". format(e.errno, e.strerror)) do_connect_ipmi(host) s.close()
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global work_dir, src_list, dist dist = get_from_config("common", "default_distribution") if dargs['<dist>'] is not None: dist = dargs["<dist>"] if dist not in get_from_config("common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format(dist)) if dargs['<chroot_dir>'] is not None: work_dir = dargs['<chroot_dir>'] else: work_dir = get_from_config("chroot", "trg_dir", dist) src_list = work_dir + "/etc/apt/sources.list" # Not executed in the following cases # - the program dies because of a signal # - os._exit() is invoked directly # - a Python fatal error is detected (in the interpreter) atexit.register(clean_and_exit) if dargs['create']: base_install() system_install() install_files() install_https_apt() remove_files() run_script_post_creation() elif dargs['edit']: edit(dargs['<chroot_dir>']) elif dargs['install']: install_packages(dargs['<packages>']) elif dargs['remove']: remove_packages(dargs['<packages>'])
def do_connect(host, j=False, f=False): nodeset = ClusterShell.NodeSet.NodeSet(host) if (len(nodeset) != 1): clara_exit('Only one host allowed for this command') pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if pat.match(host): logging.debug("The host is an IP adddres: {0}. Using ipmitool without conman.".format(host)) ipmi_do(host, True, "sol", "activate") else: conmand = get_from_config("ipmi", "conmand") port = int(get_from_config("ipmi", "port")) if (len(conmand) == 0): clara_exit("You must set the paramenter 'conmand' in the configuration file") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((conmand, port)) os.environ["CONMAN_ESCAPE"] = '!' cmd = ["conman"] if j: cmd = cmd + ["-j"] if f: cmd = cmd + ["-f"] cmd = cmd + ["-d", conmand, host] run(cmd) except socket.error as e: logging.debug("Conman not running. Message on connect: {0}" % e) ipmi_do(host, True, "sol", "activate") s.close()
def do_reprepro(action, package=None, flags=None): repo_dir = get_from_config("repo", "repo_dir", dist) reprepro_config = repo_dir + '/conf/distributions' if not os.path.isfile(reprepro_config): clara_exit( "There is not configuration for the local repository for {0}. Run first 'clara repo init <dist>'" .format(dist)) list_flags = ['--silent', '--ask-passphrase'] if conf.ddebug: list_flags = ['-V', '--ask-passphrase'] if flags is not None: list_flags.append(flags) cmd = ['reprepro'] + list_flags + \ ['--basedir', get_from_config("repo", "repo_dir", dist), '--outdir', get_from_config("repo", "mirror_local", dist), action, dist] if package is not None: cmd.append(package) run(cmd)
def ipmi_do(hosts, *cmd): imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file( get_from_config("common", "master_passwd_file"), "IMMPASSWORD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) p = multiprocessing.Pool(parallel) result_map = {} for host in nodeset: pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if not pat.match(host): prefix = get_from_config("ipmi", "prefix") host = prefix + host ipmitool = [ "ipmitool", "-I", "lanplus", "-H", host, "-U", imm_user, "-E", "-e!" ] ipmitool.extend(cmd) logging.debug("ipmi/ipmi_do: {0}".format(" ".join(ipmitool))) result_map[host] = p.apply_async(ipmi_run, (ipmitool, )) p.close() p.join() for host, result in result_map.items(): print host, result.get()
def main(): dargs = docopt.docopt(__doc__) global dist dist = get_from_config("common", "distribution") if dargs["--dist"] is not None: dist = dargs["--dist"] if dist not in get_from_config("common", "distributions"): sys.exit("{0} is not a know distribution".format(dist)) if dargs['key']: do_key() if dargs['init']: do_init() elif dargs['sync']: if dargs['create']: do_sync('create') else: do_sync() elif dargs['add']: for elem in dargs['<file>']: if elem.endswith(".deb"): do_package('includedeb', elem) elif elem.endswith(".changes"): do_package('include', elem) elif elem.endswith(".dsc"): do_package('includedsc', elem) else: sys.exit("File is not a *.deb *.dsc or *.changes") elif dargs['del']: for elem in dargs['<name>']: do_package('removesrc', elem)
def push(image, dist): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) if (squashfs_file == "" or squashfs_file == None): image_name = dist + "_image.squashfs" squashfs_file = "/var/lib/clara/images/" + image_name else: squashfs_file = image if not os.path.isfile(squashfs_file): clara_exit("{0} doesn't exist.".format(squashfs_file)) # Send files where they will be used sftp_mode = has_config_value("images", "hosts", dist) dargs = docopt.docopt(__doc__) if sftp_mode: sftp_user = get_from_config("images", "sftp_user", dist) sftp_private_key = get_from_config("images", "sftp_private_key", dist) sftp_passphrase = get_from_config_or("images", "sftp_passphrase", dist, None) sftp_hosts = get_from_config("images", "hosts", dist).split(',') sftp_client = sftp.Sftp(sftp_hosts, sftp_user, sftp_private_key, sftp_passphrase) sftp_client.upload([squashfs_file], os.path.dirname(squashfs_file), 0o755) else: clara_exit("Hosts not found for the image {0}".format(squashfs_file))
def system_install(): package_file = get_from_config("images", "package_file", dist) if os.path.isfile(package_file): shutil.copy(package_file, work_dir + "/tmp/packages.file") else: clean_and_exit("Error copying file " + package_file) preseed_file = get_from_config("images", "preseed_file", dist) if os.path.isfile(preseed_file): shutil.copy(preseed_file, work_dir + "/tmp/preseed.file") else: clean_and_exit("Error copying file " + preseed_file) mount_chroot() run_chroot(["chroot", work_dir, "apt-get", "update"]) pkgs = get_from_config("images", "important_packages", dist).split(',') run_chroot(["chroot", work_dir, "apt-get", "install", "--yes", "--force-yes"] + pkgs) run_chroot(["chroot", work_dir, "apt-get", "update"]) run_chroot(["chroot", work_dir, "aptitude", "reinstall", "~i ?not(?priority(required))"]) run_chroot(["chroot", work_dir, "/usr/lib/dpkg/methods/apt/update", "/var/lib/dpkg/"]) run_chroot(["chroot", work_dir, "debconf-set-selections", "/tmp/preseed.file"]) for i in range(0, 2): part1 = subprocess.Popen(["cat", work_dir + "/tmp/packages.file"], stdout=subprocess.PIPE) part2 = subprocess.Popen(["chroot", work_dir, "dpkg", "--set-selections"], stdin=part1.stdout, stdout=subprocess.PIPE) part1.stdout.close() # Allow part1 to receive a SIGPIPE if part2 exits. output = part2.communicate()[0] run_chroot(["chroot", work_dir, "apt-get", "dselect-upgrade", "-u", "--yes", "--force-yes"]) run_chroot(["chroot", work_dir, "apt-get", "clean"]) run_chroot(["chroot", work_dir, "/etc/init.d/rsyslog", "stop"]) umount_chroot()
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) # Use the value provided by the user in the command line if dargs['--p'] is not None and dargs['--p'].isdigit(): _opts['parallel'] = int(dargs['--p']) # Read the value from the config file and use 1 if it hasn't been set elif has_config_value("ipmi", "parallel"): _opts['parallel']= int(get_from_config("ipmi", "parallel")) else: logging.debug("parallel hasn't been set in config.ini, using 1 as default") if dargs['connect']: do_connect(dargs['<host>'], dargs['-j'], dargs['-f']) elif dargs['deconnect']: ipmi_do(dargs['<hostlist>'], "sol", "deactivate") elif dargs['status']: ipmi_do(dargs['<hostlist>'], "power", "status") elif dargs['setpwd']: imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") imm_pwd = value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") ipmi_do(dargs['<hostlist>'], "user", "set", "name", "2", imm_user) ipmi_do(dargs['<hostlist>'], "user", "set", "password", "2", imm_pwd) elif dargs['getmac']: getmac(dargs['<hostlist>']) elif dargs['on']: ipmi_do(dargs['<hostlist>'], "power", "on") elif dargs['off']: ipmi_do(dargs['<hostlist>'], "power", "off") elif dargs['soft']: ipmi_do(dargs['<hostlist>'], "power", "soft") elif dargs['reboot']: ipmi_do(dargs['<hostlist>'], "chassis", "power", "reset") elif dargs['blink']: ipmi_do(dargs['<hostlist>'], "chassis", "identify", "1") elif dargs['bios']: ipmi_do(dargs['<hostlist>'], "chassis", "bootparam", "set", "bootflag", "force_bios") elif dargs['immdhcp']: ipmi_do(dargs['<hostlist>'], "lan", "set", "1", "ipsrc", "dhcp") elif dargs['pxe']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "pxe") elif dargs['disk']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "disk") elif dargs['reset']: response = raw_input('Do you really want to restart BMC interface? (N/y) ') if response in ('Y', 'y'): ipmi_do(dargs['<hostlist>'], "mc", "reset", "cold") elif dargs['sellist']: ipmi_do(dargs['<hostlist>'], "sel", "list") elif dargs['selclear']: ipmi_do(dargs['<hostlist>'], "sel", "clear") elif dargs['ping']: do_ping(dargs['<hostlist>']) elif dargs['ssh']: do_ssh(dargs['<hostlist>'], dargs['<command>']) elif dargs['command']: ipmi_do(dargs['<hostlist>'], *dargs['<command>'])
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global parallel # Read the value from the config file and use 1 if it hasn't been set try: parallel = int(get_from_config("ipmi", "parallel")) except: logging.warning( "parallel hasn't been set in config.ini, using 1 as value") parallel = 1 # Use the value provided by the user in the command line if dargs['--p'] is not None and dargs['--p'].isdigit(): parallel = int(dargs['--p']) if dargs['connect']: do_connect(dargs['<host>'], dargs['-j'], dargs['-f']) elif dargs['deconnect']: ipmi_do(dargs['<hostlist>'], "sol", "deactivate") elif dargs['status']: ipmi_do(dargs['<hostlist>'], "power", "status") elif dargs['setpwd']: imm_user = value_from_file( get_from_config("common", "master_passwd_file"), "IMMUSER") imm_pwd = value_from_file( get_from_config("common", "master_passwd_file"), "IMMPASSWORD") ipmi_do(dargs['<hostlist>'], "user", "set", "name", "2", imm_user) ipmi_do(dargs['<hostlist>'], "user", "set", "password", "2", imm_pwd) elif dargs['getmac']: getmac(dargs['<hostlist>']) elif dargs['on']: ipmi_do(dargs['<hostlist>'], "power", "on") elif dargs['off']: ipmi_do(dargs['<hostlist>'], "power", "off") elif dargs['reboot']: ipmi_do(dargs['<hostlist>'], "chassis", "power", "reset") elif dargs['blink']: ipmi_do(dargs['<hostlist>'], "chassis", "identify", "1") elif dargs['bios']: ipmi_do(dargs['<hostlist>'], "chassis", "bootparam", "set", "bootflag", "force_bios") elif dargs['immdhcp']: ipmi_do(dargs['<hostlist>'], "lan", "set", "1", "ipsrc", "dhcp") elif dargs['pxe']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "pxe") elif dargs['disk']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "disk") elif dargs['reset']: ipmi_do(dargs['<hostlist>'], "mc", "reset", "cold") elif dargs['sellist']: ipmi_do(dargs['<hostlist>'], "sel", "list") elif dargs['selclear']: ipmi_do(dargs['<hostlist>'], "sel", "clear") elif dargs['ping']: do_ping(dargs['<hostlist>']) elif dargs['ssh']: do_ssh(dargs['<hostlist>'], dargs['<command>'])
def geninitrd(path): if (path is None): trg_dir = get_from_config("images", "trg_dir", dist) else: trg_dir = path if not os.path.isdir(trg_dir): os.makedirs(trg_dir) squashfs_file = get_from_config("images", "trg_img", dist) if not os.path.isfile(squashfs_file): clara_exit("The image {0} does not exist!".format(squashfs_file)) if conf.ddebug: run(["unsquashfs", "-li", "-f", "-d", work_dir, squashfs_file]) else: run(["unsquashfs", "-f", "-d", work_dir, squashfs_file]) mount_chroot() # Install the kernel in the image kver = get_from_config("images", "kver", dist) if len(kver) == 0: clara_exit("kver hasn't be set in config.ini") else: run_chroot(["chroot", work_dir, "apt-get", "update"]) run_chroot([ "chroot", work_dir, "apt-get", "install", "--no-install-recommends", "--yes", "--force-yes", "linux-image-" + kver ]) # Install packages from 'packages_initrd' packages_initrd = get_from_config("images", "packages_initrd", dist) if len(packages_initrd) == 0: logging.warning("packages_initrd hasn't be set in config.ini") else: pkgs = packages_initrd.split(',') run_chroot([ "chroot", work_dir, "apt-get", "install", "--no-install-recommends", "--yes", "--force-yes" ] + pkgs) # Generate the initrd in the image run_chroot( ["chroot", work_dir, "mkinitramfs", "-o", "/tmp/initrd-" + kver, kver]) umount_chroot() # Copy the initrd out of the chroot shutil.copy(work_dir + "/tmp/initrd-" + kver, trg_dir + "/initrd-" + kver) os.chmod(trg_dir + "/initrd-" + kver, 0o644) logging.info("Initrd available at " + trg_dir + "/initrd-" + kver) # Copy vmlinuz out of the chroot shutil.copy(work_dir + "/boot/vmlinuz-" + kver, trg_dir + "/vmlinuz-" + kver) logging.info("vmlinuz available at " + trg_dir + "/vmlinuz-" + kver)
def ipmi_do(hosts, cmd): install_cfg() imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file(get_from_config("common", "master_passwd_file"), "PASSWD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) for host in nodeset: print "%s: " % host run(["ipmitool", "-I", "lanplus", "-H", "imm" + host, "-U", imm_user, "-E", cmd])
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global dist dist = get_from_config("common", "default_distribution") if dargs["<dist>"] is not None: dist = dargs["<dist>"] if dist not in get_from_config("common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format(dist)) trackers = get_from_config("p2p", "trackers", dist) seeders = get_from_config("p2p", "seeders", dist) tracking_service = get_from_config("p2p", "tracking_service", dist) seeding_service = get_from_config("p2p", "seeding_service", dist) if dargs['status']: init_status = get_from_config("p2p", "init_status") clush(trackers, init_status.format(tracking_service)) clush(seeders, init_status.format(seeding_service)) elif dargs['restart']: init_stop = get_from_config("p2p", "init_stop") clush(seeders, init_stop.format(seeding_service)) clush(trackers, init_stop.format(tracking_service)) time.sleep(1) init_start = get_from_config("p2p", "init_start") clush(trackers, init_start.format(tracking_service)) clush(seeders, init_start.format(seeding_service)) elif dargs['mktorrent']: mktorrent(dargs['--image'])
def genimg(image, work_dir, dist): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) if (squashfs_file == "" or squashfs_file == None): image_name = dist + "_image.squashfs" squashfs_file = "/var/lib/clara/images/" + image_name if os.path.isfile(squashfs_file): os.rename(squashfs_file, squashfs_file + ".old") logging.info( "Previous image renamed to {0}.".format(squashfs_file + ".old")) else: path_to_image = os.path.dirname(image) if not os.path.isdir(path_to_image) and len(path_to_image) != 0: os.makedirs(path_to_image) squashfs_file = image if os.path.isfile(squashfs_file): os.rename(squashfs_file, squashfs_file + ".old") logging.info("Previous image renamed to {0}.".format(squashfs_file + ".old")) logging.info("Creating image at {0}".format(squashfs_file)) if not os.path.exists(os.path.dirname(squashfs_file)): logging.info("Creating local directory path", os.path.dirname(squashfs_file)) os.makedirs(os.path.dirname(squashfs_file)) if conf.ddebug: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend", "-info" ]) else: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend" ]) os.chmod(squashfs_file, 0o755) sftp_mode = has_config_value("images", "hosts", dist) dargs = docopt.docopt(__doc__) if sftp_mode and not dargs['--no-sync']: sftp_user = get_from_config("images", "sftp_user", dist) sftp_private_key = get_from_config("images", "sftp_private_key", dist) sftp_passphrase = get_from_config_or("images", "sftp_passphrase", dist, None) sftp_hosts = get_from_config("images", "hosts", dist).split(',') sftp_client = sftp.Sftp(sftp_hosts, sftp_user, sftp_private_key, sftp_passphrase) sftp_client.upload([squashfs_file], os.path.dirname(squashfs_file), 0o755)
def install_cfg(): passwd_file = get_from_config("common", "master_passwd_file") if not os.path.isfile(passwd_file) and os.path.isfile(passwd_file + ".enc"): password = value_from_file(get_from_config("common", "master_passwd_file"), "PASSPHRASE") if len(password) > 20: cmd = ['openssl', 'aes-256-cbc', '-d', '-in', passwd_file + ".enc", '-out', passwd_file, '-k', password] run(cmd) os.chmod(passwd_file, 0o400) else: sys.exit('There was some problem reading the PASSPHRASE')
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global dist dist = get_from_config("common", "default_distribution") if dargs["<dist>"] is not None: dist = dargs["<dist>"] if dist not in get_from_config("common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format(dist)) if dargs['key']: do_key() if dargs['init']: do_init() elif dargs['sync']: if dargs['all']: do_sync('all') else: do_sync(dargs['<dist>'], dargs['<suites>']) elif dargs['add']: for elem in dargs['<file>']: if elem.endswith(".deb"): do_reprepro('includedeb', elem, dargs['--reprepro-flags']) elif elem.endswith(".changes"): do_reprepro('include', elem, dargs['--reprepro-flags']) elif elem.endswith(".dsc"): do_reprepro('includedsc', elem, dargs['--reprepro-flags']) else: clara_exit("File is not a *.deb *.dsc or *.changes") elif dargs['del']: for elem in dargs['<name>']: do_reprepro('remove', elem) do_reprepro('removesrc', elem) elif dargs['list']: if dargs['all']: do_reprepro_cmd(['dumpreferences']) else: do_reprepro('list') elif dargs['search']: do_reprepro_cmd(['ls', dargs['<keyword>']]) elif dargs['copy']: if dargs['<from-dist>'] not in get_from_config( "common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format( dargs['<from-dist>'])) do_reprepro_cmd( ['copy', dist, dargs['<from-dist>'], dargs['<package>']]) elif dargs['jenkins']: arch = dargs['--source'] if arch is None: arch = "amd64" copy_jenkins(dargs['<job>'], arch, dargs['--reprepro-flags'])
def do_connect_ipmi(host): imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "USER") os.environ["IPMI_PASSWORD"] = value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if not pat.match(host): host = full_hostname(host) ipmitool = ["ipmitool", "-I", "lanplus", "-H", host, "-U", imm_user, "-E", "-e!", "sol", "activate"] logging.debug("ipmi/ipmi_do: {0}".format(" ".join(ipmitool))) run(ipmitool)
def do_key(): key = get_from_config("repo", "gpg_key") fnull = open(os.devnull, 'w') cmd = ['gpg', '--list-secret-keys', key] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd, stdout=fnull, stderr=fnull) fnull.close() # We import the key if it hasn't been imported before if retcode != 0: file_stored_key = get_from_config("repo", "stored_enc_key") if os.path.isfile(file_stored_key): password = value_from_file( get_from_config("common", "master_passwd_file"), "ASUPASSWD") if len(password) > 20: fdesc, temp_path = tempfile.mkstemp(prefix="tmpClara") cmd = [ 'openssl', 'aes-256-cbc', '-d', '-in', file_stored_key, '-out', temp_path, '-k', password ] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd) if retcode != 0: os.close(fdesc) os.remove(temp_path) clara_exit('Command failed {0}'.format(" ".join(cmd))) else: logging.info("Trying to import key {0}".format(key)) fnull = open(os.devnull, 'w') cmd = [ 'gpg', '--allow-secret-key-import', '--import', temp_path ] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd) fnull.close() os.close(fdesc) os.remove(temp_path) if retcode != 0: logging.info( "\nThere was a problem with the import, make sure the key you imported " "from {0} is the same you have in your configuration: {1}" .format(file_stored_key, key)) else: clara_exit( 'There was some problem reading the value of ASUPASSWD') else: clara_exit('Unable to read: {0}'.format(file_stored_key)) else: logging.info("GPG key was already imported.")
def mktorrent(image): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) else: squashfs_file = image trackers_port = get_from_config("p2p", "trackers_port", dist) trackers_schema = get_from_config("p2p", "trackers_schema", dist) seeding_service = get_from_config("p2p", "seeding_service", dist) init_stop = get_from_config("p2p", "init_stop", dist) init_start = get_from_config("p2p", "init_start", dist) # trackers is a dictionary with pairs nodeset and torrent file trackers = {} for e in get_from_config("p2p", "trackers", dist).split(";"): k, v = e.split(":") trackers[k] = v # seeders in the config file is a dictionary with pairs nodeset and torrent file seeders_dict = {} for e in get_from_config("p2p", "seeders", dist).split(";"): k, v = e.split(":") seeders_dict[k] = v seeders = ",".join(seeders_dict.keys()) if not os.path.isfile(squashfs_file): clara_exit("{0} doesn't exist".format(squashfs_file)) # Remove old torrent files for f in trackers.values(): if os.path.isfile(f): os.remove(f) clush(seeders, init_stop.format(seeding_service)) sftp_mode = has_config_value("p2p", "sftp_user", dist) if sftp_mode: sftp_user = get_from_config("p2p", "sftp_user", dist) sftp_private_key = get_from_config("p2p", "sftp_private_key", dist) sftp_passphrase = get_from_config_or("p2p", "sftp_passphrase", dist, None) sftp_client = sftp.Sftp(seeders.split(','), sftp_user, sftp_private_key, sftp_passphrase) for e in trackers.keys(): announce = [] for t in list(ClusterShell.NodeSet.NodeSet(e)): announce.append("{0}://{1}:{2}/announce".format(trackers_schema, t, trackers_port)) run(["/usr/bin/mktorrent", "-a", ",".join(announce), "-o", trackers[e], squashfs_file]) if sftp_mode: sftp_client.upload([trackers[e]], os.path.dirname(trackers[e])) clush(seeders, init_start.format(seeding_service))
def mktorrent(image): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) else: squashfs_file = image seeders = get_from_config("p2p", "seeders", dist) trackers_port = get_from_config("p2p", "trackers_port", dist) trackers_schema = get_from_config("p2p", "trackers_schema", dist) seeding_service = get_from_config("p2p", "seeding_service", dist) init_stop = get_from_config("p2p", "init_stop", dist) init_start = get_from_config("p2p", "init_start", dist) # trackers is a dictionary with pairs nodeset and torrent file trackers = {} for e in get_from_config("p2p", "trackers", dist).split(";"): k, v = e.split(":") trackers[k] = v if not os.path.isfile(squashfs_file): clara_exit("The file {0} doesn't exist".format(squashfs_file)) # Remove old torrent files for f in trackers.values(): if os.path.isfile(f): os.remove(f) clush(seeders, init_stop.format(seeding_service)) for e in trackers.keys(): announce = [] for t in list(ClusterShell.NodeSet.NodeSet(e)): announce.append("{0}://{1}:{2}/announce".format(trackers_schema, t, trackers_port)) run(["/usr/bin/mktorrent", "-a", ",".join(announce), "-o", trackers[e], squashfs_file]) clush(seeders, init_start.format(seeding_service))
def do_sync(selected_dist, input_suites=[]): suites = [] # Sync everything if selected_dist == 'all': for d in get_from_config("common", "allowed_distributions").split(","): suites = suites + get_from_config("repo", "suites", d).split(",") else: # Only sync suites related to the selected distribution if len(input_suites) == 0: suites = get_from_config("repo", "suites", selected_dist).split(",") # User selected one or several suites, check that they are valid else: for s in input_suites: if s not in get_from_config("repo", "suites", selected_dist).split(","): clara_exit( "{0} is not a valid suite from distribution {1}.\n" "Valid suites are: {2}".format( s, selected_dist, get_from_config("repo", "suites", selected_dist))) suites = input_suites logging.debug("The suites to sync are: {0}.".format(" ".join(suites))) # Read /etc/clara/repos.ini if not os.path.isfile('/etc/clara/repos.ini'): clara_exit("File /etc/clara/repos.ini not found.") repos = ConfigParser.ConfigParser() repos.read("/etc/clara/repos.ini") for s in suites: extra = [] if conf.ddebug: # if extra debug for 3rd party software extra = ['--debug'] final_dir = get(repos, s, "mirror_root") + "/" + s run(['debmirror'] + extra + [ "--diff=none", "--nosource", "--ignore-release-gpg", "--ignore-missing-release", "--method={0}".format( get(repos, s, "method")), "--arch={0}".format(get(repos, s, "archs")), "--host={0}".format( get(repos, s, "server")), "--root={0}".format( get(repos, s, "mirror_dir")), "--dist={0}".format( get(repos, s, "suite_name")), "--section={0}".format( get(repos, s, "sections")), final_dir ])
def install_https_apt(): try: list_https_repos = get_from_config("chroot", "list_https_repos", dist).split(",") except: list_https_repos = None if not list_https_repos: logging.warning("list_https_repos is not specified in config.ini") else: # Install https transport for apt run_chroot(["chroot", work_dir, "apt-get", "update"]) run_chroot([ "chroot", work_dir, "apt-get", "install", "--no-install-recommends", "--yes", "--force-yes", "apt-transport-https", "openssl" ]) # Add https sources in apt config with open(src_list, 'a') as fsources: for line in list_https_repos: fsources.write(line + '\n') # Add ssl keys apt_ssl_key_source = get_from_config("chroot", "apt_ssl_key", dist) apt_ssl_crt_source = get_from_config("chroot", "apt_ssl_crt", dist) path_dest = "/etc/ssl/" apt_ssl_key = path_dest + "private/" + os.path.basename( apt_ssl_key_source) apt_ssl_crt = path_dest + "certs/" + os.path.basename( apt_ssl_crt_source) if not os.path.isfile(apt_ssl_key_source): logging.warning("{0} is not a file!".format(apt_ssl_key_source)) if not os.path.isfile(apt_ssl_crt_source): logging.warning("{0} is not a file!".format(apt_ssl_crt_source)) if not os.path.isdir(path_dest): os.makedirs(path_dest) shutil.copy(apt_ssl_key_source, work_dir + apt_ssl_key) os.chmod(work_dir + apt_ssl_key, 0600) shutil.copy(apt_ssl_crt_source, work_dir + apt_ssl_crt) os.chmod(work_dir + apt_ssl_crt, 0644) # Add apt config for ssl key with open(work_dir + "/etc/apt/apt.conf.d/52ssl", 'w') as apt_conf_ssl: apt_conf_ssl.write("""# # Configuration for apt over https, for secured repository # Acquire::https::SslCert "{0}"; Acquire::https::SslKey "{1}"; Acquire::https::Verify-Peer "false"; """.format(apt_ssl_crt, apt_ssl_key)) # Finally update packages database run_chroot(["chroot", work_dir, "apt-get", "update"])
def do_sync(option=''): local = get_from_config("repo", "local_modules", dist).split(',') remote = get_from_config("repo", "remote_modules", dist).split(',') for elem in range(0, len(local)): if os.path.isdir(get_from_config("repo", "mirror_root", dist) + "/" + local[elem]) or (option == 'create'): run(['rsync', '-az', '--stats', '--human-readable', '--force', '--delete', '--ignore-errors', get_from_config("repo", "server", dist) + '::' + remote[elem], get_from_config("repo", "mirror_root", dist) + '/' + local[elem]]) else: sys.exit('Local repository not found. ' 'Please run: \n\tclara repo sync create')
def fake_getfromconfig(section, value, dist=''): if section == "repo" and value == "repo_dir": return repo_path if section == "repo" and value == "mirror_local": return mirror_path return get_from_config(section, value, dist)
def genimg(image): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) else: path_to_image = os.path.dirname(image) if not os.path.isdir(path_to_image) and len(path_to_image) != 0: os.makedirs(path_to_image) squashfs_file = image if os.path.isfile(squashfs_file): os.rename(squashfs_file, squashfs_file + ".old") logging.info("Previous image renamed to {0}.".format(squashfs_file + ".old")) logging.info("Creating image at {0}".format(squashfs_file)) run_chroot(["chroot", work_dir, "apt-get", "clean"]) if conf.ddebug: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend", "-info" ]) else: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend" ]) os.chmod(squashfs_file, 0o755)
def extract_image(): squashfs_file = get_from_config("images", "trg_img", dist) if not os.path.isfile(squashfs_file): sys.exit("The image {0} does not exist!".format(squashfs_file)) print "Extracting {0} to {1} ...".format(squashfs_file, work_dir) run(["unsquashfs", "-f", "-d", work_dir, squashfs_file])
def umount_chroot(): if os.path.ismount(work_dir + "/proc/sys/fs/binfmt_misc"): run(["chroot", work_dir, "umount", "/proc/sys/fs/binfmt_misc"]) if os.path.ismount(work_dir + "/sys"): run(["chroot", work_dir, "umount", "/sys"]) if os.path.ismount(work_dir + "/proc"): run(["chroot", work_dir, "umount", "/proc"]) try: extra_bind_mounts = get_from_config("chroot", "extra_bind_mounts", dist).split(",") except: extra_bind_mounts = None if not extra_bind_mounts: logging.warning("extra_bind_mounts is not specified in config.ini") else: for mounts_params in extra_bind_mounts: mountpoint = work_dir + mounts_params.split(" ")[1] with open("/proc/mounts", "r") as file_to_read: for line in file_to_read: if mountpoint in line: run(["umount", mountpoint]) time.sleep(1) # Wait one second so the system has time to unmount with open("/proc/mounts", "r") as file_to_read: for line in file_to_read: if work_dir in line: clara_exit("Something went wrong when umounting in the chroot")
def fake_getfromconfig(section, value, dist=''): if section == "p2p" and value == "seeders": return "seeders1,seeders2:{}".format(seed_file) if section == "images" and value == "trg_dir": return torrent_dir return get_from_config(section, value, dist)
def remove_files(): files_to_remove = get_from_config("images", "files_to_remove", dist).split(',') for f in files_to_remove: if os.path.isfile(work_dir + "/" + f): os.remove(work_dir + "/" + f) os.remove(work_dir + "/usr/sbin/policy-rc.d")
def base_install(): # Step 1 - Debootstrap src_list = work_dir + "/etc/apt/sources.list" apt_pref = work_dir + "/etc/apt/preferences.d/00custompreferences" apt_conf = work_dir + "/etc/apt/apt.conf.d/99nocheckvalid" dpkg_conf = work_dir + "/etc/dpkg/dpkg.cfg.d/excludes" etc_host = work_dir + "/etc/hosts" run(["debootstrap", get_from_config("images", "debiandist", dist), work_dir, get_from_config("images", "debmirror", dist) + "/debian"]) # Step 2 - Mirror setup list_repos = get_from_config("images", "list_repos", dist).split(",") with open(src_list, 'w') as fsources: for line in list_repos: fsources.write(line + '\n') with open(apt_pref, 'w') as fapt: fapt.write("""Package: * Pin: release o={0} Pin-Priority: 5000 Package: * Pin: release o={1} Pin-Priority: 6000 """.format(dist, get_from_config("common", "origin", dist))) with open(apt_conf, 'w') as fconf: fconf.write('Acquire::Check-Valid-Until "false";\n') lists_hosts = get_from_config("images", "etc_hosts", dist).split(",") if (len(lists_hosts) % 2 != 0): print "WARNING: the option etc_hosts is malformed or missing an argument" with open(etc_host, 'w') as fhost: for elem in range(0, len(lists_hosts), 2): fhost.write("{0} {1}\n".format(lists_hosts[elem], lists_hosts[elem+1])) with open(dpkg_conf, 'w') as fdpkg: fdpkg.write("""# Drop locales except French path-exclude=/usr/share/locale/* path-include=/usr/share/locale/fr/* path-include=/usr/share/locale/locale.alias # Drop manual pages # (We keep manual pages in the image) ## path-exclude=/usr/share/man/* """)
def main(): dargs = docopt.docopt(__doc__) trackers = get_from_config("p2p", "trackers") seeders = get_from_config("p2p", "seeders") if dargs['status']: clush(trackers, "service mldonkey-server status") clush(seeders, "service ctorrent status") elif dargs['restart']: clush(seeders, "service ctorrent stop") clush(trackers, "service mldonkey-server stop") time.sleep(1) clush(trackers, "service mldonkey-server start") clush(seeders, "service ctorrent start") elif dargs['mktorrent']: mktorrent(dargs['--image'])
def list_all_repos(dist): list_repos_nonsplitted = get_from_config("images", "list_repos", dist) if ';' in list_repos_nonsplitted: separator = ';' else: separator = ',' list_repos = list_repos_nonsplitted.split(separator) return list_repos
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global keep_chroot_dir keep_chroot_dir = False # Not executed in the following cases # - the program dies because of a signal # - os._exit() is invoked directly # - a Python fatal error is detected (in the interpreter) atexit.register(clean_and_exit) global dist dist = get_from_config("common", "default_distribution") if dargs['<dist>'] is not None: dist = dargs["<dist>"] if dist not in get_from_config("common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format(dist)) global work_dir if dargs['repack']: work_dir = dargs['<directory>'] else: tmpdir = get_from_config_or("images", "tmp_dir", dist, "/tmp") work_dir = tempfile.mkdtemp(prefix="tmpClara", dir=tmpdir) if dargs['create']: if dargs["--keep-chroot-dir"]: keep_chroot_dir = True base_install() install_files() system_install() remove_files() run_script_post_creation() genimg(dargs['<image>']) elif dargs['repack']: genimg(dargs['--image']) elif dargs['unpack']: extract_image(dargs['--image']) elif dargs['initrd']: geninitrd(dargs['--output']) elif dargs['edit']: edit(dargs['<image>']) elif dargs['push']: push(dargs['<image>'])
def init_config(): passwd_file = get_from_config("common", "master_passwd_file") if os.path.isfile(passwd_file): imm_user = value_from_file(passwd_file, "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file(passwd_file, "IMMPASSWORD") return imm_user else: print "%s not found. Please check config." % passwd_file sys.exit(1)
def genimg(): squashfs_file = get_from_config("images", "trg_img", dist) if os.path.isfile(squashfs_file): os.rename(squashfs_file, squashfs_file + ".old") print("Previous image renamed to {0}.".format(squashfs_file + ".old")) print "Creating image at {0}".format(squashfs_file) run_chroot(["chroot", work_dir, "apt-get", "clean"]) run(["mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend"]) os.chmod(squashfs_file, 0o755)
def do_key(): key = get_from_config("repo", "gpg_key") fnull = open(os.devnull, 'w') cmd = ['gpg', '--list-secret-keys', key] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd, stdout=fnull, stderr=fnull) fnull.close() # We import the key if it hasn't been imported before if retcode != 0: file_stored_key = get_from_config("repo", "stored_enc_key") if os.path.isfile(file_stored_key): password = value_from_file(get_from_config("common", "master_passwd_file"), "ASUPASSWD") if len(password) > 20: fdesc, temp_path = tempfile.mkstemp(prefix="tmpClara") cmd = ['openssl', 'aes-256-cbc', '-d', '-in', file_stored_key, '-out', temp_path, '-k', password] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd) if retcode != 0: os.close(fdesc) os.remove(temp_path) clara_exit('Command failed {0}'.format(" ".join(cmd))) else: logging.info("Trying to import key {0}".format(key)) fnull = open(os.devnull, 'w') cmd = ['gpg', '--allow-secret-key-import', '--import', temp_path] logging.debug("repo/do_key: {0}".format(" ".join(cmd))) retcode = subprocess.call(cmd) fnull.close() os.close(fdesc) os.remove(temp_path) if retcode != 0: logging.info("\nThere was a problem with the import, make sure the key you imported " "from {0} is the same you have in your configuration: {1}".format(file_stored_key, key)) else: clara_exit('There was some problem reading the value of ASUPASSWD') else: clara_exit('Unable to read: {0}'.format(file_stored_key)) else: logging.info("GPG key was already imported.")
def get(config, section, value): # If the value is not in the override section, look in "repos" from the config.ini if config.has_option(section, value): return config.get(section, value).strip() else: try: return get_from_config("repo", value) except: clara_exit("Value '{0}' not found in section '{1}'".format(value, section))
def run_script_post_creation(): script = get_from_config("chroot", "script_post_creation", dist) if len(script) == 0: logging.warning("script_post_creation hasn't be set in the config.ini") elif not os.path.isfile(script): logging.warning("File {0} not found!".format(script)) else: # Copy the script into the chroot and make sure it's executable shutil.copy(script, work_dir + "/tmp/script") os.chmod(work_dir + "/tmp/script", 0o755) run_chroot(["chroot", work_dir, "bash", "/tmp/script"])
def get_encryption_key(): master_passwd_file = get_from_config("common", "master_passwd_file") if os.path.isfile(master_passwd_file): password = value_from_file(master_passwd_file, "ASUPASSWD") if len(password) > 20: return password else: clara_exit("There was some problem reading the value of ASUPASSWD") else: clara_exit("Unable to read: {0}".format(master_passwd_file))
def do_init(): repo_dir = get_from_config("repo", "repo_dir", dist) reprepro_config = repo_dir + '/conf/distributions' if not os.path.isfile(reprepro_config): if not os.path.isdir(repo_dir + '/conf'): os.makedirs(repo_dir + '/conf') freprepro = open(reprepro_config, 'w') freprepro.write("""Origin: {0} Label: {1} Suite: {1} Codename: {1} Version: {2} Architectures: amd64 source Components: main contrib non-free UDebComponents: main SignWith: {3} Description: Depot Local {4} DebIndices: Packages Release . .gz .bz2 DscIndices: Sources Release . .gz .bz2 """.format(get_from_config("common", "origin", dist), dist, get_from_config("repo", "version", dist), get_from_config("repo", "gpg_key", dist), get_from_config("repo", "clustername", dist))) freprepro.close() os.chdir(repo_dir) run(['reprepro', '--ask-passphrase', '--basedir', repo_dir, '--outdir', get_from_config("repo", "mirror_local", dist), 'export', dist])
def copy_jenkins(job, arch, flags=None): repo_dir = get_from_config("repo", "repo_dir", dist) reprepro_config = repo_dir + '/conf/distributions' if not os.path.isfile(reprepro_config): clara_exit( "There is not configuration for the local repository for {0}. Run first 'clara repo init <dist>'" .format(dist)) list_flags = ['--silent', '--ask-passphrase'] if conf.ddebug: list_flags = ['-V', '--ask-passphrase'] if flags is not None: list_flags.append(flags) if not job.endswith("-binaries"): job = job + "-binaries" jenkins_dir = get_from_config("repo", "jenkins_dir") path = os.path.join(jenkins_dir, job, "configurations/builds/lastSuccessfulBuild/archive/") if not os.path.isdir(path): clara_exit( "The job {} doesn't exists or needs to be build.".format(job)) for f in os.listdir(path): if f.endswith("_{0}.changes".format(arch)): changesfile = os.path.join(path + f) if changesfile is None: clara_exit("Not changes files was found in {0}".format(path)) cmd = ['reprepro'] + list_flags + \ ['--basedir', get_from_config("repo", "repo_dir", dist), '--outdir', get_from_config("repo", "mirror_local", dist), "include", dist, changesfile] run(cmd)
def do_key(): fnull = open(os.devnull, 'w') cmd = ['gpg', '--list-secret-keys', get_from_config("repo", "gpg_key")] retcode = subprocess.call(cmd, stdout=fnull) fnull.close() # We import the key if it hasn't been imported before if retcode != 0: file_stored_key = get_from_config("repo", "stored_enc_key") if os.path.isfile(file_stored_key): password = value_from_file(get_from_config("common", "master_passwd_file"), "PASSPHRASE") if len(password) > 20: fdesc, temp_path = tempfile.mkstemp() cmd = ['openssl', 'aes-256-cbc', '-d', '-in', file_stored_key, '-out', temp_path, '-k', password] retcode = subprocess.call(cmd) if retcode != 0: os.close(fdesc) os.remove(temp_path) sys.exit('Command failed {0}'.format(" ".join(cmd))) else: fnull = open(os.devnull, 'w') cmd = ['gpg', '--allow-secret-key-import', '--import', temp_path] retcode = subprocess.call(cmd, stdout=fnull) fnull.close() os.close(fdesc) os.remove(temp_path) if retcode != 0: sys.exit('Command failed {0}'.format(" ".join(cmd))) else: sys.exit('There was some problem reading the PASSPHRASE') else: sys.exit('Unable to read: {0}'.format(file_stored_key)) else: print "GPG key was already imported."
def geninitrd(): trg_dir = get_from_config("images", "trg_dir", dist) if not os.path.isdir(trg_dir): sys.exit("Directory {0} does not exist!".format(trg_dir)) mkinitrfs = get_from_config("images", "mkinitramfs", dist) if not os.path.isfile(mkinitrfs): sys.exit("{0} does not exist!".format(mkinitrfs)) initramfsc = get_from_config("images", "initramfs-config", dist) if not os.path.isdir(initramfsc): sys.exit("Directory {0} does not exist!".format(initramfsc)) kver = get_from_config("images", "kver", dist) # Generate the initrd run([mkinitrfs, "-d", initramfsc, "-o", trg_dir + "/initrd-" + kver, kver]) os.chmod(trg_dir + "/initrd-" + kver, 0o644) print "Initrd generated in " + trg_dir + "/initrd-" + kver # Copy kernel into right directory shutil.copy("/boot/vmlinuz-" + kver, trg_dir + "/linux-" + kver) print "Kernel copied in " + trg_dir + "/linux-" + kver
def main(): dargs = docopt.docopt(__doc__) global work_dir if dargs['repack']: work_dir = dargs['<directory>'] else: work_dir = tempfile.mkdtemp() global dist dist = get_from_config("common", "distribution") if dargs["--dist"] is not None: dist = dargs["--dist"] if dist not in get_from_config("common", "distributions"): sys.exit("{0} is not a know distribution".format(dist)) if dargs['genimg']: base_install() system_install() install_files() remove_files() genimg() elif dargs['repack']: genimg() elif dargs['unpack']: extract_image() print "Modify the image at {0} and then run:\n " \ "\tclara images repack {0}".format(work_dir) elif dargs['apply_config2img']: extract_image() system_install() install_files() elif dargs['initrd']: geninitrd() elif dargs['editimg']: editimg(dargs['<image>']) if not dargs['unpack']: shutil.rmtree(work_dir)
def edit(image, work_dir, dist): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) if (squashfs_file == "" or squashfs_file == None): image_name = dist + "_image.squashfs" squashfs_file = "/var/lib/clara/images/" + image_name else: squashfs_file = image if not os.path.isfile(squashfs_file): clara_exit("{0} doesn't exist.".format(squashfs_file)) # Extract the image. logging.info("Extracting {0} to {1} ...".format(squashfs_file, work_dir)) if conf.ddebug: run(["unsquashfs", "-li", "-f", "-d", work_dir, squashfs_file]) else: run(["unsquashfs", "-f", "-d", work_dir, squashfs_file]) # Work in the image os.chdir(work_dir) logging.info( "Entering into a bash shell to edit the image. ^d when you have finished." ) os.putenv("PROMPT_COMMAND", "echo -ne '\e[1;31m({0}) clara images> \e[0m'".format(dist)) pty.spawn(["/bin/bash"]) save = raw_input('Save changes made in the image? (N/y)') logging.debug("Input from the user: '******'".format(save)) if save not in ('Y', 'y'): clara_exit( "Changes ignored. The image {0} hasn't been modified.".format( squashfs_file)) # Rename old image and recreate new one os.rename(squashfs_file, squashfs_file + ".old") if conf.ddebug: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend", "-info" ]) else: run([ "mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend" ]) os.chmod(squashfs_file, 0o755) logging.info("\nPrevious image renamed to {0}." "\nThe image has been repacked at {1}".format( squashfs_file + ".old", squashfs_file))
def getmac(hosts): imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file( get_from_config("common", "master_passwd_file"), "IMMPASSWORD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) for host in nodeset: pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if not pat.match(host): prefix = get_from_config("ipmi", "prefix") host = prefix + host logging.info("{0}: ".format(host)) cmd = [ "ipmitool", "-I", "lanplus", "-H", host, "-U", imm_user, "-E", "fru", "print", "0" ] logging.debug("ipmi/getmac: {0}".format(" ".join(cmd))) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) # The data we want is in line 15 lines = proc.stdout.readlines() if (len(lines) < 14): clara_exit("The host {0} can't be reached".format(host)) full_mac = lines[14].split(":")[1].strip().upper() mac_address1 = "{0}:{1}:{2}:{3}:{4}:{5}".format( full_mac[0:2], full_mac[2:4], full_mac[4:6], full_mac[6:8], full_mac[8:10], full_mac[10:12]) mac_address2 = "{0}:{1}:{2}:{3}:{4}:{5}".format( full_mac[12:14], full_mac[14:16], full_mac[16:18], full_mac[18:20], full_mac[20:22], full_mac[22:24]) logging.info(" eth0's MAC address is {0}\n" " eth1's MAC address is {1}".format( mac_address1, mac_address2))
def getmac(hosts): imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) for host in nodeset: pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if not pat.match(host): host = "imm" + host logging.info("{0}: ".format(host)) cmd = ["ipmitool", "-I", "lanplus", "-H", host, "-U", imm_user, "-E", "fru", "print", "0"] logging.debug("ipmi/getmac: {0}".format(" ".join(cmd))) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) # The data we want is in line 15 lines = proc.stdout.readlines() if (len(lines) < 14): clara_exit("The host {0} can't be reached".format(host)) full_mac = lines[14].split(":")[1].strip().upper() mac_address1 = "{0}:{1}:{2}:{3}:{4}:{5}".format(full_mac[0:2], full_mac[2:4], full_mac[4:6], full_mac[6:8], full_mac[8:10], full_mac[10:12]) mac_address2 = "{0}:{1}:{2}:{3}:{4}:{5}".format(full_mac[12:14], full_mac[14:16], full_mac[16:18], full_mac[18:20], full_mac[20:22], full_mac[22:24]) logging.info(" eth0's MAC address is {0}\n" " eth1's MAC address is {1}".format(mac_address1, mac_address2))
def do_reprepro(action, package=None, flags=None): repo_dir = get_from_config("repo", "repo_dir", dist) reprepro_config = repo_dir + '/conf/distributions' if not os.path.isfile(reprepro_config): clara_exit("There is not configuration for the local repository for {0}. Run first 'clara repo init <dist>'".format(dist)) list_flags = ['--silent', '--ask-passphrase'] if conf.ddebug: list_flags = ['-V', '--ask-passphrase'] if flags is not None: list_flags.append(flags) cmd = ['reprepro'] + list_flags + \ ['--basedir', get_from_config("repo", "repo_dir", dist), '--outdir', get_from_config("repo", "mirror_local", dist), action, dist] if package is not None: cmd.append(package) run(cmd)
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) if dargs['connect']: do_connect(dargs['<host>'], dargs['-j'], dargs['-f']) elif dargs['deconnect']: ipmi_do(dargs['<hostlist>'], "sol", "deactivate") elif dargs['status']: ipmi_do(dargs['<hostlist>'], "power", "status") elif dargs['setpwd']: imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") imm_pwd = value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") ipmi_do(dargs['<hostlist>'], "user", "set", "name", "2", imm_user) ipmi_do(dargs['<hostlist>'], "user", "set", "password", "2", imm_pwd) elif dargs['getmac']: getmac(dargs['<hostlist>']) elif dargs['on']: ipmi_do(dargs['<hostlist>'], "power", "on") elif dargs['off']: ipmi_do(dargs['<hostlist>'], "power", "off") elif dargs['reboot']: ipmi_do(dargs['<hostlist>'], "chassis", "power", "reset") elif dargs['blink']: ipmi_do(dargs['<hostlist>'], "chassis", "identify", "1") elif dargs['bios']: ipmi_do(dargs['<hostlist>'], "chassis", "bootparam", "set", "bootflag", "force_bios") elif dargs['immdhcp']: ipmi_do(dargs['<hostlist>'], "lan", "set", "1", "ipsrc", "dhcp") elif dargs['pxe']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "pxe") elif dargs['disk']: ipmi_do(dargs['<hostlist>'], "chassis", "bootdev", "disk") elif dargs['reset']: ipmi_do(dargs['<hostlist>'], "mc", "reset", "cold") elif dargs['ping']: do_ping(dargs['<hostlist>'])
def ipmi_do(hosts, pty=False, *cmd): command = [] if not isinstance(pty, bool): command.append(pty) pty = False command.extend(cmd) imm_user = value_from_file(get_from_config("common", "master_passwd_file"), "IMMUSER") os.environ["IPMI_PASSWORD"] = value_from_file(get_from_config("common", "master_passwd_file"), "IMMPASSWORD") nodeset = ClusterShell.NodeSet.NodeSet(hosts) for host in nodeset: pat = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") if not pat.match(host): host = "imm" + host ipmitool = ["ipmitool", "-I", "lanplus", "-H", host, "-U", imm_user, "-E", "-e!"] ipmitool.extend(command) logging.debug("ipmi/ipmi_do: {0}".format(" ".join(ipmitool))) if pty: run(ipmitool) else: os.system("echo -n '%s: ' ;" % host + " ".join(ipmitool))
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__) global dist dist = get_from_config("common", "default_distribution") if dargs["<dist>"] is not None: dist = dargs["<dist>"] if dist not in get_from_config("common", "allowed_distributions"): clara_exit("{0} is not a know distribution".format(dist)) if dargs['key']: do_key() if dargs['init']: do_init() elif dargs['sync']: if dargs['all']: do_sync('all') else: do_sync(dargs['<dist>'], dargs['<suites>']) elif dargs['add']: for elem in dargs['<file>']: if elem.endswith(".deb"): do_reprepro('includedeb', elem, dargs['--reprepro-flags']) elif elem.endswith(".changes"): do_reprepro('include', elem, dargs['--reprepro-flags']) elif elem.endswith(".dsc"): do_reprepro('includedsc', elem, dargs['--reprepro-flags']) else: clara_exit("File is not a *.deb *.dsc or *.changes") elif dargs['del']: for elem in dargs['<name>']: do_reprepro('remove', elem) do_reprepro('removesrc', elem) elif dargs['list']: do_reprepro('list')
def do_sync(selected_dist, input_suites=[]): info_suites = {} # Contains all the information suite_dist = {} # Contains the pairs suite - webdir all_suites = [] # Contains a list with all the suites names for distribution in get_from_config("common", "allowed_distributions").split(","): elements = get_from_config("repo", "info_suites", distribution).split(",") tmp_info_suites = {} for e in elements: k, v = e.split(":") all_suites.append(k) suite_dist[k] = distribution tmp_info_suites[k] = v info_suites[distribution] = tmp_info_suites suites = [] if selected_dist == 'all': # We sync everything suites = all_suites elif len(input_suites) == 0: # We only sync suites related to the default distribution suites = info_suites[selected_dist].keys() else: # If we select one or several suites, we check that are valid for s in input_suites: if s not in all_suites: clara_exit("{0} is not a valid suite. Valid suites are: {1}".format(s, " ".join(all_suites))) suites = input_suites logging.debug("The suites to sync are: {0}.".format(" ".join(suites))) for s in suites: mirror_root = get_from_config("repo", "mirror_root", suite_dist[s]) dm_server = get_from_config("repo", "server", suite_dist[s]) dm_root = info_suites[suite_dist[s]][s] suite_name = s if s in ["wheezy-security", "jessie-security"]: suite_name = s.split("-")[0] + "/updates" archs = get_from_config("repo", "archs", suite_dist[s]) sections = get_from_config("repo", "sections", suite_dist[s]) extra = [] if conf.ddebug: # if extra debug for 3rd party software extra = ['--debug'] run(['debmirror'] + extra + ["--diff=none", "--method=http", "--nosource", "--ignore-release-gpg", "--ignore-missing-release", "--arch={0}".format(archs), "--host={0}".format(dm_server), "--root={0}".format(dm_root), "--dist={0}".format(suite_name), "--section={0}".format(sections), mirror_root + "/" + s])
def do_connect(hosts): nodeset = ClusterShell.NodeSet.NodeSet(hosts) if (len(nodeset) != 1): sys.exit('Only one host allowed for this command') else: try: cmd = ["service", "conman", "status"] retcode = subprocess.call(cmd, stdout=DEVNULL, stderr=STDOUT) except OSError, e: if (e.errno == errno.ENOENT): sys.exit("Binary not found, check your path and/or retry as root." "You were trying to run:\n {0}".format(" ".join(cmd))) if retcode == 0: # if conman is running os.environ["CONMAN_ESCAPE"] = '!' conmand = value_from_file(get_from_config("nodes", "conmand")) run(["conman", "-d", conmand, hosts]) elif retcode == 1 or retcode == 3: # if conman is NOT running ipmi_do(hosts, ["sol", "activate"], pty=True) else: sys.exit('E: ' + ' '.join(cmd))
def editimg(image): if (image is None): squashfs_file = get_from_config("images", "trg_img", dist) else: squashfs_file = image if not os.path.isfile(squashfs_file): sys.exit("The image file {0} doesn't exist.".format(squashfs_file)) # Extract the image. print "Extracting {0} to {1} ...".format(squashfs_file, work_dir) run(["unsquashfs", "-f", "-d", work_dir, squashfs_file]) # Work in the image os.chdir(work_dir) print "Entering into a bash shell to edit the image. ^d when you have finished" os.putenv("PROMPT_COMMAND", "echo -ne '\e[1;31m clara images> \e[0m'") pty.spawn(["/bin/bash"]) # Rename old image and recreate new one os.rename(squashfs_file, squashfs_file + ".old") print("Previous image renamed to {0}.".format(squashfs_file + ".old")) print "Recreating image at {0}".format(squashfs_file) run(["mksquashfs", work_dir, squashfs_file, "-no-exports", "-noappend"]) os.chmod(squashfs_file, 0o755)
def mktorrent(image): ml_path = "/var/lib/mldonkey" trg_dir = get_from_config("images", "trg_dir") if (image is None): squashfs_file = get_from_config("images", "trg_img") else: squashfs_file = image seeders = get_from_config("p2p", "seeders") trackers = get_from_config("p2p", "trackers") trackers_port = get_from_config("p2p", "trackers_port") trackers_schema = get_from_config("p2p", "trackers_schema") if not os.path.isfile(squashfs_file): sys.exit("The file {0} doesn't exist".format(squashfs_file)) if os.path.isfile(trg_dir + "/image.torrent"): os.remove(trg_dir + "/image.torrent") clush(seeders, "service ctorrent stop") clush(trackers, "service mldonkey-server stop") for files in ["torrents/old", "torrents/seeded", "torrents/tracked"]: clush(trackers, "rm -f {0}/{1}/*".format(ml_path, files)) clush(trackers, "ln -sf {0} {1}/incoming/files/".format(squashfs_file, ml_path)) clush(trackers, "awk 'BEGIN{verb=1}; / tracked_files = / {verb=0}; /^$/ {verb=1}; {if (verb==1) print}' /var/lib/mldonkey/bittorrent.ini > /var/lib/mldonkey/bittorrent.ini.new") clush(trackers, "mv {0}/bittorrent.ini.new {0}/bittorrent.ini".format(ml_path)) announce = [] for t in list(ClusterShell.NodeSet.NodeSet(trackers)): announce.append("{0}://{1}:{2}/announce".format(trackers_schema, t, trackers_port)) run(["/usr/bin/mktorrent", "-a", ",".join(announce), "-o", trg_dir + "/image.torrent", squashfs_file]) clush(trackers, "ln -sf {0}/image.torrent {1}/torrents/seeded/".format(trg_dir, ml_path)) clush(trackers, "service mldonkey-server start") clush(seeders, "service ctorrent start")
def main(): logging.debug(sys.argv) dargs = docopt.docopt(__doc__, options_first=True) target_dist = dargs["<dist>"] if target_dist not in target_dists.keys(): sys.exit("Unknown target dist {0}".format(target_dist)) # Create a temp directory work_dir = tempfile.mkdtemp(prefix="tmpRebuild") if dargs["source"]: dsc_file = dargs["<dsc_file>"] # Check dsc file exists if not os.path.isfile(dsc_file): sys.exit("The file {0} doesn't exist".format(dsc_file)) # Find out versioning name, full_version = os.path.basename(dsc_file)[:-4].split("_") if "-" in full_version: upstream_version, debian_version = full_version.rsplit("-", 1) else: # Binary package upstream_version, debian_version = full_version, "" print_info(name, full_version, upstream_version, debian_version) dirname = os.path.dirname(dsc_file) copy_files_to_workdir(os.path.join(dirname, name + "_" + upstream_version + "*"), work_dir) elif dargs["repo"]: origin_dist = dargs["<origin_dist>"] package_name = dargs["<package_name>"] if origin_dist not in target_dists.keys(): sys.exit("Unknown origin dist {0}".format(origin_dist)) if not isinstance(package_name, str): clara_exit("Package name {0} is not a string".format(package_name)) # Check if the source package exists in the reprepro of origin_dist cmd = ["clara", "repo", "list", origin_dist] logging.debug(" ".join(cmd)) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) lines_proc = proc.stdout.readlines() found_package = False for line in lines_proc: if "|source: {} ".format(package_name) in line: found_package = True break # If we fail to find the package, we list what's available and exit if not found_package: logging.info("Package {0} not found. The available packages in {1} are:".format(package_name, origin_dist)) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) lines_proc = proc.stdout.readlines() for l in lines_proc: if "|source: " in l: logging.info(l.split(":")[1]) clara_exit("Select an available package and re-run clara.") # Look for the files and copy them to the temp directory area = "main" if "non-free" in line: area = "non-free" if package_name.startswith("lib"): package_dir = package_name[0:4] + "/" + package_name else: package_dir = package_name[0] + "/" + package_name # Note this is the path from the *origin* dist repo_path_pool = get_from_config("build", "repo_path_pool", origin_dist) repo_path_pool = repo_path_pool + "{0}/{1}".format(area, package_dir) full_version = line.split(" ")[-1].strip() upstream_version, debian_version = full_version.split("-") name = package_name print_info(name, full_version, upstream_version, debian_version) copy_files_to_workdir(os.path.join(repo_path_pool, name + "_" + upstream_version + "*"), work_dir) # Common code: append the calibre tag and build the package os.chdir(work_dir) cmd = ["dpkg-source", "-x", "{0}_{1}.dsc".format(name, full_version)] logging.debug(" ".join(cmd)) p = subprocess.call(cmd) path = "{0}-{1}".format(name, upstream_version) os.chdir(path) # Check if the debian version already appends the calibre tag tag = target_dists[target_dist] debian_version_re = r"(.*)\+{0}([\.\+])(\d)".format(tag) debian_version_p = re.compile(debian_version_re) debian_version_m = debian_version_p.match(debian_version) if debian_version_m: calibre_dump_s = debian_version_m.group(3) try: calibre_dump = int(calibre_dump_s) + 1 except ValueError: # calibre_dump_s was probably not an integer so start with 1 logging.info("Unable to handle calibre dump '{0}', restarting with 1".format(calibre_dump_s)) calibre_dump = 1 debian_version = debian_version_m.group(1) sep = debian_version_m.group(2) new_full_version = upstream_version + "-" + debian_version + "+" + tag + sep + str(calibre_dump) else: logging.info("Tag {0} not found in Debian version, appending new one".format(tag)) new_full_version = full_version + "+" + tag + "+1" # Bump the version, adding "+target_dist+1" cmd = ["dch", "--force-distribution", "-D", target_dist, "-v", new_full_version, "Rebuild for " + target_dist + "."] logging.debug(" ".join(cmd)) p = subprocess.call(cmd) # Recreate the source package os.chdir(work_dir) if "-" in new_full_version: cmd = ["dpkg-source", "-b", path] else: # Native cmd = ["dpkg-source", "-b", "{0}-{1}".format(name, new_full_version)] logging.debug(" ".join(cmd)) p = subprocess.call(cmd) # And build with cowbuilder cowbuilder_bin = get_from_config("build", "cowbuilder_bin", target_dist) if not os.path.isfile(cowbuilder_bin): sys.exit("The file {0} doesn't exist".format(cowbuilder_bin)) cmd = [cowbuilder_bin, "--build", "{0}_{1}.dsc".format(name, new_full_version)] logging.debug(" ".join(cmd)) p = subprocess.call(cmd) # Remove work directory shutil.rmtree(work_dir) repo_bin_dir = get_from_config("build", "repo_bin_dir", target_dist) repo_src_dir = get_from_config("build", "repo_src_dir", target_dist) dsc_file = "{0}_{1}.dsc".format(name, new_full_version) dsc_path = os.path.join(repo_bin_dir, dsc_file) changes_file = "{0}_{1}_amd64.changes".format(name, new_full_version) changes_path = os.path.join(repo_bin_dir, changes_file) orig_file = "{0}_{1}.orig.tar.gz".format(name, upstream_version) debian_file = "{0}_{1}.debian.tar.gz".format(name, new_full_version) logging.info( """ Commands you are supposed to run then: -------------8<----------------------- unset DISPLAY eval $(gpg-agent --daemon) clara repo del {0} {1} clara repo add {0} {2} clara repo add {0} {3} cp -v {4}/{{{5},{6},{7}}} {8}/ #-------------8<----------------------- """.format( target_dist, name, dsc_path, changes_path, repo_bin_dir, dsc_file, orig_file, debian_file, repo_src_dir ) )