// 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.

package com.cloud.hypervisor.ovm3.resources.helpers;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.xmlrpc.XmlRpcException;

import com.cloud.agent.api.Answer;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PlugNicAnswer;
import com.cloud.agent.api.PlugNicCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin;
import com.cloud.hypervisor.ovm3.objects.Connection;
import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException;
import com.cloud.hypervisor.ovm3.objects.OvmObject;
import com.cloud.hypervisor.ovm3.objects.Xen;
import com.cloud.hypervisor.ovm3.resources.Ovm3StorageProcessor;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.Volume;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine.State;

public class Ovm3VmSupport {
    protected Logger logger = LogManager.getLogger(getClass());
    private OvmObject ovmObject = new OvmObject();
    private ResourceManager resourceMgr;
    private Connection c;
    private Ovm3HypervisorNetwork network;
    private Ovm3Configuration config;
    private Ovm3HypervisorSupport hypervisor;
    private Ovm3StorageProcessor processor;
    private Ovm3StoragePool pool;
    private final Map<String, Map<String, String>> vmStats = new ConcurrentHashMap<String, Map<String, String>>();
    public Ovm3VmSupport(Connection conn,
            Ovm3Configuration ovm3config,
            Ovm3HypervisorSupport ovm3hyper,
            Ovm3StorageProcessor ovm3stp,
            Ovm3StoragePool ovm3sp,
            Ovm3HypervisorNetwork ovm3hvn) {
        c = conn;
        config = ovm3config;
        hypervisor = ovm3hyper;
        pool = ovm3sp;
        processor = ovm3stp;
        network = ovm3hvn;
    }
    public Boolean createVifs(Xen.Vm vm, VirtualMachineTO spec)
            throws Ovm3ResourceException {
        if (spec.getNics() != null) {
            NicTO[] nics = spec.getNics();
            return createVifs(vm, nics);
        } else {
            logger.info("No nics for vm " + spec.getName());
            return false;
        }
    }

    private Boolean createVifs(Xen.Vm vm, NicTO[] nics)
            throws Ovm3ResourceException {
        for (NicTO nic : nics) {
            if (!createVif(vm, nic)) {
                return false;
            }
        }
        return true;
    }

    /* should add bitrates and latency... */
    private Boolean createVif(Xen.Vm vm, NicTO nic)
            throws Ovm3ResourceException {
        try {
            String net = network.getNetwork(nic);
            if (net != null) {
                logger.debug("Adding vif " + nic.getDeviceId() + " "
                        + nic.getMac() + " " + net + " to " + vm.getVmName());
                vm.addVif(nic.getDeviceId(), net, nic.getMac());
            } else {
                logger.debug("Unable to add vif " + nic.getDeviceId()
                        + " no network for " + vm.getVmName());
                return false;
            }
        } catch (Exception e) {
            String msg = "Unable to add vif " + nic.getType() + " for "
                    + vm.getVmName() + " " + e.getMessage();
            logger.debug(msg);
            throw new Ovm3ResourceException(msg);
        }
        return true;
    }
    private Boolean deleteVif(Xen.Vm vm, NicTO nic)
            throws Ovm3ResourceException {
        /* here we should use the housekeeping of VLANs/Networks etc..
         * so we can clean after the last VM is gone
         */
        try {
            String net = network.getNetwork(nic);
            if (net != null) {
                logger.debug("Removing vif " + nic.getDeviceId() + " " + " "
                        + nic.getMac() + " " + net + " from " + vm.getVmName());
                vm.removeVif(net, nic.getMac());
            } else {
                logger.debug("Unable to remove vif " + nic.getDeviceId()
                        + " no network for " + vm.getVmName());
                return false;
            }
        } catch (Exception e) {
            String msg = "Unable to remove vif " + nic.getType() + " for "
                    + vm.getVmName() + " " + e.getMessage();
            logger.debug(msg);
            throw new Ovm3ResourceException(msg);
        }
        return true;
    }

