Initial support for Podman in docker-puppet

Create a new parameter in TripleO: ContainerCli.
The default is set to 'docker' for backward compatibility but it allows
to also set to 'podman'.
When podman is selected, the right commands will be run so docker-puppet
can configure the containers when Podman is the selected container
library backend.

It removes the tripleo_logs:/var/log/tripleo/ mount that was used
by tripleo-ui but we shouldn't do that here. We'll create a bind mount
in tripleo-ui container later.

It run puppet with FACTER_hostname only if NET_HOST is disabled.

Change-Id: I240b15663b720d6bd994d5114d43d51fa26d76cc
Co-Authored-by: Martin André <m.andre@redhat.com>
This commit is contained in:
Emilien Macchi 2018-08-03 16:51:23 -04:00
parent 3ad979ac72
commit e175e5ab2f
3 changed files with 73 additions and 25 deletions

View File

@ -184,6 +184,7 @@
NET_HOST: 'true'
DEBUG: '{{ docker_puppet_debug | default(false) }}'
PROCESS_COUNT: '{{ docker_puppet_process_count | default(3) }}'
CONTAINER_CLI: "{{ container_cli | default('docker') }}"
when: step == "1"
changed_when: false
check_mode: no
@ -207,6 +208,7 @@
- name: Start containers for step {{ step }}
command: >-
paunch --debug apply
--default-runtime "{{ container_cli | default('docker') }}"
--file /var/lib/tripleo-config/hashed-docker-container-startup-config-step_{{ step }}.json
--config-id tripleo_step{{ step }} --managed-by tripleo-{{ tripleo_role_name }}
changed_when: false
@ -237,6 +239,7 @@
NET_HOST: "true"
NO_ARCHIVE: "true"
STEP: "{{ step }}"
CONTAINER_CLI: "{{ container_cli | default('docker') }}"
when:
- deploy_server_id == bootstrap_server_id
- docker_puppet_tasks_json.stat.exists

View File

@ -76,6 +76,12 @@ parameters:
type: number
default: 6
description: Number of concurrent processes to use when running docker-puppet to generate config files.
ContainerCli:
type: string
default: 'docker'
description: CLI tool used to manage containers.
constraints:
- allowed_values: ['docker', 'podman']
ctlplane_service_ips:
type: json
blacklisted_ip_addresses:
@ -123,6 +129,7 @@ resources:
- name: enable_debug
- name: enable_puppet
- name: docker_puppet_debug
- name: container_cli
- name: docker_puppet_process_count
- name: role_data_step_config
- name: role_data_puppet_config
@ -366,6 +373,7 @@ resources:
enable_debug: {get_param: ConfigDebug}
enable_puppet: {get_param: EnablePuppet}
docker_puppet_debug: {get_param: DockerPuppetDebug}
container_cli: {get_param: ContainerCli}
docker_puppet_process_count: {get_param: DockerPuppetProcessCount}
role_data_step_config: {get_param: [role_data, {{role.name}}, step_config]}
role_data_puppet_config: {get_param: [role_data, {{role.name}}, puppet_config]}
@ -425,6 +433,7 @@ outputs:
UPDATE_IDENTIFIER: {get_param: DeployIdentifier}
ENABLE_DEBUG: {get_param: ConfigDebug}
ENABLE_PUPPET: {get_param: EnablePuppet}
CONTAINER_CLI: {get_param: ContainerCli}
DOCKER_PUPPET_DEBUG: {get_param: DockerPuppetDebug}
DOCKER_PUPPET_PROCESS_COUNT: {get_param: DockerPuppetProcessCount}
template: |
@ -531,6 +540,7 @@ outputs:
update_identifier: UPDATE_IDENTIFIER
enable_debug: ENABLE_DEBUG
enable_puppet: ENABLE_PUPPET
container_cli: CONTAINER_CLI
docker_puppet_debug: DOCKER_PUPPET_DEBUG
docker_puppet_process_count: DOCKER_PUPPET_PROCESS_COUNT
tasks:
@ -549,6 +559,7 @@ outputs:
vars:
bootstrap_server_id: BOOTSTRAP_SERVER_ID
step: '{{step}}'
container_cli: CONTAINER_CLI
tasks:
- import_tasks: common_deploy_steps_tasks.yaml
tags:

