예제 #1
0
    def test_watch_tasks_with_keyboardinterrupt_handler(self, stdout, sleep):
        """Raise KeyboardInterrupt inner watch_tasks with a ki_handler"""
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        cdata = koji.load_json(cfile)
        self.session.load_calls(cdata)
        sleep.side_effect = [None] * 10 + [KeyboardInterrupt]

        def customized_handler(progname, tasks, quiet):
            print('some output')

        with self.assertRaises(KeyboardInterrupt):
            # watch_tasks catches and re-raises it to display a message
            watch_tasks(self.session, [1208],
                        quiet=False,
                        poll_interval=5,
                        ki_handler=customized_handler,
                        topurl=self.options.topurl)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
some output
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #2
0
    def test_watch_tasks_with_keyboardinterrupt(self, dtrMock, dtsMock,
                                                twClzMock, stdout):
        """Raise KeyboardInterrupt inner watch_tasks.
        Raising it by SIGNAL might be better"""
        self.options.poll_interval = 0
        manager = mock.MagicMock()
        manager.attach_mock(twClzMock, 'TaskWatcherMock')
        manager.attach_mock(dtrMock, 'display_task_results_mock')
        manager.attach_mock(dtsMock, 'display_tasklist_status_mock')
        tw1 = manager.tw1
        tw1.level = 0
        tw1.is_done.side_effect = [False, KeyboardInterrupt, False]
        tw1.update.side_effect = [False, False]
        tw1.is_success.return_value = False
        tw1.str.return_value = 'tw1'
        tw1.display_state.return_value = 'tw1.display_state'
        tw2 = manager.tw2
        tw2.level = 0
        tw2.is_done.side_effect = [False, False, False, False, True]
        tw2.update.side_effect = [True, False, False, True, True]
        tw2.is_success.return_value = False
        tw2.str.return_value = 'tw2'
        tw2.display_state.return_value = 'tw2.display_state'
        self.session.getTaskChildren.side_effect = lambda p: [{
            'id': 11
        }, {
            'id': 12
        }] if (0 == p) else []
        manager.attach_mock(self.session, 'sessionMock')

        def side_effect(*args, **kwargs):
            rt = None
            if args[0] not in list(range(2)):
                rt = mock.MagicMock()
                rt.level = args[2]
                rt.is_done.return_value = True
                rt.update.return_value = True
                rt.is_success.return_value = True
                manager.attach_mock(rt, 'tw' + str(args[0]))
            else:
                rt = {0: tw1, 1: tw2}.get(args[0])
            return rt

        twClzMock.side_effect = side_effect

        with self.assertRaises(KeyboardInterrupt):
            watch_tasks(self.session,
                        list(range(2)),
                        quiet=False,
                        poll_interval=0)

        actual = stdout.getvalue()
        self.assertMultiLineEqual(
            actual, """Watching tasks (this may be safely interrupted)...
Tasks still running. You can continue to watch with the '%s watch-task' command.
Running Tasks:
tw1: tw1.display_state
tw2: tw2.display_state
""" % (os.path.basename(sys.argv[0]) or 'koji'))
예제 #3
0
def replicate_build_task(session, task, options):
    if isinstance(task, six.integer_types):
        task = session.getTaskInfo(task, request=True)
    task_id = task['id']
    logger.info("%i: Looking at task", task_id)
    if task['parent'] is not None:
        raise koji.GenericError("%(id)i: not a parent task" % task)
    if task['method'] == 'build':
        params = replicate_build_request(session, task, options)
    # TODO: ONLY build task is supported right now
    # elif task['method'] in ['image', 'livemedia', 'livecd', 'appliance']:
    #     params = replicate_image_request(session, task, options)
    else:
        raise koji.GenericError("%(id)i: can not replicate %(method)s task" %
                                task)
    channel = task['channel_id']
    if options.channel_override:
        channel = options.channel_override
    new_task_id = session.makeTask(task['method'],
                                   koji.encode_args(**params),
                                   channel=channel)
    logger.info("Original task %i replicated as task %i", task_id, new_task_id)
    rv = watch_tasks(session, [new_task_id], quiet=options.quiet)
    # always True
    return True
예제 #4
0
def ensure_tagged(buildinfo, tags, session, dryrun):
    """
    Ensure this build is tagged into Koji.

    :param dict buildinfo: dict from getBuild with this name/version/release
    :param list tags: list of tags for this build.
    :param session: Koji session
    :param bool dryrun: show what would happen, but don't do it.
    """
    task_ids = []
    nvr = '%(name)s-%(version)s-%(release)s' % buildinfo
    for tag in sorted(tags):
        tagged_builds = session.listTagged(tag,
                                           package=buildinfo['name'],
                                           type='debian')
        tagged_nvrs = [tagged_build['nvr'] for tagged_build in tagged_builds]
        if nvr in tagged_nvrs:
            log.info('%s is already tagged into %s' % (nvr, tag))
            continue
        log.info('tagging %s into %s' % (nvr, tag))
        if dryrun:
            continue
        task_id = session.tagBuild(tag, nvr)
        task_ids.append(task_id)
    if not task_ids:
        # This build is already tagged into all the necessary tags.
        return
    task_result = watch_tasks(session, task_ids, poll_interval=15)
    if task_result != 0 and not dryrun:
        raise RuntimeError('failed to tag build %s' % nvr)
예제 #5
0
def handle_save_failed_tree(options, session, args):
    "Create tarball with whole buildtree"
    usage = "usage: %prog save-failed-tree [options] ID"
    usage += "\n(Specify the --help global option for a list of other help options)"
    parser = OptionParser(usage=usage)
    parser.add_option("-f", "--full", action="store_true", default=False,
                      help="Download whole tree, if not specified, "
                           "only builddir will be downloaded")
    parser.add_option("-t", "--task", action="store_const", dest="mode", const="task",
                      default="task", help="Treat ID as a task ID (the default)")
    parser.add_option("-r", "--buildroot", action="store_const", dest="mode",
                      const="buildroot", help="Treat ID as a buildroot ID")
    parser.add_option("--quiet", action="store_true", default=options.quiet,
                      help="Do not print the task information")
    parser.add_option("--nowait", action="store_true", help="Don't wait on build")

    (opts, args) = parser.parse_args(args)

    if len(args) != 1:
        parser.error("List exactly one task or buildroot ID")

    try:
        id_val = int(args[0])
    except ValueError:
        parser.error("ID must be an integer")

    activate_session(session, options)

    if opts.mode == "buildroot":
        br_id = id_val
    else:
        brs = [b['id'] for b in session.listBuildroots(taskID=id_val)]
        if not brs:
            print("No buildroots for task %s" % id_val)
            return 1
        br_id = max(brs)
        if len(brs) > 1:
            print("Multiple buildroots for task. Choosing last one (%s)" % br_id)

    try:
        task_id = session.saveFailedTree(br_id, opts.full)
    except koji.GenericError as e:
        m = str(e)
        if 'Invalid method' in m:
            print("* The save_failed_tree plugin appears to not be installed on the koji hub.  "
                  "Please contact the administrator.")
            return 1
        raise

    if not opts.quiet:
        print("Created task %s for buildroot %s" % (task_id, br_id))
        print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))

    if opts.nowait:
        return
    else:
        session.logout()
        return watch_tasks(session, [task_id],
                           quiet=opts.quiet, poll_interval=options.poll_interval,
                           topurl=options.topurl)
