Merge ~alexmurray/ubuntu-security-tools:cmd-qrt into ubuntu-security-tools:master

Proposed by Alex Murray
Status: Merged
Merged at revision: aa982b0163d74e9bf82634768a2abf2b5796cbcf
Proposed branch: ~alexmurray/ubuntu-security-tools:cmd-qrt
Merge into: ubuntu-security-tools:master
Diff against target: 288 lines (+200/-15)
2 files modified
build-tools/umt (+199/-14)
build-tools/umt-completion.bash (+1/-1)
Reviewer Review Type Date Requested Status
Emilia Torino Approve
Eduardo Barretto Approve
Review via email: mp+376398@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Marc Deslauriers (mdeslaur) :
Revision history for this message
Marc Deslauriers (mdeslaur) :
Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks for the review Marc - I have pushed extra commits to address your comments - see https://git.launchpad.net/~alexmurray/ubuntu-security-tools/commit/?id=d8b061e61a96bce2d22829c41fb4bf39302af080 which removes the revert part - and https://git.launchpad.net/~alexmurray/ubuntu-security-tools/commit/?id=2ebdc31cb89e21acd4f35d78816823fe13e00f84 which always adds -v when running tests so we always use verbose output. Perhaps in the future we might want a way to turn this off if the diffs get too messy with it but I think for now this an improvement.

Revision history for this message
Emilia Torino (emitorino) wrote :

This is great Alex! I added 2 inline comments with just refactoring suggestions + one question. Thanks!

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

Adding a comment to Emi's suggestion as discussed on IRC.

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

sorry for the spam, my comment didn't work, commenting again!

Revision history for this message
Alex Murray (alexmurray) wrote :

emitorino + ebarretto - I just pushed https://git.launchpad.net/~alexmurray/ubuntu-security-tools/commit/?id=67f072cbf84c8479e1ce67d85a732b3101f3f504 which should resolve your concerns.

Revision history for this message
Alex Murray (alexmurray) wrote :

Whoops - accidentally left in too much old code - fixed in subsequent commit https://git.launchpad.net/~alexmurray/ubuntu-security-tools/commit/?id=8b03bce

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

LGTM

review: Approve
Revision history for this message
Steve Beattie (sbeattie) wrote :

I haven't looked at the implementation, so no real comment on that, but I did look briefly and tried to guess how it would be used; can we call the option 'test' rather than 'qrt', since the qrt tree is an implementation detail?

Revision history for this message
Emilia Torino (emitorino) :
review: Approve
Revision history for this message
Alex Murray (alexmurray) wrote :

> I haven't looked at the implementation, so no real comment on that, but I did
> look briefly and tried to guess how it would be used; can we call the option
> 'test' rather than 'qrt', since the qrt tree is an implementation detail?

