~ubuntu-branches/debian/sid/autopkgtest/sid

« back to all changes in this revision

Viewing changes to runner/adt-run

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2015-02-27 07:02:52 UTC
  • mfrom: (110.2.11 sid)
  • Revision ID: package-import@ubuntu.com-20150227070252-9p26pwaqfd5ah20j
Improvements:
* Add action argument --testname to run only one individual test from the
  next package.

Bug fixes:
* Restore click AppArmor profiles after a test, if we modified them before
  the test.
* When running a deb test in a click+AppArmor environment, update AppArmor
  rules for all clicks for introspectability and temporary test
  dependencies. This takes about a minute before the test, and another one
  after the test, but is necessary for use cases like ubuntu-sanity-tests.
  (LP: #1424889)

Show diffs side-by-side

added added

removed removed

Lines of Context:
841
841
            '[ -z "$UPSTART_SESSION" ] || /sbin/initctl --user start click-user-hooks')])
842
842
 
843
843
    def apparmor_click(self, clickpkgs, installed_clicks):
844
 
        '''Update AppArmor rules for click tests'''
 
844
        '''Update AppArmor rules for click tests
845
845
 
846
 
        if not clickpkgs and not installed_clicks:
847
 
            return
 
846
        Return True if anything was modified and apparmor_restore_click()
 
847
        needs to be called.
 
848
        '''
 
849
        # check if we are in a click+AppArmor environment
 
850
        if self.execute(['sh', '-ec',
 
851
                         '[ -d /var/cache/apparmor -a -d /var/lib/apparmor/clicks ] && '
 
852
                         'type aa-clickhook >/dev/null 2>&1'])[0] != 0:
 
853
            adtlog.debug('testbed does not have AppArmor/click, no need to adjust rules')
 
854
            return False
 
855
        adtlog.debug('testbed has AppArmor/click')
848
856
 
849
857
        if 'root-on-testbed' not in self.caps:
850
858
            adtlog.warning('Cannot adjust AppArmor rules without root/sudo '
851
859
                           'privileges; Autopilot tests will fail and test '
852
860
                           'dependencies will not be available!')
853
 
            return
 
861
            return False
854
862
 
855
863
        rules = 'dbus (receive, send) bus=session path=/com/canonical/Autopilot/**,'
856
864
        for e in self.install_tmp_env:
861
869
                        rules += ' %s/** r,' % p
862
870
                break
863
871
 
864
 
        adtlog.info('Updating AppArmor rules to allow autopilot introspection')
865
 
        script = '[ -d /var/cache/apparmor -a -d /var/lib/apparmor/clicks ] || exit 0; ' \
866
 
            'type aa-clickhook >/dev/null 2>&1 || exit 0; ' \
867
 
            '''echo '%s' > /var/cache/apparmor/click-ap.rules; ''' \
868
 
            'for c in %s; do ' \
869
 
            '   info=$(click info %s %s/$(basename "$c")); ' \
870
 
            ''' name=$(echo "$info" | sed -rn '/"name"/ {s/^.*: *"([^"]+)",/\\1/; p}'); ''' \
871
 
            ''' version=$(echo "$info" | sed -rn '/"version"/ {s/^.*: *"([^"]+)",/\\1/; p}'); ''' \
872
 
            '   touch -h /var/lib/apparmor/clicks/${name}_*_${version}.json >/dev/null || true; '\
873
 
            'done; ' \
874
 
            'for c in %s; do ' \
875
 
            '    touch -h /var/lib/apparmor/clicks/${c}_*.json 2>/dev/null || true; ' \
876
 
            'done; ' \
877
 
            'aa-clickhook --include=/var/cache/apparmor/click-ap.rules' % (
878
 
                rules,
879
 
                ' '.join(clickpkgs),
880
 
                opts.user and ('--user ' + opts.user) or '',
881
 
                self.scratch,
882
 
                ' '.join(installed_clicks))
883
 
        if self.execute(['sh', opts.verbosity >= 2 and '-exc' or '-ec', script], kind='install')[0] != 0:
884
 
            if 'root-on-testbed' not in testbed.caps:
885
 
                bomb('Failed to update click AppArmor rules: no root privileges in testbed')
886
 
            else:
887
 
                bomb('Failed to update click AppArmor rules')
 
872
        script = '''echo '%s' > /var/cache/apparmor/click-ap.rules; ''' % rules
 
873
 
 
874
        if clickpkgs or installed_clicks:
 
875
            adtlog.info('Updating AppArmor rules to allow autopilot introspection for tested clicks')
 