예제 #6
0
 def test_watch_tasks_no_tasklist(self, stdout):
     returned = watch_tasks(self.session, [],
                            poll_interval=0,
                            topurl=self.options.topurl)
     actual = stdout.getvalue()
     expected = ""
     self.assertIsNone(returned)
     self.assertEqual(actual, expected)
예제 #7
0
def tag_build(buildinfo, tag, session):
    """ Tag this build in Koji. """
    nvr = '%(name)s-%(version)s-%(release)s' % buildinfo
    log.info('tagging %s into %s' % (nvr, tag))
    task_id = session.tagBuild(tag, nvr)
    task_result = watch_tasks(session, [task_id], poll_interval=15)
    if task_result != 0:
        raise RuntimeError('failed to tag builds')
예제 #8
0
 def watch_task(self, id_, interval=5):
     """ Watch a Koji task ID, printing its state transitions to STDOUT """
     weburl = self.session.opts['weburl']
     url = posixpath.join(weburl, 'taskinfo?taskID=%s' % id_)
     print('Watching Koji task %s' % url)
     task_result = watch_tasks(self.session, [id_], poll_interval=interval)
     if task_result != 0:
         raise RuntimeError('failed buildContainer task')
예제 #9
0
def handle_osbuild_image(options, session, argv):
    "[build] Build images via osbuild"
    args = parse_args(argv)

    name, version, arch, target = args.name, args.version, args.arch, args.target
    distro, image_types = args.distro, args.image_type

    if not image_types:
        image_types = ["qcow2"]

    opts = {}

    if args.release:
        opts["release"] = args.release

    if args.repo:
        opts["repo"] = ",".join(args.repo)

    # Do some early checks to be able to give quick feedback
    check_target(session, target)

    if not options.quiet:
        print("name:", name)
        print("version:", version)
        print("distro:", distro)
        print("arches:", ", ".join(arch))
        print("target:", target)
        print("image types ", str(image_types))
        pprint(opts)

    kl.activate_session(session, options)

    task_id = session.osbuildImage(name,
                                   version,
                                   distro,
                                   image_types,
                                   target,
                                   arch,
                                   opts=opts)

    if not options.quiet:
        print("Created task: %s" % task_id)
        print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))

    # pylint: disable=protected-access
    if (args.wait is None and kl._running_in_bg()) or args.wait is False:
        # either running in the background or must not wait by user's
        # request. All done.
        return None

    session.logout()
    res = kl.watch_tasks(session, [task_id], quiet=options.quiet)

    if res == 0:
        result = session.getTaskResult(task_id)
        print(result)
    return res
예제 #10
0
def handle_build(options, session, args, flatpak=False, sourcebuild=False):
    if sourcebuild:
        build_opts, args, opts, parser = parse_source_arguments(options, args)
    else:
        build_opts, args, opts, parser = parse_arguments(
            options, args, flatpak)

    activate_session(session, options)

    target = args[0]
    build_target = session.getBuildTarget(target)
    if not build_target:
        parser.error(_("Unknown build target: %s" % target))
    dest_tag = session.getTag(build_target['dest_tag'])
    if not dest_tag:
        parser.error(
            _("Unknown destination tag: %s" % build_target['dest_tag_name']))
    if dest_tag['locked'] and not build_opts.scratch:
        parser.error(_("Destination tag %s is locked" % dest_tag['name']))

    priority = None
    if build_opts.background:
        # relative to koji.PRIO_DEFAULT
        priority = 5

    if sourcebuild:
        task_id = session.buildSourceContainer(
            target,
            opts,
            priority=priority,
            channel=build_opts.channel_override)
    else:
        source = args[1]
        task_id = session.buildContainer(source,
                                         target,
                                         opts,
                                         priority=priority,
                                         channel=build_opts.channel_override)

    if not build_opts.quiet:
        print("Created task: %s" % task_id)
        print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))
    if build_opts.wait or (build_opts.wait is None and not _running_in_bg()):
        session.logout()
        rv = watch_tasks(session, [task_id], quiet=build_opts.quiet)

        # Task completed and a result should be available.
        if rv == 0:
            result = session.getTaskResult(task_id)
            print_task_result(task_id, result, options.weburl)

        return rv
    else:
        return
def handle_build(options, session, args, flatpak):
    build_opts, args, opts, parser = parse_arguments(options, args, flatpak)

    activate_session(session, options)

    target = args[0]
    if target.lower() == "none" and build_opts.repo_id:
        target = None
        build_opts.skip_tag = True
    else:
        build_target = session.getBuildTarget(target)
        if not build_target:
            parser.error(_("Unknown build target: %s" % target))
        dest_tag = session.getTag(build_target['dest_tag'])
        if not dest_tag:
            parser.error(
                _("Unknown destination tag: %s" %
                  build_target['dest_tag_name']))
        if dest_tag['locked'] and not build_opts.scratch:
            parser.error(_("Destination tag %s is locked" % dest_tag['name']))
    source = args[1]

    priority = None
    if build_opts.background:
        # relative to koji.PRIO_DEFAULT
        priority = 5
    if '://' not in source:
        parser.error(
            _("scm URL does not look like an URL to a source repository"))
    if '#' not in source:
        parser.error(
            _("scm URL must be of the form <url_to_repository>#<revision>)"))
    task_id = session.buildContainer(source,
                                     target,
                                     opts,
                                     priority=priority,
                                     channel=build_opts.channel_override)
    if not build_opts.quiet:
        print("Created task: %s" % task_id)
        print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))
    if build_opts.wait or (build_opts.wait is None and not _running_in_bg()):
        session.logout()
        rv = watch_tasks(session, [task_id], quiet=build_opts.quiet)

        # Task completed and a result should be available.
        if rv == 0:
            result = session.getTaskResult(task_id)
            print_task_result(task_id, result, options.weburl)

        return rv
    else:
        return
예제 #12
0
    def test_watch_tasks_with_keyboardinterrupt(self, stdout, sleep):
        """Raise KeyboardInterrupt inner watch_tasks.
        Raising it by SIGNAL might be better"""
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        sleep.side_effect = [None] * 10  + [KeyboardInterrupt]
        with self.assertRaises(KeyboardInterrupt):
            # watch_tasks catches and re-raises it to display a message
            watch_tasks(self.session, [1208], quiet=False, poll_interval=5)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
