teuthology 1.0.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scripts/describe.py +1 -0
- scripts/dispatcher.py +62 -0
- scripts/exporter.py +18 -0
- scripts/lock.py +1 -1
- scripts/node_cleanup.py +58 -0
- scripts/openstack.py +9 -9
- scripts/results.py +12 -11
- scripts/run.py +4 -0
- scripts/schedule.py +4 -0
- scripts/suite.py +61 -16
- scripts/supervisor.py +44 -0
- scripts/update_inventory.py +10 -4
- scripts/wait.py +31 -0
- teuthology/__init__.py +24 -21
- teuthology/beanstalk.py +4 -3
- teuthology/config.py +17 -6
- teuthology/contextutil.py +18 -14
- teuthology/describe_tests.py +25 -18
- teuthology/dispatcher/__init__.py +365 -0
- teuthology/dispatcher/supervisor.py +374 -0
- teuthology/exceptions.py +54 -0
- teuthology/exporter.py +347 -0
- teuthology/kill.py +76 -75
- teuthology/lock/cli.py +16 -7
- teuthology/lock/ops.py +276 -70
- teuthology/lock/query.py +61 -44
- teuthology/ls.py +9 -18
- teuthology/misc.py +152 -137
- teuthology/nuke/__init__.py +12 -351
- teuthology/openstack/__init__.py +4 -3
- teuthology/openstack/openstack-centos-7.0-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.1-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.2-user-data.txt +1 -1
- teuthology/openstack/openstack-debian-8.0-user-data.txt +1 -1
- teuthology/openstack/openstack-opensuse-42.1-user-data.txt +1 -1
- teuthology/openstack/openstack-teuthology.cron +0 -1
- teuthology/orchestra/cluster.py +51 -9
- teuthology/orchestra/connection.py +23 -16
- teuthology/orchestra/console.py +111 -50
- teuthology/orchestra/daemon/cephadmunit.py +23 -5
- teuthology/orchestra/daemon/state.py +10 -3
- teuthology/orchestra/daemon/systemd.py +10 -8
- teuthology/orchestra/opsys.py +32 -11
- teuthology/orchestra/remote.py +369 -152
- teuthology/orchestra/run.py +21 -12
- teuthology/packaging.py +54 -15
- teuthology/provision/__init__.py +30 -10
- teuthology/provision/cloud/openstack.py +12 -6
- teuthology/provision/cloud/util.py +1 -2
- teuthology/provision/downburst.py +83 -29
- teuthology/provision/fog.py +68 -20
- teuthology/provision/openstack.py +5 -4
- teuthology/provision/pelagos.py +13 -5
- teuthology/repo_utils.py +91 -44
- teuthology/report.py +57 -35
- teuthology/results.py +5 -3
- teuthology/run.py +21 -15
- teuthology/run_tasks.py +114 -40
- teuthology/schedule.py +4 -3
- teuthology/scrape.py +28 -22
- teuthology/suite/__init__.py +75 -46
- teuthology/suite/build_matrix.py +34 -24
- teuthology/suite/fragment-merge.lua +105 -0
- teuthology/suite/matrix.py +31 -2
- teuthology/suite/merge.py +175 -0
- teuthology/suite/placeholder.py +8 -8
- teuthology/suite/run.py +204 -102
- teuthology/suite/util.py +67 -211
- teuthology/task/__init__.py +1 -1
- teuthology/task/ansible.py +101 -31
- teuthology/task/buildpackages.py +2 -2
- teuthology/task/ceph_ansible.py +13 -6
- teuthology/task/cephmetrics.py +2 -1
- teuthology/task/clock.py +33 -14
- teuthology/task/exec.py +18 -0
- teuthology/task/hadoop.py +2 -2
- teuthology/task/install/__init__.py +51 -22
- teuthology/task/install/bin/adjust-ulimits +16 -0
- teuthology/task/install/bin/daemon-helper +114 -0
- teuthology/task/install/bin/stdin-killer +263 -0
- teuthology/task/install/deb.py +24 -4
- teuthology/task/install/redhat.py +36 -32
- teuthology/task/install/rpm.py +41 -14
- teuthology/task/install/util.py +48 -22
- teuthology/task/internal/__init__.py +69 -11
- teuthology/task/internal/edit_sudoers.sh +10 -0
- teuthology/task/internal/lock_machines.py +3 -133
- teuthology/task/internal/redhat.py +48 -28
- teuthology/task/internal/syslog.py +31 -8
- teuthology/task/kernel.py +155 -147
- teuthology/task/lockfile.py +1 -1
- teuthology/task/mpi.py +10 -10
- teuthology/task/pcp.py +1 -1
- teuthology/task/selinux.py +17 -8
- teuthology/task/ssh_keys.py +6 -6
- teuthology/task/tests/__init__.py +137 -77
- teuthology/task/tests/test_fetch_coredumps.py +116 -0
- teuthology/task/tests/test_run.py +4 -4
- teuthology/timer.py +3 -3
- teuthology/util/loggerfile.py +19 -0
- teuthology/util/scanner.py +159 -0
- teuthology/util/sentry.py +52 -0
- teuthology/util/time.py +52 -0
- teuthology-1.2.0.data/scripts/adjust-ulimits +16 -0
- teuthology-1.2.0.data/scripts/daemon-helper +114 -0
- teuthology-1.2.0.data/scripts/stdin-killer +263 -0
- teuthology-1.2.0.dist-info/METADATA +89 -0
- teuthology-1.2.0.dist-info/RECORD +174 -0
- {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/WHEEL +1 -1
- {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/entry_points.txt +5 -2
- scripts/nuke.py +0 -45
- scripts/worker.py +0 -37
- teuthology/nuke/actions.py +0 -456
- teuthology/openstack/test/__init__.py +0 -0
- teuthology/openstack/test/openstack-integration.py +0 -286
- teuthology/openstack/test/test_config.py +0 -35
- teuthology/openstack/test/test_openstack.py +0 -1695
- teuthology/orchestra/test/__init__.py +0 -0
- teuthology/orchestra/test/integration/__init__.py +0 -0
- teuthology/orchestra/test/integration/test_integration.py +0 -94
- teuthology/orchestra/test/test_cluster.py +0 -240
- teuthology/orchestra/test/test_connection.py +0 -106
- teuthology/orchestra/test/test_console.py +0 -217
- teuthology/orchestra/test/test_opsys.py +0 -404
- teuthology/orchestra/test/test_remote.py +0 -185
- teuthology/orchestra/test/test_run.py +0 -286
- teuthology/orchestra/test/test_systemd.py +0 -54
- teuthology/orchestra/test/util.py +0 -12
- teuthology/sentry.py +0 -18
- teuthology/test/__init__.py +0 -0
- teuthology/test/fake_archive.py +0 -107
- teuthology/test/fake_fs.py +0 -92
- teuthology/test/integration/__init__.py +0 -0
- teuthology/test/integration/test_suite.py +0 -86
- teuthology/test/task/__init__.py +0 -205
- teuthology/test/task/test_ansible.py +0 -624
- teuthology/test/task/test_ceph_ansible.py +0 -176
- teuthology/test/task/test_console_log.py +0 -88
- teuthology/test/task/test_install.py +0 -337
- teuthology/test/task/test_internal.py +0 -57
- teuthology/test/task/test_kernel.py +0 -243
- teuthology/test/task/test_pcp.py +0 -379
- teuthology/test/task/test_selinux.py +0 -35
- teuthology/test/test_config.py +0 -189
- teuthology/test/test_contextutil.py +0 -68
- teuthology/test/test_describe_tests.py +0 -316
- teuthology/test/test_email_sleep_before_teardown.py +0 -81
- teuthology/test/test_exit.py +0 -97
- teuthology/test/test_get_distro.py +0 -47
- teuthology/test/test_get_distro_version.py +0 -47
- teuthology/test/test_get_multi_machine_types.py +0 -27
- teuthology/test/test_job_status.py +0 -60
- teuthology/test/test_ls.py +0 -48
- teuthology/test/test_misc.py +0 -368
- teuthology/test/test_nuke.py +0 -232
- teuthology/test/test_packaging.py +0 -763
- teuthology/test/test_parallel.py +0 -28
- teuthology/test/test_repo_utils.py +0 -204
- teuthology/test/test_report.py +0 -77
- teuthology/test/test_results.py +0 -155
- teuthology/test/test_run.py +0 -238
- teuthology/test/test_safepath.py +0 -55
- teuthology/test/test_schedule.py +0 -45
- teuthology/test/test_scrape.py +0 -167
- teuthology/test/test_timer.py +0 -80
- teuthology/test/test_vps_os_vers_parameter_checking.py +0 -84
- teuthology/test/test_worker.py +0 -303
- teuthology/worker.py +0 -339
- teuthology-1.0.0.dist-info/METADATA +0 -76
- teuthology-1.0.0.dist-info/RECORD +0 -210
- {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/LICENSE +0 -0
- {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/top_level.txt +0 -0
teuthology/task/ceph_ansible.py
CHANGED
@@ -22,7 +22,7 @@ class CephAnsible(Task):
|
|
22
22
|
|
23
23
|
- ceph-ansible:
|
24
24
|
repo: {git_base}ceph-ansible.git
|
25
|
-
branch: mybranch # defaults to
|
25
|
+
branch: mybranch # defaults to main
|
26
26
|
ansible-version: 2.4 # defaults to 2.5
|
27
27
|
vars:
|
28
28
|
ceph_dev: True ( default)
|
@@ -73,7 +73,7 @@ class CephAnsible(Task):
|
|
73
73
|
if 'ceph_dev_key' not in vars:
|
74
74
|
vars['ceph_dev_key'] = 'https://download.ceph.com/keys/autobuild.asc'
|
75
75
|
if 'ceph_dev_branch' not in vars:
|
76
|
-
vars['ceph_dev_branch'] = ctx.config.get('branch', '
|
76
|
+
vars['ceph_dev_branch'] = ctx.config.get('branch', 'main')
|
77
77
|
self.cluster_name = vars.get('cluster', 'ceph')
|
78
78
|
|
79
79
|
def setup(self):
|
@@ -296,8 +296,11 @@ class CephAnsible(Task):
|
|
296
296
|
roles = self.ctx.cluster.remotes[remote]
|
297
297
|
dev_needed = len([role for role in roles
|
298
298
|
if role.startswith('osd')])
|
299
|
-
if
|
300
|
-
|
299
|
+
if (
|
300
|
+
teuth_config.get('ceph_ansible') and
|
301
|
+
hasattr(self.ctx, "machine_type") and
|
302
|
+
self.ctx.machine_type in teuth_config['ceph_ansible']['has_lvm_scratch_disks']
|
303
|
+
):
|
301
304
|
devices = get_file(remote, "/scratch_devs").decode().split()
|
302
305
|
vols = []
|
303
306
|
|
@@ -375,7 +378,7 @@ class CephAnsible(Task):
|
|
375
378
|
'python-dev'
|
376
379
|
])
|
377
380
|
ansible_repo = self.config['repo']
|
378
|
-
branch = '
|
381
|
+
branch = 'main'
|
379
382
|
if self.config.get('branch'):
|
380
383
|
branch = self.config.get('branch')
|
381
384
|
ansible_ver = 'ansible==2.5'
|
@@ -404,7 +407,6 @@ class CephAnsible(Task):
|
|
404
407
|
run.Raw('cd ~/ceph-ansible'),
|
405
408
|
run.Raw(';'),
|
406
409
|
'virtualenv',
|
407
|
-
run.Raw('--system-site-packages'),
|
408
410
|
run.Raw('--python=python3'),
|
409
411
|
'venv',
|
410
412
|
run.Raw(';'),
|
@@ -425,6 +427,11 @@ class CephAnsible(Task):
|
|
425
427
|
run.Raw('setuptools>=11.3'),
|
426
428
|
run.Raw('notario>=0.0.13'), # FIXME: use requirements.txt
|
427
429
|
run.Raw('netaddr'),
|
430
|
+
run.Raw('six'),
|
431
|
+
run.Raw(';'),
|
432
|
+
'LANG=en_US.utf8',
|
433
|
+
'pip',
|
434
|
+
'install',
|
428
435
|
run.Raw(ansible_ver),
|
429
436
|
run.Raw(';'),
|
430
437
|
run.Raw(str_args)
|
teuthology/task/cephmetrics.py
CHANGED
@@ -5,8 +5,9 @@ import time
|
|
5
5
|
|
6
6
|
from teuthology.config import config as teuth_config
|
7
7
|
from teuthology.exceptions import CommandFailedError
|
8
|
+
from teuthology.task.ansible import Ansible
|
9
|
+
from teuthology.util.loggerfile import LoggerFile
|
8
10
|
|
9
|
-
from teuthology.ansible import Ansible, LoggerFile
|
10
11
|
|
11
12
|
log = logging.getLogger(__name__)
|
12
13
|
|
teuthology/task/clock.py
CHANGED
@@ -8,6 +8,13 @@ from teuthology.orchestra import run
|
|
8
8
|
|
9
9
|
log = logging.getLogger(__name__)
|
10
10
|
|
11
|
+
def filter_out_containers(cluster):
|
12
|
+
"""
|
13
|
+
Returns a cluster that excludes remotes which should skip this task.
|
14
|
+
Currently, only skips containerized remotes.
|
15
|
+
"""
|
16
|
+
return cluster.filter(lambda r: not r.is_container)
|
17
|
+
|
11
18
|
@contextlib.contextmanager
|
12
19
|
def task(ctx, config):
|
13
20
|
"""
|
@@ -30,8 +37,9 @@ def task(ctx, config):
|
|
30
37
|
"""
|
31
38
|
|
32
39
|
log.info('Syncing clocks and checking initial clock skew...')
|
33
|
-
|
34
|
-
|
40
|
+
cluster = filter_out_containers(ctx.cluster)
|
41
|
+
run.wait(
|
42
|
+
cluster.run(
|
35
43
|
args = [
|
36
44
|
'sudo', 'systemctl', 'stop', 'ntp.service', run.Raw('||'),
|
37
45
|
'sudo', 'systemctl', 'stop', 'ntpd.service', run.Raw('||'),
|
@@ -50,22 +58,27 @@ def task(ctx, config):
|
|
50
58
|
'true'
|
51
59
|
],
|
52
60
|
timeout = 360,
|
61
|
+
wait=False,
|
53
62
|
)
|
63
|
+
)
|
54
64
|
|
55
65
|
try:
|
56
66
|
yield
|
57
67
|
|
58
68
|
finally:
|
59
69
|
log.info('Checking final clock skew...')
|
60
|
-
|
61
|
-
|
70
|
+
cluster = filter_out_containers(ctx.cluster)
|
71
|
+
run.wait(
|
72
|
+
cluster.run(
|
62
73
|
args=[
|
63
74
|
'PATH=/usr/bin:/usr/sbin', 'ntpq', '-p', run.Raw('||'),
|
64
75
|
'PATH=/usr/bin:/usr/sbin', 'chronyc', 'sources',
|
65
76
|
run.Raw('||'),
|
66
77
|
'true'
|
67
|
-
|
68
|
-
|
78
|
+
],
|
79
|
+
wait=False,
|
80
|
+
)
|
81
|
+
)
|
69
82
|
|
70
83
|
|
71
84
|
@contextlib.contextmanager
|
@@ -77,27 +90,33 @@ def check(ctx, config):
|
|
77
90
|
:param config: Configuration
|
78
91
|
"""
|
79
92
|
log.info('Checking initial clock skew...')
|
80
|
-
|
81
|
-
|
93
|
+
cluster = filter_out_containers(ctx.cluster)
|
94
|
+
run.wait(
|
95
|
+
cluster.run(
|
82
96
|
args=[
|
83
97
|
'PATH=/usr/bin:/usr/sbin', 'ntpq', '-p', run.Raw('||'),
|
84
98
|
'PATH=/usr/bin:/usr/sbin', 'chronyc', 'sources',
|
85
99
|
run.Raw('||'),
|
86
100
|
'true'
|
87
|
-
|
88
|
-
|
101
|
+
],
|
102
|
+
wait=False,
|
103
|
+
)
|
104
|
+
)
|
89
105
|
|
90
106
|
try:
|
91
107
|
yield
|
92
108
|
|
93
109
|
finally:
|
94
110
|
log.info('Checking final clock skew...')
|
95
|
-
|
96
|
-
|
111
|
+
cluster = filter_out_containers(ctx.cluster)
|
112
|
+
run.wait(
|
113
|
+
cluster.run(
|
97
114
|
args=[
|
98
115
|
'PATH=/usr/bin:/usr/sbin', 'ntpq', '-p', run.Raw('||'),
|
99
116
|
'PATH=/usr/bin:/usr/sbin', 'chronyc', 'sources',
|
100
117
|
run.Raw('||'),
|
101
118
|
'true'
|
102
|
-
|
103
|
-
|
119
|
+
],
|
120
|
+
wait=False,
|
121
|
+
)
|
122
|
+
)
|
teuthology/task/exec.py
CHANGED
@@ -23,6 +23,16 @@ def task(ctx, config):
|
|
23
23
|
It stops and fails with the first command that does not return on success. It means
|
24
24
|
that if the first command fails, the second won't run at all.
|
25
25
|
|
26
|
+
You can run a command on all hosts `all-hosts`, or all roles with `all-roles`:
|
27
|
+
|
28
|
+
tasks:
|
29
|
+
- exec:
|
30
|
+
all-hosts:
|
31
|
+
- touch /etc/passwd
|
32
|
+
- exec:
|
33
|
+
all-roles:
|
34
|
+
- pwd
|
35
|
+
|
26
36
|
To avoid confusion it is recommended to explicitly enclose the commands in
|
27
37
|
double quotes. For instance if the command is false (without double quotes) it will
|
28
38
|
be interpreted as a boolean by the YAML parser.
|
@@ -39,6 +49,14 @@ def task(ctx, config):
|
|
39
49
|
a = config['all']
|
40
50
|
roles = teuthology.all_roles(ctx.cluster)
|
41
51
|
config = dict((id_, a) for id_ in roles)
|
52
|
+
elif 'all-roles' in config and len(config) == 1:
|
53
|
+
a = config['all-roles']
|
54
|
+
roles = teuthology.all_roles(ctx.cluster)
|
55
|
+
config = dict((id_, a) for id_ in roles)
|
56
|
+
elif 'all-hosts' in config and len(config) == 1:
|
57
|
+
a = config['all-hosts']
|
58
|
+
roles = [roles[0] for roles in ctx.cluster.remotes.values()]
|
59
|
+
config = dict((id_, a) for id_ in roles)
|
42
60
|
|
43
61
|
for role, ls in config.items():
|
44
62
|
(remote,) = ctx.cluster.only(role).remotes.keys()
|
teuthology/task/hadoop.py
CHANGED
@@ -9,6 +9,7 @@ from teuthology import misc as teuthology
|
|
9
9
|
from teuthology import contextutil, packaging
|
10
10
|
from teuthology.parallel import parallel
|
11
11
|
from teuthology.task import ansible
|
12
|
+
from teuthology.exceptions import ConfigError
|
12
13
|
|
13
14
|
from distutils.version import LooseVersion
|
14
15
|
from teuthology.task.install.util import (
|
@@ -99,11 +100,13 @@ def remove_packages(ctx, config, pkgs):
|
|
99
100
|
"deb": deb._remove,
|
100
101
|
"rpm": rpm._remove,
|
101
102
|
}
|
103
|
+
cleanup = config.get('cleanup', False)
|
102
104
|
with parallel() as p:
|
103
105
|
for remote in ctx.cluster.remotes.keys():
|
104
|
-
|
105
|
-
|
106
|
-
|
106
|
+
if not remote.is_reimageable or cleanup:
|
107
|
+
system_type = teuthology.get_system_type(remote)
|
108
|
+
p.spawn(remove_pkgs[
|
109
|
+
system_type], ctx, config, remote, pkgs[system_type])
|
107
110
|
|
108
111
|
|
109
112
|
def remove_sources(ctx, config):
|
@@ -117,13 +120,15 @@ def remove_sources(ctx, config):
|
|
117
120
|
'deb': deb._remove_sources_list,
|
118
121
|
'rpm': rpm._remove_sources_list,
|
119
122
|
}
|
123
|
+
cleanup = config.get('cleanup', False)
|
124
|
+
project = config.get('project', 'ceph')
|
120
125
|
with parallel() as p:
|
121
|
-
project = config.get('project', 'ceph')
|
122
|
-
log.info("Removing {proj} sources lists".format(
|
123
|
-
proj=project))
|
124
126
|
for remote in ctx.cluster.remotes.keys():
|
125
|
-
|
126
|
-
|
127
|
+
if not remote.is_reimageable or cleanup:
|
128
|
+
log.info("Removing {p} sources lists on {r}"
|
129
|
+
.format(p=project,r=remote))
|
130
|
+
remove_fn = remove_sources_pkgs[remote.os.package_type]
|
131
|
+
p.spawn(remove_fn, ctx, config, remote)
|
127
132
|
|
128
133
|
|
129
134
|
def get_package_list(ctx, config):
|
@@ -278,7 +283,7 @@ def upgrade_remote_to_config(ctx, config):
|
|
278
283
|
# take any remote in the dict
|
279
284
|
remote = next(iter(remotes_dict))
|
280
285
|
if remote in remotes:
|
281
|
-
log.
|
286
|
+
log.warning('remote %s came up twice (role %s)', remote, role)
|
282
287
|
continue
|
283
288
|
remotes[remote] = config.get(role)
|
284
289
|
|
@@ -454,6 +459,12 @@ def task(ctx, config):
|
|
454
459
|
are welcome to add support for other distros.
|
455
460
|
|
456
461
|
|
462
|
+
Enable Fedora copr repositories using enable_coprs:
|
463
|
+
|
464
|
+
- install:
|
465
|
+
enable_coprs: [ceph/el9]
|
466
|
+
|
467
|
+
|
457
468
|
Overrides are project specific:
|
458
469
|
|
459
470
|
overrides:
|
@@ -538,8 +549,8 @@ def task(ctx, config):
|
|
538
549
|
sha1: 1234
|
539
550
|
|
540
551
|
where sha1 matches the --ceph argument. For instance if
|
541
|
-
teuthology-suite is called with --ceph
|
542
|
-
the tip of
|
552
|
+
teuthology-suite is called with --ceph main, the sha1 will be
|
553
|
+
the tip of main. If called with --ceph v0.94.1, the sha1 will be
|
543
554
|
the v0.94.1 (as returned by git rev-parse v0.94.1 which is not to
|
544
555
|
be confused with git rev-parse v0.94.1^{commit})
|
545
556
|
|
@@ -555,11 +566,25 @@ def task(ctx, config):
|
|
555
566
|
log.debug('project %s' % project)
|
556
567
|
overrides = ctx.config.get('overrides')
|
557
568
|
repos = None
|
569
|
+
|
558
570
|
if overrides:
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
571
|
+
try:
|
572
|
+
install_overrides = overrides.get('install', {})
|
573
|
+
log.debug('INSTALL overrides: %s' % install_overrides)
|
574
|
+
teuthology.deep_merge(config, install_overrides.get(project, {}))
|
575
|
+
overrides_extra_system_packages = install_overrides.get('extra_system_packages')
|
576
|
+
if overrides_extra_system_packages:
|
577
|
+
extra_system_packages = config.get('extra_system_packages')
|
578
|
+
config['extra_system_packages'] = teuthology.deep_merge(extra_system_packages, overrides_extra_system_packages)
|
579
|
+
repos = install_overrides.get('repos', None)
|
580
|
+
except AssertionError:
|
581
|
+
raise ConfigError(
|
582
|
+
"'install' task config and its overrides contain" \
|
583
|
+
"conflicting types for the same config key. Ensure that " \
|
584
|
+
"the configuration is of the same type (dict, list, etc.) " \
|
585
|
+
"in both the task definition and its overrides."
|
586
|
+
)
|
587
|
+
|
563
588
|
log.debug('config %s' % config)
|
564
589
|
|
565
590
|
rhbuild = None
|
@@ -588,23 +613,27 @@ def task(ctx, config):
|
|
588
613
|
else:
|
589
614
|
nested_config = dict(
|
590
615
|
branch=config.get('branch'),
|
591
|
-
|
592
|
-
sha1=config.get('sha1'),
|
616
|
+
cleanup=config.get('cleanup'),
|
593
617
|
debuginfo=config.get('debuginfo'),
|
594
|
-
flavor=flavor,
|
595
618
|
downgrade_packages=config.get('downgrade_packages', []),
|
619
|
+
exclude_packages=config.get('exclude_packages', []),
|
596
620
|
extra_packages=config.get('extra_packages', []),
|
597
621
|
extra_system_packages=config.get('extra_system_packages', []),
|
598
|
-
exclude_packages=config.get('exclude_packages', []),
|
599
622
|
extras=config.get('extras', None),
|
600
|
-
|
601
|
-
|
602
|
-
packages=config.get('packages', dict()),
|
623
|
+
enable_coprs=config.get('enable_coprs', []),
|
624
|
+
flavor=flavor,
|
603
625
|
install_ceph_packages=config.get('install_ceph_packages', True),
|
626
|
+
packages=config.get('packages', dict()),
|
627
|
+
project=project,
|
604
628
|
repos_only=config.get('repos_only', False),
|
629
|
+
sha1=config.get('sha1'),
|
630
|
+
tag=config.get('tag'),
|
631
|
+
wait_for_package=config.get('wait_for_package', False),
|
605
632
|
)
|
606
633
|
if repos:
|
607
634
|
nested_config['repos'] = repos
|
635
|
+
if 'shaman' in config:
|
636
|
+
nested_config['shaman'] = config['shaman']
|
608
637
|
with contextutil.nested(
|
609
638
|
lambda: install(ctx=ctx, config=nested_config),
|
610
639
|
lambda: ship_utilities(ctx=ctx, config=None),
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# If we're running as root, allow large amounts of open files.
|
3
|
+
USER=$(whoami)
|
4
|
+
|
5
|
+
# If a ulimit call fails, exit immediately.
|
6
|
+
set -e
|
7
|
+
|
8
|
+
if [ "$USER" = "root" ]
|
9
|
+
then
|
10
|
+
# Enable large number of open files
|
11
|
+
ulimit -n 65536
|
12
|
+
fi
|
13
|
+
|
14
|
+
# Enable core dumps for everything
|
15
|
+
ulimit -c unlimited
|
16
|
+
exec "$@"
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
Helper script for running long-living processes.
|
5
|
+
|
6
|
+
(Name says daemon, but that is intended to mean "long-living", we
|
7
|
+
assume child process does not double-fork.)
|
8
|
+
|
9
|
+
We start the command passed as arguments, with /dev/null as stdin, and
|
10
|
+
then wait for EOF on stdin.
|
11
|
+
|
12
|
+
When EOF is seen on stdin, the child process is killed.
|
13
|
+
|
14
|
+
When the child process exits, this helper exits too.
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
daemon-helper <signal> [--kill-group] [nostdin] COMMAND ...
|
18
|
+
"""
|
19
|
+
|
20
|
+
from __future__ import print_function
|
21
|
+
|
22
|
+
import fcntl
|
23
|
+
import os
|
24
|
+
import select
|
25
|
+
import signal
|
26
|
+
import struct
|
27
|
+
import subprocess
|
28
|
+
import sys
|
29
|
+
from argparse import ArgumentParser
|
30
|
+
|
31
|
+
parser = ArgumentParser(epilog=
|
32
|
+
'The remaining parameters are the command to be run. If these\n' +
|
33
|
+
'parameters start wih nostdin, then no stdin input is expected.')
|
34
|
+
parser.add_argument('signal')
|
35
|
+
parser.add_argument('--kill-group', action='store_true',
|
36
|
+
help='kill all processes in the group')
|
37
|
+
parser.add_argument('--nostdin', action='store_true',
|
38
|
+
help='no stdin input expected')
|
39
|
+
parsed, args = parser.parse_known_args()
|
40
|
+
end_signal = signal.SIGKILL
|
41
|
+
if parsed.signal == 'term':
|
42
|
+
end_signal = signal.SIGTERM
|
43
|
+
group = parsed.kill_group
|
44
|
+
nostdin = parsed.nostdin
|
45
|
+
skip_nostdin = 0
|
46
|
+
try:
|
47
|
+
if args[0] == 'nostdin':
|
48
|
+
nostdin = True
|
49
|
+
skip_nostdin = 1
|
50
|
+
except IndexError:
|
51
|
+
print('No command specified')
|
52
|
+
sys.exit(1)
|
53
|
+
|
54
|
+
|
55
|
+
proc = None
|
56
|
+
if nostdin:
|
57
|
+
if len(args) - skip_nostdin == 0:
|
58
|
+
print('No command specified')
|
59
|
+
sys.exit(1)
|
60
|
+
proc = subprocess.Popen(
|
61
|
+
args=args[skip_nostdin:],
|
62
|
+
)
|
63
|
+
else:
|
64
|
+
with open('/dev/null', 'rb') as devnull:
|
65
|
+
proc = subprocess.Popen(
|
66
|
+
args=args,
|
67
|
+
stdin=devnull,
|
68
|
+
preexec_fn=os.setsid,
|
69
|
+
)
|
70
|
+
|
71
|
+
flags = fcntl.fcntl(0, fcntl.F_GETFL)
|
72
|
+
fcntl.fcntl(0, fcntl.F_SETFL, flags | os.O_NDELAY)
|
73
|
+
|
74
|
+
saw_eof = False
|
75
|
+
while True:
|
76
|
+
r,w,x = select.select([0], [], [0], 0.2)
|
77
|
+
if r:
|
78
|
+
data = os.read(0, 1)
|
79
|
+
if not data:
|
80
|
+
saw_eof = True
|
81
|
+
if not group:
|
82
|
+
proc.send_signal(end_signal)
|
83
|
+
else:
|
84
|
+
os.killpg(proc.pid, end_signal)
|
85
|
+
break
|
86
|
+
else:
|
87
|
+
sig, = struct.unpack('!b', data)
|
88
|
+
if not group:
|
89
|
+
proc.send_signal(sig)
|
90
|
+
else:
|
91
|
+
os.killpg(proc.pid, end_signal)
|
92
|
+
|
93
|
+
|
94
|
+
if proc.poll() is not None:
|
95
|
+
# child exited
|
96
|
+
break
|
97
|
+
|
98
|
+
exitstatus = proc.wait()
|
99
|
+
if exitstatus > 0:
|
100
|
+
print('{me}: command failed with exit status {exitstatus:d}'.format(
|
101
|
+
me=os.path.basename(sys.argv[0]),
|
102
|
+
exitstatus=exitstatus,
|
103
|
+
), file=sys.stderr)
|
104
|
+
sys.exit(exitstatus)
|
105
|
+
elif exitstatus < 0:
|
106
|
+
if saw_eof and exitstatus == -end_signal:
|
107
|
+
# suppress error from the exit we intentionally caused
|
108
|
+
pass
|
109
|
+
else:
|
110
|
+
print('{me}: command crashed with signal {signal:d}'.format(
|
111
|
+
me=os.path.basename(sys.argv[0]),
|
112
|
+
signal=-exitstatus,
|
113
|
+
), file=sys.stderr)
|
114
|
+
sys.exit(1)
|