Well I want to add autopkgtest support as well and so was thinking it was easier to add both as separate sub-commands, otherwise if there was a single 'test' command this would have to have multiple mutually incompatible options depending on whether it ran qrt or autopkgtest etc - so to keep it simpler, I figure it is better to have separate qrt and autopkgtest commands.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/build-tools/umt b/build-tools/umt
index 5aea099..c8939bc 100755
--- a/build-tools/umt
+++ b/build-tools/umt
@@ -36,6 +36,7 @@ binary_dest = '../binary'
36reports_dest = '../reports'36reports_dest = '../reports'
37previous_dest = '../previous'37previous_dest = '../previous'
38coverity_dest = '../coverity'38coverity_dest = '../coverity'
39tests_dest = '../tests'
3940
40# Per-package overrides for the sbuild resolver41# Per-package overrides for the sbuild resolver
41# <sbuild resolver> = sbuild_dep_resolver_overrides[<srcpkg>][<ubuntu release>]42# <sbuild resolver> = sbuild_dep_resolver_overrides[<srcpkg>][<ubuntu release>]
@@ -1364,19 +1365,11 @@ Acquire::Languages "none";
1364 recursive_rm(tempdir)1365 recursive_rm(tempdir)
13651366
13661367
1367def cmd_repo():1368def copy_to_repo(opt, details, quiet=False):
1368 '''Copy all built packages into local repository'''1369 '''Copy all built packages into local repository'''
1369 parser = umt_optparse("usage: %prog repo [options]")
1370
1371 parser.add_option("-r", "--release", dest="release", default=False,
1372 help="specify repository to copy to")
1373 parser.add_option("--purge", dest="purge", default=False, action='store_true',
1374 help="purge repository of all packages before copying")
1375
1376 (opt, args) = parser.parse_args()
1377 repo_base = ust['package_tools_repo_base']1370 repo_base = ust['package_tools_repo_base']
1378 details = parse_package_details(release = opt.release, skip_sanity=True)1371 if not quiet:
1379 print_details(details)1372 print_details(details)
13801373
1381 repo_dest = os.path.join(repo_base, details['release'])1374 repo_dest = os.path.join(repo_base, details['release'])
13821375
@@ -1404,7 +1397,8 @@ def cmd_repo():
1404 err("Could not find 'update_repo' (is '$UST' set?). Aborting.")1397 err("Could not find 'update_repo' (is '$UST' set?). Aborting.")
1405 sys.exit(1)1398 sys.exit(1)
14061399
1407 print("Repository: %s" % (repo_dest))1400 if not quiet:
1401 print("Repository: %s" % (repo_dest))
14081402
1409 # Copy the source files, ignoring stuff we don't want1403 # Copy the source files, ignoring stuff we don't want
1410 files = os.listdir(source_dest)1404 files = os.listdir(source_dest)
@@ -1412,7 +1406,8 @@ def cmd_repo():
1412 (root, ext) = os.path.splitext(f)1406 (root, ext) = os.path.splitext(f)
1413 if ext in [ ".build", ".upload", ".debdiff" ]:1407 if ext in [ ".build", ".upload", ".debdiff" ]:
1414 continue1408 continue
1415 print("Copying '%s'..." % (f))1409 if not quiet:
1410 print("Copying '%s'..." % (f))
1416 shutil.copy(os.path.join(source_dest, f), repo_dest)1411 shutil.copy(os.path.join(source_dest, f), repo_dest)
14171412
1418 # Copy the files, as we may have built multiple architectures and the1413 # Copy the files, as we may have built multiple architectures and the
@@ -1420,7 +1415,8 @@ def cmd_repo():
1420 files = os.listdir(binary_dest)1415 files = os.listdir(binary_dest)
1421 for f in files:1416 for f in files:
1422 if f.endswith("deb"):1417 if f.endswith("deb"):
1423 print("Copying '%s'..." % (f))1418 if not quiet:
1419 print("Copying '%s'..." % (f))
1424 shutil.copy(os.path.join(binary_dest, f), repo_dest)1420 shutil.copy(os.path.join(binary_dest, f), repo_dest)
14251421
1426 (rc, report) = runcmd([update_repo, details['release']], stdin=sys.stdin, stdout=None)1422 (rc, report) = runcmd([update_repo, details['release']], stdin=sys.stdin, stdout=None)
@@ -1428,6 +1424,22 @@ def cmd_repo():
1428 err("failure running '%s':\n%s" % (update_repo, report))1424 err("failure running '%s':\n%s" % (update_repo, report))
1429 sys.exit(1)1425 sys.exit(1)
14301426
1427
1428def add_repo_arguments(parser):
1429 '''Add the command-line arguments used by repo'''
1430
1431 parser.add_option("-r", "--release", dest="release", default=False,
1432 help="specify repository to copy to")
1433 parser.add_option("--purge", dest="purge", default=False, action='store_true',
1434 help="purge repository of all packages before copying")
1435
1436def cmd_repo():
1437 '''Copy all built packages into local repository'''
1438 parser = umt_optparse("usage: %prog repo [options]")
1439 add_repo_arguments(parser)
1440 (opt, args) = parser.parse_args()
1441 details = parse_package_details(release = opt.release, skip_sanity=True)
1442 copy_to_repo(opt, details)
1431 success("SUCCESS")1443 success("SUCCESS")
14321444
1433def cmd_upload():1445def cmd_upload():
@@ -1556,6 +1568,178 @@ def cmd_search():
1556 print("%s: %s, Pocket: %s, Component: %s" % (release,1568 print("%s: %s, Pocket: %s, Component: %s" % (release,
1557 pkg_list[release][0], pkg_list[release][1], pkg_list[release][2]))1569 pkg_list[release][0], pkg_list[release][1], pkg_list[release][2]))
15581570
1571def cmd_qrt():
1572 '''Run QRT tests for the package in the current directory of unpacked source'''
1573 parser = umt_optparse("usage: %prog qrt [options]")
1574 add_repo_arguments(parser)
1575 parser.add_option("-s", "--sudo", dest="sudo", default=False, action='store_true',
1576 help="Whether to run the QRT tests via sudo as a regular user")
1577 parser.add_option("-u", "--user", dest="user", default=os.getlogin(), metavar='USER',
1578 help="The username to run the QRT tests as (default: current user)")
1579 parser.add_option("-q", "--qrt-path", dest="qrt_path", default=os.getenv("QRT", ""), metavar='QRT_PATH',
1580 help="Path to the local copy of the qa-regression-tools (QRT) repo")
1581 parser.add_option("--no-update", dest="no_update", default=False, action='store_true',
1582 help="Don't update UVT VM before initial test run")
1583 parser.add_option("--no-snapshot", dest="no_snapshot", default=False, action='store_true',
1584 help="Don't revert or update snapshot of UVT VM on update")
1585 parser.add_option("-n", "--dry-run", dest="dry_run", default=False, action='store_true',
1586 help="Don't actually execute tests, instead print what would be run")
1587 parser.add_option("-p", "--uvt-prefix", dest="uvt_prefix", default="sec",
1588 help="Prefix to use for UVT VM names (default: sec)")
1589 parser.add_option("-v", "--uvt-vm", dest="uvt_vm", default=None,
1590 help="VM use for UVT tests (default: use {uvt-prefix}-release-{arch})")
1591 parser.add_option("--debug", default=False, action='store_true',
1592 help="Report additional debug details")
1593 parser.add_option("-f", "--force", dest="force", default=False, action='store_true',
1594 help="force deletion of ../tests before running")
1595 (opt, args) = parser.parse_args()
1596
1597 validate_toplevel()
1598 details = parse_package_details(skip_sanity=True)
1599 run_qrt_tests(opt, details)
1600 # also alert if there appear to be other bits in QRT worth looking at
1601 for d in ['build_testing', 'notes_testing']:
1602 testing_dir = os.path.join(opt.qrt_path, d, details["package"])
1603 try:
1604 files = os.listdir(testing_dir)
1605 except:
1606 files = []
1607 finally:
1608 if len(files) > 0:
1609 warn("QRT also contains the following relevant files for " + details["package"] + ":")
1610 for f in files:
1611 warn(" " + os.path.join(d, details["package"], f))
1612 warn("Please ensure you consult these")
1613
1614
1615def runcmdopt(cmd, opt, okrc=[0]):
1616 output = ""
1617 if opt.debug:
1618 print("[" + " ".join(cmd) + "]")
1619 if not opt.dry_run:
1620 (rc, output) = runcmd(cmd)
1621 if rc not in okrc:
1622 raise Exception("Failed to execute command: " + " ".join(cmd) + ": " + output)
1623 if opt.debug:
1624 print(output)
1625 return output
1626
1627
1628def run_qrt_tests(opt, details):
1629 qrt_test = os.path.join(opt.qrt_path, "scripts", "test-" + details["package"] + ".py")
1630 if not os.path.exists(qrt_test):
1631 print("No QRT test found for " + details["package"] + ": expected to find in " + qrt_test)
1632 return
1633 qrt_tests_dest = os.path.join(tests_dest, "qrt")
1634 prepare_dir(qrt_tests_dest, opt.force)
1635 user = opt.user
1636 sudo = ""
1637 if opt.sudo:
1638 sudo = 'echo ubuntu | sudo -S '
1639 print("Running QRT test " + qrt_test + " for " + details["package"] + " as " + user + (" via sudo" if opt.sudo else ""))
1640 if opt.uvt_vm is not None:
1641 vm = opt.uvt_vm
1642 else:
1643 # TODO suport different arch's
1644 vm = opt.uvt_prefix + "-" + details["release"] + "-amd64"
1645 # find path to uvt binary - first see if UQT is defined, otherwise try
1646 # in relative location to the current script
1647 uqt = os.getenv("UQT")
1648 if uqt != None and os.path.exists(os.path.join(uqt, "vm-tools", "uvt")):
1649 uvt = os.path.join(uqt, "vm-tools", "uvt")
1650 elif os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
1651 "ubuntu-qa-tools", "vm-tools", "uvt"):
1652 uvt = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))),
1653 "ubuntu-qa-tools", "vm-tools", "uvt")
1654 else:
1655 err("Unable to find uvt - please define QRT as the path to ubuntu-qa-tools repo")
1656 # catch any exception which occurred during execution
1657 try:
1658 if not opt.no_update:
1659 # ensure vm is stopped first - unless no_snapshot we can stop
1660 # it by force
1661 cmd = [uvt, "stop", vm]
1662 if not opt.no_snapshot:
1663 cmd.append("-f")
1664 print("Ensuring uvt VM " + vm + " is stopped...")
1665 runcmdopt(cmd, opt)
1666 print("Updating uvt VM " + vm + "...")
1667 cmd = [uvt, "update", "-f", vm]
1668 if opt.no_snapshot:
1669 cmd.append("--nosnapshot")
1670 runcmdopt(cmd, opt)
1671 print("Launching uvt VM " + vm + "...")
1672 # run headless since we don't use the GUI and wait for ssh
1673 # availability
1674 runcmdopt([uvt, "start", "-v", "-w", vm], opt)
1675 print("Packaging QRT test...")
1676 runcmdopt([os.path.join(opt.qrt_path, "scripts", "make-test-tarball"),
1677 qrt_test], opt)
1678 print("Deploying QRT test...")
1679 runcmdopt(["/usr/bin/scp",
1680 "/tmp/qrt-test-" + details["package"] + ".tar.gz",
1681 user + "@" + vm + ":"], opt)
1682 print("Extracting QRT test...")
1683 runcmdopt(["/usr/bin/ssh", "-T", user + "@" + vm,
1684 "tar -xvf qrt-test-" + details["package"] + ".tar.gz" ],
1685 opt)
1686 print("Installing packages for QRT test...")
1687 # always install packages via sudo
1688 runcmdopt(["/usr/bin/ssh", "-T", user + "@" + vm,
1689 "cd ./qrt-test-" + details["package"] + "; " +
1690 "echo ubuntu | sudo -S ./install-packages ./test-" + details["package"] + ".py"],
1691 opt)
1692 print("Executing QRT baseline test...")
1693 report = runcmdopt(["/usr/bin/ssh", "-T", user + "@" + vm,
1694 "cd ./qrt-test-" + details["package"] + ";" +
1695 sudo + " ./test-" + details["package"] + ".py -v"],
1696 opt)
1697 # save the report so we can compare it later
1698 path = os.path.join(qrt_tests_dest, "qrt-test-" + details["package"] + '-orig.txt')
1699 with open(path,"w+") as handle:
1700 handle.write(report)
1701 handle.flush()
1702
1703 print("Copying packages to umt repo...")
1704 if not opt.dry_run:
1705 copy_to_repo(opt, details, quiet=not opt.debug)
1706
1707 print("Enabling repo for uvt VM...")
1708 runcmdopt([uvt, "repo", "-e", vm], opt)
1709
1710 print("Upgrading packages in uvt VM...")
1711 runcmdopt(["/usr/bin/ssh", "-T", "root@" + vm,
1712 "apt-get dist-upgrade -y --force-yes"], opt)
1713
1714 print("Re-executing QRT test...")
1715 report = runcmdopt(["/usr/bin/ssh", "-T", user + "@" + vm,
1716 "cd ./qrt-test-" + details["package"] + ";" +
1717 sudo + " ./test-" + details["package"] + ".py -v"], opt)
1718 # save the report so we can compare it later
1719 path = os.path.join(qrt_tests_dest, "qrt-test-" + details["package"] + '.txt')
1720 with open(path,"w+") as handle:
1721 handle.write(report)
1722 handle.flush()
1723
1724 print("Generating diff of QRT tests output...")
1725 report = runcmdopt(["/usr/bin/diff", "-u",
1726 os.path.join(qrt_tests_dest, "qrt-test-" + details["package"] + '-orig.txt'),
1727 os.path.join(qrt_tests_dest, "qrt-test-" + details["package"] + '.txt')],
1728 # diff returns 1 if different and 0 if same - so
1729 # both are valid ok return codes
1730 opt, [0, 1])
1731 # save the diff
1732 path = os.path.join(qrt_tests_dest, "qrt-test-" + details["package"] + '.diff')
1733 with open(path,"w+") as handle:
1734 handle.write(report)
1735 handle.flush()
1736 print("QRT test run diff in " + path)
1737
1738 except Exception as e:
1739 err(str(e))
1740 print("Stopping uvt VM " + vm + "...")
1741 runcmdopt([uvt, "stop", vm], opt)
1742
1559#1743#
1560# Misc functions1744# Misc functions
1561#1745#
@@ -3273,6 +3457,7 @@ commands = {
3273 'compare-bin' : cmd_compare_bin,3457 'compare-bin' : cmd_compare_bin,
3274 'repo' : cmd_repo,3458 'repo' : cmd_repo,
3275 'upload' : cmd_upload,3459 'upload' : cmd_upload,
3460 'qrt' : cmd_qrt,
3276 'open' : cmd_open,3461 'open' : cmd_open,
3277 'read' : cmd_read,3462 'read' : cmd_read,
3278 'help' : cmd_help3463 'help' : cmd_help
diff --git a/build-tools/umt-completion.bash b/build-tools/umt-completion.bash
index 7935679..bd73861 100644
--- a/build-tools/umt-completion.bash
+++ b/build-tools/umt-completion.bash
@@ -12,7 +12,7 @@ _umt_complete()
12 COMPREPLY=( $( compgen -W "$( grep Package: /var/lib/apt/lists/*Sources | awk '{print $2}' | sort | uniq )" "$cur") )12 COMPREPLY=( $( compgen -W "$( grep Package: /var/lib/apt/lists/*Sources | awk '{print $2}' | sort | uniq )" "$cur") )
13 }13 }
1414
15 umt_commands="search download changelog source binary build build-orig compare-log compare-bin sign check upload"15 umt_commands="search download changelog source binary build build-orig compare-log compare-bin sign check upload qrt"
1616
17 if [ $COMP_CWORD -eq 1 ]; then17 if [ $COMP_CWORD -eq 1 ]; then
18 COMPREPLY=( $(compgen -W "$umt_commands" -- ${COMP_WORDS[COMP_CWORD]}) )18 COMPREPLY=( $(compgen -W "$umt_commands" -- ${COMP_WORDS[COMP_CWORD]}) )

Subscribers

People subscribed via source and target branches