import decimal
import textwrap

from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.resources import ServiceMonitor


class ProxmoxOVZ(ServiceController):
    model = 'vps.VPS'
    
    RESOURCES = (
        ('memory', 'mem'),
        ('swap', 'swap'),
        ('disk', 'disk')
    )
    GET_PROXMOX_INFO = textwrap.dedent("""
        function get_vz_info () {
            hostname=$1
            version=$(pveversion | cut -d '/' -f2 | cut -d'.' -f1)
            if [[ $version -lt 2 ]]; then
                conf=$(grep "CID\\|:$hostname:" /var/lib/pve-manager/vzlist | grep -B1 ":$hostname:")
                CID=$(echo "$conf" | head -n1 | cut -d':' -f2)
                CTID=$(echo "$conf" | tail -n1 | cut -d':' -f1)
                node=$(pveca -l | grep "^\\s*$CID\\s*:" | awk {'print $3'})
            else
                conf=$(grep -r "HOSTNAME=\\"$hostname\\"" /etc/pve/nodes/*/openvz/*.conf)
                node=$(echo "${conf}" | cut -d"/" -f5)
                CTID=$(echo "${conf}" | cut -d"/" -f7 | cut -d"\\." -f1)
            fi
            echo $CTID $node
        }""")
    
    def prepare(self):
        super(ProxmoxOVZ, self).prepare()
        self.append(self.GET_PROXMOX_INFO)
    
    def get_vzset_args(self, vps):
        args = []
        for resource, arg_name in self.RESOURCES:
            try:
                allocation = getattr(vps.resources, resource).allocated
            except AttributeError:
                pass
            else:
                args.append('--%s %i' % (arg_name, allocation))
        return ' '.join(args)
    
    def save(self, vps):
        context = self.get_context(vps)
        self.append('info=( $(get_vz_info %(hostname)s) )' % context)
        vzset_args = self.get_vzset_args(vps)
        if vzset_args:
            context['vzset_args'] = vzset_args
            self.append(textwrap.dedent("""\
                cat << EOF | ssh root@${info[1]}
                    pvectl vzset ${info[0]} %(vzset_args)s
                EOF""") % context
            )
        if hasattr(vps, 'password'):
            context['password'] = vps.password.replace('$', '\\$')
            self.append(textwrap.dedent("""\
                cat << EOF | ssh root@${info[1]}
                    echo 'root:%(password)s' | vzctl exec ${info[0]} chpasswd -e
                EOF""") % context
            )
    def get_context(self, vps):
        return {
            'hostname': vps.hostname,
        }


# TODO rename to proxmox
class OpenVZTraffic(ServiceMonitor):
    model = 'vps.VPS'
    resource = ServiceMonitor.TRAFFIC
    monthly_sum_old_values = True
    
    def prepare(self):
        super(OpenVZTraffic, self).prepare()
        self.append(ProxmoxOVZ.GET_PROXMOX_INFO)
        self.append(textwrap.dedent("""
            function monitor () {
                object_id=$1
                hostname=$2
                info=( $(get_vz_info $hostname) )
                cat << EOF | ssh root@${info[1]}
                    vzctl exec ${info[0]} cat /proc/net/dev \\
                        | grep venet0 \\
                        | tr ':' ' ' \\
                        | awk '{sum=\\$2+\\$10} END {printf ("$object_id %0.0f\\n", sum)}'
            EOF
            }
            """)
        )
    
    def process(self, line):
        """ diff with last stored state """
        object_id, value, state = super(OpenVZTraffic, self).process(line)
        value = decimal.Decimal(value)
        last = self.get_last_data(object_id)
        if not last or last.state > value:
            return object_id, value, value
        return object_id, value-last.state, value
    
    def monitor(self, vps):
        """ Get OpenVZ container traffic on a Proxmox cluster """
        context = self.get_context(vps)
        self.append('monitor %(object_id)s %(hostname)s' % context)
    
    def get_context(self, vps):
        return {
            'object_id': vps.id,
            'hostname': vps.hostname,
        }