Merge branch 'cgen'

Merge in content generator changes

Conflicts:
	hub/kojihub.py
This commit is contained in:
Mike McLean 2015-11-18 10:54:49 -05:00
commit 47189e0c3a
15 changed files with 1404 additions and 234 deletions

126
cli/koji
View file

@ -33,6 +33,13 @@ try:
import ast
except ImportError:
ast = None
try:
import json
except ImportError:
try:
import simplejson as json
except ImportError:
json = None
import ConfigParser
import base64
import errno
@ -1635,6 +1642,59 @@ def handle_import(options, session, args):
do_import(path, data)
def handle_import_cg(options, session, args):
"[admin] Import external builds with rich metadata"
usage = _("usage: %prog import-cg [options] metadata_file files_dir")
usage += _("\n(Specify the --help global option for a list of other help options)")
parser = OptionParser(usage=usage)
parser.add_option("--noprogress", action="store_true",
help=_("Do not display progress of the upload"))
parser.add_option("--link", action="store_true", help=_("Attempt to hardlink instead of uploading"))
parser.add_option("--test", action="store_true", help=_("Don't actually import"))
(options, args) = parser.parse_args(args)
if len(args) < 2:
parser.error(_("Please specify metadata files directory"))
assert False
if json is None:
parser.error(_("Unable to find json module"))
assert False
activate_session(session)
metadata = json.load(file(args[0], 'r'))
if 'output' not in metadata:
print _("Metadata contains no output")
sys.exit(1)
localdir = args[1]
to_upload = []
for info in metadata['output']:
if info.get('metadata_only', False):
continue
localpath = os.path.join(localdir, info.get('relpath', ''), info['filename'])
if not os.path.exists(localpath):
parser.error(_("No such file: %s") % localpath)
to_upload.append([localpath, info])
# get upload path
# XXX - need a better way
serverdir = _unique_path('cli-import')
for localpath, info in to_upload:
relpath = os.path.join(serverdir, info.get('relpath', ''))
if _running_in_bg() or options.noprogress:
callback = None
else:
callback = _progress_callback
if options.link:
linked_upload(localpath, relpath)
else:
print "Uploading %s" % localpath
session.uploadWrapper(localpath, relpath, callback=callback)
if callback:
print
session.CGImport(metadata, serverdir)
def handle_import_comps(options, session, args):
"Import group/package information from a comps file"
usage = _("usage: %prog import-comps [options] <file> <tag>")
@ -2470,6 +2530,49 @@ def handle_revoke_permission(options, session, args):
for user in users:
session.revokePermission(user['name'], perm)
def handle_grant_cg_access(options, session, args):
"[admin] Add a user to a content generator"
usage = _("usage: %prog grant-cg-access <user> <content generator>")
usage += _("\n(Specify the --help global option for a list of other help options)")
parser = OptionParser(usage=usage)
parser.add_option("--new", action="store_true", help=_("Create a new content generator"))
(options, args) = parser.parse_args(args)
if len(args) != 2:
parser.error(_("Please specify a user and content generator"))
assert False
activate_session(session)
user = args[0]
cg = args[1]
uinfo = session.getUser(user)
if uinfo is None:
parser.error(_("No such user: %s" % user))
assert False
kwargs = {}
if options.new:
kwargs['create'] = True
session.grantCGAccess(uinfo['name'], cg, **kwargs)
def handle_revoke_cg_access(options, session, args):
"[admin] Remove a user from a content generator"
usage = _("usage: %prog revoke-cg-access <user> <content generator>")
usage += _("\n(Specify the --help global option for a list of other help options)")
parser = OptionParser(usage=usage)
(options, args) = parser.parse_args(args)
if len(args) != 2:
parser.error(_("Please specify a user and content generator"))
assert False
activate_session(session)
user = args[0]
cg = args[1]
uinfo = session.getUser(user)
if uinfo is None:
parser.error(_("No such user: %s" % user))
assert False
session.revokeCGAccess(uinfo['name'], cg)
def anon_handle_latest_build(options, session, args):
"Print the latest builds for a tag"
usage = _("usage: %prog latest-build [options] tag package [package...]")
@ -3068,9 +3171,16 @@ def anon_handle_rpminfo(options, session, args):
print "No buildroot data available"
else:
br_info = session.getBuildroot(info['buildroot_id'])
print "Buildroot: %(id)i (tag %(tag_name)s, arch %(arch)s, repo %(repo_id)i)" % br_info
print "Build Host: %(host_name)s" % br_info
print "Build Task: %(task_id)i" % br_info
if br_info['br_type'] == koji.BR_TYPES['STANDARD']:
print "Buildroot: %(id)i (tag %(tag_name)s, arch %(arch)s, repo %(repo_id)i)" % br_info
print "Build Host: %(host_name)s" % br_info
print "Build Task: %(task_id)i" % br_info
else:
print "Content generator: %(cg_name)s" % br_info
print "Buildroot: %(id)i" % br_info
print "Build Host OS: %(host_os)s (%(host_arch)s)" % br_info
if info.get('extra'):
print "Extra: %(extra)r" % info
if options.buildroots:
br_list = session.listBuildroots(rpmID=info['id'], queryOpts={'order':'buildroot.id'})
print "Used in %i buildroots:" % len(br_list)
@ -3126,6 +3236,8 @@ def anon_handle_buildinfo(options, session, args):
if win_info:
print "Windows build platform: %s" % win_info['platform']
print "Tags: %s" % ' '.join(taglist)
if info.get('extra'):
print "Extra: %(extra)r" % info
maven_archives = session.listArchives(buildID=info['id'], type='maven')
if maven_archives:
print "Maven archives:"
@ -3835,6 +3947,13 @@ def _print_histline(entry, **kwargs):
fmt = "user %(user.name)s added to group %(group.name)s"
else:
fmt = "user %(user.name)s removed from group %(group.name)s"
elif table == 'cg_users':
if edit:
fmt = "user %(user.name)s re-added to content generator %(content_generator.name)s"
elif create:
fmt = "user %(user.name)s added to content generator %(content_generator.name)s"
else:
fmt = "user %(user.name)s removed from content generator %(content_generator.name)s"
elif table == 'tag_packages':
if edit:
fmt = "package list entry for %(package.name)s in %(tag.name)s updated"
@ -3970,6 +4089,7 @@ def _print_histline(entry, **kwargs):
_table_keys = {
'user_perms' : ['user_id', 'perm_id'],
'user_groups' : ['user_id', 'group_id'],
'cg_users' : ['user_id', 'cg_id'],
'tag_inheritance' : ['tag_id', 'parent_id'],
'tag_config' : ['tag_id'],
'tag_extra' : ['tag_id', 'key'],

106
docs/schema-update-cgen.sql Normal file
View file

@ -0,0 +1,106 @@
BEGIN;
-- New tables
SELECT statement_timestamp(), 'Creating new tables' as msg;
CREATE TABLE content_generator (
id SERIAL PRIMARY KEY,
name TEXT
) WITHOUT OIDS;
CREATE TABLE cg_users (
cg_id INTEGER NOT NULL REFERENCES content_generator (id),
user_id INTEGER NOT NULL REFERENCES users (id),
-- versioned
create_event INTEGER NOT NULL REFERENCES events(id) DEFAULT get_event(),
revoke_event INTEGER REFERENCES events(id),
creator_id INTEGER NOT NULL REFERENCES users(id),
revoker_id INTEGER REFERENCES users(id),
active BOOLEAN DEFAULT 'true' CHECK (active),
CONSTRAINT active_revoke_sane CHECK (
(active IS NULL AND revoke_event IS NOT NULL AND revoker_id IS NOT NULL)
OR (active IS NOT NULL AND revoke_event IS NULL AND revoker_id IS NULL)),
PRIMARY KEY (create_event, cg_id, user_id),
UNIQUE (cg_id, user_id, active)
) WITHOUT OIDS;
CREATE TABLE buildroot_tools_info (
buildroot_id INTEGER NOT NULL REFERENCES buildroot(id),
tool TEXT NOT NULL,
version TEXT NOT NULL,
PRIMARY KEY (buildroot_id, tool)
) WITHOUT OIDS;
CREATE TABLE image_archive_listing (
image_id INTEGER NOT NULL REFERENCES image_archives(archive_id),
archive_id INTEGER NOT NULL REFERENCES archiveinfo(id),
UNIQUE (image_id, archive_id)
) WITHOUT OIDS;
CREATE INDEX image_listing_archives on image_archive_listing(archive_id);
-- new columns --
select statement_timestamp(), 'Adding new columns' as msg;
ALTER TABLE build ADD COLUMN start_time TIMESTAMP;
ALTER TABLE build ADD COLUMN source TEXT;
ALTER TABLE build ADD COLUMN extra TEXT;
ALTER TABLE rpminfo ADD COLUMN metadata_only BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE rpminfo ADD COLUMN extra TEXT;
ALTER TABLE archiveinfo ADD COLUMN metadata_only BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE archiveinfo ADD COLUMN extra TEXT;
-- the more complicated stuff
SELECT statement_timestamp(), 'Copying buildroot to standard_buildroot' as msg;
CREATE TABLE standard_buildroot AS SELECT id,host_id,repo_id,task_id,create_event,retire_event,state from buildroot;
-- doing it this way and fixing up after is *much* faster than creating the empty table
-- and using insert..select to populate
SELECT statement_timestamp(), 'Fixing up standard_buildroot table' as msg;
ALTER TABLE standard_buildroot RENAME id TO buildroot_id;
ALTER TABLE standard_buildroot ALTER COLUMN buildroot_id SET NOT NULL;
ALTER TABLE standard_buildroot ALTER COLUMN host_id SET NOT NULL;
ALTER TABLE standard_buildroot ALTER COLUMN repo_id SET NOT NULL;
ALTER TABLE standard_buildroot ALTER COLUMN task_id SET NOT NULL;
ALTER TABLE standard_buildroot ALTER COLUMN create_event SET NOT NULL;
ALTER TABLE standard_buildroot ALTER COLUMN create_event SET DEFAULT get_event();
SELECT statement_timestamp(), 'Fixing up standard_buildroot table, foreign key constraints' as msg;
ALTER TABLE standard_buildroot ADD CONSTRAINT brfk FOREIGN KEY (buildroot_id) REFERENCES buildroot(id);
ALTER TABLE standard_buildroot ADD CONSTRAINT hfk FOREIGN KEY (host_id) REFERENCES host(id);
ALTER TABLE standard_buildroot ADD CONSTRAINT rfk FOREIGN KEY (repo_id) REFERENCES repo(id);
ALTER TABLE standard_buildroot ADD CONSTRAINT tfk FOREIGN KEY (task_id) REFERENCES task(id);
ALTER TABLE standard_buildroot ADD CONSTRAINT efk FOREIGN KEY (create_event) REFERENCES events(id) ;
SELECT statement_timestamp(), 'Fixing up standard_buildroot table, primary key' as msg;
ALTER TABLE standard_buildroot ADD PRIMARY KEY (buildroot_id);
SELECT statement_timestamp(), 'Altering buildroot table (dropping columns)' as msg;
ALTER TABLE buildroot DROP COLUMN host_id;
ALTER TABLE buildroot DROP COLUMN repo_id;
ALTER TABLE buildroot DROP COLUMN task_id;
ALTER TABLE buildroot DROP COLUMN create_event;
ALTER TABLE buildroot DROP COLUMN retire_event;
ALTER TABLE buildroot DROP COLUMN state;
ALTER TABLE buildroot DROP COLUMN dirtyness;
SELECT statement_timestamp(), 'Altering buildroot table (adding columns)' as msg;
ALTER TABLE buildroot ADD COLUMN br_type INTEGER NOT NULL DEFAULT 0;
ALTER TABLE buildroot ADD COLUMN cg_id INTEGER REFERENCES content_generator (id);
ALTER TABLE buildroot ADD COLUMN cg_version TEXT;
ALTER TABLE buildroot ADD COLUMN container_type TEXT;
ALTER TABLE buildroot ADD COLUMN host_os TEXT;
ALTER TABLE buildroot ADD COLUMN host_arch TEXT;
ALTER TABLE buildroot ADD COLUMN extra TEXT;
SELECT statement_timestamp(), 'Altering buildroot table (altering columns)' as msg;
ALTER TABLE buildroot RENAME arch TO container_arch;
ALTER TABLE buildroot ALTER COLUMN container_arch TYPE TEXT;
ALTER TABLE buildroot ALTER COLUMN br_type DROP DEFAULT;
COMMIT;

View file

@ -7,6 +7,7 @@ DROP TABLE log_messages;
DROP TABLE buildroot_listing;
DROP TABLE image_listing;
DROP TABLE image_archive_listing;
DROP TABLE rpminfo;
DROP TABLE image_builds;
@ -20,6 +21,8 @@ DROP TABLE groups;
DROP TABLE tag_listing;
DROP TABLE tag_packages;
DROP TABLE buildroot_tools_info;
DROP TABLE standard_buildroot;
DROP TABLE buildroot;
DROP TABLE repo;
@ -40,6 +43,9 @@ DROP TABLE host;
DROP TABLE channels;
DROP TABLE package;
DROP TABLE cg_users;
DROP TABLE content_generator;
DROP TABLE user_groups;
DROP TABLE user_perms;
DROP TABLE permissions;
@ -283,11 +289,14 @@ CREATE TABLE build (
version TEXT NOT NULL,
release TEXT NOT NULL,
epoch INTEGER,
source TEXT,
create_event INTEGER NOT NULL REFERENCES events(id) DEFAULT get_event(),
start_time TIMESTAMP,
completion_time TIMESTAMP,
state INTEGER NOT NULL,
task_id INTEGER REFERENCES task (id),
owner INTEGER NOT NULL REFERENCES users (id),
extra TEXT,
CONSTRAINT build_pkg_ver_rel UNIQUE (pkg_id, version, release),
CONSTRAINT completion_sane CHECK ((state = 0 AND completion_time IS NULL) OR
(state != 0 AND completion_time IS NOT NULL))
@ -478,19 +487,68 @@ create table tag_external_repos (
UNIQUE (tag_id, external_repo_id, active)
);
-- data for content generators
CREATE TABLE content_generator (
id SERIAL PRIMARY KEY,
name TEXT
) WITHOUT OIDS;
CREATE TABLE cg_users (
cg_id INTEGER NOT NULL REFERENCES content_generator (id),
user_id INTEGER NOT NULL REFERENCES users (id),
-- versioned - see earlier description of versioning
create_event INTEGER NOT NULL REFERENCES events(id) DEFAULT get_event(),
revoke_event INTEGER REFERENCES events(id),
creator_id INTEGER NOT NULL REFERENCES users(id),
revoker_id INTEGER REFERENCES users(id),
active BOOLEAN DEFAULT 'true' CHECK (active),
CONSTRAINT active_revoke_sane CHECK (
(active IS NULL AND revoke_event IS NOT NULL AND revoker_id IS NOT NULL)
OR (active IS NOT NULL AND revoke_event IS NULL AND revoker_id IS NULL)),
PRIMARY KEY (create_event, cg_id, user_id),
UNIQUE (cg_id, user_id, active)
) WITHOUT OIDS;
-- here we track the buildroots on the machines
CREATE TABLE buildroot (
id SERIAL NOT NULL PRIMARY KEY,
br_type INTEGER NOT NULL
cg_id INTEGER REFERENCES content_generator (id),
cg_version TEXT,
CONSTRAINT cg_sane CHECK (
(cg_id IS NULL AND cg_version IS NULL)
OR (cg_id IS NOT NULL AND cg_version IS NOT NULL)),
container_type TEXT,
container_arch TEXT,
CONSTRAINT container_sane CHECK (
(container_type IS NULL AND container_arch IS NULL)
OR (container_type IS NOT NULL AND container_arch IS NOT NULL)),
host_os TEXT,
host_arch TEXT,
extra TEXT
) WITHOUT OIDS;
CREATE TABLE standard_buildroot (
buildroot_id INTEGER NOT NULL PRIMARY KEY REFERENCES buildroot(id),
host_id INTEGER NOT NULL REFERENCES host(id),
repo_id INTEGER NOT NULL REFERENCES repo (id),
arch VARCHAR(16) NOT NULL,
task_id INTEGER NOT NULL REFERENCES task (id),
create_event INTEGER NOT NULL REFERENCES events(id) DEFAULT get_event(),
retire_event INTEGER,
state INTEGER,
dirtyness INTEGER
state INTEGER
) WITHOUT OIDS;
CREATE TABLE buildroot_tools_info (
buildroot_id INTEGER NOT NULL REFERENCES buildroot(id),
tool TEXT NOT NULL,
version TEXT NOT NULL,
PRIMARY KEY (buildroot_id, tool)
) WITHOUT OIDS;
-- track spun images (livecds, installation, VMs...)
CREATE TABLE image_builds (
build_id INTEGER NOT NULL PRIMARY KEY REFERENCES build(id)
@ -635,6 +693,8 @@ CREATE TABLE rpminfo (
payloadhash TEXT NOT NULL,
size BIGINT NOT NULL,
buildtime BIGINT NOT NULL,
metadata_only BOOLEAN NOT NULL DEFAULT FALSE,
extra TEXT,
CONSTRAINT rpminfo_unique_nvra UNIQUE (name,version,release,arch,external_repo_id)
) WITHOUT OIDS;
CREATE INDEX rpminfo_build ON rpminfo(build_id);
@ -771,7 +831,9 @@ CREATE TABLE archiveinfo (
filename TEXT NOT NULL,
size BIGINT NOT NULL,
checksum TEXT NOT NULL,
checksum_type INTEGER NOT NULL
checksum_type INTEGER NOT NULL,
metadata_only BOOLEAN NOT NULL DEFAULT FALSE,
extra TEXT
) WITHOUT OIDS;
CREATE INDEX archiveinfo_build_idx ON archiveinfo (build_id);
CREATE INDEX archiveinfo_buildroot_idx on archiveinfo (buildroot_id);
@ -798,6 +860,15 @@ CREATE TABLE image_listing (
) WITHOUT OIDS;
CREATE INDEX image_listing_rpms on image_listing(rpm_id);
-- track the archive contents of an image
CREATE TABLE image_archive_listing (
image_id INTEGER NOT NULL REFERENCES image_archives(archive_id),
archive_id INTEGER NOT NULL REFERENCES archiveinfo(id),
UNIQUE (image_id, archive_id)
) WITHOUT OIDS;
CREATE INDEX image_listing_archives on image_archive_listing(archive_id);
CREATE TABLE buildroot_archives (
buildroot_id INTEGER NOT NULL REFERENCES buildroot (id),
archive_id INTEGER NOT NULL REFERENCES archiveinfo (id),

File diff suppressed because it is too large Load diff

View file

@ -546,7 +546,10 @@ _default_policies = {
'vm' : '''
has_perm admin win-admin :: allow
all :: deny
'''
''',
'cg_import' :'''
all :: allow
''',
}
def get_policy(opts, plugins):

View file

@ -210,6 +210,11 @@ BR_STATES = Enum((
'EXPIRED',
))
BR_TYPES = Enum((
'STANDARD',
'EXTERNAL',
))
TAG_UPDATE_TYPES = Enum((
'VOLUME_CHANGE',
'IMPORT',

View file

@ -1,5 +1,6 @@
#import koji
#from kojiweb import util
#from pprint import pformat
#import urllib
#attr _PASSTHROUGH = ['archiveID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']
@ -18,6 +19,11 @@
<th>File Name</th><td>$archive.filename</td>
#end if
</tr>
#if $archive.metadata_only
<tr>
<th>Metadata only</th><td>True (file not imported)</td>
</tr>
#end if
<tr>
<th>File Type</th><td>$archive_type.description</td>
</tr>
@ -51,7 +57,12 @@
#end if
#if $builtInRoot
<tr>
<th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$builtInRoot.tag_name-$builtInRoot.id-$builtInRoot.repo_id</a></td>
<th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$util.brLabel($builtInRoot)</a></td>
</tr>
#end if
#if $archive.get('extra')
<tr>
<th>Extra</th><td class="usertext">$util.escapeHTML($pformat($archive.extra))</td>
</tr>
#end if
#if $files
@ -126,7 +137,7 @@
</tr>
#for $buildroot in $buildroots
<tr class="$util.rowToggle($self)">
<td><a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></td>
<td><a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></td>
<td>$util.formatTime($buildroot.create_event_time)</td>
<td>$util.imageTag($util.brStateName($buildroot.state))</td>
</tr>

View file

@ -3,9 +3,9 @@
#include "includes/header.chtml"
#if $type == 'component'
<h4>Component Archives of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></h4>
<h4>Component Archives of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
#else
<h4>Archives built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></h4>
<h4>Archives built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
#end if
<table class="data-list">

View file

@ -1,5 +1,6 @@
#import koji
#import koji.util
#from pprint import pformat
#from kojiweb import util
#include "includes/header.chtml"
@ -77,6 +78,11 @@
<th>Task</th><td><a href="taskinfo?taskID=$task.id" class="task$util.taskState($task.state)">$koji.taskLabel($task)</a></td>
</tr>
#end if
#if $build.get('extra')
<tr>
<th>Extra</th><td class="usertext">$util.escapeHTML($pformat($build.extra))</td>
</tr>
#end if
<tr>
<th>Tags</th>
<td class="container">
@ -105,7 +111,11 @@
#set $rpmpath = $pathinfo.rpm($rpm)
<tr>
<td></td>
#if $rpm.metadata_only
<td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (metadata only)</td>
#else
<td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$nvrpath/$rpmpath">download</a>)</td>
#end if
</tr>
#end for
#end if
@ -169,12 +179,10 @@
<tr>
<td/>
<td>
#if $mavenbuild
$archive.filename (<a href="archiveinfo?archiveID=$archive.id">info</a>) (<a href="$pathinfo.mavenbuild($build)/$pathinfo.mavenfile($archive)">download</a>)
#elif $winbuild
$pathinfo.winfile($archive) (<a href="archiveinfo?archiveID=$archive.id">info</a>) (<a href="$pathinfo.winbuild($build)/$pathinfo.winfile($archive)">download</a>)
#elif $imagebuild
$archive.filename (<a href="archiveinfo?archiveID=$archive.id">info</a>) (<a href="$pathinfo.imagebuild($build)/$archive.filename">download</a>)
#if $archive.metadata_only
$archive.display (<a href="archiveinfo?archiveID=$archive.id">info</a>)
#else
$archive.display (<a href="archiveinfo?archiveID=$archive.id">info</a>) (<a href="$archive.dl_url">download</a>)
#end if
</td>
</tr>

View file

@ -1,9 +1,10 @@
#import koji
#from kojiweb import util
#from pprint import pformat
#include "includes/header.chtml"
<h4>Information for buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></h4>
<h4>Information for buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
<table>
<tr>
@ -39,6 +40,11 @@
<tr>
<th>Repo Created</th><td>$util.formatTimeLong($buildroot.repo_create_event_time)</td>
</tr>
#if $buildroot.get('extra')
<tr>
<th>Extra</th><td class="usertext">$util.escapeHTML($pformat($buildroot.extra))</td>
</tr>
#end if
<tr>
<th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>
</tr>

View file

@ -0,0 +1,47 @@
#import koji
#from kojiweb import util
#from pprint import pformat
#include "includes/header.chtml"
<h4>Information for external buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
<table>
<tr>
<th>ID</th><td>$buildroot.id</td>
</tr>
<tr>
<th>Host OS</th><td>$buildroot.host_os</td>
</tr>
<tr>
<th>Host Arch</th><td>$buildroot.host_arch</td>
</tr>
<tr>
<th>Content Generator</th><td>$buildroot.cg_name ($buildroot.cg_version)</td>
</tr>
<tr>
<th>Container Type</th><td>$buildroot.container_type</td>
</tr>
<tr>
<th>Container Arch</th><td>$buildroot.container_arch</td>
</tr>
#if $buildroot.get('extra')
<tr>
<th>Extra</th><td class="usertext">$util.escapeHTML($pformat($buildroot.extra))</td>
</tr>
#end if
<tr>
<th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=component" title="RPMs that are installed into this buildroot when building packages">Component RPMs</a></th>
</tr>
<tr>
<th colspan="2"><a href="rpmlist?buildrootID=$buildroot.id&amp;type=built" title="RPMs that have been built in this buildroot">Built RPMs</a></th>
</tr>
<tr>
<th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=component" title="Archives that are installed into this buildroot when building packages">Component Archives</a></th>
</tr>
<tr>
<th colspan="2"><a href="archivelist?buildrootID=$buildroot.id&type=built" title="Archives that have been built in this buildroot">Built Archives</a></th>
</tr>
</table>
#include "includes/footer.chtml"

View file

@ -1098,7 +1098,18 @@ def buildinfo(environ, buildID):
archivetype = None
archives = server.listArchives(build['id'], type=archivetype, queryOpts={'order': 'filename'})
archivesByExt = {}
topurl = environ['koji.options']['KojiFilesURL']
pathinfo = koji.PathInfo(topdir=topurl)
for archive in archives:
if mavenbuild:
archive['display'] = archive['filename']
archive['dl_url'] = '/'.join([pathinfo.mavenbuild(build), pathinfo.mavenfile(archive)])
elif winbuild:
archive['display'] = pathinfo.winfile(archive)
archive['dl_url'] = '/'.join([pathinfo.winbuild(build), pathinfo.winfile(archive)])
elif imagebuild:
archive['display'] = archive['filename']
archive['dl_url'] = '/'.join([pathinfo.imagebuild(build), archive['filename']])
archivesByExt.setdefault(os.path.splitext(archive['filename'])[1][1:], []).append(archive)
rpmsByArch = {}
@ -1182,7 +1193,7 @@ def buildinfo(environ, buildID):
if not values.has_key(field):
values[field] = None
values['start_time'] = build['creation_time']
values['start_time'] = build.get('start_time') or build['creation_time']
# the build start time is not accurate for maven and win builds, get it from the
# task start time instead
if mavenbuild or winbuild:
@ -1197,8 +1208,7 @@ def buildinfo(environ, buildID):
else:
values['estCompletion'] = None
topurl = environ['koji.options']['KojiFilesURL']
values['pathinfo'] = koji.PathInfo(topdir=topurl)
values['pathinfo'] = pathinfo
return _genHTML(environ, 'buildinfo.chtml')
def builds(environ, userID=None, tagID=None, packageID=None, state=None, order='-build_id', start=None, prefix=None, inherited='1', latest='1', type=None):
@ -1623,17 +1633,21 @@ def buildrootinfo(environ, buildrootID, builtStart=None, builtOrder=None, compon
buildrootID = int(buildrootID)
buildroot = server.getBuildroot(buildrootID)
values['title'] = '%(tag_name)s-%(id)i-%(repo_id)i' % buildroot + ' | Buildroot Info'
if buildroot == None:
raise koji.GenericError, 'unknown buildroot ID: %i' % buildrootID
task = server.getTaskInfo(buildroot['task_id'], request=True)
elif buildroot['br_type'] == koji.BR_TYPES['STANDARD']:
template = 'buildrootinfo.chtml'
values['task'] = server.getTaskInfo(buildroot['task_id'], request=True)
else:
template = 'buildrootinfo_cg.chtml'
# TODO - fetch tools and extras info
values['title'] = '%s | Buildroot Info' % kojiweb.util.brLabel(buildroot)
values['buildroot'] = buildroot
values['task'] = task
return _genHTML(environ, 'buildrootinfo.chtml')
return _genHTML(environ, template)
def rpmlist(environ, type, buildrootID=None, imageID=None, start=None, order='nvr'):
"""

View file

@ -1,5 +1,6 @@
#import koji
#from kojiweb import util
#from pprint import pformat
#import time
#import urllib
@ -65,7 +66,12 @@
</tr>
#if $builtInRoot
<tr>
<th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$builtInRoot.tag_name-$builtInRoot.id-$builtInRoot.repo_id</a></td>
<th>Buildroot</th><td><a href="buildrootinfo?buildrootID=$builtInRoot.id">$util.brLabel($builtInRoot)</a></td>
</tr>
#end if
#if $rpm.get('extra')
<tr>
<th>Extra</th><td class="usertext">$util.escapeHTML($pformat($rpm.extra))</td>
</tr>
#end if
#if $rpm.external_repo_id == 0
@ -208,7 +214,7 @@
</tr>
#for $buildroot in $buildroots
<tr class="$util.rowToggle($self)">
<td><a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></td>
<td><a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></td>
<td>$util.formatTime($buildroot.create_event_time)</td>
<td>$util.imageTag($util.brStateName($buildroot.state))</td>
</tr>

View file

@ -21,11 +21,11 @@ colspan="2" #slurp
#end def
#if $type == 'component'
<h4>Component RPMs of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></h4>
<h4>Component RPMs of buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
#elif $type == 'image'
<h4>RPMs installed in <a href="archiveinfo?archiveID=$image.id">$image.filename</a></h4>
#else
<h4>RPMs built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$buildroot.tag_name-$buildroot.id-$buildroot.repo_id</a></h4>
<h4>RPMs built in buildroot <a href="buildrootinfo?buildrootID=$buildroot.id">$util.brLabel($buildroot)</a></h4>
#end if
<table class="data-list">

View file

@ -377,6 +377,14 @@ def brStateName(stateID):
"""Convert a numeric buildroot state into a readable name."""
return koji.BR_STATES[stateID].lower()
def brLabel(brinfo):
if brinfo['br_type'] == koji.BR_TYPES['STANDARD']:
return '%(tag_name)s-%(id)i-%(repo_id)i' % brinfo
else:
return '%(cg_name)s:%(id)i' % brinfo
def repoStateName(stateID):
"""Convert a numeric repository state into a readable name."""
if stateID == koji.REPO_INIT: