Skip to content

Commit

Permalink
Revert "[docker_image_ctl.j2] Share UTS namespace with host OS (#4169)"
Browse files Browse the repository at this point in the history
This reverts commit 1ef7403.
  • Loading branch information
lguohan committed Feb 28, 2020
1 parent 7b1f0a6 commit e20c26c
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 5 deletions.
48 changes: 44 additions & 4 deletions files/build_templates/docker_image_ctl.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

# single instance containers are still supported (even though it might not look like it)
# if no instance number is passed to this script, $DEV will simply be unset, resulting in docker
# if no instance number is passed to this script, $DEV will simply be unset, resulting in docker
# commands being sent to the base container name. E.g. `docker start database$DEV` simply starts
# the container `database` if no instance number is passed since `$DEV` is not defined

Expand Down Expand Up @@ -31,6 +31,32 @@ function getMountPoint()
echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null
}

function updateHostName()
{
HOSTS=/etc/hosts
HOSTS_TMP=/etc/hosts.tmp

EXEC="docker exec -i {{docker_container_name}}$DEV bash -c"

NEW_HOSTNAME="$1"
HOSTNAME=`$EXEC "hostname"`
if ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
HOSTNAME=`hostname`
fi

# copy HOSTS to HOSTS_TMP
$EXEC "cp $HOSTS $HOSTS_TMP"
# remove entry with hostname
$EXEC "sed -i \"/$HOSTNAME$/d\" $HOSTS_TMP"
# add entry with new hostname
$EXEC "echo -e \"127.0.0.1\t$NEW_HOSTNAME\" >> $HOSTS_TMP"

echo "Set hostname in {{docker_container_name}}$DEV container"
$EXEC "hostname '$NEW_HOSTNAME'"
$EXEC "cat $HOSTS_TMP > $HOSTS"
$EXEC "rm -f $HOSTS_TMP"
}

function getBootType()
{
# same code snippet in files/scripts/syncd.sh
Expand Down Expand Up @@ -135,7 +161,11 @@ start() {
{%- else %}
# Obtain our HWSKU as we will mount directories with these names in each docker
HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
HOSTNAME=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hostname"]'`
{%- endif %}
if [ -z "$HOSTNAME" ] || ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
HOSTNAME=`hostname`
fi

DOCKERCHECK=`docker inspect --type container {{docker_container_name}}$DEV 2>/dev/null`
if [ "$?" -eq "0" ]; then
Expand All @@ -153,6 +183,11 @@ start() {
preStartAction
docker start {{docker_container_name}}$DEV
postStartAction
CURRENT_HOSTNAME="$(docker exec {{docker_container_name}}$DEV hostname)"
if [ x"$HOSTNAME" != x"$CURRENT_HOSTNAME" ]; then
updateHostName "$HOSTNAME"
fi
updateHostName "$HOSTNAME"
exit $?
fi

Expand All @@ -175,7 +210,7 @@ start() {
if [ -z "$DEV" ]; then
NET="host"
else
{%- if docker_container_name == "database" %}
{%- if docker_container_name == "database" %}
NET="bridge"
{%- else %}
NET="container:database$DEV"
Expand All @@ -187,7 +222,6 @@ start() {
{%- endif %}
docker create {{docker_image_run_opt}} \
--net=$NET \
--uts=host \{# W/A: this should be set per-docker, for those dockers which really need host's UTS namespace #}
{%- if install_debug_image == "y" %}
-v /src:/src:ro -v /debug:/debug:rw \
{%- endif %}
Expand Down Expand Up @@ -224,6 +258,7 @@ start() {
preStartAction
docker start {{docker_container_name}}
postStartAction
updateHostName "$HOSTNAME"
}

wait() {
Expand All @@ -245,8 +280,13 @@ case "$1" in
start|wait|stop)
$1
;;
updateHostName)
cmd=$1
shift 2
$cmd $@
;;
*)
echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)}"
echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)|updateHostName namespace(optional) new_hostname}"
exit 1
;;
esac
51 changes: 50 additions & 1 deletion files/image_config/hostcfgd/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-

import os
import re
import sys
import subprocess
import syslog
Expand All @@ -23,6 +24,13 @@ TACPLUS_SERVER_TIMEOUT_DEFAULT = "5"
TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap"


def is_valid_hostname(hostname):
if hostname[-1] == "." or len(hostname) > 253:
return False
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))


def is_true(val):
if val == 'True' or val == 'true':
return True
Expand Down Expand Up @@ -230,6 +238,7 @@ class HostConfigDaemon:
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
self.aaacfg = AaaCfg()
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
self.hostname_cache=""
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
self.iptables = Iptables()
self.iptables.load(lpbk_table)
Expand All @@ -251,6 +260,45 @@ class HostConfigDaemon:
log_data['passkey'] = obfuscate(log_data['passkey'])
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))

def hostname_handler(self, key, data):
if key != "localhost":
return

hostname = data.get("hostname")

if not hostname:
syslog.syslog(syslog.LOG_WARNING, "hostname key is missing")
return
if not is_valid_hostname(hostname):
syslog.syslog(syslog.LOG_WARNING, "hostname {} is invalid".format(hostname))
return
if hostname == self.hostname_cache:
return

syslog.syslog(syslog.LOG_INFO, "Get all running containers")
cmd = 'docker ps --format "{{.Names}}"'
try:
containers = subprocess.check_output(cmd, shell=True).split("\n")[:-1]
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
.format(err.cmd, err.returncode, err.output))

for name in containers:
script = '/usr/bin/{}.sh'.format(name)
exists = os.path.isfile(script)
if not exists:
syslog.syslog(syslog.LOG_ERR, "Can't find control script for {}".format(name))
continue

cmd = "{} updateHostName {}".format(script, hostname)
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
.format(err.cmd, err.returncode, err.output))

self.hostname_cache = hostname

def lpbk_handler(self, key, data):
key = ConfigDBConnector.deserialize_key(key)
#Check if delete operation by fetch existing keys
Expand All @@ -261,7 +309,7 @@ class HostConfigDaemon:
add = False

self.iptables.iptables_handler(key, data, add)

def feature_status_handler(self, key, data):
status_data = self.config_db.get_table('FEATURE')
for key in status_data.keys():
Expand Down Expand Up @@ -305,6 +353,7 @@ class HostConfigDaemon:
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
self.config_db.subscribe('DEVICE_METADATA', lambda table, key, data: self.hostname_handler(key, data))
self.config_db.subscribe('LOOPBACK_INTERFACE', lambda table, key, data: self.lpbk_handler(key, data))
self.config_db.subscribe('FEATURE', lambda table, key, data: self.feature_status_handler(key, data))
self.config_db.listen()
Expand Down

0 comments on commit e20c26c

Please sign in to comment.