'Tests if a security group rules are working, by confirming
that 0. traffic is allowed when port security is disabled,
1. connection from outside of allowed security group is blocked
2. connection from allowed security group is permitted
3. traffic not explicitly allowed (eg. ICMP) is blocked,
4. a security group update takes effect,
5. a remote security group member addition works, and
6. an established connection stops by deleting a SG rule.
7. test other protocol functionality by using SCTP protocol
8. test two vms with same mac on the same host in different
networks'

def test_securitygroup(self):

    index_to_sg = [0, 0, 1]
    if (self.firewall_driver == 'iptables_hybrid'):
        index_to_host = ([0] * 3)
    else:
        index_to_host = [0, 1, 1]
    tenant_uuid = uuidutils.generate_uuid()
    network = self.safe_client.create_network(tenant_uuid)
    self.safe_client.create_subnet(tenant_uuid, network['id'], '20.0.0.0/24')
    sgs = [self.safe_client.create_security_group(tenant_uuid) for i in range(2)]
    ports = [self.safe_client.create_port(tenant_uuid, network['id'], self.environment.hosts[host].hostname, security_groups=[], port_security_enabled=False) for host in index_to_host]
    self.safe_client.create_security_group_rule(tenant_uuid, sgs[0]['id'], remote_group_id=sgs[0]['id'], direction='ingress', ethertype=constants.IPv4, protocol=constants.PROTO_NAME_TCP, port_range_min=3333, port_range_max=3333)
    vms = [self.useFixture(machine.FakeFullstackMachine(self.environment.hosts[host], network['id'], tenant_uuid, self.safe_client, neutron_port=ports[port], use_dhcp=True)) for (port, host) in enumerate(index_to_host)]
    for vm in vms:
        vm.block_until_boot()
    self.assert_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3333, net_helpers.NetcatTester.TCP)
    self.assert_connection(vms[2].namespace, vms[0].namespace, vms[0].ip, 3333, net_helpers.NetcatTester.TCP)
    net_helpers.assert_ping(vms[0].namespace, vms[1].ip)
    net_helpers.assert_ping(vms[0].namespace, vms[2].ip)
    net_helpers.assert_ping(vms[1].namespace, vms[2].ip)
    for (port, sg) in zip(ports, index_to_sg):
        self.safe_client.client.update_port(port['id'], body={'port': {'port_security_enabled': True, 'security_groups': [sgs[sg]['id']]}})
    netcat = net_helpers.NetcatTester(vms[2].namespace, vms[0].namespace, vms[0].ip, 3333, net_helpers.NetcatTester.TCP)
    common_utils.wait_until_true(netcat.test_no_connectivity, exception=AssertionError('Still    can    connect    to    the    VM    from    different    host.'))
    netcat.stop_processes()
    self.assert_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3333, net_helpers.NetcatTester.TCP)
    net_helpers.assert_no_ping(vms[0].namespace, vms[1].ip)
    net_helpers.assert_no_ping(vms[0].namespace, vms[2].ip)
    net_helpers.assert_no_ping(vms[1].namespace, vms[2].ip)
    self.assert_no_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3344, net_helpers.NetcatTester.TCP)
    self.safe_client.create_security_group_rule(tenant_uuid, sgs[0]['id'], remote_group_id=sgs[0]['id'], direction='ingress', ethertype=constants.IPv4, protocol=constants.PROTO_NAME_TCP, port_range_min=3344, port_range_max=3344)
    self.assert_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3344, net_helpers.NetcatTester.TCP)
    rule2 = self.safe_client.create_security_group_rule(tenant_uuid, sgs[0]['id'], remote_group_id=sgs[1]['id'], direction='ingress', ethertype=constants.IPv4, protocol=constants.PROTO_NAME_TCP, port_range_min=3355, port_range_max=3355)
    self.assert_connection(vms[2].namespace, vms[0].namespace, vms[0].ip, 3355, net_helpers.NetcatTester.TCP)
    index_to_host.append(index_to_host[2])
    index_to_sg.append(1)
    ports.append(self.safe_client.create_port(tenant_uuid, network['id'], self.environment.hosts[index_to_host[3]].hostname, security_groups=[sgs[1]['id']]))
    vms.append(self.useFixture(machine.FakeFullstackMachine(self.environment.hosts[index_to_host[3]], network['id'], tenant_uuid, self.safe_client, neutron_port=ports[3], use_dhcp=True)))
    vms[3].block_until_boot()
    netcat = net_helpers.NetcatTester(vms[3].namespace, vms[0].namespace, vms[0].ip, 3355, net_helpers.NetcatTester.TCP)
    self.addCleanup(netcat.stop_processes)
    self.assertTrue(netcat.test_connectivity())
    self.client.delete_security_group_rule(rule2['id'])
    common_utils.wait_until_true((lambda : netcat.test_no_connectivity()), sleep=8)
    netcat.stop_processes()
    self.assert_no_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3366, net_helpers.NetcatTester.SCTP)
    self.safe_client.create_security_group_rule(tenant_uuid, sgs[0]['id'], remote_group_id=sgs[0]['id'], direction='ingress', ethertype=constants.IPv4, protocol=constants.PROTO_NUM_SCTP, port_range_min=3366, port_range_max=3366)
    self.assert_connection(vms[1].namespace, vms[0].namespace, vms[0].ip, 3366, net_helpers.NetcatTester.SCTP)
    self._test_overlapping_mac_addresses()
