# 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 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()