84
docker/docker-puppet.py Executable file → Normal file
View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
# Shell script tool to run puppet inside of the given docker container image.
# Shell script tool to run puppet inside of the given container image.
# Uses the config file at /var/lib/docker-puppet/docker-puppet.json as a source for a JSON
# array of [config_volume, puppet_tags, manifest, config_image, [volumes]] settings
# that can be used to generate config files or run ad-hoc puppet modules
@ -29,6 +29,9 @@ import time
import multiprocessing
logger = None
sh_script = '/var/lib/docker-puppet/docker-puppet.sh'
container_cli = os.environ.get('CONTAINER_CLI', 'docker')
cli_cmd = '/usr/bin/' + container_cli
def get_logger():
@ -49,6 +52,28 @@ def get_logger():
return logger
log = get_logger()
log.info('Running docker-puppet')
config_volume_prefix = os.environ.get('CONFIG_VOLUME_PREFIX', '/var/lib/config-data')
log.debug('CONFIG_VOLUME_PREFIX: %s' % config_volume_prefix)
if not os.path.exists(config_volume_prefix):
os.makedirs(config_volume_prefix)
if container_cli == 'docker':
cli_dcmd = ['--volume', '/usr/share/openstack-puppet/modules/:/usr/share/openstack-puppet/modules/:ro,z']
env = {}
elif container_cli == 'podman':
# podman doesn't allow relabeling content in /usr and
# doesn't support named volumes
cli_dcmd = ['--volume', '/usr/share/openstack-puppet/modules/:/usr/share/openstack-puppet/modules/:ro']
# podman need to find dependent binaries that are in environment
env = {'PATH': os.environ['PATH']}
else:
log.error('Invalid container_cli: %s' % container_cli)
sys.exit(1)
# this is to match what we do in deployed-server
def short_hostname():
subproc = subprocess.Popen(['hostname', '-s'],
@ -60,7 +85,7 @@ def short_hostname():
def pull_image(name):
subproc = subprocess.Popen(['/usr/bin/docker', 'inspect', name],
subproc = subprocess.Popen([cli_cmd, 'inspect', name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
@ -74,7 +99,7 @@ def pull_image(name):
log.info('Pulling image: %s' % name)
while retval != 0:
count += 1
subproc = subprocess.Popen(['/usr/bin/docker', 'pull', name],
subproc = subprocess.Popen([cli_cmd, 'pull', name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
@ -82,7 +107,7 @@ def pull_image(name):
retval = subproc.returncode
if retval != 0:
time.sleep(3)
log.warning('docker pull failed: %s' % cmd_stderr)
log.warning('%s pull failed: %s' % (container_cli, cmd_stderr))
log.warning('retrying pulling image: %s' % name)
if count >= 5:
log.error('Failed to pull image: %s' % name)
@ -119,7 +144,7 @@ def get_config_hash(config_volume):
def rm_container(name):
if os.environ.get('SHOW_DIFF', None):
log.info('Diffing container: %s' % name)
subproc = subprocess.Popen(['/usr/bin/docker', 'diff', name],
subproc = subprocess.Popen([cli_cmd, 'diff', name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
@ -129,7 +154,7 @@ def rm_container(name):
log.debug(cmd_stderr)
log.info('Removing container: %s' % name)
subproc = subprocess.Popen(['/usr/bin/docker', 'rm', name],
subproc = subprocess.Popen([cli_cmd, 'rm', name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
@ -142,8 +167,6 @@ def rm_container(name):
process_count = int(os.environ.get('PROCESS_COUNT',
multiprocessing.cpu_count()))
log = get_logger()
log.info('Running docker-puppet')
config_file = os.environ.get('CONFIG', '/var/lib/docker-puppet/docker-puppet.json')
# If specified, only this config_volume will be used
config_volume_only = os.environ.get('CONFIG_VOLUME', None)
@ -215,7 +238,6 @@ for service in (json_data or []):
log.info('Service compilation completed.')
sh_script = '/var/lib/docker-puppet/docker-puppet.sh'
with open(sh_script, 'w') as script_file:
os.chmod(script_file.name, 0o755)
script_file.write("""#!/bin/bash
@ -236,9 +258,20 @@ with open(sh_script, 'w') as script_file:
touch $origin_of_time
sync
export NET_HOST="${NET_HOST:-false}"
set +e
FACTER_hostname=$HOSTNAME FACTER_uuid=docker /usr/bin/puppet apply --summarize \
--detailed-exitcodes --color=false --logdest syslog --logdest console --modulepath=/etc/puppet/modules:/usr/share/openstack-puppet/modules $TAGS /etc/config.pp
if [ "$NET_HOST" == "false" ]; then
export FACTER_hostname=$HOSTNAME
fi
export FACTER_uuid=docker
/usr/bin/puppet apply --summarize \
--detailed-exitcodes \
--color=false \
--logdest syslog \
--logdest console \
--modulepath=/etc/puppet/modules:/usr/share/openstack-puppet/modules \
$TAGS \
/etc/config.pp
rc=$?
set -e
if [ $rc -ne 2 -a $rc -ne 0 ]; then
@ -301,7 +334,7 @@ def mp_puppet_config(*args):
rm_container('docker-puppet-%s' % config_volume)
pull_image(config_image)
dcmd = ['/usr/bin/docker', 'run',
common_dcmd = [cli_cmd, 'run',
'--user', 'root',
'--name', 'docker-puppet-%s' % config_volume,
'--env', 'PUPPET_TAGS=%s' % puppet_tags,
@ -309,40 +342,42 @@ def mp_puppet_config(*args):
'--env', 'HOSTNAME=%s' % short_hostname(),
'--env', 'NO_ARCHIVE=%s' % os.environ.get('NO_ARCHIVE', ''),
'--env', 'STEP=%s' % os.environ.get('STEP', '6'),
'--env', 'NET_HOST=%s' % os.environ.get('NET_HOST', 'false'),
'--volume', '/etc/localtime:/etc/localtime:ro',
'--volume', '%s:/etc/config.pp:ro,z' % tmp_man.name,
'--volume', '/etc/puppet/:/tmp/puppet-etc/:ro,z',
'--volume', '/usr/share/openstack-puppet/modules/:/usr/share/openstack-puppet/modules/:ro,z',
'--volume', '%s:/var/lib/config-data/:z' % os.environ.get('CONFIG_VOLUME_PREFIX', '/var/lib/config-data'),
'--volume', 'tripleo_logs:/var/log/tripleo/',
# Syslog socket for puppet logs
'--volume', '/dev/log:/dev/log',
# OpenSSL trusted CA injection
'--volume', '/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro',
'--volume', '/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro',
'--volume', '/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro',
'--volume', '/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro',
'--volume', '%s:/var/lib/config-data/:z' % os.environ.get('CONFIG_VOLUME_PREFIX', '/var/lib/config-data'),
# Syslog socket for puppet logs
'--volume', '/dev/log:/dev/log',
# script injection
'--volume', '%s:%s:z' % (sh_script, sh_script) ]
dcmd = common_dcmd + cli_dcmd
for volume in volumes:
if volume:
dcmd.extend(['--volume', volume])
dcmd.extend(['--entrypoint', sh_script])
env = {}
# NOTE(flaper87): Always copy the DOCKER_* environment variables as
# they contain the access data for the docker daemon.
for k in filter(lambda k: k.startswith('DOCKER'), os.environ.keys()):
env[k] = os.environ.get(k)
if container_cli == 'docker':
# NOTE(flaper87): Always copy the DOCKER_* environment variables as
# they contain the access data for the docker daemon.
for k in filter(lambda k: k.startswith('DOCKER'), os.environ.keys()):
env[k] = os.environ.get(k)
if os.environ.get('NET_HOST', 'false') == 'true':
log.debug('NET_HOST enabled')
dcmd.extend(['--net', 'host', '--volume',
'/etc/hosts:/etc/hosts:ro'])
dcmd.append(config_image)
log.debug('Running docker command: %s' % ' '.join(dcmd))
log.debug('Running %s command: %s' % (container_cli, ' '.join(dcmd)))
subproc = subprocess.Popen(dcmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, env=env)
@ -405,8 +440,6 @@ for returncode, config_volume in zip(returncodes, config_volumes):
# Update the startup configs with the config hash we generated above
config_volume_prefix = os.environ.get('CONFIG_VOLUME_PREFIX', '/var/lib/config-data')
log.debug('CONFIG_VOLUME_PREFIX: %s' % config_volume_prefix)
startup_configs = os.environ.get('STARTUP_CONFIG_PATTERN', '/var/lib/tripleo-config/docker-container-startup-config-step_*.json')
log.debug('STARTUP_CONFIG_PATTERN: %s' % startup_configs)
infiles = glob.glob('/var/lib/tripleo-config/docker-container-startup-config-step_*.json')
@ -432,3 +465,4 @@ for infile in infiles:
if not success:
sys.exit(1)