# Software License Agreement (BSD License)
#
# Copyright (c) 2009-2011, Eucalyptus Systems, Inc.
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms, with or
# without modification, are permitted provided that the following conditions
# are met:
#
#   Redistributions of source code must retain the above
#   copyright notice, this list of conditions and the
#   following disclaimer.
#
#   Redistributions in binary form must reproduce the above
#   copyright notice, this list of conditions and the
#   following disclaimer in the documentation and/or other
#   materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Author: matt.clark@eucalyptus.com
'''
Created on Mar 7, 2012
@author: clarkmatthew
Place holder class to provide convenience for testing, modifying, and
retrieving Eucalyptus cloud property information
Intention is to reduce the time in looking up property names, and values
outside of the eutester test lib, etc
Note: Debug output for the tester.sys command are controled by the
eutester/eucaops object

Sample:
cat my_cloud.conf
>   192.168.1.76	CENTOS	6.3	64	REPO	[CLC WS]
>   192.168.1.77	CENTOS	6.3	64	REPO	[SC00 CC00]
>   192.168.1.78	CENTOS	6.3	64	REPO	[NC00]


    from eucaops import Eucaops
    from eutester import euproperties
    Eucaops(config_file='my_cloud.conf', password='mypassword')

    ep_mgr = euproperties.Euproperty_Manager(tester,
                                             verbose=True,
                                             debugmethod=tester.debug)


#get some storage service properties, and some property values...

    #Get/Set value from dynamic method created in Euproperty_Manager...
        san_host_prop_value = ep_mgr.get_storage_sanhost_value()
        ep_mgr.set_storage_sanhost_value('192.168.1.200')

    #Get/set value from euproperty directly...
        san_host_prop = ep_mgr.get_property('san_host', 'storage', 'PARTI00')
        san_host_prop_value = san_host_prop.get()
        san_host_prop_set('192.168.1.200'

    #Get multiple properties at once based on certain filters...
        storage_properties = ep_mgr.get_properties(service_type='storage')
        partition1_properties = ep_mgr.get_properties(partition='partition1')

'''

import types
import re
import copy


class Euproperty_Type():
    authentication = 'authentication'
    autoscaling = 'autoscaling'
    bootstrap = 'bootstrap'
    cloud = 'cloud'
    cloudwatch = 'cloudwatch'
    cluster = 'cluster'
    dns = 'dns'
    imaging = 'imaging'
    loadbalancing = 'loadbalancing'
    objectstorage = 'objectstorage'
    reporting = 'reporting'
    storage = 'storage'
    system = 'system'
    tagging = 'tagging'
    tokens = 'tokens'
    vmwarebroker = 'vmwarebroker'
    walrus = 'walrus'
    www = 'www'

    @classmethod
    def get_type_by_string(cls, typestring):
        try:
            if hasattr(cls, str(typestring)):
                return getattr(cls, str(typestring))
        except AttributeError, ae:
            print ('Property type:' + str(str) +
                   " not defined, new property type?")
            raise ae


class Euproperty():
    def __init__(self, prop_mgr, property_string, service_type, partition,
                 name, value, mandatory=False, description=""):
        self.prop_mgr = prop_mgr
        self.service_type = Euproperty_Type.get_type_by_string(service_type)
        self.partition = partition
        self.name = name
        self.value = value
        self.property_string = property_string
        self.prop_mgr = prop_mgr
        self.lastvalue = value
        self.mandatory = mandatory
        self.description = description

    def update(self):
        newprop = self.prop_mgr.update_property_list(
            property_name=self.property_string)[0]
        self = newprop

    def get(self):
        return self.value

    def set(self, value):
        return self.prop_mgr.set_property(self, value)

    def reset_to_default(self):
        return self.prop_mgr.reset_property_to_default(self)

    def print_self(self, include_header=True, show_description=True,
                   print_method=None, printout=True):
        if printout and not print_method:
            print_method = self.prop_mgr.debug
        name_len = 50
        service_len = 20
        part_len = 20
        value_len = 30
        line_len = 120
        ret = ""

        header = str('NAME').ljust(name_len)
        header += "|" + str('SERVICE TYPE').center(service_len)
        header += "|" + str('PARTITION').center(part_len)
        header += "|" + str('VALUE').center(value_len)
        header += "\n"

        out = str(self.name).ljust(name_len)
        out += "|" + str(self.service_type).center(service_len)
        out += "|" + str(self.partition).center(part_len)
        out += "|" + str(self.value).center(value_len)
        out += "\n"
        line = "-"
        for x in xrange(0, line_len):
            line += "-"
        line += "\n"
        if include_header:
            ret = "\n" + line + header + line
        ret += out
        if show_description:
            ret += "DESCRIPTION: " + self.description + "\n"
        ret += line
        if print_method:
            print_method(ret)
        return ret


class Property_Map():
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


class Euproperty_Manager():
    tester = None
    verbose = False
    debugmethod = None

    def __init__(self, tester, verbose=False, machine=None,
                 service_url=None, debugmethod=None):
        self.tester = tester
        self.debugmethod = debugmethod or tester.debug
        self.verbose = verbose

        #self.work_machine = machine or self.get_clc()
        #self.access_key = self.tester.aws_access_key_id
        #self.secret_key = self.tester.aws_secret_access_key
        #self.service_url = service_url or str(
        #    'http://' + str(self.get_clc().hostname) +
        #    ':8773/services/Eucalytpus')
        #self.cmdpath = self.tester.eucapath+'/usr/sbin/'
        self.properties = []
        #self.property_map = Property_Map()
        self.update_property_list()
        #self.tester.property_manager = self
        #self.zones = self.tester.ec2.get_zones()

    #def get_clc(self):
    #    return self.tester.service_manager.get_enabled_clc().machine

    def debug(self, msg):
        '''
        simple method for printing debug.
        msg - mandatory - string to be printed
        method - optional - callback to over ride default printing method
        '''
        if (self.debugmethod is None):
            print (str(msg))
        else:
            self.debugmethod(msg)

    def show_all_authentication_properties(self,
                                           partition=None,
                                           debug_method=None,
                                           descriptions=True):
        return self.show_all_properties(
           
 service_type=Euproperty_Type.authentication,
            partition=partition,
            debug_method=debug_method,
            descriptions=descriptions)

    def show_all_b
ootstrap_properties(self, partition=None, debug_method=None, descriptions=True):
        return self.show_all_properties(service_type=Euproperty_Type.bootstrap,
                                        partition=partition,
                                        debug_m