Tasks still running. You can continue to watch with the '%s watch-task' command.
Running Tasks:
1208 build (f24, /users/mikem/fake.git:master): open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): open (builder-01)
''' % (os.path.basename(sys.argv[0]) or 'koji'))
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #13
0
    def test_watch_tasks_with_keyboardinterrupt(self, stdout, sleep):
        """Raise KeyboardInterrupt inner watch_tasks.
        Raising it by SIGNAL might be better"""
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        sleep.side_effect = [None] * 10 + [KeyboardInterrupt]
        with self.assertRaises(KeyboardInterrupt):
            # watch_tasks catches and re-raises it to display a message
            watch_tasks(self.session, [1208], quiet=False, poll_interval=5)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
Tasks still running. You can continue to watch with the '%s watch-task' command.
Running Tasks:
1208 build (f24, /users/mikem/fake.git:master): open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): open (builder-01)
''' % (os.path.basename(sys.argv[0]) or 'koji'))
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #14
0
    def wait_task_complete(self, task_id):
        """
        Wait until koji finsihes building task
        """
        while True:
            with redirect_stdout(this.logger):
                watch_tasks(self.hub, [task_id], poll_interval=10)
            taskinfo = self.hub.getTaskInfo(task_id)
            state = taskinfo['state']

            # /usr/lib/python3.8/site-packages/koji_cli/lib.py
            if state == koji.TASK_STATES['CLOSED']:
                this.logger.info("task completed successfully")
                return True
            if state == koji.TASK_STATES['FAILED']:
                this.logger.info("task failed")
                return False
            if state == koji.TASK_STATES['CANCELED']:
                this.logger.info("was canceled")
                return False
            # shouldn't happen
            this.logger.info("task has not completed yet")
예제 #15
0
def new_repo(session, tag, src_repo, orig_repo_id):
    # cloning
    # tag_id is the ID of cloned tag
    if tag:
        act_repo = session.getRepo(tag, event=None)
        if act_repo:
            REPOCACHE.setdefault(orig_repo_id, act_repo['id'])
            return session.repoInfo(act_repo['id'])
        event = None
    # reusing/refreshing
    else:
        if isinstance(src_repo, six.integer_types):
            src_repo = session.repoInfo(src_repo)
        if src_repo and isinstance(src_repo, dict):
            event = src_repo['create_event']
            tag = src_repo['tag_id']
    rtaskid = session.newRepo(tag, event=event)
    watch_tasks(session, [rtaskid])
    new_repo_id, event_id = session.getTaskResult(rtaskid)
    repo_info = session.repoInfo(new_repo_id)
    REPOCACHE.setdefault(orig_repo_id, new_repo_id)
    return repo_info
예제 #16
0
def new_build(profile='cbs', scratch=True):
    # Very ugly: some utilities are only available in koji CLI
    # and not in the koji module
    if not KOJI_AVAILABLE:
        raise ModuleNotAvailable(module='koji')
    if not RPM_AVAILABLE:
        raise RpmModuleNotAvailable()
    import imp
    kojibin = find_executable('koji')
    kojicli = imp.load_source('kojicli', kojibin)
    # Koji 1.13 moves client internal API into another path
    try:
        from koji_cli.lib import _unique_path, _progress_callback, watch_tasks
    except ImportError:
        from kojicli import _unique_path, _progress_callback, watch_tasks

    kojiclient = setup_kojiclient(profile)
    # Note: required to make watch_tasks work
    kojicli.options = opts = munchify(kojiclient.opts)
    build_target = guess_build()
    if not build_target:
        log.warn("failed to identify build tag from branch")
        return

    retrieve_sources()
    srpm = create_srpm()
    if not srpm:
        log.warn('No srpm available')
        return
    serverdir = _unique_path('cli-build')
    kojiclient.uploadWrapper(srpm, serverdir, callback=_progress_callback)
    source = "%s/%s" % (serverdir, os.path.basename(srpm))
    task_id = kojiclient.build(source, build_target, {'scratch': scratch})
    print("Created task:", task_id)

    print("Task info: {}/taskinfo?taskID={}".format(opts['weburl'], task_id))
    kojiclient.logout()
    watch_tasks(kojiclient, [task_id])
예제 #17
0
def new_build(profile='cbs', scratch=True):
    # Very ugly: some utilities are only available in koji CLI
    # and not in the koji module
    if not KOJI_AVAILABLE:
        raise ModuleNotAvailable(module='koji')
    if not RPM_AVAILABLE:
        raise RpmModuleNotAvailable()
    import imp
    kojibin = find_executable('koji')
    kojicli = imp.load_source('kojicli', kojibin)
    # Koji 1.13 moves client internal API into another path
    try:
        from koji_cli.lib import _unique_path, _progress_callback, watch_tasks
    except ImportError:
        from kojicli import _unique_path, _progress_callback, watch_tasks

    kojiclient = setup_kojiclient(profile)
    # Note: required to make watch_tasks work
    kojicli.options = opts = bunchify(kojiclient.opts)
    build_target = guess_build()
    if not build_target:
        log.warn("failed to identify build tag from branch")
        return

    retrieve_sources()
    srpm = create_srpm()
    if not srpm:
        log.warn('No srpm available')
        return
    serverdir = _unique_path('cli-build')
    kojiclient.uploadWrapper(srpm, serverdir, callback=_progress_callback)
    source = "%s/%s" % (serverdir, os.path.basename(srpm))
    task_id = kojiclient.build(source, build_target, {'scratch': scratch})
    print("Created task:", task_id)

    print("Task info: {}/taskinfo?taskID={}".format(opts['weburl'], task_id))
    kojiclient.logout()
    watch_tasks(kojiclient, [task_id])
예제 #18
0
 def watch_tasks_with_retry(self, tasks, max_retries=20, retry_interval=20):
     tries = 0
     while True:
         try:
             return kojicli.watch_tasks(self.kojisession, tasks)
         except kojilib.ServerOffline as err:
             # these have a large chance of being bogus
             log.info("Got error from server: %s", err)
             tries += 1
             if tries < max_retries:
                 log.info("Retrying in %d seconds", retry_interval)
                 time.sleep(retry_interval)
             else:
                 raise
예제 #19
0
    def test_watch_tasks_with_keyboardinterrupt_handler(self, stdout, sleep):
        """Raise KeyboardInterrupt inner watch_tasks with a ki_handler"""
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        sleep.side_effect = [None] * 10 + [KeyboardInterrupt]

        def customized_handler(progname, tasks, quiet):
            print('some output')

        with self.assertRaises(KeyboardInterrupt):
            # watch_tasks catches and re-raises it to display a message
            watch_tasks(self.session, [1208], quiet=False, poll_interval=5,
                        ki_handler=customized_handler)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
