diff --git a/common/firewall/base.py b/common/firewall/base.py index 93378c9a6..d822fbdd6 100644 --- a/common/firewall/base.py +++ b/common/firewall/base.py @@ -301,7 +301,7 @@ def unset_tag(self, fixture, tag, **kwargs): def create_fw_policy(self, scope, rules=None, **kwargs): connections = kwargs.pop('connections', None) or self.connections return self.useFixture(FirewallPolicyFixture(scope=scope, - rules=rules, connections=connections)) + rules=rules, connections=connections, **kwargs)) def add_fw_rule(self, fwp_fixture, rule_uuid, seq_no): return fwp_fixture.add_firewall_rules([{'uuid': rule_uuid, diff --git a/common/flow_tests/base.py b/common/flow_tests/base.py index 8dc4d2947..86313a8ce 100644 --- a/common/flow_tests/base.py +++ b/common/flow_tests/base.py @@ -74,91 +74,3 @@ def setup_flow_export_rate(self, value): self.addCleanup(vnc_lib_fixture.set_flow_export_rate, current_rate) # end setup_flow_export_rate - def enable_logging_on_compute(self, node_ip, log_type, - restart_on_cleanup=True): - ''' Enable local logging on compute node - log_type: can be agent/syslog - ''' - container_name = 'agent' - conf_file = '/etc/contrail/contrail-vrouter-agent.conf' - service_name = 'contrail-vrouter-agent' - #Take backup of original conf file to revert back later - conf_file_backup = '/tmp/'+ get_random_name(conf_file.split('/')[-1]) - cmd = 'cp %s %s' % (conf_file, conf_file_backup) - status = self.inputs.run_cmd_on_server(node_ip, cmd, - container=container_name) - - self.addCleanup( - self.restore_default_config_file, conf_file, - conf_file_backup, service_name, node_ip, container_name, - restart_on_cleanup) - - oper = 'set' - section = 'DEFAULT' - self.update_contrail_conf(service_name, oper, section, - 'log_flow', 1, node_ip, container_name) - self.update_contrail_conf(service_name, oper, section, - 'log_local', 1, node_ip, container_name) - self.update_contrail_conf(service_name, oper, section, - 'log_level', 'SYS_INFO', node_ip, container_name) - - if log_type == 'syslog': - self.update_contrail_conf(service_name, oper, section, - 'use_syslog', 1, node_ip, container_name) - - self.inputs.restart_service(service_name, [node_ip], - container=container_name, verify_service=True) - #end enable_logging_on_compute - - def restore_default_config_file(self, conf_file, conf_file_backup, - service_name, node_ip, container=None, restart_on_cleanup=True): - '''Restore config file from conf_file_backup - conf_file: full path of config file location - conf_file_backup: full path of backup config file from where it will be restored - service_name: service name - ''' - cmd = "mv %s %s" % (conf_file_backup, conf_file) - output = self.inputs.run_cmd_on_server( - node_ip, - cmd, - container=container) - - if restart_on_cleanup: - self.inputs.restart_service(service_name, [node_ip], - container=container, verify_service=True) - - @retry(delay=1, tries=10) - def search_session_in_log(self, log_file, node_ip, session_log, - object_name='SessionEndpointObject'): - '''Search session in log file on node node_ip''' - - container_name = 'agent' - username = self.inputs.host_data[node_ip]['username'] - password = self.inputs.host_data[node_ip]['password'] - cmd = 'grep -a %s %s | grep -aP "%s"' % (object_name, log_file, - session_log) - output = self.inputs.run_cmd_on_server( - node_ip, cmd, username, password, container=container_name) - - if not output: - return False, None - else: - self.logger.debug("\nSession Expected: %s, \nSession found: %s", - session_log, output) - return True, output - - def search_session_in_agent_log(self, node_ip, session_log): - '''Search session in agent log file''' - - log_file = '/var/log/contrail/contrail-vrouter-agent.log*' - object_name = 'SessionEndpointObject' - return self.search_session_in_log(log_file, node_ip, session_log, - object_name=object_name) - - def search_session_in_syslog(self, node_ip, session_log): - '''Search session in syslog''' - - log_file = '/var/log/syslog*' - object_name = 'SessionData' - return self.search_session_in_log(log_file, node_ip, session_log, - object_name=object_name) diff --git a/common/sessionlogging/base.py b/common/sessionlogging/base.py index af8668a66..b963d153e 100644 --- a/common/sessionlogging/base.py +++ b/common/sessionlogging/base.py @@ -1,10 +1,11 @@ from common.flow_tests.base import FlowTestBase from common.introspect.base import BaseIntrospectSsl +from common.firewall.base import BaseFirewallTest from policy_test import PolicyFixture from vn_policy_test import VN_Policy_Fixture -from tcutils.util import retry +from tcutils.util import retry, get_random_name from security_group import list_sg_rules -import random +import random, re AGENT_LOG = 'agent' SYS_LOG = 'syslog' @@ -49,6 +50,16 @@ LOGGED_SESSION = "\[ vmi = %s vn = %s security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s sess_agg_info= \[ \[ \[ local_ip = %s service_port = %s protocol = %s ] \[ logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s sessionMap= \[ \[ \[ ip = %s port = %s ] \[ forward_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] reverse_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ], ] ] ], ] ] ]" +LOGGED_SESSION_FW = "\[ vmi = %s vn = %s application = %s remote_application = %s security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s sess_agg_info= \[ \[ \[ local_ip = %s service_port = %s protocol = %s ] \[ logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s sessionMap= \[ \[ \[ ip = %s port = %s ] \[ forward_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] reverse_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ], ] ] ], ] ] ]" + +LOGGED_TEARDOWN = "\[ vmi = %s vn = %s security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s sess_agg_info= \[ \[ \[ local_ip = %s service_port = %s protocol = %s ] \[ logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s sessionMap= \[ \[ \[ ip = %s port = %s ] \[ forward_flow_info= \[ flow_uuid = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s ] reverse_flow_info= \[ flow_uuid = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ], ] ] ], ] ] ]" + +LOGGED_TEARDOWN_FW = "\[ vmi = %s vn = %s application = %s remote_application = %s security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s sess_agg_info= \[ \[ \[ local_ip = %s service_port = %s protocol = %s ] \[ logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s sessionMap= \[ \[ \[ ip = %s port = %s ] \[ forward_flow_info= \[ flow_uuid = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s ] reverse_flow_info= \[ flow_uuid = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ], ] ] ], ] ] ]" + +LOGGED_TEARDOWN_TCP = "\[ vmi = %s vn = %s security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s sess_agg_info= \[ \[ \[ local_ip = %s service_port = %s protocol = %s ] \[ logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s sessionMap= \[ \[ \[ ip = %s port = %s ] \[ forward_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] reverse_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s teardown_time = %s teardown_bytes = %s teardown_pkts = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ], ] ] ], ] ] ]" + +LOGGED_SYSLOG = "\[ vmi = %s vn = %s ] security_policy_rule = %s remote_vn = %s is_client_session = %s is_si = %s vrouter_ip = %s local_ip = %s service_port = %s protocol = %s logged_forward_bytes = %s logged_forward_pkts = %s logged_reverse_bytes = %s logged_reverse_pkts = %s ip = %s port = %s forward_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] reverse_flow_info= \[ logged_bytes = %s logged_pkts = %s flow_uuid = %s tcp_flags = %s setup_time = %s action = %s sg_rule_uuid = %s nw_ace_uuid = %s underlay_source_port = %s ] vm = %s other_vrouter_ip = %s underlay_proto = %s ]" + class SessionLoggingBase(FlowTestBase, BaseIntrospectSsl): @classmethod @@ -130,10 +141,100 @@ def _create_resources(self, test_type='intra-node', no_of_client=1, self.verify_vms(self.client_fixtures + self.server_fixtures) + def enable_logging_on_compute(self, node_ip, log_type, + restart_on_cleanup=True): + ''' Enable local logging on compute node + log_type: can be agent/syslog + ''' + container_name = 'agent' + conf_file = '/etc/contrail/contrail-vrouter-agent.conf' + service_name = 'contrail-vrouter-agent' + #Take backup of original conf file to revert back later + conf_file_backup = '/tmp/'+ get_random_name(conf_file.split('/')[-1]) + cmd = 'cp %s %s' % (conf_file, conf_file_backup) + status = self.inputs.run_cmd_on_server(node_ip, cmd, + container=container_name) + + self.addCleanup( + self.restore_default_config_file, conf_file, + conf_file_backup, service_name, node_ip, container_name, + restart_on_cleanup) + + oper = 'set' + section = 'DEFAULT' + self.update_contrail_conf(service_name, oper, section, + 'log_flow', 1, node_ip, container_name) + self.update_contrail_conf(service_name, oper, section, + 'log_local', 1, node_ip, container_name) + self.update_contrail_conf(service_name, oper, section, + 'log_level', 'SYS_INFO', node_ip, container_name) + + if log_type == 'syslog': + self.update_contrail_conf(service_name, oper, section, + 'use_syslog', 1, node_ip, container_name) + + self.inputs.restart_service(service_name, [node_ip], + container=container_name, verify_service=True) + #end enable_logging_on_compute + + def restore_default_config_file(self, conf_file, conf_file_backup, + service_name, node_ip, container=None, restart_on_cleanup=True): + '''Restore config file from conf_file_backup + conf_file: full path of config file location + conf_file_backup: full path of backup config file from where it will be restored + service_name: service name + ''' + cmd = "mv %s %s" % (conf_file_backup, conf_file) + output = self.inputs.run_cmd_on_server( + node_ip, + cmd, + container=container) + + if restart_on_cleanup: + self.inputs.restart_service(service_name, [node_ip], + container=container, verify_service=True) + + @retry(delay=1, tries=10) + def search_session_in_log(self, log_file, node_ip, session_log, + object_name='SessionEndpointObject', container_name='agent'): + '''Search session in log file on node node_ip''' + + username = self.inputs.host_data[node_ip]['username'] + password = self.inputs.host_data[node_ip]['password'] + cmd = 'grep --no-messages -a %s %s | grep -aP "%s"' % (object_name, log_file, + session_log) + output = self.inputs.run_cmd_on_server( + node_ip, cmd, username, password, container=container_name) + if not output: + return False, None + elif not re.search(session_log, output): + return False, None + else: + self.logger.debug("\nSession Expected: %s, \nSession found: %s", + session_log, output) + return True, output + + def search_session_in_agent_log(self, node_ip, session_log): + '''Search session in agent log file''' + + log_file = '/var/log/contrail/contrail-vrouter-agent.log*' + object_name = 'SessionEndpointObject' + return self.search_session_in_log(log_file, node_ip, session_log, + object_name=object_name) + + def search_session_in_syslog(self, node_ip, session_log): + '''Search session in syslog''' + + log_file = '/var/log/syslog* /var/log/messages*' + object_name = 'SessionData' + return self.search_session_in_log(log_file, node_ip, session_log, + object_name=object_name, container_name=None) + def start_traffic(self, client_fixture, server_fixture, proto=1): ''' - Starts the traffic for protocol proto, supported proto are tcp, udp and icmp + Starts the traffic for protocol proto, supported proto are tcp, udp, + icmp and icmpv6 ''' self.pkt_count = 10 @@ -509,13 +610,103 @@ def start_traffic_validate_sessions_in_syslog(self, client_fixture, assert result, ("Expected server session not found in syslog for " "protocol %s" % (proto)) + def start_traffic_validate_slo_in_syslog(self, client_fixture, + server_fixture, policy_fixture=None, proto=1, underlay_proto=0, + slo_rate=1, sg_uuid=None, exp_session_count=None): + ''' + Start the traffic for protocol proto and validates the client and server + SLO sessions in syslog + ''' + + assert self.start_traffic(client_fixture, server_fixture, proto) + pkt_count = self.pkt_count + pkt_count2 = self.pkt_count2 + client_port = self.client_port + service_port = self.service_port + srv_session_c_port = self.srv_session_c_port + srv_session_s_port = self.srv_session_s_port + proto = self.proto + if exp_session_count is None: + exp_session_count = pkt_count/slo_rate if proto == 1 else 1 + + eth_type = 'IPv4' if (self.inputs.get_af() == 'v4') else 'IPv6' + proto_str = 'any' + if sg_uuid is not None: + sg_rule_id_ingress = list_sg_rules(self.connections, sg_uuid, + eth_type=eth_type, proto=proto_str, direction='ingress')[0]['id'] + sg_rule_id_egress = list_sg_rules(self.connections, sg_uuid, + eth_type=eth_type, proto=proto_str, direction='egress')[0]['id'] + else: + sg_rule_id_ingress = sg_rule_id_egress = UUID_RE + + tcp_flags = 120 if proto == 6 else 0 + project_fqname = ':'.join(self.project.project_fq_name) + client_vmi_fqname = project_fqname + ':' +\ + client_fixture.vmi_ids[client_fixture.vn_fq_name] + is_client_session = 1 + if policy_fixture: + policy_api_obj = self.vnc_lib.network_policy_read( + id=policy_fixture.get_id()) + nw_ace_uuid = policy_api_obj.get_network_policy_entries( + ).policy_rule[0].rule_uuid + else: + nw_ace_uuid = UUID_RE + + expected_client_session = LOGGED_SYSLOG % ( + client_vmi_fqname, + client_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + server_fixture.vn_fq_name, is_client_session, 0, + client_fixture.vm_node_ip, + client_fixture.vm_ip, service_port, proto, + INT_RE, pkt_count2, INT_RE, pkt_count2, + server_fixture.vm_ip, client_port, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + client_fixture.vm_id, + server_fixture.vm_node_ip, underlay_proto) + + #Verify client session + result, output = self.verify_no_of_sessions_in_syslog( + client_fixture.vm_node_ip, + expected_client_session, exp_session_count) + assert result, ("Expected No. of client session not found in syslog for " + "protocol %s" % (proto)) + + server_vmi_fqname = project_fqname + ':' +\ + server_fixture.vmi_ids[server_fixture.vn_fq_name] + is_client_session = 0 + + expected_server_session = LOGGED_SYSLOG % ( + server_vmi_fqname, + server_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + client_fixture.vn_fq_name, is_client_session, 0, + server_fixture.vm_node_ip, + server_fixture.vm_ip, srv_session_s_port, proto, + INT_RE, pkt_count2, INT_RE, pkt_count2, + client_fixture.vm_ip, srv_session_c_port, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + server_fixture.vm_id, + client_fixture.vm_node_ip, underlay_proto) + + #Verify server session + result, output = self.verify_no_of_sessions_in_syslog( + server_fixture.vm_node_ip, + expected_server_session) + assert result, ("Expected No. of server session not found in syslog for " + "protocol %s" % (proto)) + def start_traffic_validate_slo(self, client_fixture, server_fixture, policy_fixture=None, proto=1, underlay_proto=0, - slo_rate=1, sg_uuid=None): + slo_rate=1, sg_uuid=None, exp_session_count=None): ''' Start the traffic for protocol proto and validates the client and server sessions logged matching SLO in agent log. - Supported proto is(are) 1, 17 + Supported protocols are 1, 58, 17 and 6 ''' assert self.start_traffic(client_fixture, server_fixture, proto) @@ -526,7 +717,8 @@ def start_traffic_validate_slo(self, client_fixture, srv_session_c_port = self.srv_session_c_port srv_session_s_port = self.srv_session_s_port proto = self.proto - exp_session_count = pkt_count/slo_rate if proto == 1 else None + if exp_session_count is None: + exp_session_count = pkt_count/slo_rate if proto in [1, 58] else 1 eth_type = 'IPv4' if (self.inputs.get_af() == 'v4') else 'IPv6' proto_str = 'any' @@ -598,7 +790,6 @@ def start_traffic_validate_slo(self, client_fixture, result, output = self.verify_no_of_sessions_in_agent_log( server_fixture.vm_node_ip, expected_server_session, exp_session_count) - import pdb;pdb.set_trace() assert result, ("Expected no. of server sessions not found in agent log" " for protocol %s, exp:%s, got:%s" % (proto, exp_session_count, output)) @@ -606,18 +797,276 @@ def start_traffic_validate_slo(self, client_fixture, self.sleep(1) self.delete_all_flows_on_vms_compute([client_fixture, server_fixture]) - #Verify teardown sessions + #Verify teardown sessions + tcp_flags = 0 + expected_client_session = LOGGED_TEARDOWN % ( + client_vmi_fqname, + client_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + server_fixture.vn_fq_name, 1, 0, + client_fixture.vm_node_ip, + client_fixture.vm_ip, service_port, proto, + 0, 0, 0, 0, + server_fixture.vm_ip, client_port, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count,#Fwd flow + 'pass', sg_rule_id_egress, nw_ace_uuid, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count,#Reverse flow + 'pass', sg_rule_id_egress, nw_ace_uuid, + client_fixture.vm_id, + server_fixture.vm_node_ip, underlay_proto) - @retry(delay=1, tries=10) - def verify_no_of_sessions_in_agent_log(self, node_ip, session_log, - exp_session_count=None): + result, output = self.search_session_in_agent_log( + client_fixture.vm_node_ip, + expected_client_session) - log_file = '/var/log/contrail/contrail-vrouter-agent.log*' - container_name = 'agent' + if ((not result) and (proto == 6)): + expected_client_session = LOGGED_TEARDOWN_TCP % ( + client_vmi_fqname, + client_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + server_fixture.vn_fq_name, 1, 0, + client_fixture.vm_node_ip, + client_fixture.vm_ip, service_port, proto, + INT_RE, INT_RE, INT_RE, INT_RE, + server_fixture.vm_ip, client_port, + INT_RE, INT_RE, + UUID_RE, tcp_flags, INT_RE, INT_RE, INT_RE, pkt_count,#Fwd flow + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + INT_RE, INT_RE, + UUID_RE, tcp_flags, INT_RE, INT_RE, INT_RE, pkt_count,#Reverse flow + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + client_fixture.vm_id, + server_fixture.vm_node_ip, underlay_proto) + + result_tcp, output = self.search_session_in_agent_log( + client_fixture.vm_node_ip, + expected_client_session) + result = result or result_tcp + + assert result, ("Expected client session not found in agent log " + "for protocol %s" % (proto)) + + server_vmi_fqname = project_fqname + ':' +\ + server_fixture.vmi_ids[server_fixture.vn_fq_name] + + expected_server_session = LOGGED_TEARDOWN % ( + server_vmi_fqname, + server_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + client_fixture.vn_fq_name, 0, 0, + server_fixture.vm_node_ip, + server_fixture.vm_ip, srv_session_s_port, proto, + 0, 0, 0, 0, + client_fixture.vm_ip, srv_session_c_port, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, + server_fixture.vm_id, + client_fixture.vm_node_ip, underlay_proto) + + result, output = self.search_session_in_agent_log( + server_fixture.vm_node_ip, + expected_server_session) + + if ((not result) and (proto == 6)): + expected_server_session = LOGGED_TEARDOWN_TCP % ( + server_vmi_fqname, + server_fixture.vn_fq_name, FIREWALL_RULE_ID_DEFAULT, + client_fixture.vn_fq_name, 0, 0, + server_fixture.vm_node_ip, + server_fixture.vm_ip, srv_session_s_port, proto, + INT_RE, INT_RE, INT_RE, INT_RE, + client_fixture.vm_ip, srv_session_c_port, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + server_fixture.vm_id, + client_fixture.vm_node_ip, underlay_proto) + + result_tcp, output = self.search_session_in_agent_log( + server_fixture.vm_node_ip, + expected_server_session) + result = result or result_tcp + + assert result, ("Expected server session not found in agent log " + "for protocol %s" % (proto)) + + def start_traffic_validate_slo_fw(self, client_fixture, + server_fixture, policy_fixture=None, proto=1, underlay_proto=0, + slo_rate=1, sg_uuid=None, + fw_objs_dict=None, exp_srv_session_count=None, + exp_clnt_session_count=None): + ''' + Start the traffic for protocol proto and validates the client and server + sessions logged matching SLO in agent log with firewall rules and tags + ''' + + assert self.start_traffic(client_fixture, server_fixture, proto) + pkt_count = self.pkt_count + pkt_count2 = self.pkt_count2 + client_port = self.client_port + service_port = self.service_port + srv_session_c_port = self.srv_session_c_port + srv_session_s_port = self.srv_session_s_port + proto = self.proto + if exp_srv_session_count is None: + exp_srv_session_count = pkt_count/slo_rate if proto in [1, 58] else 1 + if exp_clnt_session_count is None: + exp_clnt_session_count = pkt_count/slo_rate if proto in [1, 58] else 1 + + eth_type = 'IPv4' if (self.inputs.get_af() == 'v4') else 'IPv6' + proto_str = 'any' + if sg_uuid is not None: + sg_rule_id_ingress = list_sg_rules(self.connections, sg_uuid, + eth_type=eth_type, proto=proto_str, direction='ingress')[0]['id'] + sg_rule_id_egress = list_sg_rules(self.connections, sg_uuid, + eth_type=eth_type, proto=proto_str, direction='egress')[0]['id'] + else: + sg_rule_id_ingress = sg_rule_id_egress = UUID_RE + + tcp_flags = 120 if proto == 6 else 0 + project_fqname = ':'.join(self.project.project_fq_name) + client_vmi_fqname = project_fqname + ':' +\ + client_fixture.vmi_ids[client_fixture.vn_fq_name] + is_client_session = 1 + if policy_fixture: + policy_api_obj = self.vnc_lib.network_policy_read( + id=policy_fixture.get_id()) + nw_ace_uuid = policy_api_obj.get_network_policy_entries( + ).policy_rule[0].rule_uuid + else: + nw_ace_uuid = UUID_RE + + tag_fq_name = fw_objs_dict['tag'].get_fq_name_str() + #Remote tags are sent as id + tag_id = fw_objs_dict['tag'].get_tag_id() + fwp_rule = ':'.join(fw_objs_dict['fwp'].fq_name + + [fw_objs_dict['fwr'].uuid]) + + expected_client_session = LOGGED_SESSION_FW % ( + client_vmi_fqname, + client_fixture.vn_fq_name, tag_fq_name, tag_id, + fwp_rule, + server_fixture.vn_fq_name, is_client_session, 0, + client_fixture.vm_node_ip, + client_fixture.vm_ip, service_port, proto, + INT_RE, pkt_count2, INT_RE, pkt_count2, + server_fixture.vm_ip, client_port, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE,#Fwd flow info + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE,#Reverse flow info + 'pass', sg_rule_id_egress, nw_ace_uuid, INT_RE, + client_fixture.vm_id, + server_fixture.vm_node_ip, underlay_proto) + + self.sleep(1) + #Verify No. of Client sessions + result, output = self.verify_no_of_sessions_in_agent_log( + client_fixture.vm_node_ip, + expected_client_session, exp_clnt_session_count) + assert result, ("Expected no. of client session not found in agent log " + "for protocol %s, exp:%s, got:%s" % (proto, exp_clnt_session_count, + output)) + + server_vmi_fqname = project_fqname + ':' +\ + server_fixture.vmi_ids[server_fixture.vn_fq_name] + is_client_session = 0 + + expected_server_session = LOGGED_SESSION_FW % ( + server_vmi_fqname, + server_fixture.vn_fq_name, tag_fq_name, tag_id, + fwp_rule, + client_fixture.vn_fq_name, is_client_session, 0, + server_fixture.vm_node_ip, + server_fixture.vm_ip, srv_session_s_port, proto, + INT_RE, pkt_count2, INT_RE, pkt_count2, + client_fixture.vm_ip, srv_session_c_port, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + INT_RE, pkt_count2, UUID_RE, tcp_flags, INT_RE, + 'pass', sg_rule_id_ingress, nw_ace_uuid, INT_RE, + server_fixture.vm_id, + client_fixture.vm_node_ip, underlay_proto) + + #Verify No. of Server sessions + result, output = self.verify_no_of_sessions_in_agent_log( + server_fixture.vm_node_ip, + expected_server_session, exp_srv_session_count) + assert result, ("Expected no. of server sessions not found in agent log" + " for protocol %s, exp:%s, got:%s" % (proto, exp_srv_session_count, + output)) + + self.sleep(1) + self.delete_all_flows_on_vms_compute([client_fixture, server_fixture]) + # + #Verify teardown sessions + tcp_flags = 0 + expected_client_session = LOGGED_TEARDOWN_FW % ( + client_vmi_fqname, + client_fixture.vn_fq_name, tag_fq_name, tag_id, + fwp_rule, + server_fixture.vn_fq_name, 1, 0, + client_fixture.vm_node_ip, + client_fixture.vm_ip, service_port, proto, + 0, 0, 0, 0, + server_fixture.vm_ip, client_port, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count,#Fwd flow + 'pass', sg_rule_id_egress, nw_ace_uuid, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count,#Reverse flow + 'pass', sg_rule_id_egress, nw_ace_uuid, + client_fixture.vm_id, + server_fixture.vm_node_ip, underlay_proto) + + teardown_session_count = 1 if exp_clnt_session_count else 0 + result, output = self.verify_no_of_sessions_in_agent_log( + client_fixture.vm_node_ip, + expected_client_session, teardown_session_count) + assert result, ("Expected No. of client teardown session not found in agent log " + "for protocol %s" % (proto)) + + server_vmi_fqname = project_fqname + ':' +\ + server_fixture.vmi_ids[server_fixture.vn_fq_name] + + expected_server_session = LOGGED_TEARDOWN_FW % ( + server_vmi_fqname, + server_fixture.vn_fq_name, tag_fq_name, tag_id, + fwp_rule, + client_fixture.vn_fq_name, 0, 0, + server_fixture.vm_node_ip, + server_fixture.vm_ip, srv_session_s_port, proto, + 0, 0, 0, 0, + client_fixture.vm_ip, srv_session_c_port, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, + UUID_RE, INT_RE, INT_RE, INT_RE, pkt_count, + 'pass', sg_rule_id_ingress, nw_ace_uuid, + server_fixture.vm_id, + client_fixture.vm_node_ip, underlay_proto) + + teardown_session_count = 1 if exp_srv_session_count else 0 + result, output = self.verify_no_of_sessions_in_agent_log( + server_fixture.vm_node_ip, + expected_server_session, teardown_session_count) + assert result, ("Expected No. of server teardown session not found in agent log " + "for protocol %s" % (proto)) + + @retry(delay=1, tries=10) + def verify_no_of_sessions_in_log(self, node_ip, log_type, session_log, + exp_session_count=None, container_name='agent'): + ''' Verify No. of sessions on compute node for given log type + log_type: agent/syslog + ''' + if log_type == 'agent': + log_file = '/var/log/contrail/contrail-vrouter-agent.log*' + object_name = 'SessionEndpointObject' + elif log_type == 'syslog': + log_file = '/var/log/syslog* /var/log/messages*' + object_name = 'SessionData' username = self.inputs.host_data[node_ip]['username'] password = self.inputs.host_data[node_ip]['password'] - cmd = 'grep -a SessionEndpointObject %s | grep -aP "%s" | wc -l' % ( + cmd = 'grep --no-messages -a %s %s | grep -aP "%s" | wc -l' % (object_name, log_file, session_log) output = self.inputs.run_cmd_on_server( node_ip, cmd, username, password, container=container_name) @@ -626,3 +1075,86 @@ def verify_no_of_sessions_in_agent_log(self, node_ip, session_log, return (exp_session_count == int(output)), int(output) else: return True, int(output) + + def verify_no_of_sessions_in_agent_log(self, node_ip, session_log, + exp_session_count=None): + + return self.verify_no_of_sessions_in_log(node_ip, 'agent', session_log, + exp_session_count=exp_session_count) + + def verify_no_of_sessions_in_syslog(self, node_ip, session_log, + exp_session_count=None): + + return self.verify_no_of_sessions_in_log(node_ip, 'syslog', session_log, + exp_session_count=exp_session_count, container_name=None) + + def get_total_no_of_sessions_in_agent_log(self, node_ip): + '''Returns total no. of sessions in agent log file''' + log_file = '/var/log/contrail/contrail-vrouter-agent.log*' + container_name = 'agent' + + username = self.inputs.host_data[node_ip]['username'] + password = self.inputs.host_data[node_ip]['password'] + cmd = "grep -a SessionEndpointObject %s" % (log_file) +\ + "| grep -ao \" ip = \"| wc -l" + output = self.inputs.run_cmd_on_server( + node_ip, cmd, username, password, container=container_name) + + return int(output) + + def clear_log_file(self, node_ip, log_file=None): + '''Clears log file''' + log_file = log_file or '/var/log/contrail/contrail-vrouter-agent.log' + container_name = 'agent' + + username = self.inputs.host_data[node_ip]['username'] + password = self.inputs.host_data[node_ip]['password'] + cmd = 'rm %s.*;echo \'\' > %s' % (log_file, log_file) + output = self.inputs.run_cmd_on_server( + node_ip, cmd, username, password, container=container_name) + +class SessionLoggingFwBase(SessionLoggingBase, BaseFirewallTest): + + @classmethod + def setUpClass(cls): + super(SessionLoggingBase, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(SessionLoggingBase, cls).tearDownClass() + + def config_tag_firewall_policy(self, vn_fixtures, + slo=None): + ''' config firewall rule and policy for udp with given SLO''' + + scope = 'local' + proto = 'udp' + #Create tag + tag_type = 'application' + tag_value = get_random_name('app1') + tag1_obj = self.create_tag(tag_type, tag_value, scope=scope) + #Add tag to VNs + for fixture in vn_fixtures: + self.set_tag(fixture, tag1_obj) + + #Create service group + services = [(proto, (0,65535), (0,65535))] + sg_udp = self.create_service_group(scope, services) + + #Create firewall rule + source_ep = {'virtual_network': vn_fixtures[0].vn_fq_name} + dest_ep = {'virtual_network': vn_fixtures[1].vn_fq_name} + fwr_udp = self.create_fw_rule(scope=scope, + service_groups=[sg_udp.uuid], + source=source_ep, destination=dest_ep, match=[tag_type]) + + #Create firewall policy + rules = [{'uuid': fwr_udp.uuid, 'seq_no': 20}] + fw_policy = self.create_fw_policy(scope=scope, rules=rules, slo=slo) + + #Create application policy set + aps = self.create_aps(scope, policies=[{'uuid': fw_policy.uuid, 'seq_no': 20}], + application=tag1_obj) + + return {'tag': tag1_obj, 'sg': sg_udp, 'fwp': fw_policy, + 'fwr': fwr_udp, 'aps':aps} diff --git a/common/slo/base.py b/common/slo/base.py index 5a4970679..017fd73b1 100644 --- a/common/slo/base.py +++ b/common/slo/base.py @@ -12,13 +12,16 @@ def setUpClass(cls): def tearDownClass(cls): super(SloBase, cls).tearDownClass() - def create_slo(self, parent_obj, rate=None, sg_obj=None, vn_policy_obj=None - ): + def create_slo(self, parent_obj=None, rate=None, sg_obj=None, + vn_policy_obj=None, rules_list=None): ''' parent_obj: global-vrouter-config or tenant + rules_list: list of dict of rule uuid and slo rate, {'uuid':, + 'rate':} ''' sg_refs = None vn_policy_refs = None + slo_rule_list_obj = None if sg_obj: ref_data = SecurityLoggingObjectRuleListType() sg_refs = [{'obj':sg_obj, 'ref_data':ref_data}] @@ -27,14 +30,43 @@ def create_slo(self, parent_obj, rate=None, sg_obj=None, vn_policy_obj=None ref_data = SecurityLoggingObjectRuleListType() vn_policy_refs = [{'obj':vn_policy_obj, 'ref_data':ref_data}] + if rules_list: + slo_rule_entry_list = [] + for rule in rules_list: + slo_rule_entry = SecurityLoggingObjectRuleEntryType( + rule_uuid=rule['uuid'], rate=rule['rate']) + slo_rule_entry_list.append(slo_rule_entry) + slo_rule_list_obj = SecurityLoggingObjectRuleListType( + rule=slo_rule_entry_list) + slo_fixture = self.useFixture( SLOFixture( parent_obj=parent_obj, connections=self.connections, - sg_refs=sg_refs, vn_policy_refs=vn_policy_refs, rate=rate)) + sg_refs=sg_refs, vn_policy_refs=vn_policy_refs, rate=rate, + rules=slo_rule_list_obj)) slo_fixture.verify_on_setup() return slo_fixture + def update_slo(self, slo_obj, new_rules_list): + ''' + rules_list: list of dict of rule uuid and slo rate, {'uuid':, + 'rate':} + ''' + slo_rule_list_obj = None + + if new_rules_list: + slo_rule_entry_list = [] + for rule in new_rules_list: + slo_rule_entry = SecurityLoggingObjectRuleEntryType( + rule_uuid=rule['uuid'], rate=rule['rate']) + slo_rule_entry_list.append(slo_rule_entry) + slo_rule_list_obj = SecurityLoggingObjectRuleListType( + rule=slo_rule_entry_list) + + slo_obj.security_logging_object_rules = slo_rule_list_obj + self.vnc_h.security_logging_object_update(slo_obj) + def add_slo_to_vn(self, slo_fixture, vn_fixture, cleanup=True): '''Add the SLO to VN''' slo_ref_list_old = vn_fixture.get_slo_list() @@ -42,3 +74,32 @@ def add_slo_to_vn(self, slo_fixture, vn_fixture, cleanup=True): if cleanup: self.addCleanup(vn_fixture.set_slo_list, slo_ref_list_old) + + def add_slo_to_vmi(self, slo_fixture, vmi_id, cleanup=True): + '''Add the SLO to VMI''' + vmi_obj = self.vnc_h.virtual_machine_interface_read(id=vmi_id) + slo_ref_list_old = vmi_obj.get_security_logging_object_refs() + vmi_obj.add_security_logging_object(slo_fixture.obj) + + self.vnc_h.virtual_machine_interface_update(vmi_obj) + if cleanup: + self.addCleanup(self.set_slo_list_to_vmi, slo_ref_list_old, vmi_id) + + def set_slo_list_to_vmi(self, slo_obj_list, vmi_id): + '''Set SLO list to VMI''' + vmi_obj = self.vnc_h.virtual_machine_interface_read(id=vmi_id) + vmi_obj.set_security_logging_object_list(slo_obj_list) + + self.vnc_h.virtual_machine_interface_update(vmi_obj) + + def set_global_slo_flag(self, enable=True, cleanup=True): + ''' + Enable/disable SLO in default global vrouter config + ''' + vnc_lib_fixture = self.connections.vnc_lib_fixture + current_value = vnc_lib_fixture.get_global_slo_flag() + if current_value == enable: + return True + vnc_lib_fixture.set_global_slo_flag(enable) + if cleanup: + self.addCleanup(vnc_lib_fixture.set_global_slo_flag, current_value) diff --git a/common/vrouter/base.py b/common/vrouter/base.py index 857842ed4..ad92d5792 100644 --- a/common/vrouter/base.py +++ b/common/vrouter/base.py @@ -177,6 +177,13 @@ def delete_all_flows_on_vms_compute(self, vm_fixtures): for vm in vm_fixtures: self.compute_fixtures_dict[vm.vm_node_ip].delete_all_flows() + def restart_agent_on_vms_compute(self, vm_fixtures): + ''' + Restart agent on the compute node of the VMs + ''' + for vm in vm_fixtures: + self.compute_fixtures_dict[vm.vm_node_ip].restart_agent() + def send_hping3_traffic(self, sender_vm_fix, dest_ip, srcport, destport, count=1, interval='u100', stop=True, wait=False, **kwargs): diff --git a/fixtures/contrailapi.py b/fixtures/contrailapi.py index 960d8ec5f..0accaae81 100644 --- a/fixtures/contrailapi.py +++ b/fixtures/contrailapi.py @@ -1206,12 +1206,17 @@ def create_firewall_policy(self, fq_name, parent_type=None, rules=None, **kwargs :param parent_type : one of 'project' or 'policy-management' :param rules : Ordered list of dict of firewall rules and seq no [{'uuid': rule_uuid, 'seq_no': }] + :param slo: {'slo_obj': slo obj, 'rate_obj':rate obj} ''' obj = FirewallPolicy(fq_name[-1], fq_name=fq_name, parent_type=parent_type) for rule in rules or []: seq = FirewallSequence(str(rule['seq_no'])) rule_obj = self.read_firewall_rule(id=rule['uuid']) obj.add_firewall_rule(rule_obj, seq) + + slo = kwargs.get('slo') or None + if slo is not None: + obj.add_security_logging_object(slo['slo_obj'], slo['rate_obj']) self._log.debug('creating firewall policy %s'%fq_name) return self._vnc.firewall_policy_create(obj) diff --git a/fixtures/firewall_policy.py b/fixtures/firewall_policy.py index f1272403b..9c8468225 100644 --- a/fixtures/firewall_policy.py +++ b/fixtures/firewall_policy.py @@ -16,6 +16,7 @@ def __init__(self, *args, **kwargs): self.uuid = kwargs.get('uuid') self.scope = kwargs.get('scope') or 'local' self.rules = kwargs.get('rules') or list() + self.slo = kwargs.get('slo') or None self.created = False self.verify_is_run = False @@ -63,7 +64,7 @@ def create(self): self.uuid = self.vnc_h.create_firewall_policy( parent_type=self.parent_type, fq_name=self.fq_name, - rules=self.rules) + rules=self.rules, slo=self.slo) self.created = True self.logger.info('Created Firewall Policy %s(%s)'%(self.name, self.uuid)) diff --git a/fixtures/slo_fixture.py b/fixtures/slo_fixture.py index 2dd581b5d..530d1fef3 100644 --- a/fixtures/slo_fixture.py +++ b/fixtures/slo_fixture.py @@ -7,12 +7,14 @@ class SLOFixture(vnc_api_test.VncLibFixture): Security Logging Object Fixture ''' - def __init__(self, parent_obj, **kwargs): + def __init__(self, parent_obj=None, **kwargs): ''' Optional param: + parent_obj: parent tenant obj or global-vrouter-config sg_refs: list of dict of SG objects and ref_data of SecurityLoggingObjectRuleListType object [{'obj':, 'ref_data':}] vn_policy_refs: same as sg_refs but for VN policy + rules: SecurityLoggingObjectRuleListType obj ''' super(SLOFixture, self).__init__(self, **kwargs) self.parent_obj = parent_obj @@ -20,6 +22,7 @@ def __init__(self, parent_obj, **kwargs): self.uuid = None self.obj = None self.rate = None + self.rules = None self.sg_refs = None self.vn_policy_refs = None self.parse_slo_kwargs(**kwargs) @@ -28,7 +31,7 @@ def __init__(self, parent_obj, **kwargs): if self.parent_obj is None: fq_name = [ 'default-global-system-config', 'default-global-vrouter-config'] - self.parent_obj = self.vnc_lib.global_vrouter_config_read(fq_name=fq_name) + self.parent_obj = self.vnc_api_h.global_vrouter_config_read(fq_name=fq_name) def parse_slo_kwargs(self, **kwargs): self.sg_refs = kwargs.get('sg_refs', @@ -41,6 +44,8 @@ def parse_slo_kwargs(self, **kwargs): self.name) self.uuid = kwargs.get('uuid', self.uuid) + self.rules = kwargs.get('rules', + self.rules) def _populate_attr(self): if self.obj: @@ -115,11 +120,13 @@ def create_slo(self): if self.rate is not None: self.obj = SecurityLoggingObject(name=self.name, parent_obj=self.parent_obj, - security_logging_object_rate=self.rate) + security_logging_object_rate=self.rate, + security_logging_object_rules=self.rules) else: #Default SLO rate self.obj = SecurityLoggingObject(name=self.name, - parent_obj=self.parent_obj) + parent_obj=self.parent_obj, + security_logging_object_rules=self.rules) if self.sg_refs: for sg_ref in self.sg_refs: diff --git a/fixtures/vnc_api_test.py b/fixtures/vnc_api_test.py index 44c5418f0..75edb28ae 100644 --- a/fixtures/vnc_api_test.py +++ b/fixtures/vnc_api_test.py @@ -360,7 +360,7 @@ def set_flow_export_rate(self, value): fq_name = [ 'default-global-system-config', 'default-global-vrouter-config'] gv_obj = self.vnc_api_h.global_vrouter_config_read(fq_name=fq_name) - gv_obj.set_flow_export_rate(int(value) if value else None) + gv_obj.set_flow_export_rate(int(value) if (value is not None) else None) self.vnc_api_h.global_vrouter_config_update(gv_obj) self.logger.info('Setting flow export rate: %s' % (value)) return True @@ -418,5 +418,26 @@ def set_global_igmp_config(self, igmp_enable=True): self.vnc_api_h.global_system_config_update(gsc_obj) # end set_global_igmp_enable + def set_global_slo_flag(self, enable=True): + ''' + Enable/disable SLO in default global vrouter config + ''' + fq_name = [ 'default-global-system-config', + 'default-global-vrouter-config'] + gv_obj = self.vnc_api_h.global_vrouter_config_read(fq_name=fq_name) + gv_obj.set_enable_security_logging(enable) + self.vnc_api_h.global_vrouter_config_update(gv_obj) + self.logger.info('Setting global SLO flag to : %s' % ( + 'True' if enable else 'False')) + return True + def get_global_slo_flag(self): + ''' + Get SLO flag from default global vrouter config + ''' + fq_name = [ 'default-global-system-config', + 'default-global-vrouter-config'] + gv_obj = self.vnc_api_h.global_vrouter_config_read(fq_name=fq_name) + value = gv_obj.get_enable_security_logging() + return value # end VncLibFixture diff --git a/serial_scripts/vm_regression/test_vm_serial.py b/serial_scripts/vm_regression/test_vm_serial.py index b58ab1cc3..01c80e13c 100644 --- a/serial_scripts/vm_regression/test_vm_serial.py +++ b/serial_scripts/vm_regression/test_vm_serial.py @@ -627,8 +627,8 @@ def test_control_node_switchover(self): vn1_fixture = self.create_vn(vn1_name, vn1_subnets) assert vn1_fixture.verify_on_setup() vm1_fixture = self.create_vm(vn1_fixture, vn1_vm1_name) - assert vm1_fixture.wait_till_vm_is_up() vm2_fixture = self.create_vm(vn1_fixture, vn1_vm2_name) + assert vm1_fixture.wait_till_vm_is_up() assert vm2_fixture.wait_till_vm_is_up() assert vm1_fixture.ping_to_ip(vm2_fixture.vm_ip) assert vm2_fixture.ping_to_ip(vm1_fixture.vm_ip) diff --git a/serial_scripts/vrouter/test_slo.py b/serial_scripts/vrouter/test_slo.py index 445c1fa32..08a9ee96e 100644 --- a/serial_scripts/vrouter/test_slo.py +++ b/serial_scripts/vrouter/test_slo.py @@ -1,8 +1,9 @@ from tcutils.wrappers import preposttest_wrapper from common.slo.base import * import test -from tcutils.util import get_random_name -from security_group import get_secgrp_id_from_name +from tcutils.util import get_random_name, is_almost_same, skip_because +from security_group import get_secgrp_id_from_name, list_sg_rules +import random AF_TEST = 'v6' @@ -27,7 +28,7 @@ def test_slo_intra_node(self): 4. start icmp/tcp/udp traffic and verify the session logs in agent log as well as in syslog Pass criteria: - step 3 should pass + step 4 should pass """ self._create_resources(test_type='intra-node', session_export_rate=0) @@ -40,7 +41,7 @@ def test_slo_intra_node(self): parent_obj = self.vnc_h.project_read( fq_name=[self.connections.domain_name, project_name]) - slo_rate = 10 + slo_rate = 1 slo_fixture = self.create_slo(parent_obj, rate=slo_rate, sg_obj=sg_obj, vn_policy_obj=policy_obj) for vn in self.vn_fixtures: @@ -48,8 +49,7 @@ def test_slo_intra_node(self): #For intra node traffic there is no tunnel so underlay_proto would be zero underlay_proto = 0 - #proto_list = [1, 17, 6] - proto_list = [1, 17] + proto_list = [1, 17, 6] self.enable_logging_on_compute(self.client_fixture.vm_node_ip, log_type=AGENT_LOG) #Clear local ips after agent restart @@ -62,8 +62,23 @@ def test_slo_intra_node(self): self.server_fixture, self.policy_fixture, proto=proto, underlay_proto=underlay_proto, slo_rate=slo_rate) self.logger.info("SLO: Expected Session logs found in agent log for " - "protocol %s" % (proto)) - # + "protocol %s" % (self.proto)) + + # + #SLO logged session verification in syslog + self.enable_logging_on_compute(self.client_fixture.vm_node_ip, + log_type=SYS_LOG) + #Clear local ips after agent restart + self.client_fixture.clear_local_ips() + self.server_fixture.clear_local_ips() + + #Verify Session logs in syslog + for proto in proto_list: + self.start_traffic_validate_slo_in_syslog(self.client_fixture, + self.server_fixture, self.policy_fixture, proto=proto, + underlay_proto=underlay_proto) + self.logger.info("Expected Session logs found in syslog for " + "protocol %s" % (self.proto)) @preposttest_wrapper def test_slo_inter_node(self): @@ -74,9 +89,8 @@ def test_slo_inter_node(self): 2. launch 1 VM in each VN on diff compute node 3. set session export rate to 0 4. start icmp/tcp/udp traffic and verify the session logs in agent log - as well as in syslog Pass criteria: - step 3 should pass + step 4 should pass """ self._create_resources(test_type='inter-node', session_export_rate=0) @@ -89,7 +103,7 @@ def test_slo_inter_node(self): parent_obj = self.vnc_h.project_read( fq_name=[self.connections.domain_name, project_name]) - slo_rate = 10 + slo_rate = 1 slo_fixture = self.create_slo(parent_obj, rate=slo_rate, sg_obj=sg_obj, vn_policy_obj=policy_obj) for vn in self.vn_fixtures: @@ -97,9 +111,11 @@ def test_slo_inter_node(self): underlay_proto = UNDERLAY_PROTO[ self.connections.read_vrouter_config_encap()[0]] - proto_list = [1, 17] + proto_list = [1, 17, 6] self.enable_logging_on_compute(self.client_fixture.vm_node_ip, log_type=AGENT_LOG) + self.enable_logging_on_compute(self.server_fixture.vm_node_ip, + log_type=AGENT_LOG) #Clear local ips after agent restart self.client_fixture.clear_local_ips() self.server_fixture.clear_local_ips() @@ -110,4 +126,338 @@ def test_slo_inter_node(self): self.server_fixture, self.policy_fixture, proto=proto, underlay_proto=underlay_proto, slo_rate=slo_rate, sg_uuid=sg_id) self.logger.info("SLO: Expected Session logs found in agent log for " - "protocol %s" % (proto)) + "protocol %s" % (self.proto)) + + @preposttest_wrapper + def test_slo_rate(self): + """ + Description: Verify security logging rate for inter/intra node traffic + Steps: + 1. create 2 VNs and connect them using policy + 2. launch 1 VM in each VN on diff compute node + 3. set session export rate to 0 and SLO rate to 5 + 4. send 10 ping packets and verify the no. of session logs in agent log + Pass criteria: + No. of session logs should be 1 for session creation and 1 for teardown + """ + self._create_resources(test_type='intra-node', session_export_rate=0) + + policy_obj = self.policy_fixture.policy_obj + project_name = self.project.project_name + sg_fq_name = '%s:%s:default' % (self.connections.domain_name, + project_name) + sg_id = get_secgrp_id_from_name(self.connections, sg_fq_name) + sg_obj = self.vnc_h._vnc.security_group_read(id=sg_id) + + parent_obj = self.vnc_h.project_read( + fq_name=[self.connections.domain_name, project_name]) + slo_rate = 5 + slo_fixture = self.create_slo(parent_obj, rate=slo_rate, + vn_policy_obj=policy_obj) + for vn in self.vn_fixtures: + self.add_slo_to_vn(slo_fixture, vn) + + underlay_proto = 0 + proto = 1 + self.enable_logging_on_compute(self.client_fixture.vm_node_ip, + log_type=AGENT_LOG) + #Clear local ips after agent restart + self.client_fixture.clear_local_ips() + self.server_fixture.clear_local_ips() + + #Verify Session logs in agent logs for SLO + self.start_traffic_validate_slo(self.client_fixture, + self.server_fixture, self.policy_fixture, proto=proto, + underlay_proto=underlay_proto, slo_rate=slo_rate, + exp_session_count=2) + self.logger.info("SLO: Expected Session logs found in agent log for " + "protocol %s" % (self.proto)) + + ## + #Verify SLO rate for inter node icmp traffic + compute_hosts = self.orch.get_hosts() + if not (len(compute_hosts) < 2): + client_node_ip = self.client_fixture.vm_node_ip + server2_node_name = compute_hosts[1] if self.inputs.compute_info[ + compute_hosts[1]] != client_node_ip else compute_hosts[0] + + server2_fixture = self.create_vms(vn_fixture=self.vn2_fixture, + count=1, node_name=server2_node_name, image_name='ubuntu-traffic')[0] + self.verify_vms([server2_fixture]) + + self.enable_logging_on_compute(server2_fixture.vm_node_ip, + log_type=AGENT_LOG) + #Clear local ips after agent restart + server2_fixture.clear_local_ips() + + underlay_proto = UNDERLAY_PROTO[ + self.connections.read_vrouter_config_encap()[0]] + #Verify Session logs in agent logs for SLO + self.start_traffic_validate_slo(self.client_fixture, + server2_fixture, self.policy_fixture, proto=proto, + underlay_proto=underlay_proto, slo_rate=slo_rate, sg_uuid=sg_id, + exp_session_count=2) + self.logger.info("SLO: Expected Session logs found in agent log for " + "protocol %s" % (self.proto)) + +class SecurityLoggingFw(SloBase, SessionLoggingFwBase): + + @classmethod + def setUpClass(cls): + super(SecurityLoggingFw, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(SecurityLoggingFw, cls).tearDownClass() + + def _test_slo_with_fw(self, exp_srv_session_count=None, + exp_clnt_session_count=None, create_resources=True, slo_fixture=None, + fw_objs_dict=None): + + if create_resources: + self._create_resources(test_type='inter-node', session_export_rate=0) + + policy_obj = self.policy_fixture.policy_obj + project_name = self.project.project_name + sg_fq_name = '%s:%s:default' % (self.connections.domain_name, + project_name) + sg_id = get_secgrp_id_from_name(self.connections, sg_fq_name) + sg_obj = self.vnc_h._vnc.security_group_read(id=sg_id) + + parent_obj = self.vnc_h.project_read( + fq_name=[self.connections.domain_name, project_name]) + slo_rate = 1 + if slo_fixture is None: + slo_fixture = self.create_slo(parent_obj, rate=slo_rate) + for vn in self.vn_fixtures: + self.add_slo_to_vn(slo_fixture, vn) + + if fw_objs_dict is None: + #create firewall rule and policy + slo_rate_obj = SloRateType(rate=slo_rate) + slo_dict = {'slo_obj': slo_fixture.obj, 'rate_obj':slo_rate_obj} + fw_objs_dict = self.config_tag_firewall_policy(self.vn_fixtures, slo=slo_dict) + + underlay_proto = UNDERLAY_PROTO[ + self.connections.read_vrouter_config_encap()[0]] + proto_list = [17] + self.enable_logging_on_compute(self.client_fixture.vm_node_ip, + log_type=AGENT_LOG) + self.enable_logging_on_compute(self.server_fixture.vm_node_ip, + log_type=AGENT_LOG) + #Clear local ips after agent restart + self.client_fixture.clear_local_ips() + self.server_fixture.clear_local_ips() + + #Verify Session logs in agent logs for SLO + for proto in proto_list: + self.start_traffic_validate_slo_fw(self.client_fixture, + self.server_fixture, self.policy_fixture, proto=proto, + underlay_proto=underlay_proto, slo_rate=slo_rate, sg_uuid=sg_id, + fw_objs_dict=fw_objs_dict, + exp_srv_session_count=exp_srv_session_count, + exp_clnt_session_count=exp_clnt_session_count) + self.logger.info("SLO: Expected Session logs found in agent log for " + "protocol %s" % (self.proto)) + + return {'sg_obj':sg_obj, 'slo_fix':slo_fixture, 'fw_objs':fw_objs_dict} + + @preposttest_wrapper + def test_slo_on_vmi(self): + """ + Description: Verify SLO on vmi + Steps: + 1. create 2 VNs and connect them using network and firewall policy + 2. launch 1 VM in each VN on diff compute node + 3. set session export rate to 0 and attach SLO to dest vmi only + 4. start udp traffic and verify the session logs in agent log on dest node + and no logs in src node + Pass criteria: + step 4 should pass + """ + self._create_resources(test_type='inter-node', session_export_rate=0) + + policy_obj = self.policy_fixture.policy_obj + project_name = self.project.project_name + sg_fq_name = '%s:%s:default' % (self.connections.domain_name, + project_name) + sg_id = get_secgrp_id_from_name(self.connections, sg_fq_name) + sg_obj = self.vnc_h._vnc.security_group_read(id=sg_id) + + parent_obj = self.vnc_h.project_read( + fq_name=[self.connections.domain_name, project_name]) + slo_rate = 1 + slo_fixture = self.create_slo(parent_obj, rate=slo_rate, sg_obj=sg_obj, + vn_policy_obj=policy_obj) + server_vmi_id = self.server_fixture.get_vmi_ids().values()[0] + self.add_slo_to_vmi(slo_fixture, server_vmi_id) + + #create firewall rule and policy + slo_rate_obj = SloRateType(rate=slo_rate) + slo_dict = {'slo_obj': slo_fixture.obj, 'rate_obj':slo_rate_obj} + fw_objs_dict = self.config_tag_firewall_policy(self.vn_fixtures, slo=slo_dict) + + underlay_proto = UNDERLAY_PROTO[ + self.connections.read_vrouter_config_encap()[0]] + proto_list = [17] + self.enable_logging_on_compute(self.client_fixture.vm_node_ip, + log_type=AGENT_LOG) + self.enable_logging_on_compute(self.server_fixture.vm_node_ip, + log_type=AGENT_LOG) + #Clear local ips after agent restart + self.client_fixture.clear_local_ips() + self.server_fixture.clear_local_ips() + + #Verify Session logs in agent logs for SLO + for proto in proto_list: + self.start_traffic_validate_slo_fw(self.client_fixture, + self.server_fixture, self.policy_fixture, proto=proto, + underlay_proto=underlay_proto, slo_rate=slo_rate, sg_uuid=sg_id, + fw_objs_dict=fw_objs_dict, exp_clnt_session_count=0) + self.logger.info("SLO: Expected Session logs found in agent log for " + "protocol %s" % (self.proto)) + + @preposttest_wrapper + def test_slo_global(self): + """ + Description: Verify global security logging for inter-VN inter-Node traffic + with firewall policy and rules + Steps: + 1. disable/enable global SLO flag and verify logging + 2. Create global and tenant level SLO and verify logging + 3. Delete global SLO and verify session get logged only matching tenant level SLO + Pass criteria: + All logging verifications should pass + """ + self.set_global_slo_flag(enable=False) + #Logged session should be 0 when global slo is disabled + created_objs = self._test_slo_with_fw(exp_srv_session_count=0,exp_clnt_session_count=0) + + self.set_global_slo_flag(enable=True) + #Logged session should be seen when global slo is enabled + self._test_slo_with_fw(create_resources=False, + slo_fixture=created_objs['slo_fix'], + fw_objs_dict=created_objs['fw_objs']) + + eth_type = 'IPv4' if (self.inputs.get_af() == 'v4') else 'IPv6' + proto_str = 'any' + sg_rule_id_ingress = list_sg_rules(self.connections, + created_objs['sg_obj'].uuid, + eth_type=eth_type, proto=proto_str, direction='ingress')[0]['id'] + sg_rule_id_egress = list_sg_rules(self.connections, + created_objs['sg_obj'].uuid, + eth_type=eth_type, proto=proto_str, direction='egress')[0]['id'] + + #Create global SLO using sg_rule_id_ingress + slo_rate = 10 + rules_list = [{'uuid':sg_rule_id_ingress, 'rate':100}] + g_slo_fixture = self.create_slo(rate=slo_rate, rules_list=rules_list) + + #Remove old slo from VNs + for vn in self.vn_fixtures: + vn.set_slo_list([]) + + #Create tenant level SLO with sg_rule_id_egress and add to VNs + project_name = self.project.project_name + parent_obj = self.vnc_h.project_read( + fq_name=[self.connections.domain_name, project_name]) + rules_list = [{'uuid':sg_rule_id_egress, 'rate':1}] + slo_fixture = self.create_slo(parent_obj, rate=slo_rate, rules_list=rules_list) + for vn in self.vn_fixtures: + self.add_slo_to_vn(slo_fixture, vn) + #With tenant level SLO created above, Client session will match and logged + #With global SLO, server session will match and logged + self._test_slo_with_fw(create_resources=False, + slo_fixture=slo_fixture, fw_objs_dict=created_objs['fw_objs']) + + #Disable global slo again + self.set_global_slo_flag(enable=False) + #Now no logging should happen + self._test_slo_with_fw(create_resources=False, + slo_fixture=slo_fixture, fw_objs_dict=created_objs['fw_objs'], + exp_srv_session_count=0, exp_clnt_session_count=0) + + #Enable global slo again + self.set_global_slo_flag(enable=True) + #Delete global SLO + g_slo_fixture.cleanUp() + self._remove_fixture_from_cleanup(g_slo_fixture) + #Now only Client session should get logged matching tenant level SLO + #Server session should be 0 as it will match ingress rule + self._test_slo_with_fw(create_resources=False, + exp_srv_session_count=0, + slo_fixture=slo_fixture, fw_objs_dict=created_objs['fw_objs']) + + @preposttest_wrapper + def test_slo_fw_update(self): + """ + Description: Verify security logging for inter-VN inter-Node traffic + with firewall policy and rules and verify SLO update + Steps: + 1. create 2 VNs and connect them using network and firewall policy + 2. launch 1 VM in each VN on diff compute node + 3. set session export rate to 0 + 4. start udp traffic and verify the session logs in agent log + Pass criteria: + step 4 should pass + """ + created_objs = self._test_slo_with_fw() + + eth_type = 'IPv4' if (self.inputs.get_af() == 'v4') else 'IPv6' + proto_str = 'any' + sg_rule_id_ingress = list_sg_rules(self.connections, + created_objs['sg_obj'].uuid, + eth_type=eth_type, proto=proto_str, direction='ingress')[0]['id'] + sg_rule_id_egress = list_sg_rules(self.connections, + created_objs['sg_obj'].uuid, + eth_type=eth_type, proto=proto_str, direction='egress')[0]['id'] + + #Remove old slo from VNs + for vn in self.vn_fixtures: + vn.set_slo_list([]) + + #Create tenant level SLO with sg_rule_id_egress and add to VNs + project_name = self.project.project_name + parent_obj = self.vnc_h.project_read( + fq_name=[self.connections.domain_name, project_name]) + rules_list = [{'uuid':sg_rule_id_egress, 'rate':1}] + slo_fixture = self.create_slo(parent_obj, rate=10, rules_list=rules_list) + + for vn in self.vn_fixtures: + self.add_slo_to_vn(slo_fixture, vn) + #With tenant level SLO created above, Client session will match and logged + self._test_slo_with_fw(create_resources=False, + slo_fixture=slo_fixture, fw_objs_dict=created_objs['fw_objs'], + exp_srv_session_count=0) + + #Update SLO with both rules + rules_list.append({'uuid':sg_rule_id_ingress, 'rate':1}) + self.update_slo(slo_fixture.obj, rules_list) + + #Now both client and server sessions should get logged + self._test_slo_with_fw(create_resources=False, + slo_fixture=slo_fixture, fw_objs_dict=created_objs['fw_objs']) + +class SecurityLoggingIpv6(SecurityLogging): + @classmethod + def setUpClass(cls): + super(SecurityLoggingIpv6, cls).setUpClass() + cls.inputs.set_af(AF_TEST) + + def is_test_applicable(self): + if (self.inputs.orchestrator == 'vcenter') and ( + not self.orch.is_feature_supported('ipv6')): + return(False, 'Skipping IPv6 Test on vcenter setup') + return (True, None) + +class SecurityLoggingFwIpv6(SecurityLoggingFw): + @classmethod + def setUpClass(cls): + super(SecurityLoggingFwIpv6, cls).setUpClass() + cls.inputs.set_af(AF_TEST) + + def is_test_applicable(self): + if (self.inputs.orchestrator == 'vcenter') and ( + not self.orch.is_feature_supported('ipv6')): + return(False, 'Skipping IPv6 Test on vcenter setup') + return (True, None) diff --git a/tcutils/traffic_utils/hping_traffic.py b/tcutils/traffic_utils/hping_traffic.py index 7cac224e6..d5f363013 100644 --- a/tcutils/traffic_utils/hping_traffic.py +++ b/tcutils/traffic_utils/hping_traffic.py @@ -161,7 +161,7 @@ def get_cmd_args(self, **kwargs): def _check_if_hping_still_running(self): result = self.sender_vm_fixture.run_cmd_on_vm( - cmds=['kill `cat %s`' %(self.pid_file)], + cmds=['ps -p `cat %s`' %(self.pid_file)], raw=True) status = result.values()[0] if status.succeeded: diff --git a/tcutils/wrappers.py b/tcutils/wrappers.py index c0f539340..cf6896915 100644 --- a/tcutils/wrappers.py +++ b/tcutils/wrappers.py @@ -147,7 +147,7 @@ def wrapper(self, *args, **kwargs): test_time = datetime.now().replace(microsecond=0) - start_time if cores == {} and crashes == {} and not testfail and \ not cleanupfail and (result is None or result is True) and \ - flap_check_result: + flap_check_result and not testskip: log.info("END TEST : %s : PASSED[%s]", function.__name__, test_time) log.info('-' * 80)