'''
Linode Cloud Module
===================

The Linode cloud module is used to control access to the Linode VPS system

Use of this module only requires the LINODE.apikey paramater to be set in
the cloud configuration file

.. code-block:: yaml

    # Linode account api key
    LINODE.apikey: JVkbSJDGHSDKUKSDJfhsdklfjgsjdkflhjlsdfffhgdgjkenrtuinv

'''

# Import python libs
import os
import types
import logging

# Import libcloud
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from libcloud.compute.deployment import MultiStepDeployment, ScriptDeployment, SSHKeyDeployment
from libcloud.compute.types import NodeState
from libcloud.compute.base import NodeAuthPassword

# Import salt libs
from saltcloud.libcloudfuncs import *

# Import saltcloud libs
from saltcloud.utils import namespaced_function


# Get logging started
log = logging.getLogger(__name__)


# Redirect linode functions to this module namespace
avail_images = namespaced_function(avail_images, globals())
avail_sizes = namespaced_function(avail_sizes, globals())
script = namespaced_function(script, globals())
destroy = namespaced_function(destroy, globals())
list_nodes = namespaced_function(list_nodes, globals())
list_nodes_full = namespaced_function(list_nodes_full, globals())
list_nodes_select = namespaced_function(list_nodes_select, globals())


# Only load in this module if the LINODE configurations are in place
def __virtual__():
    '''
    Set up the libcloud funcstions and check for RACKSPACE configs
    '''
    if 'LINODE.apikey' in __opts__:
        log.debug('Loading Linode cloud module')
        return 'linode'
    return False


def get_conn():
    '''
    Return a conn object for the passed VM data
    '''
    driver = get_driver(Provider.LINODE)
    return driver(
            __opts__['LINODE.apikey'],
            )


def get_location(conn, vm_):
    '''
    Return the node location to use
    '''
    locations = conn.list_locations()
    # Default to Dallas if not otherwise set
    loc = 2
    if 'location' in vm_:
        loc = vm_['location']
    elif 'LINODE.location' in __opts__:
        loc = __opts__['LINODE.location']
    for location in locations:
        if str(location.id) == str(loc):
            return location
        if location.name == loc:
            return location


def get_password(vm_):
    '''
    Return the password to use
    '''
    if 'password' in vm_:
        return vm_['password']
    elif 'passwd' in vm_:
        return vm_['passwd']
    elif 'LINODE.password' in __opts__:
        return __opts__['LINODE.password']


def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    log.info('Creating Cloud VM {0}'.format(vm_['name']))
    conn = get_conn()
    deploy_script = script(vm_)
    kwargs = {}
    kwargs['name'] = vm_['name']
    kwargs['image'] = get_image(conn, vm_)
    kwargs['size'] = get_size(conn, vm_)
    kwargs['location'] = get_location(conn, vm_)
    kwargs['auth'] = NodeAuthPassword(get_password(vm_))
    try:
        data = conn.create_node(**kwargs)
    except Exception as exc:
        err = ('Error creating {0} on LINODE\n\n'
               'The following exception was thrown by libcloud when trying to '
               'run the initial deployment: \n{1}').format(
                       vm_['name'], exc.message
                       )
        sys.stderr.write(err)
        log.error(err)
        return False

    if __opts__['deploy'] is True:
        deployed = saltcloud.utils.deploy_script(
            host=data.public_ips[0],
            username='root',
            password=__opts__['LINODE.password'],
            script=deploy_script.script,
            name=vm_['name'],
            start_action=__opts__['start_action'],
            sock_dir=__opts__['sock_dir'])
        if deployed:
            log.info('Salt installed on {0}'.format(vm_['name']))
        else:
            log.error('Failed to start Salt on Cloud VM {0}'.format(vm_['name']))

    log.info('Created Cloud VM {0} with the following values:'.format(vm_['name']))
    for key, val in data.__dict__.items():
        log.info('  {0}: {1}'.format(key, val))

@@ -3500,43 +3500,19 @@
 ploy
-ed = saltcloud.utils.deploy_script(
+_kwargs = %7B
 %0A   
@@ -3524,13 +3524,16 @@
     
+'
 host
-=
+': 
 data
@@ -3564,16 +3564,17 @@
     
+'
 username
 ='ro
@@ -3569,17 +3569,19 @@
 username
-=
+': 
 'root',%0A
@@ -3592,24 +3592,25 @@
         
+'
 password
 =__opts_
@@ -3601,17 +3601,19 @@
 password
-=
+': 
 __opts__
@@ -3649,15 +3649,18 @@
     
+'
 script
-=
+': 
 depl
@@ -3693,13 +3693,16 @@
     
+'
 name
-=
+': 
 vm_%5B
@@ -3722,16 +3722,65 @@
         
+'deploy_command': '/tmp/deploy.sh',%0A            '
 start_ac
@@ -3783,17 +3783,19 @@
 t_action
-=
+': 
 __opts__
@@ -3824,24 +3824,25 @@
         
+'
 sock_dir
 =__opts_
@@ -3833,17 +3833,19 @@
 sock_dir
-=
+': 
 __opts__
@@ -3856,16 +3856,318 @@
 ck_dir'%5D
+,%0A            'conf_file': __opts__%5B'conf_file'%5D,%0A            'minion_pem': vm_%5B'priv_key'%5D,%0A            'minion_pub': vm_%5B'pub_key'%5D,%0A            %7D%0A        deploy_kwargs%5B'minion_conf'%5D = saltcloud.utils.minion_conf_string(__opts__, vm_)%0A        deployed = saltcloud.utils.deploy_script(**deploy_kwargs
 )%0A      

Refactor Linode to use bootstrap-salt-minion