some output
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #20
0
    def test_watch_tasks(self, stdout):
        # self.setup_record('foo.json')
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks1.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        rv = watch_tasks(self.session, [1188], quiet=False, poll_interval=0)
        self.assertEqual(rv, 0)
        expected = ('''Watching tasks (this may be safely interrupted)...
1188 build (f24, /users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e): closed
  1189 buildSRPMFromSCM (/users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e): closed
  1190 buildArch (fake-1.1-21.src.rpm, noarch): closed

1188 build (f24, /users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e) completed successfully
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #21
0
    def test_watch_tasks(self, stdout):
        # self.setup_record('foo.json')
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks1.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        rv = watch_tasks(self.session, [1188], quiet=False, poll_interval=0)
        self.assertEqual(rv, 0)
        expected = (
'''Watching tasks (this may be safely interrupted)...
1188 build (f24, /users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e): closed
  1189 buildSRPMFromSCM (/users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e): closed
  1190 buildArch (fake-1.1-21.src.rpm, noarch): closed

1188 build (f24, /users/mikem/fake.git:adaf62586b4b4a23b24394da5586abd7cd9f679e) completed successfully
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
def handle_build(options, session, args, flatpak):
    build_opts, args, opts, parser = parse_arguments(options, args, flatpak)

    activate_session(session, options)

    target = args[0]
    build_target = session.getBuildTarget(target)
    if not build_target:
        parser.error(_("Unknown build target: %s" % target))
    dest_tag = session.getTag(build_target['dest_tag'])
    if not dest_tag:
        parser.error(_("Unknown destination tag: %s" %
                       build_target['dest_tag_name']))
    if dest_tag['locked'] and not build_opts.scratch:
        parser.error(_("Destination tag %s is locked" % dest_tag['name']))

    source = args[1]

    priority = None
    if build_opts.background:
        # relative to koji.PRIO_DEFAULT
        priority = 5
    if '://' not in source:
        parser.error(_("scm URL does not look like an URL to a source repository"))
    if '#' not in source:
        parser.error(_("scm URL must be of the form <url_to_repository>#<revision>)"))
    task_id = session.buildContainer(source, target, opts, priority=priority,
                                     channel=build_opts.channel_override)
    if not build_opts.quiet:
        print("Created task: %s" % task_id)
        print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id))
    if build_opts.wait or (build_opts.wait is None and not _running_in_bg()):
        session.logout()
        rv = watch_tasks(session, [task_id], quiet=build_opts.quiet)

        # Task completed and a result should be available.
        if rv == 0:
            result = session.getTaskResult(task_id)
            print_task_result(task_id, result, options.weburl)

        return rv
    else:
        return
예제 #23
0
    def test_watch_tasks_fail(self, stdout, sleep):
        # self.setup_record('foo.json')
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        rv = watch_tasks(self.session, [1208], quiet=False, poll_interval=5)
        self.assertEqual(rv, 1)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
1208 build (f24, /users/mikem/fake.git:master): open (builder-01) -> FAILED: GenericError: Build already exists (id=425, state=COMPLETE): {'name': 'fake', 'task_id': 1208, 'extra': None, 'pkg_id': 298, 'epoch': 7, 'completion_time': None, 'state': 0, 'version': '1.1', 'source': None, 'volume_id': 0, 'owner': 1, 'release': '22', 'start_time': 'NOW'}
  0 free  1 open  0 done  1 failed
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): open (builder-01) -> closed
  0 free  0 open  1 done  1 failed

1208 build (f24, /users/mikem/fake.git:master) failed
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #24
0
    def test_watch_tasks_fail(self, stdout, sleep):
        # self.setup_record('foo.json')
        cfile = os.path.dirname(__file__) + '/data/calls/watchtasks2.json'
        with open(cfile) as fp:
            cdata = json.load(fp)
        self.session.load_calls(cdata)
        rv = watch_tasks(self.session, [1208], quiet=False, poll_interval=5, topurl=None)
        self.assertEqual(rv, 1)
        expected = ('''Watching tasks (this may be safely interrupted)...
1208 build (f24, /users/mikem/fake.git:master): free
1208 build (f24, /users/mikem/fake.git:master): free -> open (builder-01)
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): free -> open (builder-01)
1208 build (f24, /users/mikem/fake.git:master): open (builder-01) -> FAILED: GenericError: Build already exists (id=425, state=COMPLETE): {'name': 'fake', 'task_id': 1208, 'extra': None, 'pkg_id': 298, 'epoch': 7, 'completion_time': None, 'state': 0, 'version': '1.1', 'source': None, 'volume_id': 0, 'owner': 1, 'release': '22', 'start_time': 'NOW'}
  0 free  1 open  0 done  1 failed
  1209 buildSRPMFromSCM (/users/mikem/fake.git:master): open (builder-01) -> closed
  0 free  0 open  1 done  1 failed

1208 build (f24, /users/mikem/fake.git:master) failed
''')
        self.assertMultiLineEqual(stdout.getvalue(), expected)
