Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 66 additions & 43 deletions files/image_config/hostcfgd/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,40 @@ def obfuscate(data):
else:
return data


def update_feature_status(feature_name, status):
if status == "enabled":
start_cmds = []
start_cmds.append("sudo systemctl unmask {}.service".format(feature_name))
start_cmds.append("sudo systemctl enable {}.service".format(feature_name))
start_cmds.append("sudo systemctl start {}.service".format(feature_name))
for cmd in start_cmds:
syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd))
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}"
.format(err.cmd, err.returncode, err.output))
continue
syslog.syslog(syslog.LOG_INFO, "Feature '{}' is enabled and started".format(feature_name))
elif status == "disabled":
stop_cmds = []
stop_cmds.append("sudo systemctl stop {}.service".format(feature_name))
stop_cmds.append("sudo systemctl disable {}.service".format(feature_name))
stop_cmds.append("sudo systemctl mask {}.service".format(feature_name))
for cmd in stop_cmds:
syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd))
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}"
.format(err.cmd, err.returncode, err.output))
continue
syslog.syslog(syslog.LOG_INFO, "Feature '{}' is stopped and disabled".format(feature_name))
else:
syslog.syslog(syslog.LOG_ERR, "Unexpected status value '{}' for feature '{}'".format(status, feature_name))


class Iptables(object):
def __init__(self):
'''
Expand Down Expand Up @@ -114,7 +148,7 @@ class Iptables(object):
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as err:
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}"
.format(err.cmd, err.returncode, err.output))

class AaaCfg(object):
Expand Down Expand Up @@ -234,26 +268,40 @@ class HostConfigDaemon:
self.iptables = Iptables()
self.iptables.load(lpbk_table)

def update_all_feature_statuses(self):
feature_table = self.config_db.get_table('FEATURE')
for feature_name in feature_table.keys():
if not feature_name:
syslog.syslog(syslog.LOG_WARNING, "Feature is None")
continue

status = feature_table[feature_name]['status']
if not status:
syslog.syslog(syslog.LOG_WARNING, "Status of feature '{}' is None".format(feature_name))
continue

update_feature_status(feature_name, status)

def aaa_handler(self, key, data):
self.aaacfg.aaa_update(key, data)

def tacacs_server_handler(self, key, data):
self.aaacfg.tacacs_server_update(key, data)
log_data = copy.deepcopy(data)
if log_data.has_key('passkey'):
if 'passkey' in log_data:
log_data['passkey'] = obfuscate(log_data['passkey'])
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))

def tacacs_global_handler(self, key, data):
self.aaacfg.tacacs_global_update(key, data)
log_data = copy.deepcopy(data)
if log_data.has_key('passkey'):
if 'passkey' in log_data:
log_data['passkey'] = obfuscate(log_data['passkey'])
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))

def lpbk_handler(self, key, data):
key = ConfigDBConnector.deserialize_key(key)
#Check if delete operation by fetch existing keys
# Check if delete operation by fetch existing keys
keys = self.config_db.get_keys('LOOPBACK_INTERFACE')
if key in keys:
add = True
Expand All @@ -263,48 +311,23 @@ class HostConfigDaemon:
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():
if not key:
syslog.syslog(syslog.LOG_WARNING, "FEATURE key is missing")
continue
feature_name = key
feature_table = self.config_db.get_table('FEATURE')
if feature_name not in feature_table.keys():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is it possible to delete a feature from feature_table after it is enabled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The concept is that "features" are built into the image. They cannot be removed, only disabled.

syslog.syslog(syslog.LOG_WARNING, "Feature '{}' not in FEATURE table".format(feature_name))
return

status = status_data[key]['status']
if not status:
syslog.syslog(syslog.LOG_WARNING, "status is missing for {}".format(key))
continue
if status == "enabled":
start_cmds=[]
start_cmds.append("sudo systemctl unmask {}.service".format(key))
start_cmds.append("sudo systemctl enable {}.service".format(key))
start_cmds.append("sudo systemctl start {}.service".format(key))
for cmd in start_cmds:
syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd))
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))
continue
syslog.syslog(syslog.LOG_INFO, "Feature '{}' is enabled and started".format(key))
elif status == "disabled":
stop_cmds=[]
stop_cmds.append("sudo systemctl stop {}.service".format(key))
stop_cmds.append("sudo systemctl disable {}.service".format(key))
stop_cmds.append("sudo systemctl mask {}.service".format(key))
for cmd in stop_cmds:
syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd))
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))
continue
syslog.syslog(syslog.LOG_INFO, "Feature '{}' is stopped and disabled".format(key))
else:
syslog.syslog(syslog.LOG_ERR, "Unexpected status value '{}' for '{}'".format(status, key))
status = feature_table[feature_name]['status']
if not status:
syslog.syslog(syslog.LOG_WARNING, "Status of feature '{}' is None".format(feature_name))
return

update_feature_status(feature_name, status)

def start(self):
# Update all feature statuses once upon starting
self.update_all_feature_statuses()

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))
Expand Down