# -*- coding: utf-8 -*-
'''
Beacon that fires events on vm state changes

.. code-block:: yaml

    ## minimal
    # - check for vm changes every 1 second (salt default)
    # - does not send events at startup
    beacons:
      vmadm: []

    ## standard
    # - check for vm changes every 60 seconds
    # - send create event at startup for all vms
    beacons:
      vmadm:
        - interval: 60
        - startup_create_event: True
'''

# Import Python libs
from __future__ import absolute_import, unicode_literals
import logging

# Import 3rd-party libs
# pylint: disable=import-error
from salt.ext.six.moves import map
# pylint: enable=import-error

__virtualname__ = 'vmadm'
VMADM_STATE = {
  'first_run': True,
  'vms': [],
}

log = logging.getLogger(__name__)


def __virtual__():
    '''
    Provides vmadm beacon on SmartOS
    '''
    if 'vmadm.list' in __salt__:
        return True
    else:
        return (
            False,
            '{0} beacon can only be loaded on SmartOS compute nodes'.format(
                __virtualname__
            )
        )


def validate(config):
    '''
    Validate the beacon configuration
    '''
    vcfg_ret = True
    vcfg_msg = 'Valid beacon configuration'

    if not isinstance(config, list):
        vcfg_ret = False
        vcfg_msg = 'Configuration for vmadm beacon must be a list!'

    return vcfg_ret, vcfg_msg


def beacon(config):
    '''
    Poll vmadm for changes
    '''
    ret = []

    # NOTE: lookup current images
    current_vms = __salt__['vmadm.list'](
        keyed=True,
        order='uuid,state,alias,hostname,dns_domain',
    )

    # NOTE: apply configuration
    if VMADM_STATE['first_run']:
        log.info('Applying configuration for vmadm beacon')

        _config = {}
        list(map(_config.update, config))

        if 'startup_create_event' not in _config or not _config['startup_create_event']:
            VMADM_STATE['vms'] = current_vms

    # NOTE: create events
    for uuid in current_vms:
        event = {}
        if uuid not in VMADM_STATE['vms']:
            event['tag'] = "created/{}".format(uuid)
            for label in current_vms[uuid]:
                if label == 'state':
                    continue
                event[label] = current_vms[uuid][label]

        if event:
            ret.append(event)

    # NOTE: deleted events
    for uuid in VMADM_STATE['vms']:
        event = {}
        if uuid not in current_vms:
            event['tag'] = "deleted/{}".format(uuid)
            for label in VMADM_STATE['vms'][uuid]:
                if label == 'state':
                    continue
                event[label] = VMADM_STATE['vms'][uuid][label]

        if event:
            ret.append(event)

    # NOTE: state change events
    for uuid in current_vms:
        event = {}
        if VMADM_STATE['first_run'] or \
           uuid not in VMADM_STATE['vms'] or \
           current_vms[uuid].get('state', 'unknown') != VMADM_STATE['vms'][uuid].get('state', 'unknown'):
            event['tag'] = "{}/{}".format(current_vms[uuid].get('state', 'unknown'), uuid)
            for label in current_vms[uuid]:
                if label == 'state':
                    continue
                event[label] = current_vms[uuid][label]

        if event:
            ret.append(event)

    # NOTE: update stored state
    VMADM_STATE['vms'] = current_vms

    # NOTE: disable first_run
    if VMADM_STATE['first_run']:
        VMADM_STATE['first_run'] = False

    return ret

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