예제 #25
0
 def test_watch_tasks_no_tasklist(self, stdout):
     returned = watch_tasks(self.session, [], poll_interval=0)
     actual = stdout.getvalue()
     expected = ""
     self.assertIsNone(returned)
     self.assertEqual(actual, expected)
    def process(self, message: fedora_messaging.api.Message):
        logger.debug(message.topic)
        logger.debug(message.body)

        # Grab the raw message body and the status from that
        msg = message.body
        branch = msg['ref']
        repo = msg['repository']['full_name']

        if (repo != self.github_repo_fullname):
            logger.info(f'Skipping message from unrelated repo: {repo}')
            return

        if (branch != self.github_repo_branch):
            logger.info(f'Skipping message from unrelated branch: {branch}')
            return

        # Some messages don't have commit information
        # For example: https://apps.fedoraproject.org/datagrepper/id?id=2019-f32c811b-658b-4ac7-a455-a7edf616a033&is_raw=true&size=extra-large
        commit = None
        if msg['head_commit']:
            commit = msg['head_commit']['id']
        if commit is None:
            logger.error('No commit id in message!')
            return

        # Now grab lockfile data from the commit we should operate on:
        desiredrpms = set()
        for arch in ['x86_64', 'aarch64', 'ppc64le', 's390x']:
            for lockfile in ['manifest-lock', 'manifest-lock.overrides']:
                url = f'https://raw.githubusercontent.com/{repo}/{commit}/{lockfile}.{arch}.json'
                logger.info(f'Attempting to retrieve data from {url}')
                r = requests.get(url)
                if r.ok:
                    # parse the lockfile and add the set of rpm NEVRAs (strings)
                    desiredrpms.update(parse_lockfile_data(r.text))
                else:
                    # Log any errors we encounter. 404s are ok, but won't hurt to log
                    logger.warn('URL request error: %s' % r.text.strip())

        # NOMENCLATURE:
        #
        # In koji there is the concept of a pkg and a build. A pkg
        # is a piece of software (i.e. kernel) whereas a build is a
        # specific build of that software that is unique by NVR (i.e.
        # kernel-5.0.17-300.fc30). RPMs are output of a build. There
        # can be many rpms (including subpackages) output from a build
        # (for example kernel-5.0.17-300.fc30.x86_64.rpm and
        # kernel-devel-5.0.17-300.fc30.x86_64.rpm). So we have:
        #
        # kernel                              --> koji pkg
        # kernel-5.0.17-300.fc30              --> koji build (matches srpm name)
        # kernel-5.0.17-300.fc30.x86_64       --> main rpm package
        # kernel-devel-5.0.17-300.fc30.x86_64 --> rpm subpackage
        #
        # STRATEGY:
        #
        # The lockfile input gives a list of rpm names in NEVRA format. We
        # must derive the srpm name (koji build name) from that and compare
        # that with existing koji builds in the tag. Once we have a list of
        # koji builds that aren't in the tag we can add the koji pkg to the
        # tag (if needed) and then tag the koji build into the tag.

        # convert the NEVRAs into a dict of build IDs -> BuildInfo objects
        buildsinfo = self.get_buildsinfo_from_rpmnevras(desiredrpms)
        desiredbuildids = buildsinfo.keys()

        # Grab the build IDs of currently tagged builds
        currentbuildids = self.get_tagged_buildids(self.target_tag)

        # Get the set of names of pkgs needed
        desiredpkgs = set([x.name for x in buildsinfo.values()])

        # Grab the set of names of pkgs that can be tagged into the tag
        pkgsintag = self.get_pkglist_in_tag(self.target_tag)

        # compute the pkgstoadd and the buildstotag
        pkgstoadd = desiredpkgs - pkgsintag
        buildstotag = desiredbuildids - currentbuildids

        # Log if there is nothing to do
        if not pkgstoadd and not buildstotag:
            logger.info(f'No new builds to tag.. going back to sleep')
            return

        # Make sure all packages desired are in the pkglist
        if pkgstoadd:
            logger.info('Adding packages to the '
                        f'{self.target_tag} tag: {pkgstoadd}')
            if self.keytab_file:
                with self.koji_client.multicall(strict=True) as m:
                    for pkg in pkgstoadd:
                        m.packageListAdd(self.target_tag,
                                         pkg,
                                         owner=self.koji_user)
                logger.info('Package adding done')

        # Perform the tagging for each release into the intermediate
        # tag for that release if we have credentials
        if buildstotag:
            # Get a set of tuples of build name to tag to tag into
            tuples = [(self.intermediate_tag.format(
                releasever=buildsinfo[x].releasever), buildsinfo[x].nvr)
                      for x in buildstotag]
            logger.info('Tagging the following (tag, nvr): \n\t%s' %
                        '\n\t'.join(map(str, tuples)))
            if self.keytab_file:
                with self.koji_client.multicall(strict=True) as m:
                    tasks = [
                        m.tagBuild(tag=tag, build=nvr) for (tag, nvr) in tuples
                    ]
                watch_tasks(self.koji_client, [task.result for task in tasks],
                            poll_interval=10)
                logger.info('Tagging done')
예제 #27
0
def watch_scratch_build(session, task_id):
    error = watch_tasks(session, [task_id], poll_interval=4)
    if error:
        raise RuntimeError('scratch build failed')
예제 #28
0
    def process_lockfiles(self, rev):
        # Now grab lockfile data from the commit we should operate on:
        desiredrpms = set()
        for arch in ['x86_64', 'aarch64', 'ppc64le', 's390x']:
            for lockfile in ['manifest-lock', 'manifest-lock.overrides']:
                for filetype in ['yaml', 'json']:
                    url = f'https://raw.githubusercontent.com/{self.github_repo_fullname}/{rev}/{lockfile}.{arch}.{filetype}'
                    logger.info(f'Attempting to retrieve data from {url}')
                    r = requests.get(url)
                    if r.ok:
                        # parse the lockfile and add the set of rpm NEVRAs (strings)
                        desiredrpms.update(
                            parse_lockfile_data(r.text, filetype))
                        break  # If both yaml and json files exist, only parse one
                        # of them. Prefer yaml.
                    else:
                        # Log any errors we encounter. 404s are ok, but won't hurt to log
                        logger.warning('URL request error: %s' %
                                       r.text.strip())
        if not desiredrpms:
            logger.warning('No locked RPMs found!')
            logger.warning("Does the repo:ref (%s:%s) have any lockfiles?" %
                           (self.github_repo_fullname, rev))
            logger.warning('Continuing...')
            return

        # NOMENCLATURE:
        #
        # In koji there is the concept of a pkg and a build. A pkg
        # is a piece of software (i.e. kernel) whereas a build is a
        # specific build of that software that is unique by NVR (i.e.
        # kernel-5.0.17-300.fc30). RPMs are output of a build. There
        # can be many rpms (including subpackages) output from a build
        # (for example kernel-5.0.17-300.fc30.x86_64.rpm and
        # kernel-devel-5.0.17-300.fc30.x86_64.rpm). So we have:
        #
        # kernel                              --> koji pkg
        # kernel-5.0.17-300.fc30              --> koji build (matches srpm name)
        # kernel-5.0.17-300.fc30.x86_64       --> main rpm package
        # kernel-devel-5.0.17-300.fc30.x86_64 --> rpm subpackage
        #
        # STRATEGY:
        #
        # The lockfile input gives a list of rpm names in NEVRA format. We
        # must derive the srpm name (koji build name) from that and compare
        # that with existing koji builds in the tag. Once we have a list of
        # koji builds that aren't in the tag we can add the koji pkg to the
        # tag (if needed) and then tag the koji build into the tag.

        # convert the NEVRAs into a dict of build IDs -> BuildInfo objects
        buildsinfo = self.get_buildsinfo_from_rpmnevras(desiredrpms)
        desiredbuildids = buildsinfo.keys()

        # Grab the build IDs of currently tagged builds
        currentbuildids = self.get_tagged_buildids(self.target_tag)

        # Get the set of names of pkgs needed
        desiredpkgs = set([x.name for x in buildsinfo.values()])

        # Grab the set of names of pkgs that can be tagged into the tag
        pkgsintag = self.get_pkglist_in_tag(self.target_tag)

        # compute the pkgstoadd and the buildstotag
        pkgstoadd = desiredpkgs - pkgsintag
        buildstotag = desiredbuildids - currentbuildids

        # Log if there is nothing to do
        if not pkgstoadd and not buildstotag:
            logger.info(f'No new builds to tag.. going back to sleep')
            return

        # Make sure all packages desired are in the pkglist
        if pkgstoadd:
            logger.info('Adding packages to the '
                        f'{self.target_tag} tag: {pkgstoadd}')
            if self.keytab_file:
                # pylint: disable=E1102
                with self.koji_client.multicall(strict=True) as m:
                    for pkg in pkgstoadd:
                        m.packageListAdd(self.target_tag,
                                         pkg,
                                         owner=self.koji_user)
                logger.info('Package adding done')

        # Perform the tagging for each release into the intermediate
        # tag for that release if we have credentials
        if buildstotag:
            # Get a set of tuples of build name to tag to tag into
            tuples = [(self.intermediate_tag.format(
                releasever=buildsinfo[x].releasever), buildsinfo[x].nvr)
                      for x in buildstotag]
            logger.info('Tagging the following (tag, nvr): \n\t%s' %
                        '\n\t'.join(map(str, tuples)))
            if self.keytab_file:
                # pylint: disable=E1102
                with self.koji_client.multicall(strict=True) as m:
                    tasks = [
                        m.tagBuild(tag=tag, build=nvr) for (tag, nvr) in tuples
                    ]
                watch_tasks(self.koji_client, [task.result for task in tasks],
                            poll_interval=10)
                logger.info('Tagging done')

                # Subsequently run a distrepo task because there are
                # races in tag2distrepo. https://pagure.io/koji/issue/1630
                # Before running distrepo let's wait for all rpms to
                # pass through signing and make it into the target tag
                #
                # If not done in ten minutes then just timeout (60*10s = 10 minutes)
                for x in range(0, 60):
                    currentbuildids = self.get_tagged_buildids(self.target_tag)
                    difference = desiredbuildids - currentbuildids
                    if difference:
                        logger.info('Waiting on builds to be signed')
                        logger.info('Remaining builds: %s' %
                                    [buildsinfo[x].nvr for x in difference])
                        time.sleep(10)
                        continue
                    break
                # If all the builds didn't make it into the target
                # then just return here.
                if difference:
                    logger.error('Some builds never got signed..  Giving up')
                    return
                # This code is mostly stolen from:
                # https://pagure.io/releng/tag2distrepo/blob/master/f/tag2distrepo.py
                taginfo = self.koji_client.getTag(self.target_tag)
                keys = taginfo['extra'].get("tag2distrepo.keys", '').split()
                task_opts = {
                    'arch': taginfo['arches'].split(),
                    'comp': None,
                    'delta': [],
                    'event': None,
                    'inherit': False,
                    'latest': False,
                    'multilib': False,
                    'split_debuginfo': False,
                    'skip_missing_signatures': False,
                    'allow_missing_signatures': False,
                }
                task = self.koji_client.distRepo(self.target_tag, keys,
                                                 **task_opts)
                watch_tasks(self.koji_client, [task], poll_interval=10)
                logger.info('Dist-repo task has finished')
