#!/usr/bin/env python
#
#   ConVirt   -  Copyright (c) 2008 Convirture Corp.
#   ======
#
# ConVirt is a Virtualization management tool with a graphical user
# interface that allows for performing the standard set of VM operations
# (start, stop, pause, kill, shutdown, reboot, snapshot, etc...). It
# also attempts to simplify various aspects of VM lifecycle management.
#
#
# This software is subject to the GNU General Public License, Version 2 (GPLv2)
# and for details, please consult it at:
#
#    http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
# 
#
#

import gtk, gtk.glade, gobject
import traceback

from convirt.core.utils.utils import get_path, get_prop, is_host_remote
from convirt.core.utils.utils import dynamic_map
from convirt.client.ui_utils import Container
from convirt.core.utils.utils import XMConfig
from convirt.core.utils.NodeProxy import Node
import convirt.core.utils.constants
constants = convirt.core.utils.constants 
from convirt.client.dialogs import showmsg

(path, gladefile) = get_path("platformui.glade")


# Common add node dialog for the platforms.    
class AddNodeDialog (Container):
    """ Class that handles adding new managed node to the host"""
        
    def __init__(self, manager, client_config, left_nav):
        """ Constructor"""
        Container.__init__(self)
        self.context = dynamic_map()
        self.manager = manager
        self.client_config = client_config
        self.left_nav = left_nav

        default_use_keys = client_config.get(XMConfig.CLIENT_CONFIG,
                                             constants.prop_default_use_keys)
        
        self.default_use_keys = False
        if default_use_keys:
            self.default_use_keys = eval(default_use_keys)

        default_ssh_port = self.client_config.get(XMConfig.CLIENT_CONFIG,
                                             constants.prop_default_ssh_port)
        if default_ssh_port:
            self.default_ssh_port = int(default_ssh_port)

        # controls to gather and scatter data
        self.context.default_ssh_port = 22
        self.context.default_use_keys = False
        self.context.username = "root"
        self.context.password = ""
        self.context.hostname = ""
        self.context.default_use_keys = self.default_use_keys

        self.ui_init(self.context)
        

    def ui_init(self, context):
        wtree = gtk.glade.XML(gladefile, "AddNode")
        context.wtree = wtree

        self.dialog = wtree.get_widget("AddNode")      
        
        self.init_widgets(wtree, ["add_node_hostname",
                                  "add_node_username",
                                  "add_node_password",
                                  "add_node_ssh_port",
                                  "add_node_use_keys_checkbox",
                                  "advanced_expander",
                                  "add_node_host_table",
                                  "add_node_advanced_table",                                  
                                  ])
                       
        self.dialog.set_default_response(gtk.RESPONSE_OK)
                            
        wtree.signal_autoconnect({"on_add_node_cancelbutton_clicked":self.on_cancel_button_clicked,
                                  "on_add_node_okbutton_clicked":self.on_ok_button_clicked,
                                  "on_add_node_use_keys_checkbox_toggled" : self.on_use_keys_toggled,
                                  }
                                 )
        
    def scatter(self, context):        
        self.widgets["add_node_ssh_port"].set_text(str(context.default_ssh_port))
        self.widgets["add_node_username"].set_text(context.username)
        self.widgets["add_node_password"].set_text(context.password)
        self.widgets["add_node_hostname"].set_text(context.hostname)
        self.widgets["add_node_use_keys_checkbox"].set_active(context.default_use_keys)
        self.widgets["advanced_expander"].set_expanded(context.default_use_keys)

    def gather(self, context):        
        context.default_ssh_port = self.widgets["add_node_ssh_port"].get_text()
        context.hostname = self.widgets["add_node_hostname"].get_text()
        context.username = self.widgets["add_node_username"].get_text()
        context.password = self.widgets["add_node_password"].get_text()        
        context.default_use_keys = self.widgets["add_node_use_keys_checkbox"].get_active()

    def on_use_keys_toggled(self, widget):
        use_keys = widget.get_active()
        self.widgets["add_node_password"].set_sensitive(not use_keys)

    def init(self):
        self.scatter(self.context)
        self.widgets["add_node_hostname"].grab_focus()


    def move_down(self, table, num_rows):
        for c in table.get_children():
            (left, right, top, bottom) =  \
                   table.child_get_property(c,"left-attach"),\
                   table.child_get_property(c,"right-attach"), \
                   table.child_get_property(c,"top-attach"),\
                   table.child_get_property(c,"bottom-attach")
            table.remove(c)
            table.attach(c, left, right, top + num_rows, bottom+num_rows)

    def show_in_edit_mode(self):
        """ Displays add node dialog in edit mode """
        self.widgets.add_node_hostname.set_sensitive(False)
        self.dialog.set_title("Edit Server")

        self.context.default_ssh_port = self.existing_node.ssh_port
        self.context.username = self.existing_node.username
        self.context.hostname = self.existing_node.hostname

        if self.existing_node.use_keys is None:
            self.context.default_use_keys = False
        else:
            self.context.default_use_keys = self.existing_node.use_keys

        self.init()

        ret = self.dialog.run()
        self.dialog.destroy()
        return ret
        
    def show(self, mode, group_name = None, platform = None,
             existing_node = None,
             parentwin = None):
        """ Displays add node dialog"""
        self.mode = mode
        self.parentwin = parentwin
        self.existing_node = existing_node
        self.group_name = group_name
        self.platform = platform

        if parentwin is not None:
            self.dialog.set_transient_for(parentwin)

        if mode == "add":
            return self.show_in_add_mode()
        else:
            return self.show_in_edit_mode()
        

    def show_in_add_mode(self):
        self.dialog.set_title("Add Server")
        self.init()
        ret = self.dialog.run()

        if ret == gtk.RESPONSE_DELETE_EVENT:
            self.dialog.destroy()


    def on_cancel_button_clicked(self, widget):
       """  Cancel on add node dialog """
       self.dialog.destroy()
       
    def on_ok_button_clicked(self, widget):
       """  Ok  button on add node """
       # validate parameters
       
       nodeinfo = dynamic_map()
       self.gather( nodeinfo )
       if nodeinfo.hostname == "":
           showmsg("Please enter valid host name")
           return

       if nodeinfo.default_ssh_port == "":
           showmsg("Please enter valid ssh port")
           return

       remote = is_host_remote(nodeinfo.hostname)
       
       # create a new node

       try:
           factory = self.manager.getFactory(self.platform)
           node = factory.create_node( platform = self.platform, 
                                       hostname = nodeinfo.hostname,
                                       username = nodeinfo.username,
                                       password = nodeinfo.password,
                                       is_remote = remote, 
                                       #protocol = None,
                                       #tcp_port = -1,
                                       #migration_port = 8002, # put xen def now
                                       ssh_port = int(nodeinfo.default_ssh_port),
                                       use_keys = nodeinfo.default_use_keys,
                                       address  = nodeinfo.hostname
                                       )
           node.connect()

           if self.mode == "edit":
               self.left_nav.remove_node(self.existing_node, self.group_name)
               # do cleanup for the main thread.
               # invading privacy of node uggh
               if self.existing_node is not None and \
                      self.existing_node._node_proxy is not None: 
                   try:
                       Node.clean_locals(self.existing_node.node_proxy)
                   except Exception, ex:
                       print "Exception while cleaning locals ", ex
                       pass
           self.left_nav.add_node(node, self.group_name)
       except Exception , ex:
           traceback.print_exc()
           #try:
           #    if node is not None and node.node_proxy is not None:
           #        Node.clean_locals(node.node_proxy)
           #except Exception, e:
           #    pass
           showmsg(ex)
           return
       # username and password are not stored

       # clear the passwords from memory.
       self.init()
       self.dialog.destroy()
