154 lines
4.3 KiB
Python
Executable File
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))
|