    /* Migration should make sure both HVs are the same ? */
    public PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
        VirtualMachineTO vm = cmd.getVirtualMachine();
        if (logger.isDebugEnabled()) {
            logger.debug("Preparing host for migrating " + vm.getName());
        }
        NicTO[] nics = vm.getNics();
        try {
            for (NicTO nic : nics) {
                network.getNetwork(nic);
            }
            hypervisor.setVmState(vm.getName(), State.Migrating);
            logger.debug("VM " + vm.getName() + " is in Migrating state");
            return new PrepareForMigrationAnswer(cmd);
        } catch (Ovm3ResourceException e) {
            logger.error("Catch Exception " + e.getClass().getName()
                    + " prepare for migration failed due to: " + e.getMessage());
            return new PrepareForMigrationAnswer(cmd, e);
        }
    }

    /* do migrations of VMs in a simple way just inside a cluster for now */
    public MigrateAnswer execute(final MigrateCommand cmd) {
        final String vmName = cmd.getVmName();
        String destUuid = cmd.getHostGuid();
        String destIp = cmd.getDestinationIp();
        State state = State.Error;
        /*
         * TODO: figure out non pooled migration, works from CLI but not from
         * the agent... perhaps pause the VM and then migrate it ? for now just
         * stop the VM.
         */
        String msg = "Migrating " + vmName + " to " + destIp;
        logger.info(msg);
        if (!config.getAgentInOvm3Cluster() && !config.getAgentInOvm3Pool()) {
            try {
                Xen xen = new Xen(c);
                Xen.Vm vm = xen.getRunningVmConfig(vmName);
                HostVO destHost = resourceMgr.findHostByGuid(destUuid);
                if (destHost == null) {
                    msg = "Unable to find migration target host in DB "
                            + destUuid + " with ip " + destIp;
                    logger.info(msg);
                    return new MigrateAnswer(cmd, false, msg, null);
                }
                xen.stopVm(ovmObject.deDash(vm.getVmRootDiskPoolId()),
                        vm.getVmUuid());
                msg = destHost.toString();
                state = State.Stopping;
                return new MigrateAnswer(cmd, false, msg, null);
            } catch (Ovm3ResourceException e) {
                msg = "Unpooled VM Migrate of " + vmName + " to " + destUuid
                        + " failed due to: " + e.getMessage();
                logger.debug(msg, e);
                return new MigrateAnswer(cmd, false, msg, null);
            } finally {
                /* shouldn't we just reinitialize completely as a last resort ? */
                hypervisor.setVmState(vmName, state);
            }
        } else {
            try {
                Xen xen = new Xen(c);
                Xen.Vm vm = xen.getRunningVmConfig(vmName);
                if (vm == null) {
                    state = State.Stopped;
                    msg = vmName + " is no running on " + config.getAgentHostname();
                    return new MigrateAnswer(cmd, false, msg, null);
                }
                /* not a storage migration!!! */
                xen.migrateVm(ovmObject.deDash(vm.getVmRootDiskPoolId()),
                        vm.getVmUuid(), destIp);
                state = State.Stopping;
                msg = "Migration of " + vmName + " successful";
                return new MigrateAnswer(cmd, true, msg, null);
            } catch (Ovm3ResourceException e) {
                msg = "Pooled VM Migrate" + ": Migration of " + vmName + " to "
                        + destIp + " failed due to " + e.getMessage();
                logger.debug(msg, e);
                return new MigrateAnswer(cmd, false, msg, null);
            } finally {
                hypervisor.setVmState(vmName, state);
            }
        }
    }

    /*
     */
    public GetVncPortAnswer execute(GetVncPortCommand cmd) {
        try {
            Xen host = new Xen(c);
            Xen.Vm vm = host.getRunningVmConfig(cmd.getName());
            Integer vncPort = vm.getVncPort();
            logger.debug("get vnc port for " + cmd.getName() + ": " + vncPort);
            return new GetVncPortAnswer(cmd, c.getIp(), vncPort);
        } catch (Ovm3ResourceException e) {
            logger.debug("get vnc port for " + cmd.getName() + " failed", e);
            return new GetVncPortAnswer(cmd, e.getMessage());
        }
    }

    private VmStatsEntry getVmStat(String vmName) {
        CloudstackPlugin cSp = new CloudstackPlugin(c);
        Map<String, String> oldVmStats = null;
        Map<String, String> newVmStats = null;
        VmStatsEntry stats = new VmStatsEntry();
        try {
            if (vmStats.containsKey(vmName)) {
                oldVmStats = new HashMap<String, String>();
                oldVmStats.putAll(vmStats.get(vmName));
            }
            newVmStats = cSp.ovsDomUStats(vmName);
        } catch (Ovm3ResourceException e) {
            logger.info("Unable to retrieve stats from " + vmName, e);
            return stats;
        }
        if (oldVmStats == null) {
            logger.debug("No old stats retrieved stats from " + vmName);
            stats.setNumCPUs(1);
            stats.setNetworkReadKBs(0);
            stats.setNetworkWriteKBs(0);
            stats.setDiskReadKBs(0);
            stats.setDiskWriteKBs(0);
            stats.setDiskReadIOs(0);
            stats.setDiskWriteIOs(0);
            stats.setCPUUtilization(0);
            stats.setEntityType("vm");
        } else {
            logger.debug("Retrieved new stats from " + vmName);
            int cpus = Integer.parseInt(newVmStats.get("vcpus"));
            stats.setNumCPUs(cpus);
            stats.setNetworkReadKBs(doubleMin(newVmStats.get("rx_bytes"), oldVmStats.get("rx_bytes")));
            stats.setNetworkWriteKBs(doubleMin(newVmStats.get("tx_bytes"), oldVmStats.get("tx_bytes")));
            stats.setDiskReadKBs(doubleMin(newVmStats.get("rd_bytes"), oldVmStats.get("rd_bytes")));
            stats.setDiskWriteKBs(doubleMin(newVmStats.get("rw_bytes"), oldVmStats.get("rw_bytes")));
            stats.setDiskReadIOs(doubleMin(newVmStats.get("rd_ops"), oldVmStats.get("rd_ops")));
            stats.setDiskWriteIOs(doubleMin(newVmStats.get("rw_ops"), oldVmStats.get("rw_ops")));
            Double dCpu = doubleMin(newVmStats.get("cputime"), oldVmStats.get("cputime"));
            Double dTime = doubleMin(newVmStats.get("uptime"), oldVmStats.get("uptime"));
            Double cpupct = dCpu / dTime * 100 * cpus;
            stats.setCPUUtilization(cpupct);
            stats.setEntityType("vm");
        }
        ((ConcurrentHashMap<String, Map<String, String>>) vmStats).put(
                vmName, newVmStats);
        return stats;
    }
    private Double doubleMin(String x, String y) {
        try {
            return (Double.parseDouble(x) - Double.parseDouble(y));
        } catch (NullPointerException e) {
            return 0D;
        }
    }

    public GetVmStatsAnswer execute(GetVmStatsCommand cmd) {
        List<String> vmNames = cmd.getVmNames();
        Map<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>();
        for (String vmName : vmNames) {
            VmStatsEntry e = getVmStat(vmName);
            vmStatsNameMap.put(vmName, e);
        }
        return new GetVmStatsAnswer(cmd,
                (HashMap<String, VmStatsEntry>) vmStatsNameMap);
    }

    /* This is not create for us, but really start */