876
            script += 'for c in %s; do ' \
 
877
                '   info=$(click info %s %s/$(basename "$c")); ' \
 
878
                ''' name=$(echo "$info" | sed -rn '/"name"/ {s/^.*: *"([^"]+)",/\\1/; p}'); ''' \
 
879
                ''' version=$(echo "$info" | sed -rn '/"version"/ {s/^.*: *"([^"]+)",/\\1/; p}'); ''' \
 
880
                '   touch -h /var/lib/apparmor/clicks/${name}_*_${version}.json >/dev/null || true; '\
 
881
                'done; ' \
 
882
                'for c in %s; do ' \
 
883
                '    touch -h /var/lib/apparmor/clicks/${c}_*.json 2>/dev/null || true; ' \
 
884
                'done; ' \
 
885
                'aa-clickhook --include=/var/cache/apparmor/click-ap.rules' % (
 
886
                    ' '.join(clickpkgs),
 
887
                    opts.user and ('--user ' + opts.user) or '',
 
888
                    self.scratch,
 
889
                    ' '.join(installed_clicks))
 
890
        else:
 
891
            adtlog.info('Updating AppArmor rules to allow autopilot introspection for all clicks (will take a minute)...')
 
892
            script += 'aa-clickhook --force --include=/var/cache/apparmor/click-ap.rules'
 
893
 
 
894
        if self.execute(['sh', opts.verbosity >= 2 and '-exc' or '-ec', script], kind='install')[0] != 0:
 
895
            bomb('Failed to update click AppArmor rules')
 
896
 
 
897
        return True
 
898
 
 
899
    def apparmor_restore_click(self, clickpkgs, installed_clicks):
 
900
        '''Restore AppArmor rules after click tests'''
 
901
 
 
902
        adtlog.info('Restoring click package AppArmor rules')
 
903
        # if we only modified some clicks above, --force will be fast, so it's
 
904
        # ok to always do that
 
905
        script = 'rm /var/cache/apparmor/click-ap.rules; aa-clickhook --force'
 
906
        if self.execute(['sh', opts.verbosity >= 2 and '-exc' or '-ec', script], kind='install')[0] != 0:
 
907
            bomb('Failed to update click AppArmor rules')
888
908
 
889
909
    def satisfy_dependencies_string(self, deps, what, recommends=False):
890
910
        '''Install dependencies from a string into the testbed'''
940
960
        self.prepare(test.depends, 'needs-recommends' in test.restrictions)
941
961
        for c in test.clicks:
942
962
            testbed.install_click(c)
943
 
        self.apparmor_click(test.clicks, test.installed_clicks)
 
963
        need_click_restore = self.apparmor_click(test.clicks, test.installed_clicks)
944
964
 
945
965
        # record installed package versions
946
966
        if opts.output_dir:
1123
1143
        if opts.shell or (opts.shell_fail and not test.result):
1124
1144
            self.run_shell(tree.tb)
1125
1145
 
 
1146
        if need_click_restore:
 
1147
            self.apparmor_restore_click(test.clicks, test.installed_clicks)
 
1148
        else:
 
1149
            adtlog.debug('no need to restore click AppArmor profiles')
 
1150
 
1126
1151
 
1127
1152
class TestbedPath:
1128
1153
    '''Represent a file/dir with a host and a testbed path'''
1697
1722
    binaries = Binaries(testbed)
1698
1723
    binaries.reset()
1699
1724
    control_override = None
 
1725
    testname = None
1700
1726
    pending_click_source = None
1701
1727
 
1702
1728
    for (kind, arg, built_binaries) in actions:
1704
1730
        if kind == 'override-control':
1705
1731
            control_override = arg
1706
1732
            continue
 
1733
        if kind == 'testname':
 
1734
            testname = arg
 
1735
            continue
1707
1736
        if kind == 'binary':
1708
1737
            testbed.blame('arg:' + arg)
1709
1738
            pkg = deb_package_name(arg)
1761
1790
 
1762
1791
        if skipped:
1763
1792
            errorcode |= 2
 
1793
 
 
1794
        if testname:
 
1795
            adtlog.debug('filtering testname %s for package %s %s' %
 
1796
                         (testname, kind, arg))
 
1797
            tests = [t for t in tests if t.name == testname]
 
1798
            if not tests:
 
1799
                adtlog.error('%s %s has no test matching --testname %s' %
 
1800
                             (kind, arg, testname))
 
1801
                # error code will be set later
 
1802
            testname = None
 
1803
 
1764
1804
        control_override = None
1765
1805
        run_tests(tests, tests_tree)
1766
1806