예제 #29
0
        "-o",
        "--output",
        help="Add output to the specified file",
        default=None,
    )

    args = parser.parse_args()

    logger = configure_logging(verbose=args.verbose, output=args.output)
    build = session.getBuild(args.build_id)

    package = build["name"]
    source = build["source"]

    if not is_eln(package):
        logger.info("{0} is not in ELN".format(package))
        exit(0)

    task_id = rebuild_source(source, scratch=args.scratch)

    info_fmt = ("{0}\n"
                "https://koji.fedoraproject.org/koji/taskinfo?taskID={1}\n\n"
                "{2}\n")
    logger.info(info_fmt.format(package, task_id, source))

    if task_id and args.wait:
        with redirect_stdout(logger):
            rv = watch_tasks(session, [task_id], poll_interval=10)

        exit(rv)
예제 #30
0
 def watch_tasks(self, tasks):
     return kojicli.watch_tasks(self.kojisession, tasks)
예제 #31
0
    def test_watch_tasks(self, dtrMock, dtsMock, twClzMock, stdout):
        self.options.poll_interval = 0
        manager = mock.MagicMock()
        manager.attach_mock(twClzMock, 'TaskWatcherMock')
        manager.attach_mock(dtrMock, 'display_task_results_mock')
        manager.attach_mock(dtsMock, 'display_tasklist_status_mock')
        tw1 = manager.tw1
        tw1.level = 0
        tw1.is_done.side_effect = [False, True, False, True, True]
        tw1.update.side_effect = [False, False, True, True, True]
        tw1.is_success.return_value = False
        tw2 = manager.tw2
        tw2.level = 0
        tw2.is_done.side_effect = [False, False, False, False, True]
        tw2.update.side_effect = [True, False, False, True, True]
        tw2.is_success.return_value = False
        self.session.getTaskChildren.side_effect = lambda p: [{
            'id': 11
        }, {
            'id': 12
        }] if (0 == p) else []
        manager.attach_mock(self.session, 'sessionMock')

        def side_effect(*args, **kwargs):
            rt = None
            if args[0] not in list(range(2)):
                rt = mock.MagicMock()
                rt.level = args[2]
                rt.is_done.return_value = True
                rt.update.return_value = True
                rt.is_success.return_value = True
                manager.attach_mock(rt, 'tw' + str(args[0]))
            else:
                rt = {0: tw1, 1: tw2}.get(args[0])
            return rt

        twClzMock.side_effect = side_effect
        rv = watch_tasks(self.session,
                         list(range(2)),
                         quiet=False,
                         poll_interval=0)
        actual = stdout.getvalue()
        self.assertMultiLineEqual(
            actual, "Watching tasks (this may be safely interrupted)...\n\n")
        self.assertEqual(rv, 1)
        self.assertEqual(manager.mock_calls, [
            call.TaskWatcherMock(0, self.session, quiet=False),
            call.TaskWatcherMock(1, self.session, quiet=False),
            call.tw1.update(),
            call.tw1.is_done(),
            call.sessionMock.getTaskChildren(0),
            call.TaskWatcherMock(11, self.session, 1, quiet=False),
            call.tw11.update(),
            call.TaskWatcherMock(12, self.session, 1, quiet=False),
            call.tw12.update(),
            call.tw2.update(),
            call.tw2.is_done(),
            call.sessionMock.getTaskChildren(1),
            call.tw1.update(),
            call.tw1.is_done(),
            call.tw1.is_success(),
            call.sessionMock.getTaskChildren(0),
            call.tw2.update(),
            call.tw2.is_done(),
            call.sessionMock.getTaskChildren(1),
            call.tw11.update(),
            call.tw11.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw11.is_success(),
            call.sessionMock.getTaskChildren(11),
            call.tw12.update(),
            call.tw12.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw12.is_success(),
            call.sessionMock.getTaskChildren(12),
            call.tw1.update(),
            call.tw1.is_done(),
            call.sessionMock.getTaskChildren(0),
            call.tw2.update(),
            call.tw2.is_done(),
            call.sessionMock.getTaskChildren(1),
            call.tw11.update(),
            call.tw11.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw11.is_success(),
            call.sessionMock.getTaskChildren(11),
            call.tw12.update(),
            call.tw12.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw12.is_success(),
            call.sessionMock.getTaskChildren(12),
            call.tw1.update(),
            call.tw1.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw1.is_success(),
            call.sessionMock.getTaskChildren(0),
            call.tw2.update(),
            call.tw2.is_done(),
            call.sessionMock.getTaskChildren(1),
            call.tw11.update(),
            call.tw11.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw11.is_success(),
            call.sessionMock.getTaskChildren(11),
            call.tw12.update(),
            call.tw12.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw12.is_success(),
            call.sessionMock.getTaskChildren(12),
            call.tw1.update(),
            call.tw1.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw1.is_success(),
            call.sessionMock.getTaskChildren(0),
            call.tw2.update(),
            call.tw2.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw2.is_success(),
            call.sessionMock.getTaskChildren(1),
            call.tw11.update(),
            call.tw11.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw11.is_success(),
            call.sessionMock.getTaskChildren(11),
            call.tw12.update(),
            call.tw12.is_done(),
            call.display_tasklist_status_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            }),
            call.tw12.is_success(),
            call.sessionMock.getTaskChildren(12),
            call.display_task_results_mock({
                0: tw1,
                1: tw2,
                11: manager.tw11,
                12: manager.tw12
            })
        ])
