heat-agents/heat-config-docker-cmd/os-refresh-config/configure.d/50-heat-config-docker-cmd

154 lines
4.3 KiB
Python
Executable File

#!/usr/bin/env python
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import logging
import os
import sys
import subprocess
CONF_FILE = os.environ.get('HEAT_SHELL_CONFIG',
'/var/run/heat-config/heat-config')
DOCKER_CMD = os.environ.get('HEAT_DOCKER_CMD', 'docker')
log = None
def main(argv=sys.argv):
global log
log = logging.getLogger('heat-config')
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(
logging.Formatter(
'[%(asctime)s] (%(name)s) [%(levelname)s] %(message)s'))
log.addHandler(handler)
log.setLevel('DEBUG')
if not os.path.exists(CONF_FILE):
log.warning('No config file %s' % CONF_FILE)
return 0
try:
configs = json.load(open(CONF_FILE))
except ValueError as e:
log.warning('Could not load config json: %s' % e)
return 0
cmd_config_ids = [c['id'] for c in configs
if c['group'] == 'docker-cmd']
try:
delete_missing_configs(cmd_config_ids)
except Exception as e:
log.exception(e)
try:
rename_containers()
except Exception as e:
log.exception(e)
def delete_missing_configs(config_ids):
for conf_id in current_config_ids():
if type(conf_id) is bytes:
conf_id = conf_id.decode('utf-8')
if conf_id not in config_ids:
log.debug('%s no longer exists, deleting containers' % conf_id)
remove_containers(conf_id)
def execute(cmd):
log.debug("execute command: %s" % cmd)
subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
return cmd_stdout, cmd_stderr, subproc.returncode
def current_config_ids():
# List all config_id labels for containers managed by docker-cmd
cmd = [
DOCKER_CMD, 'ps', '-a',
'--filter', 'label=managed_by=docker-cmd',
'--format', '{{.Label "config_id"}}'
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
return set()
return set(cmd_stdout.split())
def remove_containers(conf_id):
cmd = [
DOCKER_CMD, 'ps', '-q', '-a',
'--filter', 'label=managed_by=docker-cmd',
'--filter', 'label=config_id=%s' % conf_id
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode == 0:
for container in cmd_stdout.split():
remove_container(container)
def remove_container(container):
cmd = [DOCKER_CMD, 'rm', '-f', container]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
log.error('Error removing container: %s' % container)
log.error(cmd_stderr)
def rename_containers():
# list every container name, and its container_name label
cmd = [
DOCKER_CMD, 'ps', '-a',
'--format', '{{.Names}} {{.Label "container_name"}}'
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
return
lines = cmd_stdout.split(b"\n")
current_containers = []
need_renaming = {}
for line in lines:
entry = line.split()
if not entry:
continue
current_containers.append(entry[0])
# ignore if container_name label not set
if len(entry) < 2:
continue
# ignore if desired name is already actual name
if entry[0] == entry[-1]:
continue
need_renaming[entry[0]] = entry[-1]
for current, desired in sorted(need_renaming.items()):
if desired in current_containers:
log.info('Cannot rename "%s" since "%s" still exists' % (
current, desired))
else:
cmd = [DOCKER_CMD, 'rename', current, desired]
execute(cmd)
if __name__ == '__main__':
sys.exit(main(sys.argv))