#coding:utf-8

import subprocess
import sys
from IPy import IP
import re
import time

# 编号规则
# 2188<xx><yy><zzzz>
#   xx - 产品类型，虚拟网关统一为00； yy虚拟网关附属的服务器，换一台新服务器后加1； zzzz:区分同一服务器下不同的虚拟网关间
SN_START = 0x218800002001
SN_END = 0x21880000FFFF

# need first run network create command manually before run the script
# docker network create --subnet=172.18.0.0/24 --gateway 172.18.0.1 mynetwork

def execute_cmd(cmd):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    output, err = p.communicate()
    # 判断命令是否执行成功
    status = 1 if err else 0
    if status == 0:
        print('[SUCCESS] %s' % cmd)
    else:
        print('[ERROR] %s' % cmd)
        print(err)
    output = output.decode(encoding="utf-8")
    output = output.strip()
    return status, output

def get_number(x):
    return re.match("^[0-9a-fA-F]+$", x)



def get_exist_containers_info():
    ret, output = execute_cmd("docker inspect --format='{{.Name}},{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)")
    containers = output.splitlines()
    infos = []
    used_ips = []
    used_sns = []

    patternStr = r'sn\s=\s(.+)'
    p = re.compile(patternStr, re.IGNORECASE)
    for c in containers:
        info = {}
        info['name'] = c.split(',')[0]
        info['ip'] = c.split(',')[1]
        ret, output = execute_cmd("docker exec " + info['name'] + " cat /app/config/fac.ini")
        print(output)
        SNs = re.findall(patternStr, output)
        if (len(SNs)==0):
            continue
        else:
            info['SN'] = SNs[0]
            infos.append(info)
            used_ips.append(info['ip'])
            i = get_number(info['SN'])
            print(i)
            if i is not None:
                used_sns.append(int(info['SN'], 16))



    return infos,used_ips,used_sns

def get_network_info():
    ret, output = execute_cmd("docker network inspect --format='{{/*查看容器的默认网关*/}}{{range .IPAM.Config}}{{.Subnet}},{{.Gateway}}{{end}}' mynetwork")
    network = output.split(',')
    if (len(network) == 0):
        return
    else:
        subnet = network[0]
        gateway = network[1]

    return subnet,gateway

def start_and_config_container(name, image, ip, netmask, sn, gateway):
    cmd = "docker run --privileged --name='" + name +"' --restart=always --ulimit nofile=262144:262144 --ulimit msgqueue=81920000:81920000  --net mynetwork --ip " + ip + \
          "  --detach=true " + image + " /sbin/init"
    ret, output = execute_cmd(cmd)
    time.sleep(120)
    cmd = "docker exec " + name + " uci set network.wan.proto='static'"
    execute_cmd(cmd)
    cmd = "docker exec " + name + " uci set network.wan.ifname='eth0'"
    execute_cmd(cmd)
    cmd = "docker exec " + name + " uci set network.wan.netmask='" + netmask + "'"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " uci set network.wan.ipaddr='" + ip + "'"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " uci set network.wan.gateway='" + gateway + "'"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " uci add_list network.wan.dns='114.114.114.114'"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " uci set network.wan.defaultroute=1"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " uci commit"
    execute_cmd(cmd)
    cmd = "docker exec  " + name + " echo 'none' > /app/config/4g_modem"
    execute_cmd(cmd)
    cmd = 'docker exec  ' + name + ' sed -i "s/sn = [0-9A-Za-z]\+/sn = ' + sn + '/" /app/config/fac.ini'
    execute_cmd(cmd)
    cmd = 'docker restart ' + name
    execute_cmd(cmd)

if __name__ == '__main__':
    name = sys.argv[1]
    image = sys.argv[2]

    infos, used_ip, used_sn = get_exist_containers_info()
    print(infos)
    print(used_ip)
    print(used_sn)

    subnet, gateway = get_network_info()
    subnet_ips = IP(subnet, make_net=1)
    netmask = str(subnet_ips.netmask())

    used_ip.append(gateway)
    used_ip.append(str(subnet_ips.broadcast()))
    used_ip.append(subnet.split('/')[0])

    for ip in subnet_ips:
        if str(ip) not in used_ip:
            got_ip = str(ip)
            break

    sn = SN_START
    while sn < SN_END:
        if sn not in used_sn:
            got_sn = "%X" % sn
            break
        sn = sn + 1
    print(got_ip, sn, gateway)
    start_and_config_container(name, image, got_ip, netmask, got_sn, gateway)