예제 #32
0
def handle_save_failed_tree(options, session, args):
    "Create tarball with whole buildtree"
    usage = _("usage: %prog save-failed-tree [options] ID")
    usage += _("\n(Specify the --help global option for a list of other help options)")
    parser = OptionParser(usage=usage)
    parser.add_option("-f", "--full", action="store_true", default=False,
            help=_("Download whole tree, if not specified, only builddir will be downloaded"))
    parser.add_option("-t", "--task", action="store_const", dest="mode",
            const="task", default="task",
            help=_("Treat ID as a task ID (the default)"))
    parser.add_option("-r", "--buildroot", action="store_const", dest="mode",
            const="buildroot",
            help=_("Treat ID as a buildroot ID"))
    parser.add_option("--quiet", action="store_true", default=options.quiet,
                      help=_("Do not print the task information"))
    parser.add_option("--nowait", action="store_true",
                      help=_("Don't wait on build"))

    (opts, args) = parser.parse_args(args)

    if len(args) != 1:
        parser.error(_("List exactly one task or buildroot ID"))

    try:
        id_val = int(args[0])
    except ValueError:
        parser.error(_("ID must be an integer"))

    activate_session(session, options)

    if opts.mode == "buildroot":
        br_id = id_val
    else:
        brs = [b['id'] for b in session.listBuildroots(taskID=id_val)]
        if not brs:
            print(_("No buildroots for task %s") % id_val)
            return 1
        br_id = max(brs)
        if len(brs) > 1:
            print(_("Multiple buildroots for task. Choosing last one (%s)") % br_id)

    try:
        task_id = session.saveFailedTree(br_id, opts.full)
    except koji.GenericError as e:
        m = str(e)
        if 'Invalid method' in m:
            print(_("* The save_failed_tree plugin appears to not be "
                    "installed on the koji hub.  Please contact the "
                    "administrator."))
            return 1
        raise

    if not opts.quiet:
        print(_("Created task %s for buildroot %s") % (task_id, br_id))
        print("Task info: %s/taskinfo?taskID=%s"
                % (options.weburl, task_id))

    if opts.nowait:
        return
    else:
        session.logout()
        return watch_tasks(session, [task_id], quiet=opts.quiet, poll_interval=options.poll_interval)
예제 #33
0
def handle_runroot(options, session, args):
    "[admin] Run a command in a buildroot"
    usage = _("usage: %prog runroot [options] <tag> <arch> <command>")
    usage += _("\n(Specify the --help global option for a list of other help options)")
    parser = OptionParser(usage=usage)
    parser.disable_interspersed_args()
    parser.add_option("-p", "--package", action="append", default=[], help=_("make sure this package is in the chroot"))
    parser.add_option("-m", "--mount", action="append", default=[], help=_("mount this directory read-write in the chroot"))
    parser.add_option("--skip-setarch", action="store_true", default=False,
            help=_("bypass normal setarch in the chroot"))
    parser.add_option("-w", "--weight", type='int', help=_("set task weight"))
    parser.add_option("--channel-override", help=_("use a non-standard channel"))
    parser.add_option("--task-id", action="store_true", default=False,
            help=_("Print the ID of the runroot task"))
    parser.add_option("--use-shell", action="store_true", default=False,
            help=_("Run command through a shell, otherwise uses exec"))
    parser.add_option("--new-chroot", action="store_true", default=None,
            help=_("Run command with the --new-chroot (systemd-nspawn) option to mock"))
    parser.add_option("--old-chroot", action="store_false", default=None, dest='new_chroot',
            help=_("Run command with the --old-chroot (systemd-nspawn) option to mock"))
    parser.add_option("--repo-id", type="int", help=_("ID of the repo to use"))
    parser.add_option("--nowait", action="store_false", dest="wait",
            default=True, help=_("Do not wait on task"))
    parser.add_option("--watch", action="store_true", help=_("Watch task instead of printing runroot.log"))
    parser.add_option("--quiet", action="store_true", default=options.quiet,
                      help=_("Do not print the task information"))

    (opts, args) = parser.parse_args(args)

    if len(args) < 3:
        parser.error(_("Incorrect number of arguments"))
        assert False  # pragma: no cover

    activate_session(session, options)
    tag = args[0]
    arch = args[1]
    if opts.use_shell:
        # everything must be correctly quoted
        command = ' '.join(args[2:])
    else:
        command = args[2:]
    try:
        kwargs = { 'channel':       opts.channel_override,
                   'packages':      opts.package,
                   'mounts':        opts.mount,
                   'repo_id':       opts.repo_id,
                   'skip_setarch':  opts.skip_setarch,
                   'weight':        opts.weight }
        # Only pass this kwarg if it is true - this prevents confusing older
        # builders with a different function signature
        if opts.new_chroot is not None:
            kwargs['new_chroot'] = opts.new_chroot

        task_id = session.runroot(tag, arch, command, **kwargs)
    except koji.GenericError as e:
        if 'Invalid method' in str(e):
            print("* The runroot plugin appears to not be installed on the"
                  " koji hub.  Please contact the administrator.")
        raise
    if opts.task_id:
        print(task_id)

    if not opts.wait:
        return

    if opts.watch:
        session.logout()
        return watch_tasks(session, [task_id], quiet=opts.quiet,
                           poll_interval=options.poll_interval)

    try:
        while True:
            # wait for the task to finish
            if session.taskFinished(task_id):
                break
            time.sleep(options.poll_interval)
    except KeyboardInterrupt:
        # this is probably the right thing to do here
        print("User interrupt: canceling runroot task")
        session.cancelTask(task_id)
        raise
    sys.stdout.flush()
    if not opts.quiet:
        output = list_task_output_all_volumes(session, task_id)
        if 'runroot.log' in output:
            for volume in output['runroot.log']:
                log = session.downloadTaskOutput(task_id, 'runroot.log', volume=volume)
                # runroot output, while normally text, can be *anything*, so
                # treat it as binary
                bytes_to_stdout(log)
    info = session.getTaskInfo(task_id)
    if info is None:
        sys.exit(1)
    state = koji.TASK_STATES[info['state']]
    if state in ('FAILED', 'CANCELED'):
        sys.exit(1)
