# Copyright (c) 2015 Mirantis Inc.
#
# Licensed 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.
"""
# Overview

Implements intercloud live migration functionality.

# Live migration process

 1. Create fake VM on destination node using nova APIs with the same dependent
    objects (networks, images, flavors, etc).
    - This creates all the infrastructure needed for VM to work properly (such
      as virtual network interfaces, openvswitch ports, iptables rules, etc).
 2. Stop nova-compute on destination host
    - This allows us to work with VM at the libvirt level, without Nova
      "knowing" about it
 3. Merge source VM libvirt XML with destination fake VM libvirt XML
    - Source libvirt XML contains source-specific values (virtual network
      interface names, network namespace names, etc), which are invalid on
      destination. Those must be updated with destination node values.
 4. Destroy VM on destination from libvirt level
 5. Live migrate VM using libvirt using XML from step above
 6. Start nova compute on destination

# Tested on

 - Grizzly to Icehouse
"""


import os
from fabric.operations import prompt

import cfglib
from cloudferrylib.base.action import action
from cloudferrylib.os.compute import libvirt
from cloudferrylib.os.compute.nova_compute import instance_host
from cloudferrylib.os.compute.nova_compute import instance_libvirt_name
from cloudferrylib.utils import files
from cloudferrylib.utils import ubuntu
from cloudferrylib.utils import remote_runner
from cloudferrylib.utils import utils


LOG = utils.get_log(__name__)


class LiveMigration(action.Action):
    """
    Runs live migration of VMs

    Process:
     - Create fake VM on DST using nova
     - Update SRC VM's libvirt XML with DST devices
     - Disable nova-compute on DST so that we can replace VM image with
       libvirt. Otherwise nova will track instance state, which we don't want.
     - Destroy fake VM on DST from the libvirt level, so that all the
       infrastructure (virtual networking) required for VM is left intact
     - Live-migrate instance
     - Enable nova-compute on DST

    Requires:
     - qemu 2.0 on source and destination compute nodes
     - remote privileged SSH access to compute nodes
    """

    def run(self, info=None, **kwargs):
        new_id, instance = info[utils.INSTANCES_TYPE].items()[0]
        old_id = instance['old_id']

        dst_compute = self.dst_cloud.resources[utils.COMPUTE_RESOURCE]
        src_compute = self.src_cloud.resources[utils.COMPUTE_RESOURCE]

        dst_compute.change_status('active', instance_id=new_id)