/*
    public boolean startVm(String repoId, String vmId) throws XmlRpcException {
        Xen host = new Xen(c);
        try {
            if (host.getRunningVmConfig(vmId) == null) {
                logger.error("Create VM " + vmId + " first on " + c.getIp());
                return false;
            } else {
                logger.info("VM " + vmId + " exists on " + c.getIp());
            }
            host.startVm(repoId, vmId);
        } catch (Exception e) {
            logger.error("Failed to start VM " + vmId + " on " + c.getIp()
                    + " " + e.getMessage());
            return false;
        }
        return true;
    }
*/
    /*
     * TODO: OVM already cleans stuff up, just not the extra bridges which we
     * don't want right now, as we'd have to keep a state table of which vlans
     * need to stay on the host!? A map with vlanid -> list-o-hosts
     */
    private void cleanupNetwork(List<String> vifs) throws XmlRpcException {
        /* peel out vif info for vlan stuff */
    }

    public void cleanup(Xen.Vm vm) {
        try {
            cleanupNetwork(vm.getVmVifs());
        } catch (XmlRpcException e) {
            logger.info("Clean up network for " + vm.getVmName() + " failed", e);
        }
        String vmName = vm.getVmName();
        /* should become a single entity */
        vmStats.remove(vmName);
    }

    /*
     * Add rootdisk, datadisk and iso's
     */
    public Boolean createVbds(Xen.Vm vm, VirtualMachineTO spec) {
        if (spec.getDisks() == null) {
            logger.info("No disks defined for " + vm.getVmName());
            return false;
        }
        for (DiskTO disk : spec.getDisks()) {
            try {
                if (disk.getType() == Volume.Type.ROOT) {
                    VolumeObjectTO vol = (VolumeObjectTO) disk.getData();
                    String diskFile = processor.getVirtualDiskPath(vol.getUuid(),  vol.getDataStore().getUuid());
                    vm.addRootDisk(diskFile);
                    vm.setPrimaryPoolUuid(vol.getDataStore().getUuid());
                    logger.debug("Adding root disk: " + diskFile);
                } else if (disk.getType() == Volume.Type.ISO) {
                    DataTO isoTO = disk.getData();
                    if (isoTO.getPath() != null) {
                        TemplateObjectTO template = (TemplateObjectTO) isoTO;
                        DataStoreTO store = template.getDataStore();
                        if (!(store instanceof NfsTO)) {
                            throw new CloudRuntimeException(
                                    "unsupported protocol");
                        }
                        NfsTO nfsStore = (NfsTO) store;
                        String secPoolUuid = pool.setupSecondaryStorage(nfsStore
                                .getUrl());
                        String isoPath = config.getAgentSecStoragePath() + "/"
                                + secPoolUuid + "/"
                                + template.getPath();
                        vm.addIso(isoPath);
                        /* check if secondary storage is mounted */
                        logger.debug("Adding ISO: " + isoPath);
                    }
                } else if (disk.getType() == Volume.Type.DATADISK) {
                    VolumeObjectTO vol = (VolumeObjectTO) disk.getData();
                    String diskFile = processor.getVirtualDiskPath(vol.getUuid(),  vol.getDataStore().getUuid());
                    vm.addDataDisk(diskFile);
                    logger.debug("Adding data disk: "
                            + diskFile);
                } else {
                    throw new CloudRuntimeException("Unknown disk type: "
                            + disk.getType());
                }
            } catch (Exception e) {
                logger.debug("CreateVbds failed", e);
                throw new CloudRuntimeException("Exception" + e.getMessage(), e);
            }
        }
        return true;
    }

    /**
     * Implements the unplug and plug feature for Nics, the boolan decides
     * to either plug (true) or unplug (false)
     *
     * @param nic
     * @param vmName
     * @param plug
     * @return
     */
    private Answer plugNunplugNic(NicTO nic, String vmName, Boolean plug) {
        try {
            Xen xen = new Xen(c);
            Xen.Vm vm = xen.getVmConfig(vmName);
            /* check running */
            if (vm == null) {
                return new Answer(null, false,
                        "Unable to execute command due to missing VM");
            }
            // setup the NIC in the VM config.
            if (plug) {
                createVif(vm, nic);
                vm.setupVifs();
            } else {
                deleteVif(vm, nic);
            }
            // execute the change
            xen.configureVm(ovmObject.deDash(vm.getPrimaryPoolUuid()),
                    vm.getVmUuid());
        } catch (Ovm3ResourceException e) {
            String msg = "Unable to execute command due to " + e.toString();
            logger.debug(msg);
            return new Answer(null, false, msg);
        }
        return new Answer(null, true, "success");
    }
    /**
     * PlugNicAnswer: plug a network interface into a VM
     * @param cmd
     * @return
     */
    public PlugNicAnswer execute(PlugNicCommand cmd) {
        Answer ans = plugNunplugNic(cmd.getNic(), cmd.getVmName(), true);
        return new PlugNicAnswer(cmd, ans.getResult(), ans.getDetails());
    }

    /**
     * UnPlugNicAnswer: remove a nic from a VM
     * @param cmd
     * @return
     */
    public UnPlugNicAnswer execute(UnPlugNicCommand cmd) {
        Answer ans = plugNunplugNic(cmd.getNic(), cmd.getVmName(), false);
        return new UnPlugNicAnswer(cmd, ans.getResult(), ans.getDetails());
    }
}
