diff --git a/scripts/caclmgrd b/scripts/caclmgrd old mode 100644 new mode 100755 index ae195be984c5..48a8f4c8ab31 --- a/scripts/caclmgrd +++ b/scripts/caclmgrd @@ -17,7 +17,7 @@ try: import sys import threading import time - from sonic_py_common.general import getstatusoutput_noshell_pipe + from sonic_py_common import daemon_base, device_info, multi_asic from swsscommon import swsscommon except ImportError as err: @@ -136,7 +136,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): self.iptables_cmd_ns_prefix = {} self.config_db_map[DEFAULT_NAMESPACE] = swsscommon.ConfigDBConnector(use_unix_socket_path=True, namespace=DEFAULT_NAMESPACE) self.config_db_map[DEFAULT_NAMESPACE].connect() - self.iptables_cmd_ns_prefix[DEFAULT_NAMESPACE] = [] + self.iptables_cmd_ns_prefix[DEFAULT_NAMESPACE] = "" self.namespace_mgmt_ip = self.get_namespace_mgmt_ip(self.iptables_cmd_ns_prefix[DEFAULT_NAMESPACE], DEFAULT_NAMESPACE) self.namespace_mgmt_ipv6 = self.get_namespace_mgmt_ipv6(self.iptables_cmd_ns_prefix[DEFAULT_NAMESPACE], DEFAULT_NAMESPACE) self.namespace_docker_mgmt_ip = {} @@ -174,60 +174,38 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): self.update_docker_mgmt_ip_acl(fabric_asic_namespace) def update_docker_mgmt_ip_acl(self, namespace): - self.iptables_cmd_ns_prefix[namespace] = ["ip", "netns", "exec", str(namespace)] + self.iptables_cmd_ns_prefix[namespace] = "ip netns exec " + namespace + " " self.namespace_docker_mgmt_ip[namespace] = self.get_namespace_mgmt_ip(self.iptables_cmd_ns_prefix[namespace], namespace) self.namespace_docker_mgmt_ipv6[namespace] = self.get_namespace_mgmt_ipv6(self.iptables_cmd_ns_prefix[namespace], namespace) def get_namespace_mgmt_ip(self, iptable_ns_cmd_prefix, namespace): - ip_address_cmd0 = iptable_ns_cmd_prefix + ['ip', '-4', '-o', 'addr', 'show', ("eth0" if namespace else "docker0")] - ip_address_cmd1 = ['awk', '{print $4}'] - ip_address_cmd2 = ['cut', '-d', '/', '-f1'] - ip_address_cmd3 = ['head', '-1'] + ip_address_get_command = iptable_ns_cmd_prefix + "ip -4 -o addr show " + ("eth0" if namespace else "docker0") +\ + " | awk '{print $4}' | cut -d'/' -f1 | head -1" - return self.run_commands_pipe(ip_address_cmd0, ip_address_cmd1, ip_address_cmd2, ip_address_cmd3) + return self.run_commands([ip_address_get_command]) def get_namespace_mgmt_ipv6(self, iptable_ns_cmd_prefix, namespace): - ipv6_address_cmd0 = iptable_ns_cmd_prefix + ['ip', '-6', '-o', 'addr', 'show', 'scope', 'global', ("eth0" if namespace else "docker0")] - ipv6_address_cmd1 = ['awk', '{print $4}'] - ipv6_address_cmd2 = ['cut', '-d', '/', '-f1'] - ipv6_address_cmd3 = ['head', '-1'] - return self.run_commands_pipe(ipv6_address_cmd0, ipv6_address_cmd1, ipv6_address_cmd2, ipv6_address_cmd3) - - def log_output(self, cmd, exitcodes, stdout): - if any(exitcodes): - self.log_error("Error running command '{}'".format(cmd)) - elif stdout: - return stdout.rstrip('\n') - return None + ipv6_address_get_command = iptable_ns_cmd_prefix + "ip -6 -o addr show scope global " + ("eth0" if namespace else "docker0") +\ + " | awk '{print $4}' | cut -d'/' -f1 | head -1" + return self.run_commands([ipv6_address_get_command]) def run_commands(self, commands): """ Given a list of shell commands, run them in order Args: - commands: List of List of Strings, each string is a shell command + commands: List of strings, each string is a shell command """ for cmd in commands: - proc = subprocess.Popen(cmd, universal_newlines=True, stdout=subprocess.PIPE) + proc = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE) (stdout, stderr) = proc.communicate() - output = self.log_output(cmd, [proc.returncode], stdout) - if output is not None: return output - return "" - def run_commands_pipe(self, *args): - """ - Run commands connected by shell pipes in a secure way without invoking shell injections. - Return empty string and log error if not success. Otherwise, return the command output. - Args: - args: List of strings - """ - exitcodes, stdout = getstatusoutput_noshell_pipe(*args) - cmd_list = [' '.join(arg) for arg in args] - cmd = '|'.join(cmd_list) - output = self.log_output(cmd, exitcodes, stdout) - if output is not None: return output + if proc.returncode != 0: + self.log_error("Error running command '{}'".format(cmd)) + elif stdout: + return stdout.rstrip('\n') return "" def parse_int_to_tcp_flags(self, hex_value): @@ -288,9 +266,9 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): ip_addr = next(ip_ntwrk.hosts()) if iface_table_name == "VLAN_INTERFACE" else ip_ntwrk.network_address if isinstance(ip_ntwrk, ipaddress.IPv4Network): - block_ip2me_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-d', '{}/{}'.format(ip_addr, ip_ntwrk.max_prefixlen), '-j', 'DROP']) + block_ip2me_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -d {}/{} -j DROP".format(ip_addr, ip_ntwrk.max_prefixlen)) elif isinstance(ip_ntwrk, ipaddress.IPv6Network): - block_ip2me_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-d', '{}/{}'.format(ip_addr, ip_ntwrk.max_prefixlen), '-j', 'DROP']) + block_ip2me_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -d {}/{} -j DROP".format(ip_addr, ip_ntwrk.max_prefixlen)) else: self.log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) @@ -301,27 +279,35 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): if namespace: # For namespace docker allow local communication on docker management ip for all proto - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-s', self.namespace_docker_mgmt_ip[namespace], '-d', self.namespace_docker_mgmt_ip[namespace], '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_docker_mgmt_ip[namespace], self.namespace_docker_mgmt_ip[namespace])) - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-s', self.namespace_docker_mgmt_ipv6[namespace], '-d', self.namespace_docker_mgmt_ipv6[namespace], '-j', 'ACCEPT']) - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-s', self.namespace_mgmt_ip, '-d', self.namespace_docker_mgmt_ip[namespace], '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_docker_mgmt_ipv6[namespace], self.namespace_docker_mgmt_ipv6[namespace])) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_mgmt_ip, self.namespace_docker_mgmt_ip[namespace])) - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-s', self.namespace_mgmt_ipv6, '-d', 'self.namespace_docker_mgmt_ipv6[namespace]', '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_mgmt_ipv6, self.namespace_docker_mgmt_ipv6[namespace])) else: # Also host namespace communication on docker bridge on multi-asic. if self.namespace_docker_mgmt_ip: - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-s', self.namespace_mgmt_ip, '-d', self.namespace_mgmt_ip, '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_mgmt_ip, self.namespace_mgmt_ip)) if self.namespace_docker_mgmt_ipv6: - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-s', self.namespace_mgmt_ipv6, '-d', self.namespace_mgmt_ipv6, '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -s {} -d {} -j ACCEPT".format + (self.namespace_mgmt_ipv6, self.namespace_mgmt_ipv6)) # In host allow all tcp/udp traffic from namespace docker eth0 management ip to host docker bridge for docker_mgmt_ip in list(self.namespace_docker_mgmt_ip.values()): - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-s', docker_mgmt_ip, '-d', self.namespace_mgmt_ip, '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -s {} -d {} -j ACCEPT".format + (docker_mgmt_ip, self.namespace_mgmt_ip)) for docker_mgmt_ipv6 in list(self.namespace_docker_mgmt_ipv6.values()): - allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-s', docker_mgmt_ipv6, '-d', self.namespace_mgmt_ipv6, '-j', 'ACCEPT']) + allow_internal_docker_ip_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -s {} -d {} -j ACCEPT".format + (docker_mgmt_ipv6, self.namespace_mgmt_ipv6)) return allow_internal_docker_ip_cmds @@ -337,7 +323,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): vlan_table = self.config_db_map[DEFAULT_NAMESPACE].get_table(self.VLAN_INTF_TABLE) vlan_address = get_ip_from_interface_table(vlan_table, vlan_name) fwd_dualtor_grpc_traffic_from_host_to_soc_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-t', 'nat', '--flush', 'POSTROUTING']) + "iptables -t nat --flush POSTROUTING") if loopback_address is not None: mux_table = self.config_db_map[DEFAULT_NAMESPACE].get_table(self.CONFIG_MUX_CABLE) @@ -346,7 +332,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): kvp = mux_table.get(key) if 'cable_type' in kvp and kvp['cable_type'] == 'active-active': fwd_dualtor_grpc_traffic_from_host_to_soc_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-t', 'nat', '-A', 'POSTROUTING', '--destination', kvp['soc_ipv4'], '--source', vlan_address, '-j', 'SNAT', '--to-source', loopback_address]) + "iptables -t nat -A POSTROUTING --destination {} --source {} -j SNAT --to-source {}".format(kvp['soc_ipv4'], vlan_address, loopback_address)) return fwd_dualtor_grpc_traffic_from_host_to_soc_cmds @@ -361,10 +347,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): return [] fwd_traffic_from_namespace_to_host_cmds = [] - fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-t', 'nat', '-X']) - fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-t', 'nat', '-F']) - fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-t', 'nat', '-X']) - fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-t', 'nat', '-F']) + fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -t nat -X") + fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -t nat -F") + fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -t nat -X") + fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -t nat -F") for acl_service in self.ACL_SERVICES: if self.ACL_SERVICES[acl_service]["multi_asic_ns_to_host_fwd"]: @@ -378,15 +364,23 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): for ipv4_src_ip in nat_source_ipv4_set: # IPv4 rules fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-t', 'nat', '-A', 'PREROUTING', '-p', ip_protocol, '-s', ipv4_src_ip, '--dport', dst_port, '-j', 'DNAT', '--to-destination', self.namespace_mgmt_ip]) + "iptables -t nat -A PREROUTING -p {} -s {} --dport {} -j DNAT --to-destination {}".format + (ip_protocol, ipv4_src_ip, dst_port, + self.namespace_mgmt_ip)) fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-t', 'nat', '-A', 'POSTROUTING', '-p', ip_protocol, '-s', ipv4_src_ip, '--dport', dst_port, '-j', 'SNAT', '--to-source', self.namespace_docker_mgmt_ip[namespace]]) + "iptables -t nat -A POSTROUTING -p {} -s {} --dport {} -j SNAT --to-source {}".format + (ip_protocol, ipv4_src_ip, dst_port, + self.namespace_docker_mgmt_ip[namespace])) for ipv6_src_ip in nat_source_ipv6_set: # IPv6 rules fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['ip6tables', '-t', 'nat', '-A', 'PREROUTING', '-p', ip_protocol, '-s', ipv6_src_ip, '--dport', dst_port, '-j', 'DNAT', '--to-destination', self.namespace_mgmt_ipv6]) + "ip6tables -t nat -A PREROUTING -p {} -s {} --dport {} -j DNAT --to-destination {}".format + (ip_protocol, ipv6_src_ip, dst_port, + self.namespace_mgmt_ipv6)) fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['ip6tables', '-t', 'nat', '-A', 'POSTROUTING', '-p', ip_protocol, '-s', ipv6_src_ip, '--dport', dst_port, '-j', 'SNAT', '--to-source', self.namespace_docker_mgmt_ipv6[namespace]]) + "ip6tables -t nat -A POSTROUTING -p {} -s {} --dport {} -j SNAT --to-source {}".format + (ip_protocol,ipv6_src_ip, dst_port, + self.namespace_docker_mgmt_ipv6[namespace])) return fwd_traffic_from_namespace_to_host_cmds @@ -410,24 +404,22 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): iptables_cmds = [] if dhcp_chain_exist: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-F', 'DHCP']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -F DHCP") self.log_info("DHCP chain exists, flush") else: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-N', 'DHCP']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -N DHCP") self.log_info("DHCP chain does not exist, create") - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'DHCP', '-j', 'RETURN']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A DHCP -j RETURN") self.log_info("Issuing the following iptables commands for DHCP chain:") for cmd in iptables_cmds: - self.log_info(" " + ' '.join(cmd)) + self.log_info(" " + cmd) self.run_commands(iptables_cmds) def get_chain_list(self, iptable_ns_cmd_prefix, exclude_list): - cmd0 = iptable_ns_cmd_prefix + ['iptables', '-L', '-v', '-n'] - cmd1 = ['grep', 'Chain'] - cmd2 = ['awk', '{print $2}'] - chain_list = self.run_commands_pipe(cmd0, cmd1, cmd2).splitlines() + command = iptable_ns_cmd_prefix + "iptables -L -v -n | grep Chain | awk '{print $2}'" + chain_list = self.run_commands([command]).splitlines() for chain in exclude_list: if chain in chain_list: @@ -441,9 +433,9 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): sample: iptables --insert/delete/check DHCP -m mark --mark 0x67004 -j DROP ''' if mark is None: - return iptable_ns_cmd_prefix + ['iptables', '--'+str(op), 'DHCP', '-m', 'physdev', '--physdev-in', str(intf), '-j', 'DROP'] + return iptable_ns_cmd_prefix + 'iptables --{} DHCP -m physdev --physdev-in {} -j DROP'.format(op, intf) else: - return iptable_ns_cmd_prefix + ['iptables', '--'+str(op), 'DHCP', '-m', 'mark', '--mark', str(mark), '-j', 'DROP'] + return iptable_ns_cmd_prefix + 'iptables --{} DHCP -m mark --mark {} -j DROP'.format(op, mark) def update_dhcp_chain(self, op, intf, mark): for namespace in list(self.config_db_map.keys()): @@ -451,7 +443,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): update_cmd = self.dhcp_acl_rule(self.iptables_cmd_ns_prefix[namespace], op, intf, mark) execute = 0 - ret = subprocess.call(check_cmd) # ret==0 indicates the rule exists + ret = subprocess.call(check_cmd, shell=True) # ret==0 indicates the rule exists if op == "insert" and ret == 1: execute = 1 @@ -459,8 +451,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): execute = 1 if execute == 1: - subprocess.call(update_cmd) - self.log_info("Update DHCP chain: {}".format(' '.join(update_cmd))) + subprocess.call(update_cmd, shell=True) + self.log_info("Update DHCP chain: {}".format(update_cmd)) def update_dhcp_acl(self, key, op, data, mark): if "state" not in data: @@ -485,17 +477,17 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): for namespace in list(self.config_db_map.keys()): check_cmd = self.dhcp_acl_rule(self.iptables_cmd_ns_prefix[namespace], "check", key, pre_mark) - ret = subprocess.call(check_cmd) # ret==0 indicates the rule exists + ret = subprocess.call(check_cmd, shell=True) # ret==0 indicates the rule exists '''update only when the rule with pre_mark exists''' if ret == 0: delete_cmd = self.dhcp_acl_rule(self.iptables_cmd_ns_prefix[namespace], "delete", key, pre_mark) insert_cmd = self.dhcp_acl_rule(self.iptables_cmd_ns_prefix[namespace], "insert", key, cur_mark) - subprocess.call(delete_cmd) - self.log_info("Update DHCP chain: {}".format(' '.join(delete_cmd))) - subprocess.call(insert_cmd) - self.log_info("Update DHCP chain: {}".format(' '.join(insert_cmd))) + subprocess.call(delete_cmd, shell=True) + self.log_info("Update DHCP chain: {}".format(delete_cmd)) + subprocess.call(insert_cmd, shell=True) + self.log_info("Update DHCP chain: {}".format(insert_cmd)) def get_acl_rules_and_translate_to_iptables_commands(self, namespace): """ @@ -511,73 +503,73 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): # First, add iptables commands to set default policies to accept all # traffic. In case we are connected remotely, the connection will not # drop when we flush the current rules - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-P', 'INPUT', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-P', 'FORWARD', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-P', 'OUTPUT', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -P INPUT ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -P FORWARD ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -P OUTPUT ACCEPT") # Add iptables command to flush the current rules and delete all non-default chains chain_list = self.get_chain_list(self.iptables_cmd_ns_prefix[namespace], ["DHCP"] if self.DualToR else [""]) for chain in chain_list: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-F', chain]) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -F " + chain) if chain not in ["INPUT", "FORWARD", "OUTPUT"]: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-X', chain]) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -X " + chain) # Add same set of commands for ip6tables - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-P', 'INPUT', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-P', 'FORWARD', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-P', 'OUTPUT', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-F']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-X']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -P INPUT ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -P FORWARD ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -P OUTPUT ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -F") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -X") # Add iptables/ip6tables commands to allow all traffic from localhost - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-s', '127.0.0.1', '-i', 'lo', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-s', '::1', '-i', 'lo', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -s 127.0.0.1 -i lo -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -s ::1 -i lo -j ACCEPT") # Add iptables commands to allow internal docker traffic iptables_cmds += self.generate_allow_internal_docker_ip_traffic_commands(namespace) # Add iptables/ip6tables commands to allow all incoming packets from established # connections or new connections which are related to established connections - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-m', 'conntrack', '--ctstate', 'ESTABLISHED,RELATED', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-m', 'conntrack', '--ctstate', 'ESTABLISHED,RELATED', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT") # Add iptables/ip6tables commands to allow bidirectional ICMPv4 ping and traceroute # TODO: Support processing ICMPv4 service ACL rules, and remove this blanket acceptance - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'icmp', '--icmp-type', 'echo-request', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'icmp', '--icmp-type', 'echo-reply', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'icmp', '--icmp-type', 'destination-unreachable', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'icmp', '--icmp-type', 'time-exceeded', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT") # Add iptables/ip6tables commands to allow bidirectional ICMPv6 ping and traceroute # TODO: Support processing ICMPv6 service ACL rules, and remove this blanket acceptance - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'echo-request', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'echo-reply', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'destination-unreachable', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'time-exceeded', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT") # Add iptables/ip6tables commands to allow all incoming Neighbor Discovery Protocol (NDP) NS/NA/RS/RA messages # TODO: Support processing NDP service ACL rules, and remove this blanket acceptance - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'neighbor-solicitation', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'neighbor-advertisement', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'router-solicitation', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'icmpv6', '--icmpv6-type', 'router-advertisement', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT") # Add iptables commands to link the DCHP chain to block dhcp packets based on ingress interfaces if self.DualToR: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'udp', '--dport', '67', '-j', 'DHCP']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p udp --dport 67 -j DHCP") # Add iptables/ip6tables commands to allow all incoming IPv4 DHCP packets - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'udp', '--dport', '67:68', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'udp', '--dport', '67:68', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p udp --dport 67:68 -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p udp --dport 67:68 -j ACCEPT") # Add iptables/ip6tables commands to allow all incoming IPv6 DHCP packets - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'udp', '--dport', '546:547', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'udp', '--dport', '546:547', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p udp --dport 546:547 -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p udp --dport 546:547 -j ACCEPT") # Add iptables/ip6tables commands to allow all incoming BGP traffic # TODO: Determine BGP ACLs based on configured device sessions, and remove this blanket acceptance - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -p tcp --dport 179 -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p tcp --dport 179 -j ACCEPT") # Get current ACL tables and rules from Config DB self._tables_db_info = self.config_db_map[namespace].get_table(self.ACL_TABLE) @@ -683,24 +675,24 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): # Apply the rule to the default protocol(s) for this ACL service for ip_protocol in ip_protocols: for dst_port in dst_ports: - rule_cmd = ["ip6tables"] if table_ip_version == 6 else ["iptables"] + rule_cmd = "ip6tables" if table_ip_version == 6 else "iptables" - rule_cmd += ["-A", "INPUT"] + rule_cmd += " -A INPUT" if ip_protocol != "any": - rule_cmd += ["-p", str(ip_protocol)] + rule_cmd += " -p {}".format(ip_protocol) if "SRC_IPV6" in rule_props and rule_props["SRC_IPV6"]: - rule_cmd += ["-s", str(rule_props["SRC_IPV6"])] + rule_cmd += " -s {}".format(rule_props["SRC_IPV6"]) if rule_props["PACKET_ACTION"] == "ACCEPT": ipv6_src_ip_set.add(rule_props["SRC_IPV6"]) elif "SRC_IP" in rule_props and rule_props["SRC_IP"]: - rule_cmd += ["-s", str(rule_props["SRC_IP"])] + rule_cmd += " -s {}".format(rule_props["SRC_IP"]) if rule_props["PACKET_ACTION"] == "ACCEPT": ipv4_src_ip_set.add(rule_props["SRC_IP"]) # Destination port 0 is reserved/unused port, so, using it to apply the rule to all ports. if dst_port != "0": - rule_cmd += ["--dport", str(dst_port)] + rule_cmd += " --dport {}".format(dst_port) # If there are TCP flags present and ip protocol is TCP, append them if ip_protocol == "tcp" and "TCP_FLAGS" in rule_props and rule_props["TCP_FLAGS"]: @@ -710,10 +702,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): tcp_flags_mask = int(tcp_flags_mask, 16) if tcp_flags_mask > 0: - rule_cmd += ["--tcp-flags", "{}".format(self.parse_int_to_tcp_flags(tcp_flags_mask)), "{}".format(self.parse_int_to_tcp_flags(tcp_flags))] + rule_cmd += " --tcp-flags {mask} {flags}".format(mask=self.parse_int_to_tcp_flags(tcp_flags_mask), flags=self.parse_int_to_tcp_flags(tcp_flags)) # Append the packet action as the jump target - rule_cmd += ["-j", "{}".format(rule_props["PACKET_ACTION"])] + rule_cmd += " -j {}".format(rule_props["PACKET_ACTION"]) iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + rule_cmd) num_ctrl_plane_acl_rules += 1 @@ -726,14 +718,14 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): # Add iptables/ip6tables commands to allow all incoming packets with TTL of 0 or 1 # This allows the device to respond to tools like tcptraceroute - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-m', 'ttl', '--ttl-lt', '2', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'tcp', '-m', 'hl', '--hl-lt', '2', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -m ttl --ttl-lt 2 -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -p tcp -m hl --hl-lt 2 -j ACCEPT") # Finally, if the device has control plane ACLs configured, # add iptables/ip6tables commands to drop all other incoming packets if num_ctrl_plane_acl_rules > 0: - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-j', 'DROP']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-j', 'DROP']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -A INPUT -j DROP") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -A INPUT -j DROP") return iptables_cmds, service_to_source_ip_map @@ -746,7 +738,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): iptables_cmds, service_to_source_ip_map = self.get_acl_rules_and_translate_to_iptables_commands(namespace) self.log_info("Issuing the following iptables commands:") for cmd in iptables_cmds: - self.log_info(" " + ' '.join(cmd)) + self.log_info(" " + cmd) self.run_commands(iptables_cmds) @@ -764,14 +756,14 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): self.log_info("Issuing the following iptables commands:") for cmd in iptables_cmds: - self.log_info(" " + ' '.join(cmd)) + self.log_info(" " + cmd) self.run_commands(iptables_cmds) if self.DualToR: dualtor_iptables_cmds = self.generate_fwd_traffic_from_host_to_soc(namespace) for cmd in dualtor_iptables_cmds: - self.log_info(" " + ' '.join(cmd)) + self.log_info(" " + cmd) self.run_commands(dualtor_iptables_cmds) @@ -813,8 +805,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): def allow_bfd_protocol(self, namespace): iptables_cmds = [] # Add iptables/ip6tables commands to allow all BFD singlehop and multihop sessions - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "iptables -I INPUT 2 -p udp -m multiport --dports 3784,4784 -j ACCEPT") + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + "ip6tables -I INPUT 2 -p udp -m multiport --dports 3784,4784 -j ACCEPT") self.run_commands(iptables_cmds) def run(self): diff --git a/scripts/hostcfgd b/scripts/hostcfgd old mode 100644 new mode 100755 index c0bcdb9b67f0..c0fe58cdcf86 --- a/scripts/hostcfgd +++ b/scripts/hostcfgd @@ -11,7 +11,6 @@ import signal import re import jinja2 from sonic_py_common import device_info -from sonic_py_common.general import check_output_pipe from swsscommon.swsscommon import ConfigDBConnector, DBConnector, Table, SonicDBConfig from swsscommon import swsscommon @@ -87,17 +86,7 @@ def signal_handler(sig, frame): def run_cmd(cmd, log_err=True, raise_exception=False): try: - subprocess.check_call(cmd) - except Exception as err: - if log_err: - syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" - .format(err.cmd, err.returncode, err.output)) - if raise_exception: - raise - -def run_cmd_pipe(cmd0, cmd1, cmd2, log_err=True, raise_exception=False): - try: - check_output_pipe(cmd0, cmd1, cmd2) + subprocess.check_call(cmd, shell=True) except Exception as err: if log_err: syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" @@ -347,9 +336,9 @@ class FeatureHandler(object): if unit_file_state != "disabled" and not feature_config.has_per_asic_scope: cmds = [] for suffix in reversed(feature_suffixes): - cmds.append(["sudo", "systemctl", "stop", "{}.{}".format(feature_name, suffix)]) - cmds.append(["sudo", "systemctl", "disable", "{}.{}".format(feature_name, feature_suffixes[-1])]) - cmds.append(["sudo", "systemctl", "mask", "{}.{}".format(feature_name, feature_suffixes[-1])]) + cmds.append("sudo systemctl stop {}.{}".format(feature_name, suffix)) + cmds.append("sudo systemctl disable {}.{}".format(feature_name, feature_suffixes[-1])) + cmds.append("sudo systemctl mask {}.{}".format(feature_name, feature_suffixes[-1])) for cmd in cmds: syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd)) try: @@ -398,7 +387,7 @@ class FeatureHandler(object): try: syslog.syslog(syslog.LOG_INFO, "Reloading systemd configuration files ...") - run_cmd(["sudo", "systemctl", "daemon-reload"], raise_exception=True) + run_cmd("sudo systemctl daemon-reload", raise_exception=True) syslog.syslog(syslog.LOG_INFO, "Systemd configuration files are reloaded!") except Exception as err: syslog.syslog(syslog.LOG_ERR, "Failed to reload systemd configuration files!") @@ -422,8 +411,8 @@ class FeatureHandler(object): def get_systemd_unit_state(self, unit): """ Returns service configuration """ - cmd = ["sudo", "systemctl", "show", unit, "--property", "UnitFileState"] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + cmd = "sudo systemctl show {} --property UnitFileState".format(unit) + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: syslog.syslog(syslog.LOG_ERR, "Failed to get status of {}: rc={} stderr={}".format(unit, proc.returncode, stderr)) @@ -441,13 +430,13 @@ class FeatureHandler(object): continue cmds = [] for suffix in feature_suffixes: - cmds.append(["sudo", "systemctl", "unmask", "{}.{}".format(feature_name, suffix)]) + cmds.append("sudo systemctl unmask {}.{}".format(feature_name, suffix)) # If feature has timer associated with it, start/enable corresponding systemd .timer unit # otherwise, start/enable corresponding systemd .service unit - cmds.append(["sudo", "systemctl", "enable", "{}.{}".format(feature_name, feature_suffixes[-1])]) - cmds.append(["sudo", "systemctl", "start", "{}.{}".format(feature_name, feature_suffixes[-1])]) + cmds.append("sudo systemctl enable {}.{}".format(feature_name, feature_suffixes[-1])) + cmds.append("sudo systemctl start {}.{}".format(feature_name, feature_suffixes[-1])) for cmd in cmds: syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd)) @@ -470,9 +459,9 @@ class FeatureHandler(object): continue cmds = [] for suffix in reversed(feature_suffixes): - cmds.append(["sudo", "systemctl", "stop", "{}.{}".format(feature_name, suffix)]) - cmds.append(["sudo", "systemctl", "disable", "{}.{}".format(feature_name, feature_suffixes[-1])]) - cmds.append(["sudo", "systemctl", "mask", "{}.{}".format(feature_name, feature_suffixes[-1])]) + cmds.append("sudo systemctl stop {}.{}".format(feature_name, suffix)) + cmds.append("sudo systemctl disable {}.{}".format(feature_name, feature_suffixes[-1])) + cmds.append("sudo systemctl mask {}.{}".format(feature_name, feature_suffixes[-1])) for cmd in cmds: syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd)) try: @@ -521,11 +510,11 @@ class Iptables(object): self.iptables_handler(row, lpbk_table[row]) def command(self, chain, ip, ver, op): - cmd = ['iptables'] if ver == '4' else ['ip6tables'] - cmd += ['-t', 'mangle', '--{}'.format(op), chain, "-p", "tcp", "--tcp-flags", 'SYN', 'SYN'] - cmd += ['-d'] if chain == 'PREROUTING' else ['-s'] - mss = str(self.tcpmss) if ver == '4' else str(self.tcp6mss) - cmd += [ip, "-j", "TCPMSS", "--set-mss", mss] + cmd = 'iptables' if ver == '4' else 'ip6tables' + cmd += ' -t mangle --{} {} -p tcp --tcp-flags SYN SYN'.format(op, chain) + cmd += ' -d' if chain == 'PREROUTING' else ' -s' + mss = self.tcpmss if ver == '4' else self.tcp6mss + cmd += ' {} -j TCPMSS --set-mss {}'.format(ip, mss) return cmd @@ -561,12 +550,12 @@ class Iptables(object): as a new rule even if it is the same as an existing one. Check this and do nothing if rule exists ''' - ret = subprocess.call(cmd) + ret = subprocess.call(cmd, shell=True) if ret == 0: syslog.syslog(syslog.LOG_INFO, "{} rule exists in {}".format(ip, chain)) else: # Modify command from Check to Append - iptables_cmds.append([word.replace('check', 'append') for word in cmd]) + iptables_cmds.append(cmd.replace("check", "append")) for cmd in iptables_cmds: syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd)) @@ -794,12 +783,8 @@ class AaaCfg(object): def modify_single_file(self, filename, operations=None): if operations: - e_list = ['-e'] * len(operations) - e_operations = [item for sublist in zip(e_list, operations) for item in sublist] - with open(filename+'.new', 'w') as f: - subprocess.call(["sed"] + e_operations + [filename], stdout=f) - subprocess.call(["mv", '-f', filename, filename+'.old']) - subprocess.call(['mv', '-f', filename+'.new', filename]) + cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}".format(' -e '.join(operations), filename) + os.system(cmd) def modify_conf_file(self): authentication = self.authentication_default.copy() @@ -881,25 +866,25 @@ class AaaCfg(object): # /etc/pam.d/sudo is not handled, because it would change the existing # behavior. It can be modified once a config knob is added for sudo. if os.path.isfile(PAM_AUTH_CONF): - self.modify_single_file(ETC_PAMD_SSHD, [ "/^@include/s/common-auth$/common-auth-sonic/" ]) - self.modify_single_file(ETC_PAMD_LOGIN, [ "/^@include/s/common-auth$/common-auth-sonic/" ]) + self.modify_single_file(ETC_PAMD_SSHD, [ "'/^@include/s/common-auth$/common-auth-sonic/'" ]) + self.modify_single_file(ETC_PAMD_LOGIN, [ "'/^@include/s/common-auth$/common-auth-sonic/'" ]) else: - self.modify_single_file(ETC_PAMD_SSHD, [ "/^@include/s/common-auth-sonic$/common-auth/" ]) - self.modify_single_file(ETC_PAMD_LOGIN, [ "/^@include/s/common-auth-sonic$/common-auth/" ]) + self.modify_single_file(ETC_PAMD_SSHD, [ "'/^@include/s/common-auth-sonic$/common-auth/'" ]) + self.modify_single_file(ETC_PAMD_LOGIN, [ "'/^@include/s/common-auth-sonic$/common-auth/'" ]) # Add tacplus/radius in nsswitch.conf if TACACS+/RADIUS enable if 'tacacs+' in authentication['login']: if os.path.isfile(NSS_CONF): - self.modify_single_file(NSS_CONF, [ "/^passwd/s/ radius//" ]) - self.modify_single_file(NSS_CONF, [ "/tacplus/b", "/^passwd/s/compat/tacplus &/", "/^passwd/s/files/tacplus &/" ]) + self.modify_single_file(NSS_CONF, [ "'/^passwd/s/ radius//'" ]) + self.modify_single_file(NSS_CONF, [ "'/tacplus/b'", "'/^passwd/s/compat/tacplus &/'", "'/^passwd/s/files/tacplus &/'" ]) elif 'radius' in authentication['login']: if os.path.isfile(NSS_CONF): self.modify_single_file(NSS_CONF, [ "'/^passwd/s/tacplus //'" ]) - self.modify_single_file(NSS_CONF, [ "/radius/b", "/^passwd/s/compat/& radius/", "/^passwd/s/files/& radius/" ]) + self.modify_single_file(NSS_CONF, [ "'/radius/b'", "'/^passwd/s/compat/& radius/'", "'/^passwd/s/files/& radius/'" ]) else: if os.path.isfile(NSS_CONF): - self.modify_single_file(NSS_CONF, [ "/^passwd/s/tacplus //g" ]) - self.modify_single_file(NSS_CONF, [ "/^passwd/s/ radius//" ]) + self.modify_single_file(NSS_CONF, [ "'/^passwd/s/tacplus //g'" ]) + self.modify_single_file(NSS_CONF, [ "'/^passwd/s/ radius//'" ]) # Add tacplus authorization configration in nsswitch.conf tacacs_authorization_conf = None @@ -958,12 +943,12 @@ class AaaCfg(object): # Start the statistics service. Only RADIUS implemented if ('radius' in authentication['login']) and ('statistics' in radius_global) and \ radius_global['statistics']: - cmd = ['service', 'aaastatsd', 'start'] + cmd = 'service aaastatsd start' else: - cmd = ['service', 'aaastatsd', 'stop'] + cmd = 'service aaastatsd stop' syslog.syslog(syslog.LOG_INFO, "cmd - {}".format(cmd)) try: - subprocess.check_call(cmd) + subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" @@ -1010,9 +995,9 @@ class PasswHardening(object): def modify_single_file_inplace(self, filename, operations=None): if operations: - cmd = ["sed", '-i'] + operations + [filename] + cmd = "sed -i {0} {1}".format(' -i '.join(operations), filename) syslog.syslog(syslog.LOG_DEBUG, "modify_single_file_inplace: cmd - {}".format(cmd)) - subprocess.call(cmd) + os.system(cmd) def set_passw_hardening_policies(self, passw_policies): # Password Hardening flow @@ -1057,14 +1042,14 @@ class PasswHardening(object): self.passwd_aging_expire_modify(curr_expiration, 'MAX_DAYS') # Aging policy for new users - self.modify_single_file_inplace(ETC_LOGIN_DEF, ["/^PASS_MAX_DAYS/c\PASS_MAX_DAYS " +str(curr_expiration)]) + self.modify_single_file_inplace(ETC_LOGIN_DEF, ["\'/^PASS_MAX_DAYS/c\PASS_MAX_DAYS " +str(curr_expiration)+"\'"]) if self.is_passwd_aging_expire_update(curr_expiration_warning, 'WARN_DAYS'): # Aging policy for existing users self.passwd_aging_expire_modify(curr_expiration_warning, 'WARN_DAYS') # Aging policy for new users - self.modify_single_file_inplace(ETC_LOGIN_DEF, ["/^PASS_WARN_AGE/c\PASS_WARN_AGE " +str(curr_expiration_warning)]) + self.modify_single_file_inplace(ETC_LOGIN_DEF, ["\'/^PASS_WARN_AGE/c\PASS_WARN_AGE " +str(curr_expiration_warning)+"\'"]) def passwd_aging_expire_modify(self, curr_expiration, age_type): normal_accounts = self.get_normal_accounts() @@ -1183,21 +1168,21 @@ class KdumpCfg(object): else: enabled = False if enabled: - run_cmd(["sonic-kdump-config", "--enable"]) + run_cmd("sonic-kdump-config --enable") else: - run_cmd(["sonic-kdump-config", "--disable"]) + run_cmd("sonic-kdump-config --disable") # Memory configuration memory = self.kdump_defaults["memory"] if data.get("memory") is not None: memory = data.get("memory") - run_cmd(["sonic-kdump-config", "--memory", memory]) + run_cmd("sonic-kdump-config --memory " + memory) # Num dumps num_dumps = self.kdump_defaults["num_dumps"] if data.get("num_dumps") is not None: num_dumps = data.get("num_dumps") - run_cmd(["sonic-kdump-config", "--num_dumps", num_dumps]) + run_cmd("sonic-kdump-config --num_dumps " + num_dumps) class NtpCfg(object): """ @@ -1230,7 +1215,7 @@ class NtpCfg(object): return else: # just restart ntp config - cmd = ['systemctl', 'restart', 'ntp-config'] + cmd = 'systemctl restart ntp-config' run_cmd(cmd) def ntp_global_update(self, key, data, is_load=False): @@ -1257,12 +1242,12 @@ class NtpCfg(object): if orig_src_set != new_src_set: syslog.syslog(syslog.LOG_INFO, "ntp global update for source intf old {} new {}, restarting ntp-config" .format(orig_src_set, new_src_set)) - cmd = ['systemctl', 'restart', 'ntp-config'] + cmd = 'systemctl restart ntp-config' run_cmd(cmd) elif new_vrf != orig_vrf: syslog.syslog(syslog.LOG_INFO, "ntp global update for vrf old {} new {}, restarting ntp service" .format(orig_vrf, new_vrf)) - cmd = ['service', 'ntp', 'restart'] + cmd = 'service ntp restart' run_cmd(cmd) def ntp_server_update(self, key, op, is_load=False): @@ -1280,7 +1265,7 @@ class NtpCfg(object): restart_config = True if restart_config: - cmd = ['systemctl', 'restart', 'ntp-config'] + cmd = 'systemctl restart ntp-config' syslog.syslog(syslog.LOG_INFO, 'ntp server update, restarting ntp-config, ntp servers configured {}'.format(self.ntp_servers)) run_cmd(cmd) @@ -1381,12 +1366,13 @@ class DeviceMetaCfg(object): .format(new_hostname)) self.hostname = new_hostname try: - run_cmd(['sudo', 'service', 'hostname-config', 'restart'], True, True) + run_cmd('sudo service hostname-config restart', True, True) except subprocess.CalledProcessError as e: syslog.syslog(syslog.LOG_ERR, 'DeviceMetaCfg: Failed to set new' ' hostname: {}'.format(e)) return - run_cmd(['sudo', 'monit', 'reload']) + + run_cmd('sudo monit reload') class MgmtIfaceCfg(object): """ @@ -1420,8 +1406,8 @@ class MgmtIfaceCfg(object): syslog.syslog(syslog.LOG_INFO, f'MgmtIfaceCfg: Set new interface ' f'config {cfg} for {iface}') try: - run_cmd(['sudo', 'systemctl', 'restart', 'interfaces-config'], True, True) - run_cmd(['sudo', 'systemctl', 'restart', 'ntp-config'], True, True) + run_cmd('sudo systemctl restart interfaces-config', True, True) + run_cmd('sudo systemctl restart ntp-config', True, True) except subprocess.CalledProcessError: syslog.syslog(syslog.LOG_ERR, f'Failed to restart management ' 'interface services') @@ -1444,9 +1430,9 @@ class MgmtIfaceCfg(object): # Restart related vrfs services try: - run_cmd(['service', 'ntp', 'stop'], True, True) - run_cmd(['systemctl', 'restart', 'interfaces-config'], True, True) - run_cmd(['service', 'ntp', 'start'], True, True) + run_cmd('service ntp stop', True, True) + run_cmd('systemctl restart interfaces-config', True, True) + run_cmd('service ntp start', True, True) except subprocess.CalledProcessError: syslog.syslog(syslog.LOG_ERR, f'Failed to restart management vrf ' 'services') @@ -1465,16 +1451,16 @@ class MgmtIfaceCfg(object): 202 00000000 0 0 0 """ try: - cmd0 = ['cat', '/proc/net/route'] - cmd1 = ['grep', '-E', r"eth0\s+00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+202"] - cmd2 = ['wc', '-l'] - run_cmd_pipe(cmd0, cmd1, cmd2, True, True) + run_cmd(r"""cat /proc/net/route | grep -E \"eth0\s+""" + r"""00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+""" + r"""\s+202\" | wc -l""", + True, True) except subprocess.CalledProcessError: syslog.syslog(syslog.LOG_ERR, 'MgmtIfaceCfg: Could not delete ' 'eth0 route') return - run_cmd(["ip", "-4", "route", "del", "default", "dev", "eth0", "metric", "202"], False) + run_cmd("ip -4 route del default dev eth0 metric 202", False) # Update cache self.mgmt_vrf_enabled = enabled @@ -1513,8 +1499,8 @@ class SyslogCfg: syslog.syslog(syslog.LOG_INFO, f'Configure syslog rate limit interval={new_interval} (old:{self.current_interval}), burst={new_burst} (old:{self.current_burst})') try: - run_cmd(['systemctl', 'reset-failed', 'rsyslog-config', 'rsyslog'], raise_exception=True) - run_cmd(['systemctl', 'restart', 'rsyslog-config'], raise_exception=True) + run_cmd('systemctl reset-failed rsyslog-config rsyslog', raise_exception=True) + run_cmd('systemctl restart rsyslog-config', raise_exception=True) self.current_interval = new_interval self.current_burst = new_burst except Exception as e: @@ -1731,8 +1717,8 @@ class HostConfigDaemon: def wait_till_system_init_done(self): # No need to print the output in the log file so using the "--quiet" # flag - systemctl_cmd = ["sudo", "systemctl", "is-system-running", "--wait", "--quiet"] - subprocess.call(systemctl_cmd) + systemctl_cmd = "sudo systemctl is-system-running --wait --quiet" + subprocess.call(systemctl_cmd, shell=True) def register_callbacks(self): diff --git a/scripts/procdockerstatsd b/scripts/procdockerstatsd index 6c3c05dc4fc9..da6fa433e325 100755 --- a/scripts/procdockerstatsd +++ b/scripts/procdockerstatsd @@ -13,7 +13,6 @@ from datetime import datetime from sonic_py_common import daemon_base from swsscommon import swsscommon -from sonic_py_common.general import getstatusoutput_noshell_pipe VERSION = '1.0' @@ -30,7 +29,7 @@ class ProcDockerStats(daemon_base.DaemonBase): self.state_db.connect("STATE_DB") def run_command(self, cmd): - proc = subprocess.Popen(cmd, universal_newlines=True, stdout=subprocess.PIPE) + proc = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE) (stdout, stderr) = proc.communicate() if proc.returncode != 0: self.log_error("Error running command '{}'".format(cmd)) @@ -119,7 +118,7 @@ class ProcDockerStats(daemon_base.DaemonBase): return dockerdict def update_dockerstats_command(self): - cmd = ["docker", "stats", "--no-stream", "-a"] + cmd = "docker stats --no-stream -a" data = self.run_command(cmd) if not data: self.log_error("'{}' returned null output".format(cmd)) @@ -136,13 +135,7 @@ class ProcDockerStats(daemon_base.DaemonBase): return True def update_processstats_command(self): - cmd0 = ["ps", "-eo", "uid,pid,ppid,%mem,%cpu,stime,tty,time,cmd", "--sort", "-%cpu"] - cmd1 = ["head", "-1024"] - cmd = ' | '.join([' '.join(cmd0), ' '.join(cmd1)]) - exitcode, data = getstatusoutput_noshell_pipe(cmd0, cmd1) - if any(exitcode): - self.log_error("Error running command '{}'".format(cmd)) - data = None + data = self.run_command("ps -eo uid,pid,ppid,%mem,%cpu,stime,tty,time,cmd --sort -%cpu | head -1024") processdata = self.format_process_cmd_output(data) value = "" # wipe out all data before updating with new values diff --git a/tests/caclmgrd/caclmgrd_bfd_test.py b/tests/caclmgrd/caclmgrd_bfd_test.py index b5128860d278..358d4c413b9c 100644 --- a/tests/caclmgrd/caclmgrd_bfd_test.py +++ b/tests/caclmgrd/caclmgrd_bfd_test.py @@ -34,18 +34,17 @@ def test_caclmgrd_bfd(self, test_name, test_data, fs): MockConfigDb.set_config_db(test_data["config_db"]) - with mock.patch("caclmgrd.ControlPlaneAclManager.run_commands_pipe", return_value='sonic'): - with mock.patch("caclmgrd.subprocess") as mocked_subprocess: - popen_mock = mock.Mock() - popen_attrs = test_data["popen_attributes"] - popen_mock.configure_mock(**popen_attrs) - mocked_subprocess.Popen.return_value = popen_mock - mocked_subprocess.PIPE = -1 - - call_rc = test_data["call_rc"] - mocked_subprocess.call.return_value = call_rc - - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - caclmgrd_daemon.allow_bfd_protocol('') - mocked_subprocess.Popen.assert_has_calls(test_data["expected_subprocess_calls"], any_order=True) + with mock.patch("caclmgrd.subprocess") as mocked_subprocess: + popen_mock = mock.Mock() + popen_attrs = test_data["popen_attributes"] + popen_mock.configure_mock(**popen_attrs) + mocked_subprocess.Popen.return_value = popen_mock + mocked_subprocess.PIPE = -1 + + call_rc = test_data["call_rc"] + mocked_subprocess.call.return_value = call_rc + + caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") + caclmgrd_daemon.allow_bfd_protocol('') + mocked_subprocess.Popen.assert_has_calls(test_data["expected_subprocess_calls"], any_order=True) diff --git a/tests/caclmgrd/caclmgrd_dhcp_test.py b/tests/caclmgrd/caclmgrd_dhcp_test.py index ff7f707003ee..a6eae7ba1230 100644 --- a/tests/caclmgrd/caclmgrd_dhcp_test.py +++ b/tests/caclmgrd/caclmgrd_dhcp_test.py @@ -33,22 +33,21 @@ def test_caclmgrd_dhcp(self, test_name, test_data, fs): MockConfigDb.set_config_db(test_data["config_db"]) - with mock.patch("caclmgrd.ControlPlaneAclManager.run_commands_pipe", return_value='sonic'): - with mock.patch("caclmgrd.subprocess") as mocked_subprocess: - popen_mock = mock.Mock() - popen_attrs = test_data["popen_attributes"] - popen_mock.configure_mock(**popen_attrs) - mocked_subprocess.Popen.return_value = popen_mock + with mock.patch("caclmgrd.subprocess") as mocked_subprocess: + popen_mock = mock.Mock() + popen_attrs = test_data["popen_attributes"] + popen_mock.configure_mock(**popen_attrs) + mocked_subprocess.Popen.return_value = popen_mock - call_rc = test_data["call_rc"] - mocked_subprocess.call.return_value = call_rc + call_rc = test_data["call_rc"] + mocked_subprocess.call.return_value = call_rc - mark = test_data["mark"] + mark = test_data["mark"] - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - mux_update = test_data["mux_update"] + caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") + mux_update = test_data["mux_update"] - for key,data in mux_update: - caclmgrd_daemon.update_dhcp_acl(key, '', data, mark) + for key,data in mux_update: + caclmgrd_daemon.update_dhcp_acl(key, '', data, mark) - mocked_subprocess.call.assert_has_calls(test_data["expected_subprocess_calls"], any_order=False) + mocked_subprocess.call.assert_has_calls(test_data["expected_subprocess_calls"], any_order=False) diff --git a/tests/caclmgrd/caclmgrd_external_client_acl_test.py b/tests/caclmgrd/caclmgrd_external_client_acl_test.py index 04c1ba1b7d8a..6fbb7a8f728a 100644 --- a/tests/caclmgrd/caclmgrd_external_client_acl_test.py +++ b/tests/caclmgrd/caclmgrd_external_client_acl_test.py @@ -41,10 +41,8 @@ def test_caclmgrd_external_client_acl(self, test_name, test_data, fs): caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") iptables_rules_ret, _ = caclmgrd_daemon.get_acl_rules_and_translate_to_iptables_commands('') - test_data['return'] = [tuple(i) for i in test_data['return']] - iptables_rules_ret = [tuple(i) for i in iptables_rules_ret] self.assertEqual(set(test_data["return"]).issubset(set(iptables_rules_ret)), True) - caclmgrd_daemon.iptables_cmd_ns_prefix['asic0'] = ['ip', 'netns', 'exec', 'asic0'] + caclmgrd_daemon.iptables_cmd_ns_prefix['asic0'] = 'ip netns exec asic0' caclmgrd_daemon.namespace_docker_mgmt_ip['asic0'] = '1.1.1.1' caclmgrd_daemon.namespace_mgmt_ip = '2.2.2.2' caclmgrd_daemon.namespace_docker_mgmt_ipv6['asic0'] = 'fd::01' diff --git a/tests/caclmgrd/caclmgrd_feature_test.py b/tests/caclmgrd/caclmgrd_feature_test.py index 399370ea7c63..b162ed01b586 100644 --- a/tests/caclmgrd/caclmgrd_feature_test.py +++ b/tests/caclmgrd/caclmgrd_feature_test.py @@ -34,18 +34,17 @@ def test_feature_present(self, test_name, test_data, fs): MockConfigDb.set_config_db(test_data["config_db"]) - with mock.patch("caclmgrd.ControlPlaneAclManager.run_commands_pipe", return_value='sonic'): - with mock.patch("caclmgrd.subprocess") as mocked_subprocess: - popen_mock = mock.Mock() - popen_attrs = test_data["popen_attributes"] - popen_mock.configure_mock(**popen_attrs) - mocked_subprocess.Popen.return_value = popen_mock - mocked_subprocess.PIPE = -1 - - call_rc = test_data["call_rc"] - mocked_subprocess.call.return_value = call_rc - - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - caclmgrd_daemon.update_feature_present() - self.assertTrue("bgp" in caclmgrd_daemon.feature_present) - self.assertEqual(caclmgrd_daemon.feature_present["bgp"], True) + with mock.patch("caclmgrd.subprocess") as mocked_subprocess: + popen_mock = mock.Mock() + popen_attrs = test_data["popen_attributes"] + popen_mock.configure_mock(**popen_attrs) + mocked_subprocess.Popen.return_value = popen_mock + mocked_subprocess.PIPE = -1 + + call_rc = test_data["call_rc"] + mocked_subprocess.call.return_value = call_rc + + caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") + caclmgrd_daemon.update_feature_present() + self.assertTrue("bgp" in caclmgrd_daemon.feature_present) + self.assertEqual(caclmgrd_daemon.feature_present["bgp"], True) diff --git a/tests/caclmgrd/caclmgrd_soc_rules_test.py b/tests/caclmgrd/caclmgrd_soc_rules_test.py index 626aed9756be..29550628b4da 100644 --- a/tests/caclmgrd/caclmgrd_soc_rules_test.py +++ b/tests/caclmgrd/caclmgrd_soc_rules_test.py @@ -36,20 +36,19 @@ def test_caclmgrd_soc(self, test_name, test_data, fs): MockConfigDb.set_config_db(test_data["config_db"]) - with mock.patch("caclmgrd.ControlPlaneAclManager.run_commands_pipe", return_value='sonic'): - with mock.patch("caclmgrd.subprocess") as mocked_subprocess: - popen_mock = mock.Mock() - popen_attrs = test_data["popen_attributes"] - popen_mock.configure_mock(**popen_attrs) - mocked_subprocess.Popen.return_value = popen_mock - mocked_subprocess.PIPE = -1 - - call_rc = test_data["call_rc"] - mocked_subprocess.call.return_value = call_rc - - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - caclmgrd_daemon.update_control_plane_nat_acls('', {}) - mocked_subprocess.Popen.assert_has_calls(test_data["expected_subprocess_calls"], any_order=True) + with mock.patch("caclmgrd.subprocess") as mocked_subprocess: + popen_mock = mock.Mock() + popen_attrs = test_data["popen_attributes"] + popen_mock.configure_mock(**popen_attrs) + mocked_subprocess.Popen.return_value = popen_mock + mocked_subprocess.PIPE = -1 + + call_rc = test_data["call_rc"] + mocked_subprocess.call.return_value = call_rc + + caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") + caclmgrd_daemon.update_control_plane_nat_acls('', {}) + mocked_subprocess.Popen.assert_has_calls(test_data["expected_subprocess_calls"], any_order=True) def test_get_ip_from_interface_table(self): if not os.path.exists(DBCONFIG_PATH): diff --git a/tests/caclmgrd/caclmgrd_test.py b/tests/caclmgrd/caclmgrd_test.py deleted file mode 100644 index 13dc6874dab1..000000000000 --- a/tests/caclmgrd/caclmgrd_test.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import sys -import swsscommon -from unittest.mock import call -from unittest import TestCase, mock -from tests.common.mock_configdb import MockConfigDb -from sonic_py_common.general import load_module_from_source - -class TestCaclmgrd(TestCase): - def setUp(self): - swsscommon.swsscommon.ConfigDBConnector = MockConfigDb - test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - modules_path = os.path.dirname(test_path) - scripts_path = os.path.join(modules_path, "scripts") - sys.path.insert(0, modules_path) - caclmgrd_path = os.path.join(scripts_path, 'caclmgrd') - self.caclmgrd = load_module_from_source('caclmgrd', caclmgrd_path) - - def test_run_commands_pipe(self): - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - output = caclmgrd_daemon.run_commands_pipe(['echo', 'caclmgrd'], ['awk', '{print $1}']) - assert output == 'caclmgrd' - - output = caclmgrd_daemon.run_commands_pipe([sys.executable, "-c", "import sys; sys.exit(6)"], [sys.executable, "-c", "import sys; sys.exit(8)"]) - assert output == '' - - def test_get_chain_list(self): - expected_calls = [call(['iptables', '-L', '-v', '-n'], ['grep', 'Chain'], ['awk', '{print $2}'])] - caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd") - with mock.patch("caclmgrd.ControlPlaneAclManager.run_commands_pipe") as mock_run_commands_pipe: - caclmgrd_daemon.get_chain_list([], ['']) - mock_run_commands_pipe.assert_has_calls(expected_calls) - diff --git a/tests/caclmgrd/test_bfd_vectors.py b/tests/caclmgrd/test_bfd_vectors.py index 8a0e5b982535..f7469376331d 100644 --- a/tests/caclmgrd/test_bfd_vectors.py +++ b/tests/caclmgrd/test_bfd_vectors.py @@ -23,8 +23,8 @@ }, }, "expected_subprocess_calls": [ - call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE), - call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE) + call("iptables -I INPUT 2 -p udp -m multiport --dports 3784,4784 -j ACCEPT", shell=True, universal_newlines=True, stdout=subprocess.PIPE), + call("ip6tables -I INPUT 2 -p udp -m multiport --dports 3784,4784 -j ACCEPT", shell=True, universal_newlines=True, stdout=subprocess.PIPE) ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), diff --git a/tests/caclmgrd/test_dhcp_vectors.py b/tests/caclmgrd/test_dhcp_vectors.py index 99b5ea504c25..242faae34d09 100644 --- a/tests/caclmgrd/test_dhcp_vectors.py +++ b/tests/caclmgrd/test_dhcp_vectors.py @@ -22,10 +22,10 @@ ("Ethernet8", {"state": "active"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -51,8 +51,8 @@ ("Ethernet4", {"state": "active"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), + call("iptables --delete DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -79,8 +79,8 @@ ("Ethernet8", {"state": "active"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -106,7 +106,7 @@ ("Ethernet4", {"state": "active"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -133,8 +133,8 @@ ("Ethernet8", {"state": "standby"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -160,7 +160,7 @@ ("Ethernet4", {"state": "standby"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -187,10 +187,10 @@ ("Ethernet8", {"state": "standby"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--insert', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), - call(['iptables', '--insert', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --insert DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --insert DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -216,8 +216,8 @@ ("Ethernet4", {"state": "standby"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), - call(['iptables', '--insert', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), + call("iptables --insert DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -244,10 +244,10 @@ ("Ethernet8", {"state": "unknown"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), + call("iptables --delete DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -273,8 +273,8 @@ ("Ethernet4", {"state": "unknown"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), - call(['iptables', '--delete', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), + call("iptables --delete DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -301,8 +301,8 @@ ("Ethernet8", {"state": "unknown"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet4', '-j', 'DROP']), - call(['iptables', '--check', 'DHCP', '-m', 'physdev', '--physdev-in', 'Ethernet8', '-j', 'DROP']), + call("iptables --check DHCP -m physdev --physdev-in Ethernet4 -j DROP", shell=True), + call("iptables --check DHCP -m physdev --physdev-in Ethernet8 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -328,7 +328,7 @@ ("Ethernet4", {"state": "unknown"}), ], "expected_subprocess_calls": [ - call(['iptables', '--check', 'DHCP', '-m', 'mark', '--mark', '0x67004', '-j', 'DROP']), + call("iptables --check DHCP -m mark --mark 0x67004 -j DROP", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), diff --git a/tests/caclmgrd/test_external_client_acl_vectors.py b/tests/caclmgrd/test_external_client_acl_vectors.py index 5f9a9a02f660..ed005dcb04a3 100644 --- a/tests/caclmgrd/test_external_client_acl_vectors.py +++ b/tests/caclmgrd/test_external_client_acl_vectors.py @@ -72,8 +72,8 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'] + "iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8081 -j ACCEPT", + "iptables -A INPUT -p tcp --dport 8081 -j DROP" ], } ], @@ -110,12 +110,12 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8082', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8083', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP'], + "iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8081 -j ACCEPT", + "iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8082 -j ACCEPT", + "iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8083 -j ACCEPT", + "iptables -A INPUT -p tcp --dport 8081 -j DROP", + "iptables -A INPUT -p tcp --dport 8082 -j DROP", + "iptables -A INPUT -p tcp --dport 8083 -j DROP", ], } ], @@ -152,8 +152,8 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'] + "iptables -A INPUT -p tcp -s 2001::2/128 --dport 8081 -j ACCEPT", + "iptables -A INPUT -p tcp --dport 8081 -j DROP" ], } ], @@ -190,12 +190,12 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8082', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8083', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP'], + "iptables -A INPUT -p tcp -s 2001::2/128 --dport 8081 -j ACCEPT", + "iptables -A INPUT -p tcp -s 2001::2/128 --dport 8082 -j ACCEPT", + "iptables -A INPUT -p tcp -s 2001::2/128 --dport 8083 -j ACCEPT", + "iptables -A INPUT -p tcp --dport 8081 -j DROP", + "iptables -A INPUT -p tcp --dport 8082 -j DROP", + "iptables -A INPUT -p tcp --dport 8083 -j DROP", ], } ] diff --git a/tests/caclmgrd/test_ip2me_vectors.py b/tests/caclmgrd/test_ip2me_vectors.py index 4cb75a329ea5..0784eb664e46 100644 --- a/tests/caclmgrd/test_ip2me_vectors.py +++ b/tests/caclmgrd/test_ip2me_vectors.py @@ -53,9 +53,9 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-d', '10.10.10.10/32', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-d', '10.10.11.10/32', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-d', '10.10.12.10/32', '-j', 'DROP'], + "iptables -A INPUT -d 10.10.10.10/32 -j DROP", + "iptables -A INPUT -d 10.10.11.10/32 -j DROP", + "iptables -A INPUT -d 10.10.12.10/32 -j DROP", ], }, ], @@ -81,7 +81,7 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-d', '10.10.11.1/32', '-j', 'DROP'], + "iptables -A INPUT -d 10.10.11.1/32 -j DROP", ], }, ], @@ -113,11 +113,11 @@ "FEATURE": {}, }, "return": [ - ['ip6tables', '-A', 'INPUT', '-d', '2001:db8:10::/128', '-j', 'DROP'], - ['ip6tables', '-A', 'INPUT', '-d', '2001:db8:11::1/128', '-j', 'DROP'], - ['ip6tables', '-A', 'INPUT', '-d', '2001:db8:12::/128', '-j', 'DROP'], - ['ip6tables', '-A', 'INPUT', '-d', '2001:db8:13::/128', '-j', 'DROP'] - ], + "ip6tables -A INPUT -d 2001:db8:10::/128 -j DROP", + "ip6tables -A INPUT -d 2001:db8:11::1/128 -j DROP", + "ip6tables -A INPUT -d 2001:db8:12::/128 -j DROP", + "ip6tables -A INPUT -d 2001:db8:13::/128 -j DROP" + ], }, ] ] diff --git a/tests/caclmgrd/test_soc_rules_vectors.py b/tests/caclmgrd/test_soc_rules_vectors.py index c3b871c79188..d8016dbe0672 100644 --- a/tests/caclmgrd/test_soc_rules_vectors.py +++ b/tests/caclmgrd/test_soc_rules_vectors.py @@ -35,7 +35,7 @@ }, }, "expected_subprocess_calls": [ - call(['iptables', '-t', 'nat', '-A', 'POSTROUTING', '--destination', '192.168.1.0/32', '--source', '10.10.10.10', '-j', 'SNAT', '--to-source', '10.10.10.10'], universal_newlines=True, stdout=-1) + call("iptables -t nat -A POSTROUTING --destination 192.168.1.0/32 --source 10.10.10.10 -j SNAT --to-source 10.10.10.10",shell=True, universal_newlines=True, stdout=-1) ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), diff --git a/tests/hostcfgd/hostcfgd_passwh_test.py b/tests/hostcfgd/hostcfgd_passwh_test.py index 8cf080343e0e..da68ad861207 100755 --- a/tests/hostcfgd/hostcfgd_passwh_test.py +++ b/tests/hostcfgd/hostcfgd_passwh_test.py @@ -9,7 +9,6 @@ from parameterized import parameterized from unittest import TestCase, mock -from sonic_py_common.general import getstatusoutput_noshell from tests.hostcfgd.test_passwh_vectors import HOSTCFGD_TEST_PASSWH_VECTOR from tests.common.mock_configdb import MockConfigDb, MockDBConnector @@ -45,7 +44,7 @@ class TestHostcfgdPASSWH(TestCase): """ def run_diff(self, file1, file2): try: - _, diff_out = getstatusoutput_noshell(['diff', '-ur', file1, file2]) + diff_out = subprocess.check_output('diff -ur {} {} || true'.format(file1, file2), shell=True) return diff_out except subprocess.CalledProcessError as err: syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}".format(err.cmd, err.returncode, err.output)) @@ -180,4 +179,4 @@ def test_hostcfgd_passwh_classes(self, test_name, test_data): None """ - self.check_config(test_name, test_data, "enable_digits_class") + self.check_config(test_name, test_data, "enable_digits_class") \ No newline at end of file diff --git a/tests/hostcfgd/hostcfgd_radius_test.py b/tests/hostcfgd/hostcfgd_radius_test.py index f45f24158648..c08cd1829add 100644 --- a/tests/hostcfgd/hostcfgd_radius_test.py +++ b/tests/hostcfgd/hostcfgd_radius_test.py @@ -4,13 +4,13 @@ import shutil import os import sys +import subprocess from swsscommon import swsscommon from parameterized import parameterized from unittest import TestCase, mock from tests.hostcfgd.test_radius_vectors import HOSTCFGD_TEST_RADIUS_VECTOR from tests.common.mock_configdb import MockConfigDb, MockDBConnector -from sonic_py_common.general import getstatusoutput_noshell test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -40,8 +40,7 @@ class TestHostcfgdRADIUS(TestCase): Test hostcfd daemon - RADIUS """ def run_diff(self, file1, file2): - _, output = getstatusoutput_noshell(['diff', '-uR', file1, file2]) - return output + return subprocess.check_output('diff -uR {} {} || true'.format(file1, file2), shell=True) @parameterized.expand(HOSTCFGD_TEST_RADIUS_VECTOR) diff --git a/tests/hostcfgd/hostcfgd_tacacs_test.py b/tests/hostcfgd/hostcfgd_tacacs_test.py index 6c2e4a0aed0a..a6478c08dc0d 100644 --- a/tests/hostcfgd/hostcfgd_tacacs_test.py +++ b/tests/hostcfgd/hostcfgd_tacacs_test.py @@ -4,11 +4,11 @@ import shutil import os import sys +import subprocess from swsscommon import swsscommon from parameterized import parameterized from unittest import TestCase, mock -from sonic_py_common.general import getstatusoutput_noshell from tests.hostcfgd.test_tacacs_vectors import HOSTCFGD_TEST_TACACS_VECTOR from tests.common.mock_configdb import MockConfigDb, MockDBConnector @@ -39,8 +39,7 @@ class TestHostcfgdTACACS(TestCase): Test hostcfd daemon - TACACS """ def run_diff(self, file1, file2): - _, output = getstatusoutput_noshell(['diff', '-uR', file1, file2]) - return output + return subprocess.check_output('diff -uR {} {} || true'.format(file1, file2), shell=True) """ Check different config diff --git a/tests/hostcfgd/hostcfgd_test.py b/tests/hostcfgd/hostcfgd_test.py index ae75bc428c60..df0743c20b47 100644 --- a/tests/hostcfgd/hostcfgd_test.py +++ b/tests/hostcfgd/hostcfgd_test.py @@ -276,7 +276,7 @@ def test_ntp_global_update_ntp_servers(self): ntpcfgd = hostcfgd.NtpCfg() ntpcfgd.ntp_global_update('global', MockConfigDb.CONFIG_DB['NTP']['global']) ntpcfgd.ntp_server_update('0.debian.pool.ntp.org', 'SET') - mocked_subprocess.check_call.assert_has_calls([call(['systemctl', 'restart', 'ntp-config'])]) + mocked_subprocess.check_call.assert_has_calls([call('systemctl restart ntp-config', shell=True)]) def test_loopback_update(self): with mock.patch('hostcfgd.subprocess') as mocked_subprocess: @@ -290,7 +290,7 @@ def test_loopback_update(self): ntpcfgd.ntp_servers.add('0.debian.pool.ntp.org') ntpcfgd.handle_ntp_source_intf_chg('eth0') - mocked_subprocess.check_call.assert_has_calls([call(['systemctl', 'restart', 'ntp-config'])]) + mocked_subprocess.check_call.assert_has_calls([call('systemctl restart ntp-config', shell=True)]) class TestHostcfgdDaemon(TestCase): @@ -318,19 +318,19 @@ def test_feature_events(self, fs): daemon.start() except TimeoutError: pass - expected = [call(['sudo', 'systemctl', 'daemon-reload']), - call(['sudo', 'systemctl', 'unmask', 'dhcp_relay.service']), - call(['sudo', 'systemctl', 'enable', 'dhcp_relay.service']), - call(['sudo', 'systemctl', 'start', 'dhcp_relay.service']), - call(['sudo', 'systemctl', 'daemon-reload']), - call(['sudo', 'systemctl', 'unmask', 'mux.service']), - call(['sudo', 'systemctl', 'enable', 'mux.service']), - call(['sudo', 'systemctl', 'start', 'mux.service']), - call(['sudo', 'systemctl', 'daemon-reload']), - call(['sudo', 'systemctl', 'unmask', 'telemetry.service']), - call(['sudo', 'systemctl', 'unmask', 'telemetry.timer']), - call(['sudo', 'systemctl', 'enable', 'telemetry.timer']), - call(['sudo', 'systemctl', 'start', 'telemetry.timer'])] + expected = [call('sudo systemctl daemon-reload', shell=True), + call('sudo systemctl unmask dhcp_relay.service', shell=True), + call('sudo systemctl enable dhcp_relay.service', shell=True), + call('sudo systemctl start dhcp_relay.service', shell=True), + call('sudo systemctl daemon-reload', shell=True), + call('sudo systemctl unmask mux.service', shell=True), + call('sudo systemctl enable mux.service', shell=True), + call('sudo systemctl start mux.service', shell=True), + call('sudo systemctl daemon-reload', shell=True), + call('sudo systemctl unmask telemetry.service', shell=True), + call('sudo systemctl unmask telemetry.timer', shell=True), + call('sudo systemctl enable telemetry.timer', shell=True), + call('sudo systemctl start telemetry.timer', shell=True)] mocked_subprocess.check_call.assert_has_calls(expected) # Change the state to disabled @@ -340,12 +340,12 @@ def test_feature_events(self, fs): daemon.start() except TimeoutError: pass - expected = [call(['sudo', 'systemctl', 'stop', 'telemetry.timer']), - call(['sudo', 'systemctl', 'disable', 'telemetry.timer']), - call(['sudo', 'systemctl', 'mask', 'telemetry.timer']), - call(['sudo', 'systemctl', 'stop', 'telemetry.service']), - call(['sudo', 'systemctl', 'disable', 'telemetry.timer']), - call(['sudo', 'systemctl', 'mask', 'telemetry.timer'])] + expected = [call('sudo systemctl stop telemetry.timer', shell=True), + call('sudo systemctl disable telemetry.timer', shell=True), + call('sudo systemctl mask telemetry.timer', shell=True), + call('sudo systemctl stop telemetry.service', shell=True), + call('sudo systemctl disable telemetry.timer', shell=True), + call('sudo systemctl mask telemetry.timer', shell=True)] mocked_subprocess.check_call.assert_has_calls(expected) def test_loopback_events(self): @@ -364,9 +364,9 @@ def test_loopback_events(self): daemon.start() except TimeoutError: pass - expected = [call(['systemctl', 'restart', 'ntp-config']), - call(['iptables', '-t', 'mangle', '--append', 'PREROUTING', '-p', 'tcp', '--tcp-flags', 'SYN', 'SYN', '-d', '10.184.8.233', '-j', 'TCPMSS', '--set-mss', '1460']), - call(['iptables', '-t', 'mangle', '--append', 'POSTROUTING', '-p', 'tcp', '--tcp-flags', 'SYN', 'SYN', '-s', '10.184.8.233', '-j', 'TCPMSS', '--set-mss', '1460'])] + expected = [call('systemctl restart ntp-config', shell=True), + call('iptables -t mangle --append PREROUTING -p tcp --tcp-flags SYN SYN -d 10.184.8.233 -j TCPMSS --set-mss 1460', shell=True), + call('iptables -t mangle --append POSTROUTING -p tcp --tcp-flags SYN SYN -s 10.184.8.233 -j TCPMSS --set-mss 1460', shell=True)] mocked_subprocess.check_call.assert_has_calls(expected, any_order=True) def test_kdump_event(self): @@ -383,9 +383,9 @@ def test_kdump_event(self): daemon.start() except TimeoutError: pass - expected = [call(['sonic-kdump-config', '--disable']), - call(['sonic-kdump-config', '--num_dumps', '3']), - call(['sonic-kdump-config', '--memory', '0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M'])] + expected = [call('sonic-kdump-config --disable', shell=True), + call('sonic-kdump-config --num_dumps 3', shell=True), + call('sonic-kdump-config --memory 0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M', shell=True)] mocked_subprocess.check_call.assert_has_calls(expected, any_order=True) def test_devicemeta_event(self): @@ -414,8 +414,8 @@ def test_devicemeta_event(self): pass expected = [ - call(['sudo', 'service', 'hostname-config', 'restart']), - call(['sudo', 'monit', 'reload']) + call('sudo service hostname-config restart', shell=True), + call('sudo monit reload', shell=True) ] mocked_subprocess.check_call.assert_has_calls(expected, any_order=True) @@ -468,31 +468,30 @@ def test_mgmtiface_event(self): daemon.iptables = mock.MagicMock() daemon.passwcfg = mock.MagicMock() daemon.load(HOSTCFG_DAEMON_INIT_CFG_DB) - with mock.patch('hostcfgd.check_output_pipe') as mocked_check_output: - with mock.patch('hostcfgd.subprocess') as mocked_subprocess: - popen_mock = mock.Mock() - attrs = {'communicate.return_value': ('output', 'error')} - popen_mock.configure_mock(**attrs) - mocked_subprocess.Popen.return_value = popen_mock - - try: - daemon.start() - except TimeoutError: - pass - - expected = [ - call(['sudo', 'systemctl', 'restart', 'interfaces-config']), - call(['sudo', 'systemctl', 'restart', 'ntp-config']), - call(['service', 'ntp', 'stop']), - call(['systemctl', 'restart', 'interfaces-config']), - call(['service', 'ntp', 'start']), - call(['ip', '-4', 'route', 'del', 'default', 'dev', 'eth0', 'metric', '202']) - ] - mocked_subprocess.check_call.assert_has_calls(expected) - expected = [ - call(['cat', '/proc/net/route'], ['grep', '-E', r"eth0\s+00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+202"], ['wc', '-l']) - ] - mocked_check_output.assert_has_calls(expected) + with mock.patch('hostcfgd.subprocess') as mocked_subprocess: + popen_mock = mock.Mock() + attrs = {'communicate.return_value': ('output', 'error')} + popen_mock.configure_mock(**attrs) + mocked_subprocess.Popen.return_value = popen_mock + + try: + daemon.start() + except TimeoutError: + pass + + expected = [ + call('sudo systemctl restart interfaces-config', shell=True), + call('sudo systemctl restart ntp-config', shell=True), + call('service ntp stop', shell=True), + call('systemctl restart interfaces-config', shell=True), + call('service ntp start', shell=True), + call('cat /proc/net/route | grep -E \\"eth0\\s+00000000' + '\\s+[0-9A-Z]+\\s+[0-9]+\\s+[0-9]+\\s+[0-9]+\\s+202\\" | ' + 'wc -l', shell=True), + call('ip -4 route del default dev eth0 metric 202', shell=True) + ] + mocked_subprocess.check_call.assert_has_calls(expected, + any_order=True) class TestSyslogHandler: @mock.patch('hostcfgd.run_cmd') @@ -511,8 +510,8 @@ def test_syslog_update(self, mock_run_cmd): 'rate_limit_burst': '200' } syslog_cfg.syslog_update(data) - expected = [call(['systemctl', 'reset-failed', 'rsyslog-config', 'rsyslog'], raise_exception=True), - call(['systemctl', 'restart', 'rsyslog-config'], raise_exception=True)] + expected = [call('systemctl reset-failed rsyslog-config rsyslog', raise_exception=True), + call('systemctl restart rsyslog-config', raise_exception=True)] mock_run_cmd.assert_has_calls(expected) data = { diff --git a/tests/hostcfgd/test_radius_vectors.py b/tests/hostcfgd/test_radius_vectors.py index 5e8bd939028c..df10499e1a23 100644 --- a/tests/hostcfgd/test_radius_vectors.py +++ b/tests/hostcfgd/test_radius_vectors.py @@ -111,7 +111,7 @@ }, }, "expected_subprocess_calls": [ - call(["service", "aaastatsd", "start"]), + call("service aaastatsd start", shell=True), ], } ], @@ -174,7 +174,7 @@ }, }, "expected_subprocess_calls": [ - call(["service", "aaastatsd", "start"]), + call("service aaastatsd start", shell=True), ], }, ], diff --git a/tests/hostcfgd/test_vectors.py b/tests/hostcfgd/test_vectors.py index dbfa91fd94b8..0a39b48053d1 100644 --- a/tests/hostcfgd/test_vectors.py +++ b/tests/hostcfgd/test_vectors.py @@ -90,19 +90,19 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "unmask", "dhcp_relay.service"]), - call(["sudo", "systemctl", "enable", "dhcp_relay.service"]), - call(["sudo", "systemctl", "start", "dhcp_relay.service"]), - call(["sudo", "systemctl", "unmask", "mux.service"]), - call(["sudo", "systemctl", "enable", "mux.service"]), - call(["sudo", "systemctl", "start", "mux.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.timer"]), - call(["sudo", "systemctl", "enable", "telemetry.timer"]), - call(["sudo", "systemctl", "start", "telemetry.timer"]), + call("sudo systemctl unmask dhcp_relay.service", shell=True), + call("sudo systemctl enable dhcp_relay.service", shell=True), + call("sudo systemctl start dhcp_relay.service", shell=True), + call("sudo systemctl unmask mux.service", shell=True), + call("sudo systemctl enable mux.service", shell=True), + call("sudo systemctl start mux.service", shell=True), + call("sudo systemctl unmask telemetry.service", shell=True), + call("sudo systemctl unmask telemetry.timer", shell=True), + call("sudo systemctl enable telemetry.timer", shell=True), + call("sudo systemctl start telemetry.timer", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -212,19 +212,19 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "stop", "mux.service"]), - call(["sudo", "systemctl", "disable", "mux.service"]), - call(["sudo", "systemctl", "mask", "mux.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.timer"]), - call(["sudo", "systemctl", "enable", "telemetry.timer"]), - call(["sudo", "systemctl", "start", "telemetry.timer"]), - call(["sudo", "systemctl", "unmask", "sflow.service"]), - call(["sudo", "systemctl", "enable", "sflow.service"]), - call(["sudo", "systemctl", "start", "sflow.service"]), + call("sudo systemctl stop mux.service", shell=True), + call("sudo systemctl disable mux.service", shell=True), + call("sudo systemctl mask mux.service", shell=True), + call("sudo systemctl unmask telemetry.service", shell=True), + call("sudo systemctl unmask telemetry.timer", shell=True), + call("sudo systemctl enable telemetry.timer", shell=True), + call("sudo systemctl start telemetry.timer", shell=True), + call("sudo systemctl unmask sflow.service", shell=True), + call("sudo systemctl enable sflow.service", shell=True), + call("sudo systemctl start sflow.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -316,16 +316,16 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "stop", "mux.service"]), - call(["sudo", "systemctl", "disable", "mux.service"]), - call(["sudo", "systemctl", "mask", "mux.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.timer"]), - call(["sudo", "systemctl", "enable", "telemetry.timer"]), - call(["sudo", "systemctl", "start", "telemetry.timer"]), + call("sudo systemctl stop mux.service", shell=True), + call("sudo systemctl disable mux.service", shell=True), + call("sudo systemctl mask mux.service", shell=True), + call("sudo systemctl unmask telemetry.service", shell=True), + call("sudo systemctl unmask telemetry.timer", shell=True), + call("sudo systemctl enable telemetry.timer", shell=True), + call("sudo systemctl start telemetry.timer", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -417,19 +417,19 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "unmask", "dhcp_relay.service"]), - call(["sudo", "systemctl", "enable", "dhcp_relay.service"]), - call(["sudo", "systemctl", "start", "dhcp_relay.service"]), - call(["sudo", "systemctl", "stop", "mux.service"]), - call(["sudo", "systemctl", "disable", "mux.service"]), - call(["sudo", "systemctl", "mask", "mux.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.service"]), - call(["sudo", "systemctl", "unmask", "telemetry.timer"]), - call(["sudo", "systemctl", "enable", "telemetry.timer"]), - call(["sudo", "systemctl", "start", "telemetry.timer"]), + call("sudo systemctl unmask dhcp_relay.service", shell=True), + call("sudo systemctl enable dhcp_relay.service", shell=True), + call("sudo systemctl start dhcp_relay.service", shell=True), + call("sudo systemctl stop mux.service", shell=True), + call("sudo systemctl disable mux.service", shell=True), + call("sudo systemctl mask mux.service", shell=True), + call("sudo systemctl unmask telemetry.service", shell=True), + call("sudo systemctl unmask telemetry.timer", shell=True), + call("sudo systemctl enable telemetry.timer", shell=True), + call("sudo systemctl start telemetry.timer", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -523,7 +523,7 @@ }, "enable_feature_subprocess_calls": [], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('enabled', 'error') @@ -613,12 +613,12 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "stop", "bgp.service"]), - call(["sudo", "systemctl", "disable", "bgp.service"]), - call(["sudo", "systemctl", "mask", "bgp.service"]), + call("sudo systemctl stop bgp.service", shell=True), + call("sudo systemctl disable bgp.service", shell=True), + call("sudo systemctl mask bgp.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -708,12 +708,12 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "stop", "bgp.service"]), - call(["sudo", "systemctl", "disable", "bgp.service"]), - call(["sudo", "systemctl", "mask", "bgp.service"]), + call("sudo systemctl stop bgp.service", shell=True), + call("sudo systemctl disable bgp.service", shell=True), + call("sudo systemctl mask bgp.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -803,16 +803,16 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "start", "bgp.service"]), - call(["sudo", "systemctl", "enable", "bgp.service"]), - call(["sudo", "systemctl", "unmask", "bgp.service"]), - call(["sudo", "systemctl", "start", "teamd.service"]), - call(["sudo", "systemctl", "enable", "teamd.service"]), - call(["sudo", "systemctl", "unmask", "teamd.service"]), + call("sudo systemctl start bgp.service", shell=True), + call("sudo systemctl enable bgp.service", shell=True), + call("sudo systemctl unmask bgp.service", shell=True), + call("sudo systemctl start teamd.service", shell=True), + call("sudo systemctl enable teamd.service", shell=True), + call("sudo systemctl unmask teamd.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -902,16 +902,16 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "start", "bgp.service"]), - call(["sudo", "systemctl", "enable", "bgp.service"]), - call(["sudo", "systemctl", "unmask", "bgp.service"]), - call(["sudo", "systemctl", "start", "teamd.service"]), - call(["sudo", "systemctl", "enable", "teamd.service"]), - call(["sudo", "systemctl", "unmask", "teamd.service"]), + call("sudo systemctl start bgp.service", shell=True), + call("sudo systemctl enable bgp.service", shell=True), + call("sudo systemctl unmask bgp.service", shell=True), + call("sudo systemctl start teamd.service", shell=True), + call("sudo systemctl enable teamd.service", shell=True), + call("sudo systemctl unmask teamd.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -1002,28 +1002,28 @@ }, }, "enable_feature_subprocess_calls": [ - call(["sudo", "systemctl", "stop", "bgp@0.service"]), - call(["sudo", "systemctl", "disable", "bgp@0.service"]), - call(["sudo", "systemctl", "mask", "bgp@0.service"]), - call(["sudo", "systemctl", "stop", "bgp@1.service"]), - call(["sudo", "systemctl", "disable", "bgp@1.service"]), - call(["sudo", "systemctl", "mask", "bgp@1.service"]), - call(["sudo", "systemctl", "start", "teamd@0.service"]), - call(["sudo", "systemctl", "enable", "teamd@0.service"]), - call(["sudo", "systemctl", "unmask", "teamd@0.service"]), - call(["sudo", "systemctl", "start", "teamd@1.service"]), - call(["sudo", "systemctl", "enable", "teamd@1.service"]), - call(["sudo", "systemctl", "unmask", "teamd@1.service"]), - call(["sudo", "systemctl", "stop", "lldp@0.service"]), - call(["sudo", "systemctl", "disable", "lldp@0.service"]), - call(["sudo", "systemctl", "mask", "lldp@0.service"]), - call(["sudo", "systemctl", "stop", "lldp@1.service"]), - call(["sudo", "systemctl", "disable", "lldp@1.service"]), - call(["sudo", "systemctl", "mask", "lldp@1.service"]), + call("sudo systemctl stop bgp@0.service", shell=True), + call("sudo systemctl disable bgp@0.service", shell=True), + call("sudo systemctl mask bgp@0.service", shell=True), + call("sudo systemctl stop bgp@1.service", shell=True), + call("sudo systemctl disable bgp@1.service", shell=True), + call("sudo systemctl mask bgp@1.service", shell=True), + call("sudo systemctl start teamd@0.service", shell=True), + call("sudo systemctl enable teamd@0.service", shell=True), + call("sudo systemctl unmask teamd@0.service", shell=True), + call("sudo systemctl start teamd@1.service", shell=True), + call("sudo systemctl enable teamd@1.service", shell=True), + call("sudo systemctl unmask teamd@1.service", shell=True), + call("sudo systemctl stop lldp@0.service", shell=True), + call("sudo systemctl disable lldp@0.service", shell=True), + call("sudo systemctl mask lldp@0.service", shell=True), + call("sudo systemctl stop lldp@1.service", shell=True), + call("sudo systemctl disable lldp@1.service", shell=True), + call("sudo systemctl mask lldp@1.service", shell=True), ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') @@ -1129,36 +1129,36 @@ }, }, "enable_feature_subprocess_calls": [ - call(['sudo', 'systemctl', 'unmask', 'bgp@0.service']), - call(['sudo', 'systemctl', 'enable', 'bgp@0.service']), - call(['sudo', 'systemctl', 'start', 'bgp@0.service']), - call(['sudo', 'systemctl', 'unmask', 'bgp@1.service']), - call(['sudo', 'systemctl', 'enable', 'bgp@1.service']), - call(['sudo', 'systemctl', 'start', 'bgp@1.service']), - call(['sudo', 'systemctl', 'unmask', 'teamd@0.service']), - call(['sudo', 'systemctl', 'enable', 'teamd@0.service']), - call(['sudo', 'systemctl', 'start', 'teamd@0.service']), - call(['sudo', 'systemctl', 'unmask', 'teamd@1.service']), - call(['sudo', 'systemctl', 'enable', 'teamd@1.service']), - call(['sudo', 'systemctl', 'start', 'teamd@1.service']), - call(['sudo', 'systemctl', 'unmask', 'lldp.service']), - call(['sudo', 'systemctl', 'enable', 'lldp.service']), - call(['sudo', 'systemctl', 'start', 'lldp.service']), - call(['sudo', 'systemctl', 'unmask', 'lldp@0.service']), - call(['sudo', 'systemctl', 'enable', 'lldp@0.service']), - call(['sudo', 'systemctl', 'start', 'lldp@0.service']), - call(['sudo', 'systemctl', 'unmask', 'lldp@1.service']), - call(['sudo', 'systemctl', 'enable', 'lldp@1.service']), - call(['sudo', 'systemctl', 'start', 'lldp@1.service']), - call(['sudo', 'systemctl', 'unmask', 'macsec@0.service']), - call(['sudo', 'systemctl', 'enable', 'macsec@0.service']), - call(['sudo', 'systemctl', 'start', 'macsec@0.service']), - call(['sudo', 'systemctl', 'unmask', 'macsec@1.service']), - call(['sudo', 'systemctl', 'enable', 'macsec@1.service']), - call(['sudo', 'systemctl', 'start', 'macsec@1.service']) + call('sudo systemctl unmask bgp@0.service', shell=True), + call('sudo systemctl enable bgp@0.service', shell=True), + call('sudo systemctl start bgp@0.service', shell=True), + call('sudo systemctl unmask bgp@1.service', shell=True), + call('sudo systemctl enable bgp@1.service', shell=True), + call('sudo systemctl start bgp@1.service', shell=True), + call('sudo systemctl unmask teamd@0.service', shell=True), + call('sudo systemctl enable teamd@0.service', shell=True), + call('sudo systemctl start teamd@0.service', shell=True), + call('sudo systemctl unmask teamd@1.service', shell=True), + call('sudo systemctl enable teamd@1.service', shell=True), + call('sudo systemctl start teamd@1.service', shell=True), + call('sudo systemctl unmask lldp.service', shell=True), + call('sudo systemctl enable lldp.service', shell=True), + call('sudo systemctl start lldp.service', shell=True), + call('sudo systemctl unmask lldp@0.service', shell=True), + call('sudo systemctl enable lldp@0.service', shell=True), + call('sudo systemctl start lldp@0.service', shell=True), + call('sudo systemctl unmask lldp@1.service', shell=True), + call('sudo systemctl enable lldp@1.service', shell=True), + call('sudo systemctl start lldp@1.service', shell=True), + call('sudo systemctl unmask macsec@0.service', shell=True), + call('sudo systemctl enable macsec@0.service', shell=True), + call('sudo systemctl start macsec@0.service', shell=True), + call('sudo systemctl unmask macsec@1.service', shell=True), + call('sudo systemctl enable macsec@1.service', shell=True), + call('sudo systemctl start macsec@1.service', shell=True) ], "daemon_reload_subprocess_call": [ - call(["sudo", "systemctl", "daemon-reload"]), + call("sudo systemctl daemon-reload", shell=True), ], "popen_attributes": { 'communicate.return_value': ('output', 'error') diff --git a/tests/mock_connector.py b/tests/mock_connector.py index 0543bac97923..d32017ff8485 100644 --- a/tests/mock_connector.py +++ b/tests/mock_connector.py @@ -22,10 +22,3 @@ def keys(self, db_id, pattern): def get_all(self, db_id, key): return MockConnector.data[key] - - def delete_all_by_pattern(self, db_id, pattern): - match = pattern.split('*')[0] - for key in MockConnector.data.keys(): - if match in key: - del MockConnector.data[key] - diff --git a/tests/procdockerstatsd_test.py b/tests/procdockerstatsd_test.py index b30c313bca11..4db198be7d75 100644 --- a/tests/procdockerstatsd_test.py +++ b/tests/procdockerstatsd_test.py @@ -1,7 +1,7 @@ import sys import os import pytest -from unittest.mock import call, patch + from swsscommon import swsscommon from sonic_py_common.general import load_module_from_source @@ -41,11 +41,3 @@ def test_convert_to_bytes(self): for test_input, expected_output in test_data: res = pdstatsd.convert_to_bytes(test_input) assert res == expected_output - - def test_update_processstats_command(self): - expected_calls = [call(["ps", "-eo", "uid,pid,ppid,%mem,%cpu,stime,tty,time,cmd", "--sort", "-%cpu"], ["head", "-1024"])] - pdstatsd = procdockerstatsd.ProcDockerStats(procdockerstatsd.SYSLOG_IDENTIFIER) - with patch("procdockerstatsd.getstatusoutput_noshell_pipe", return_value=([0, 0], 'output')) as mock_cmd: - pdstatsd.update_processstats_command() - mock_cmd.assert_has_calls(expected_calls) -