#!/usr/bin/python2.7 # -*- python -*- # -*- coding: utf-8 -*- # Started 30/06/2011 by Seblu ''' InstallSystems Command line Tool ''' import os import time import fnmatch import datetime import argparse import installsystems import installsystems.tools as istools from installsystems.printer import * from installsystems.repository import Repository from installsystems.repository import RepositoryManager from installsystems.repository import RepositoryConfig from installsystems.image import PackageImage, SourceImage from installsystems.config import MainConfigFile, RepoConfigFile def load_repositories(args): ''' Load repositories on a repository manager ''' # remove cache is asked if args.no_cache: args.cache = None # init repo cache object repoman = RepositoryManager(args.cache, timeout=args.timeout) # register repositories (order matter) # load repo configs if args.repo_path is not None: # from command line repoman.register(RepositoryConfig(None, path=args.repo_path)) else: # from config for repoconf in RepoConfigFile(args.repo_config).repos: if args.repo_filter is None: repoman.register(repoconf) else: if len(fnmatch.filter([repoconf.name], args.repo_filter)) > 0: repoman.register(repoconf) return repoman def select_one_repository(repoman): if len(repoman) == 0: raise Exception("No repository selected") elif len(repoman) > 1: raise Exception("Please select only one repository") return repoman[0] def c_new(parser, args): ''' Create a new source image ''' simg = SourceImage.create(args.path) def c_build(parser, args): ''' Build an image source ''' # build start time t0 = time.time() # load source image simg = SourceImage(args.path) # do the job simg.build(force=args.force, check=not args.no_check) # compute building time t1 = time.time() dt = int(t1 - t0) arrow("Build time: %s" % datetime.timedelta(seconds=dt)) def c_init(parser, args): ''' Create a empty repository ''' # we cannot use load_repositories because repo doesn't exists if args.repo_path is not None: # from command line Repository.create(RepositoryConfig(None, path=args.repo_path)) else: # from config for repoconf in RepoConfigFile(args.repo_config).repos: # filtering on repository name if present if args.repo_filter is not None and repoconf.name != args.repo_filter: continue Repository.create(repoconf) def c_add(parser, args): ''' Add an image package into a repository ''' repoman = load_repositories(args) repo = select_one_repository(repoman) for image in args.path: pkg = PackageImage(image) repo.add(pkg, delete=not args.preserve) def c_del(parser, args): ''' Remove an image package from a repository ''' repoman = load_repositories(args) repo = select_one_repository(repoman) repo.delete(args.image_name, args.image_version) def c_install(parser, args): ''' Install an image ''' # looks if arguments is a file or image name if istools.pathtype(args.image) == "file" and os.path.isfile(args.image): pkg = PackageImage(istools.abspath(args.image)) elif PackageImage.check_image_name(args.image): # get image package repoman = load_repositories(args) pkg = repoman.get(args.image, args.image_version) # add default show help options args.subparser.add_argument("-h", "--help", action="help", default=argparse.SUPPRESS, help="show program's version number and exit") # Print setup information arrow("Installing %s v%s" % (pkg.name, pkg.version)) # install start time t0 = time.time() # run parser scripts with parser parser argument pkg.run_parser(parser=args.subparser) # call parser again, with extended attributes arrow("Parsing arguments") args = parser.parse_args(namespace=args) # run setup scripts pkg.run_setup(namespace=args) # compute building time t1 = time.time() dt = int(t1 - t0) arrow("Install time: %s" % datetime.timedelta(seconds=dt)) def c_list(parser, args): ''' List images in repository or image content ''' # List available repositories if len(args.values) == 0: repoman = load_repositories(args) arrow("Repositories") repoman.show(verbose=args.detail) return # list direct image or reposity content elif len(args.values) == 1: # list image file content if (istools.pathtype(args.values[0]) == "file" and os.path.isfile(args.values[0])): pkg = PackageImage(args.values[0]) arrow("Image %s v%s" % (pkg.name, pkg.version)) pkg.show(verbose=args.detail) # list repository content else: args.repo_filter = args.values[0] repoman = load_repositories(args) for repo in repoman: arrow("Image in %s" % repo.config.name) repo.show(args.detail) return # list last image version elif len(args.values) == 2: args.repo_filter = args.values[0] args.image = args.values[1] args.image_version = None # list specific image version elif len(args.values) == 3: args.repo_filter = args.values[0] args.image = args.values[1] args.image_version = args.values[2] else: args.subparser.print_usage() exit(1) # display content of image accross a repositories repoman = load_repositories(args) pkg = repoman.get(args.image, args.image_version) arrow("Image %s v%s" % (pkg.name, pkg.version)) pkg.show(verbose=args.detail) def c_update(parser, args): ''' Build and update image on repo ''' c_build(parser, args) simg = SourceImage(args.path) repoman = load_repositories(args) repo = select_one_repository(repoman) image = simg.description["name"] version = simg.description["version"] if repo.has(image, version): repo.delete(image, version) pkg = PackageImage(simg.image_name) repo.add(pkg, delete=not args.preserve) def c_cat(parser, args): ''' Display image's file(s) ''' # looks if arguments is a file or image name if istools.pathtype(args.image) == "file" and os.path.isfile(args.image): pkg = PackageImage(istools.abspath(args.image)) elif PackageImage.check_image_name(args.image): # get image package repoman = load_repositories(args) pkg = repoman.get(args.image, args.image_version) for filename in args.files: pkg.cat(filename) def c_search(parser, args): ''' Search in repository ''' repoman = load_repositories(args) for repo in repoman: arrow(repo.config.name) repo.search(args.pattern) def c_get(parser, args): ''' Get a remove image in current directory ''' raise NotImplementedError("Not yet implemented") def c_clean(parser, args): ''' Clean a repository ''' raise NotImplementedError("Not yet implemented") def c_copy(parser, args): ''' Copy an image from a repository to another one ''' # load repositories repoman = load_repositories(args) srcrepo = repoman[args.repo_src] dstrepo = repoman[args.repo_dst] # load source image srcimg = srcrepo.get(args.image, args.image_version) # Advertise arrow("Copying %s v%s from %s to %s" % (srcimg.name, srcimg.version, srcrepo.config.name, dstrepo.config.name)) arrowlevel(1) dstrepo.add(srcimg) arrowlevel(-1) def c_help(parser, args): ''' Show help ''' if args.command is None: parser.print_help() else: args.subparser.choices[args.command].print_help() def c_version(parser, args): ''' Print installsystems version ''' out(installsystems.version) # Top level argument parsing p_main = argparse.ArgumentParser() p_main.add_argument("-V", "--version", action="version", version=installsystems.version, help="show installsystems version") # exclusive group on debug/quiet ex_group = p_main.add_mutually_exclusive_group() ex_group.add_argument("-d", "--debug", action="store_true", help="active debug mode") ex_group.add_argument("-q", "--quiet", action="store_true", help="active quiet mode") # common options p_main.add_argument("-c", "--config", default="installsystems", help="config file path") p_main.add_argument("-R", "--repo-config", default="repository", help="repository config file path") p_main.add_argument("-f", "--repo-filter", default=None, help="select repository by name in config files") p_main.add_argument("-r", "--repo-path", default=None, help="repository path") p_main.add_argument("-C", "--cache", default=None, help="path of the repository cache") p_main.add_argument("--no-cache", action="store_true", default=False, help="Not use persistent db caching") p_main.add_argument("-t", "--timeout", dest="timeout", type=int, default=3, help="download timeout (default 3)") # create a subparsers for each command subparsers = p_main.add_subparsers() # new command parser p_new = subparsers.add_parser("new", help=c_new.__doc__.lower()) p_new.add_argument("path", help="Path of new image directory") p_new.set_defaults(func=c_new) # build command parser p_build = subparsers.add_parser("build", help=c_build.__doc__.lower()) p_build.add_argument("-f", "--force", action="store_true", default=False, help="overwrite existing image") p_build.add_argument("-c", "--no-check", action="store_true", default=False, help="do not check compilation before adding scripts") p_build.add_argument("path", nargs="?", default=".") p_build.set_defaults(func=c_build) # init command parser p_init = subparsers.add_parser("init", help=c_init.__doc__.lower()) p_init.add_argument("repo_filter", nargs="?", default=argparse.SUPPRESS, help="Name or path of a repository to init") p_init.set_defaults(func=c_init) # add command parser p_add = subparsers.add_parser("add", help=c_add.__doc__.lower()) p_add.add_argument("-p", "--preserve", action="store_true", default=False, help="don't remove image after adding to database") p_add.add_argument("path", nargs="+") p_add.set_defaults(func=c_add) # del command parser p_del = subparsers.add_parser("del", help=c_del.__doc__.lower()) p_del.add_argument("image_name") p_del.add_argument("image_version") p_del.set_defaults(func=c_del) # install command parser p_install = subparsers.add_parser("install", add_help=False, help=c_install.__doc__.lower()) p_install.add_argument("-f", "--force", action="store_true", default=False, help="overwrite existing image") p_install.add_argument("-v", "--image-version", type=int, default=None, help="image version") p_install.add_argument("image", help="image to install (path or name)") p_install.set_defaults(func=c_install, subparser=p_install) # list command parser p_list = subparsers.add_parser("list", help=c_list.__doc__.lower()) p_list.add_argument("-l", action="store_true", dest="detail", default=False, help="detailled list output") p_list.add_argument("values", nargs="*", help="image or repositories to list") p_list.set_defaults(func=c_list, subparser=p_list) # update command parser p_update = subparsers.add_parser("update", help=c_update.__doc__.lower()) p_update.add_argument("-f", "--force", action="store_true", default=False, help="overwrite existing image") p_update.add_argument("-c", "--no-check", action="store_true", default=False, help="do not check compilation before adding scripts") p_update.add_argument("-p", "--preserve", action="store_true", default=False, help="don't remove image after adding to database") p_update.add_argument("path", nargs="?", default=".") p_update.set_defaults(func=c_update) # cat command parser p_cat = subparsers.add_parser("cat", help=c_cat.__doc__.lower()) p_cat.add_argument("-v", "--image-version", type=int, default=None, help="image version") p_cat.add_argument("image", help="image (path or name)") p_cat.add_argument("files", nargs="+", help="files to cat") p_cat.set_defaults(func=c_cat) # search command parser p_search = subparsers.add_parser("search", help=c_search.__doc__.lower()) p_search.add_argument("pattern", help="search pattern in repository") p_search.set_defaults(func=c_search) # get command parser p_get = subparsers.add_parser("get", help=c_get.__doc__.lower()) p_get.set_defaults(func=c_get) # clean command parser p_clean = subparsers.add_parser("clean", help=c_clean.__doc__.lower()) p_clean.set_defaults(func=c_clean) # copy command parser p_copy = subparsers.add_parser("copy", help=c_copy.__doc__.lower()) p_copy.add_argument("repo_src", help="name of source repository") p_copy.add_argument("repo_dst", help="name of destination repository") p_copy.add_argument("image", help="image name") p_copy.add_argument("image_version", nargs="?", help="image version") p_copy.set_defaults(func=c_copy) # help command parser p_help = subparsers.add_parser("help", help=c_help.__doc__.lower()) p_help.add_argument("command", choices=subparsers.choices, nargs="?", help="command name") p_help.set_defaults(func=c_help, subparser=subparsers) # version command parser p_version = subparsers.add_parser("version", help=c_version.__doc__.lower()) p_version.set_defaults(func=c_version) try: # Parse and run args = p_main.parse_known_args()[0] # set debug and quiet mode before merge installsystems.debug = args.debug installsystems.quiet = args.quiet # load isinstall config config = MainConfigFile(args.config, "installsystems") config.merge(args) # set debug and quiet mode after merge installsystems.debug = args.debug installsystems.quiet = args.quiet if args.func is not c_install: args = p_main.parse_args(namespace=args) # let's go args.func(p_main, args) except Exception as e: error(e) except KeyboardInterrupt: warn("Keyboard Interrupted")