예제 #34
0
파일: runroot.py 프로젝트: joyxu/koji
def handle_runroot(options, session, args):
    "[admin] Run a command in a buildroot"
    usage = _("usage: %prog runroot [options] <tag> <arch> <command>")
    usage += _(
        "\n(Specify the --help global option for a list of other help options)"
    )
    parser = OptionParser(usage=usage)
    parser.disable_interspersed_args()
    parser.add_option("-p",
                      "--package",
                      action="append",
                      default=[],
                      help=_("make sure this package is in the chroot"))
    parser.add_option("-m",
                      "--mount",
                      action="append",
                      default=[],
                      help=_("mount this directory read-write in the chroot"))
    parser.add_option("--skip-setarch",
                      action="store_true",
                      default=False,
                      help=_("bypass normal setarch in the chroot"))
    parser.add_option("-w", "--weight", type='int', help=_("set task weight"))
    parser.add_option("--channel-override",
                      help=_("use a non-standard channel"))
    parser.add_option("--task-id",
                      action="store_true",
                      default=False,
                      help=_("Print the ID of the runroot task"))
    parser.add_option(
        "--use-shell",
        action="store_true",
        default=False,
        help=_("Run command through a shell, otherwise uses exec"))
    parser.add_option(
        "--new-chroot",
        action="store_true",
        default=False,
        help=_(
            "Run command with the --new-chroot (systemd-nspawn) option to mock"
        ))
    parser.add_option("--repo-id", type="int", help=_("ID of the repo to use"))
    parser.add_option("--nowait",
                      action="store_false",
                      dest="wait",
                      default=True,
                      help=_("Do not wait on task"))
    parser.add_option("--watch",
                      action="store_true",
                      help=_("Watch task instead of printing runroot.log"))
    parser.add_option("--quiet",
                      action="store_true",
                      default=options.quiet,
                      help=_("Do not print the task information"))

    (opts, args) = parser.parse_args(args)

    if len(args) < 3:
        parser.error(_("Incorrect number of arguments"))
        assert False  # pragma: no cover

    activate_session(session, options)
    tag = args[0]
    arch = args[1]
    if opts.use_shell:
        # everything must be correctly quoted
        command = ' '.join(args[2:])
    else:
        command = args[2:]
    try:
        kwargs = {
            'channel': opts.channel_override,
            'packages': opts.package,
            'mounts': opts.mount,
            'repo_id': opts.repo_id,
            'skip_setarch': opts.skip_setarch,
            'weight': opts.weight
        }
        # Only pass this kwarg if it is true - this prevents confusing older
        # builders with a different function signature
        if opts.new_chroot:
            kwargs['new_chroot'] = True

        task_id = session.runroot(tag, arch, command, **kwargs)
    except koji.GenericError as e:
        if 'Invalid method' in str(e):
            print("* The runroot plugin appears to not be installed on the"
                  " koji hub.  Please contact the administrator.")
        raise
    if opts.task_id:
        print(task_id)

    if not opts.wait:
        return

    if opts.watch:
        session.logout()
        return watch_tasks(session, [task_id],
                           quiet=opts.quiet,
                           poll_interval=options.poll_interval)

    try:
        while True:
            # wait for the task to finish
            if session.taskFinished(task_id):
                break
            time.sleep(options.poll_interval)
    except KeyboardInterrupt:
        # this is probably the right thing to do here
        print("User interrupt: canceling runroot task")
        session.cancelTask(task_id)
        raise
    output = list_task_output_all_volumes(session, task_id)
    if 'runroot.log' in output:
        for volume in output['runroot.log']:
            log = session.downloadTaskOutput(task_id,
                                             'runroot.log',
                                             volume=volume)
            sys.stdout.write(log)
    info = session.getTaskInfo(task_id)
    if info is None:
        sys.exit(1)
    state = koji.TASK_STATES[info['state']]
    if state in ('FAILED', 'CANCELED'):
        sys.exit(1)
예제 #35
0
def handle_kiwi_build(goptions, session, args):
    "[build] Run a command in a buildroot"
    usage = "usage: %prog kiwi-build [options] <target> <description_scm> <description_path>"
    usage += "\n(Specify the --help global option for a list of other help options)"
    parser = OptionParser(usage=usage)
    parser.add_option("--scratch",
                      action="store_true",
                      default=False,
                      help="Perform a scratch build")
    parser.add_option(
        "--repo",
        action="append",
        help="Specify a repo that will override the repo used to install "
        "RPMs in the image. May be used multiple times. The "
        "build tag repo associated with the target is the default.")
    parser.add_option("--noprogress",
                      action="store_true",
                      help="Do not display progress of the upload")
    parser.add_option("--kiwi-profile",
                      action="store",
                      default=None,
                      help="Select profile from description file")
    parser.add_option("--can-fail",
                      action="store",
                      dest="optional_arches",
                      metavar="ARCH1,ARCH2,...",
                      default="",
                      help="List of archs which are not blocking for build "
                      "(separated by commas.")
    parser.add_option("--arch",
                      action="append",
                      dest="arches",
                      default=[],
                      help="Limit arches to this subset")
    parser.add_option("--nowait",
                      action="store_false",
                      dest="wait",
                      default=True)
    parser.add_option(
        "--wait",
        action="store_true",
        help="Wait on the image creation, even if running in the background")
    (options, args) = parser.parse_args(args)

    if len(args) != 3:
        parser.error("Incorrect number of arguments")
        assert False  # pragma: no cover
    target, scm, path = args

    activate_session(session, goptions)

    kwargs = {
        'scratch':
        options.scratch,
        'optional_arches': [
            canonArch(arch) for arch in options.optional_arches.split(',')
            if arch
        ],
        'profile':
        options.kiwi_profile,
    }

    arches = []
    if options.arches:
        arches = [canonArch(arch) for arch in options.arches]

    task_id = session.kiwiBuild(target=target,
                                arches=arches,
                                desc_url=scm,
                                desc_path=path,
                                **kwargs)

    if not goptions.quiet:
        print("Created task: %d" % task_id)
        print("Task info: %s/taskinfo?taskID=%s" % (goptions.weburl, task_id))
    if options.wait or (options.wait is None and not _running_in_bg()):
        session.logout()
        return watch_tasks(session, [task_id],
                           quiet=goptions.quiet,
                           poll_interval=goptions.poll_interval,
                           topurl=goptions.topurl)