# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Basic integration test that runs update_config.py."""

from nose.plugins.attrib import attr
from cuisine import file_write, run
from fabric.api import hide
import json
import random
import datetime
import subprocess
from envassert import file, process, package, user, group, port, cron, detect, ip
import copy
from fabric import state

try:
    from . import SystemVMTestCase, has_line, print_doc
except (ImportError, ValueError):
    from systemvm import SystemVMTestCase, has_line, print_doc


def deep_copy(obj):
    return json.loads(json.dumps(obj))


class UpdateConfigTestCase(SystemVMTestCase):
    basic_config = {
        "ip_address": [
            {
                "public_ip": "10.0.2.102",
                "source_nat": True,
                "add": True,
                "one_to_one_nat": False,
                "first_i_p": False,
                "gateway": "10.0.2.1",
                "netmask": "255.255.255.0",
                "vif_mac_address": "06:cb:aa:00:00:03",
                "nic_dev_id": 1,
                "new_nic": False,
                "nw_type": "public"
            }
        ],
        "type": "ips"
    }

    basic_acl = {
        "device":"eth2",
        "mac_address":"02:00:5d:8d:00:03",
        "private_gateway_acl":False,
        "nic_ip":"172.16.1.1",
        "nic_netmask":"24",
        "ingress_rules":
        [
            {"type":"all",
            "cidr":"0.0.0.0/0",
            "allowed":False}
        ],
        "egress_rules":
        [
            {"type":"all",
            "cidr":"0.0.0.0/0",
            "allowed":False}
        ],
        "type":"networkacl"
    }

    basic_dhcp_entry = {
        "host_name":"VM-58976c22-0832-451e-9ab2-039e9f27e415",
        "mac_address":"02:00:26:c3:00:02",
        "ipv4_address":"172.16.1.102",
        "ipv6_duid":"00:03:00:01:02:00:26:c3:00:02",
        "default_gateway":"172.16.1.1",
        "default_entry":True,
        "type":"dhcpentry"
    }

    basic_network_acl = {
        "device":"eth2",
        "mac_address":"02:00:5d:8d:00:03",
        "private_gateway_acl":False,
        "nic_ip":"172.16.1.1",
        "nic_netmask":"24",
        "ingress_rules":
        [ ],
        "egress_rules":
        [ ],
        "type":"networkacl"
    }

    basic_acl_rules = [
        # block range tcp
        {
            "allowed": False,
            "cidr": "1.2.3.0/24",
            "first_port": 60,
            "last_port": 70,
            "type": "tcp"
        },
        # block range udp
        {
            "allowed": False,
            "cidr": "1.2.3.0/24",
            "first_port": 60,
            "last_port": 70,
            "type": "udp"
        },
        # ipv6
        {
            "allowed": True,
            "cidr": "1.2.3.0/24",
            "protocol": 41,
            "type": "protocol"
        },
        # Single port
        {
            "allowed": True,
            "cidr": "1.2.3.0/24",
            "first_port": 30,
            "last_port": 30,
            "type": "tcp"
        },
        # Icmp
        {
            "allowed": True,
            "cidr": "10.0.0.0/8",
            "icmp_code": -1,
            "icmp_type": -1,
            "type": "icmp"
        }
    ]

    def redundant(self, what):
        with hide("everything"):
            result = run("python /opt/cloud/bin/set_redundant.py %s" % what,
                         timeout=600, warn_only=True)
            assert result.succeeded, 'Set redundancy to %s' % what

    def configure(self):
        with hide("everything"):
            result = run("python /opt/cloud/bin/configure.py",
                         timeout=600, warn_only=True)
            assert result.succeeded, "Configure ran"

    def update_config(self, config):
        config_json = json.dumps(config, indent=2)
        #print_doc('config.json', config_json)
        file_write('/var/cache/cloud/update_config_test.json', config_json)
        with hide("everything"):
            result = run("python /opt/cloud/bin/update_config.py update_config_test.json",
                         timeout=600, warn_only=True)
            assert result.succeeded, 'update_config.py ran without errors'
            assert result.find("Convergence is achieved") >= 0, 'update_config.py should report convergence'

    def clear_log(self):
        tstamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        run("test -f /var/log/cloud.log && mv /var/log/cloud.log /var/log/cloud.log.%s || true" % tstamp)

    def setUp(self):
        super(UpdateConfigTestCase, self).setUp()
        self.clear_log()

    def check_no_errors(self):
        # todo config update should exit 1 on convergence errors!
        found, context = has_line('/var/log/cloud.log', 'cannot be configured')
        if found:
            #print_doc('/var/log/cloud.log', context)
            pass
        assert not found, 'cloud.log should not contain "cannot be configured"'

    @attr(tags=["systemvm"], required_hardware="true")
    def test_basic_config(self):
        self.update_config(self.basic_config)
        self.check_no_errors()
        # should be able to run twice with same config
        self.clear_log()
        self.update_config(self.basic_config)
        self.check_no_errors()

    @attr(tags=["systemvm"], required_hardware="true")
    def test_various_random_ip_addresses(self):
        buffer = []
        r = random.Random()
        r.seed()
        for i in range(0, 10):
            ip_address = {}
            # todo need to know what kind of configurations are valid!
            config = deep_copy(self.basic_config)
            ip_address = deep_copy(self.basic_config["ip_address"][0])
            ip_address["public_ip"] = "10.0.2.%d" % (i + 103)
            ip_address["source_nat"] = r.choice((True, False))
            ip_address["add"] = True
            ip_address["one_to_one_nat"] = r.choice((True, False))
            ip_address["first_i_p"] = r.choice((True, False))
            ip_address["nic_dev_id"] = r.choice((2,3))
            config["ip_address"].append(ip_address)
            # runs a bunch of times adding an IP address each time
            self.update_config(config)
            ip_address["add"] = False
            buffer.append(copy.deepcopy(ip_address))
            self.check_no_errors()
            self.clear_log()
            assert ip.has_ip("%s/24" % ip_address["public_ip"], "eth%s" % ip_address["nic_dev_id"]), \
                    "Configure %s on eth%s failed" % (ip_address["public_ip"], ip_address["nic_dev_id"])
        # Create some acls for the IPs we just created
        # This will lead to multiple attempts to add the same acl - *this is intentional*
        self.check_acl(buffer)
        # Now delete all the IPs we just made
        for ips in buffer:
            config = copy.deepcopy(self.basic_config)
            config["ip_address"].append(ips)
            self.update_config(config)
            assert not ip.has_ip("%s/24" % ips["public_ip"], "eth%s" % ips["nic_dev_id"]), \
                    "Delete %s on eth%s failed" % (ips["public_ip"], ips["nic_dev_id"])

    def test_create_guest_network(self):
        config = { "add":True,
                   "mac_address":"02:00:56:36:00:02",
                   "device":"eth4",
                   "router_guest_ip":"172.16.1.1",
                   "router_guest_gateway":"172.16.1.0",
                   "router_guest_netmask":"255.255.255.0",
                   "cidr":"24",
                   "dns":"8.8.8.8,8.8.8.4",
                   "domain_name":"devcloud.local",
                   "type":"guestnetwork"
                   }
        config['add'] = False
        # Clear up from any failed test runs
        self.update_config(config)
        config['add'] = True
        self.guest_network(config)
        passw = { "172.16.1.20" : "20",
                  "172.16.1.21" : "21",
                  "172.16.1.22" : "22"
                  }
        self.check_password(passw)

        passw = { "172.16.1.20" : "120",
                  "172.16.1.21" : "121",
                  "172.16.1.22" : "122"
                  }
        self.check_password(passw)

        config = { "add":True,
                   "mac_address":"02:00:56:36:00:02",
                   "device":"eth4",
                   "router_guest_ip":"172.16.2.1",
                   "router_guest_gateway":"172.16.2.0",
                   "router_guest_netmask":"255.255.255.0",
                   "cidr":"24",
                   "dns":"8.8.8.8,8.8.8.4",
                   "domain_name":"devcloud2.local",
                   "type":"guestnetwork"
                   }
        self.guest_network(config)

    def check_acl(self, list):
        clear1 = self.clear_all_acls()
        clear2 = self.clear_all_acls()
        assert clear1 == clear2, "Clear all acls called twice and produced different results"
        unique = {}

        # How many unique devices
        for ips in list:
            unique["eth%s" % ips["nic_dev_id"]] = 1

        # If this is the first run, the drops will not be there yet
        # this is so I can get get a true count of what is explicitly added
        drops = len(unique)
        for dev in unique:
            drops -= ip.count_fw_rules('ACL_INBOUND_%s -j DROP' % dev)

        for ips in list:
            config = copy.deepcopy(self.basic_network_acl)
            config['device'] = "eth%s" % ips["nic_dev_id"]
            config['nic_ip'] = ips["public_ip"]
            for rule in self.basic_acl_rules:
                config['ingress_rules'].append(rule)
                config['egress_rules'].append(rule)
            self.update_config(config)

        # Check the default drop rules are there
        for dev in unique:
            drop = ip.count_fw_rules('ACL_INBOUND_%s -j DROP' % dev)
            assert drop == 1, "ACL_INBOUND_%s does not have a default drop rule" % dev

        after = ip.count_fw_rules()
        # How many new acls should we get?
        # The number of rules * the number of devices * 2 (in and out)
        expected = len(unique) * 2 * len(self.basic_acl_rules) + clear2 + drops
        assert expected == after, "Number of acl rules does not match what I expected to see"
        for dev in range(6):
            config = copy.deepcopy(self.basic_network_acl)
            config['device'] = "eth%s" % dev
            self.update_config(config)
        clear2 = self.clear_all_acls() - drops
        assert clear1 == clear2, "Clear all acls appears to have failed"

    def clear_all_acls(self):
        for dev in range(6):
            config = copy.deepcopy(self.basic_network_acl)
            config['device'] = "eth%s" % dev
            self.update_config(config)
        return ip.count_fw_rules()

    def check_password(self,passw):
        for val in passw:
            self.add_password(val, passw[val])
        for val in passw:
            assert file.has_line("/var/cache/cloud/passwords", "%s=%s" % (val, passw[val]))

    def add_password(self, ip, password):
        config = { "ip_address": ip,
                   "password":password,
                   "type":"vmpassword"
                 }
        self.update_config(config)
        assert file.has_line("/var/cache/cloud/passwords", "%s=%s" % (ip, password))

    def guest_network(self,config):
        vpn_config = {
            "local_public_ip": config['router_guest_ip'],
            "local_guest_cidr":"%s/%s" % (config['router_guest_gateway'], config['cidr']),
            "local_public_gateway":"172.16.1.1",
            "peer_gateway_ip":"10.200.200.1",
            "peer_guest_cidr_list":"10.0.0.0/24",
            "esp_policy":"3des-md5",
            "ike_policy":"3des-md5",
            "ipsec_psk":"vpnblabla",
            "ike_lifetime":86400,
            "esp_lifetime":3600,
            "create":True,
            "dpd":False,
            "passive":False,
            "type":"site2sitevpn"
        }
        octets = config['router_guest_ip'].split('.')
        configs = []

        # This should fail because the network does not yet exist
        self.update_config(vpn_config)
        assert not file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])

        self.update_config(config)
        self.update_config(vpn_config)
        assert ip.has_ip("%s/%s" % (config['router_guest_ip'], config['cidr']), config['device'])
        assert process.is_up("apache2"), "Apache2 should be running after adding a guest network"
        assert process.is_up("dnsmasq"), "Dnsmasq should be running after adding a guest network"

        assert file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])
        assert file.mode_is("/etc/ipsec.d/ipsec.vpn-%s.secrets" % vpn_config['peer_gateway_ip'], "400")
        result = run("/usr/sbin/ipsec setup status", timeout=600, warn_only=True)
        assert result.succeeded, 'ipsec returned non zero status %s' % config['router_guest_ip']
		# Add a host to the dhcp server
		# This must happen in order for dnsmasq to be listening
        for n in range(3,13):
            ipb = ".".join(octets[0:3])
            ipa = "%s.%s" % (ipb, n)
            gw = "%s.1" % ipb
            self.basic_dhcp_entry['ipv4_address'] =  ipa
            self.basic_dhcp_entry['default_gateway'] =  gw
            self.basic_dhcp_entry['host_name'] =  "host_%s" % (ipa)
            self.update_config(self.basic_dhcp_entry)
            configs.append(copy.deepcopy(self.basic_dhcp_entry))
        assert port.is_listening(80)
        assert port.is_listening(53)
        assert port.is_listening(53)
        assert port.is_listening(67)
        for o in configs:
            line = "%s,%s,%s,infinite" % (o['mac_address'], o['ipv4_address'], o['host_name'])
            assert file.has_line("/etc/dhcphosts.txt", line)
        config['add'] = False
        self.update_config(config)
        assert not ip.has_ip("%s/%s" % (config['router_guest_ip'], config['cidr']), config['device'])
        # Now setup what we have redundant
        self.redundant("-e")
        self.configure()
        assert process.is_up("keepalived"), "Keepalived should be running after enabling redundancy"
        assert process.is_up("conntrackd"), "Conntrackd should be running after enabling redundancy"
        self.redundant("-d")
        self.configure()
        assert not process.is_up("keepalived"), "Keepalived should be not running after disabling redundancy"
        assert not process.is_up("conntrackd"), "Conntrackd should be not running after disabling redundancy"
        for o in configs:
            o['add'] = False
            self.update_config(o)
        for o in configs:
            line = "%s,%s,%s,infinite" % (o['mac_address'], o['ipv4_address'], o['host_name'])
            assert file.has_line("/etc/dhcphosts.txt", line) is False
        # If the network gets deleted so should the vpn
        assert not file.exists("/etc/ipsec.d/ipsec.vpn-%s.conf" % vpn_config['peer_gateway_ip'])

if __name__ == '__main__':
    unittest.main()
