#!/usr/bin/python
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Manage vms through vagrant.

The intent of this interface is to provde a layer of abstraction
between the box providers and the creation of a lab cluster. To switch to a
different provider:

* Create a VagrantFile template and specify _template in the subclass
  Eg: GCE VagrantFiles need a :google section
* Override vagrant_cmd to massage parameters
  Eg: vagrant up => vagrant up --provider=google

Note that the second is optional because most providers honor
`VAGRANT_DEFAULT_PROVIDER` directly in the template.
"""


import logging
import subprocess
import sys
import os

import common
from autotest_lib.site_utils.lib import infra


class VagrantCmdError(Exception):
    """Raised when a vagrant command fails."""


# TODO: We don't really need to setup everythig in the same VAGRANT_DIR.
# However managing vms becomes a headache once the VagrantFile and its
# related dot files are removed, as one has to resort to directly
# querying the box provider. Always running the cluster from the same
# directory simplifies vm lifecycle management.
VAGRANT_DIR = os.path.abspath(os.path.join(__file__, os.pardir))
VAGRANT_VERSION = '1.6.0'


def format_msg(msg):
    """Format the give message.

    @param msg: A message to format out to stdout.
    """
    print '\n{:^20s}%s'.format('') % msg


class VagrantProvisioner(object):
    """Provisiong vms with vagrant."""

    # A path to a Vagrantfile template specific to the vm provider, specified
    # in the child class.
    _template = None
    _box_name = 'base'


    @classmethod
    def vagrant_cmd(cls, cmd, stream_output=False):
        """Execute a vagrant command in VAGRANT_DIR.

        @param cmd: The command to execute.
        @param stream_output: If True, stream the output of `cmd`.
                Waits for `cmd` to finish and returns a string with the
                output if false.
        """
        with infra.chdir(VAGRANT_DIR):
            try:
                return infra.execute_command(
                        'localhost',
                        'vagrant %s' % cmd, stream_output=stream_output)
            except subprocess.CalledProcessError as e:
                raise VagrantCmdError(
                        'Command "vagrant %s" failed with %s' % (cmd, e))


    def _check_vagrant(self):
        """Check Vagrant."""

        # TODO: Automate the installation of vagrant.
        try:
            version = int(self.vagrant_cmd('--version').rstrip('\n').rsplit(
                    ' ')[-1].replace('.', ''))
        except VagrantCmdError:
            logging.error(
                    'Looks like you don\'t have vagrant. Please run: \n'
                    '`apt-get install virtualbox vagrant`. This assumes you '
                    'are on Trusty; There is a TODO to automate installation.')
            sys.exit(1)
        except TypeError as e:
            logging.warning('The format of the vagrant version string seems to '
                            'have changed, assuming you have a version > %s.',
                            VAGRANT_VERSION)
            return
        if version < int(VAGRANT_VERSION.replace('.', '')):
            logging.error('Please upgrade vagrant to a version > %s by '
                          'downloading a deb file from '
                          'https://www.vagrantup.com/downloads and installing '
                          'it with dpkg -i file.deb', VAGRANT_VERSION)
            sys.exit(1)


    def __init__(self, puppet_path):
        """Initialize a vagrant provisioner.

        @param puppet_path: Since vagrant uses puppet to provision machines,
                this is the location of puppet modules for various server roles.
        """
        self._check_vagrant()
        self.puppet_path = puppet_path


    def register_box(self, source, name=_box_name):
        """Register a box with vagrant.

        Eg: vagrant box add core_cluster chromeos_lab_core_cluster.box

        @param source: A path to the box, typically a file path on localhost.
        @param name: A name to register the box under.
        """
        if name in self.vagrant_cmd('box list'):
            logging.warning("Name %s already in registry, will reuse.", name)
            return
        logging.info('Adding a new box from %s under name: %s', source, name)
        self.vagrant_cmd('box add %s %s' % (name, source))


    def unregister_box(self, name):
        """Unregister a box.

        Eg: vagrant box remove core_cluster.

        @param name: The name of the box as it appears in `vagrant box list`
        """
        if name not in self.vagrant_cmd('box list'):
            logging.warning("Name %s not in registry.", name)
            return
        logging.info('Removing box %s', name)
        self.vagrant_cmd('box remove %s' % name)


    def create_vagrant_file(self, **kwargs):
        """Create a vagrant file.

        Read the template, apply kwargs and the puppet_path so vagrant can find
        server provisioning rules, and write it back out as the VagrantFile.

        @param kwargs: Extra args needed to convert a template
                to a real VagrantFile.
        """
        vagrant_file = os.path.join(VAGRANT_DIR, 'Vagrantfile')
        kwargs.update({
            'manifest_path': os.path.join(self.puppet_path, 'manifests'),
            'module_path': os.path.join(self.puppet_path, 'modules'),
        })
        vagrant_template = ''
        with open(self._template, 'r') as template:
            vagrant_template = template.read()
        with open(vagrant_file, 'w') as vagrantfile:
            vagrantfile.write(vagrant_template % kwargs)


    # TODO: This is a leaky abstraction, since it isn't really clear
    # what the kwargs are. It's the best we can do, because the kwargs
    # really need to match the VagrantFile. We leave parsing the VagrantFile
    # for the right args upto the caller.
    def initialize_vagrant(self, **kwargs):
        """Initialize vagrant.

        @param kwargs: The kwargs to pass to the VagrantFile.
            Eg: {
                'shard1': 'lumpyshard',
                'shard1_port': 8002,
                'shard1_shadow_config_hostname': 'localhost:8002',
            }
        @return: True if vagrant was initialized, False if the cwd already
                 contains a vagrant environment.
        """
        # TODO: Split this out. There are cases where we will need to
        # reinitialize (by destroying all vms and recreating the VagrantFile)
        # that we cannot do without manual intervention right now.
        try:
            self.vagrant_cmd('status')
            logging.info('Vagrant already initialized in %s', VAGRANT_DIR)
            return False
        except VagrantCmdError:
            logging.info('Initializing vagrant in %s', VAGRANT_DIR)
            self.create_vagrant_file(**kwargs)
            return True


    def provision(self, force=False):
        """Provision vms according to the vagrant file.

        @param force: If True, vms in the VAGRANT_DIR will be destroyed and
                reprovisioned.
        """
        if force:
            logging.info('Destroying vagrant setup.')
            try:
                self.vagrant_cmd('destroy --force', stream_output=True)
            except VagrantCmdError:
                pass
        format_msg('Starting vms. This should take no longer than 5 minutes')
        self.vagrant_cmd('up', stream_output=True)


class VirtualBox(VagrantProvisioner):
    """A VirtualBoxProvisioner."""

    _template = os.path.join(VAGRANT_DIR, 'ClusterTemplate')


