#!/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
# 
#
#

# UI for network configuration
import sys
from convirt.core.utils.utils import get_path
from convirt.core.utils.IPy import *
import convirt.core.model.network
from convirt.core.model.network import NwManager, NwDef
from convirt.client.dialogs import confirmation

network = convirt.core.model.network

(path, nw_gladefile) = get_path("network.glade")
if not path:
    print "ERROR: Couldn't find glade interface definition file network.glade!"
    sys.exit(1)   # bad, but ok for now.


from convirt.core.utils.utils import dynamic_map
from convirt.client.ui_utils import Container, Dlg
from convirt.client.ui_utils import *


nw_type_map = {NwDef.PUBLIC_NW : "Public",
               NwDef.HOST_PRIVATE_NW: "Host Private ",
               }

def get_ids_from_context(context):
    pool_id = None
    node_id = None
    if context.server_pool:
        pool_id = context.server_pool.id
    if context.managed_server is not None:
        node_id = context.managed_server.hostname
    return (pool_id, node_id)


class NWListDlg (Dlg):
    """ Class that handles manipulating network definitions"""
    (
        NW_NAME,
        NW_TYPE,
        NW_DESCRIPTION,
        NW_DEFINITION,
        NW_SYNC_STATUS,
        NW_ID
     ) = range(6)

    def __init__(self):
        Dlg.__init__(self)
        self.context=None
        self.ui_init()

    def ui_init(self):
        wtree = gtk.glade.XML(nw_gladefile, "NWListDlg")
        self.dialog = get_widget(wtree,"NWListDlg")
 
        # init widget list
        self.init_widgets(wtree, ['nw_view',
                                  'nw_definition_add',
                                  'nw_definition_remove',
                                  #'nw_definition_rename',
                                  'nw_definition_edit',
                                  'nw_list_table_hdr'
                                  ])


        wtree.signal_autoconnect({"on_nw_add_clicked":(cb_wrapper,
                                                       self.add_clicked),
                                  "on_nw_remove_clicked":(cb_wrapper,
                                                          self.remove_clicked),
                                  #"on_nw_rename_clicked":(cb_wrapper,
                                  #                        self.rename_clicked),
                                  "on_nw_edit_clicked":(cb_wrapper,
                                                        self.edit_clicked),
                                  }
                                 )



        # init list views
        self.init_nw_list()
        #self.init_pub_nw_list()

        # init combo boxes
        #init_combo(widget
        #           map
        #           order)


    def get_status(self, nw_manager, def_id, pool_id, node_id):
        status = "N/A" #network.UNKNOWN
        if pool_id is None:
            nstatus_info = nw_manager.get_node_status(def_id, 
                                                      node_id)
            if nstatus_info:
                status = nstatus_info.status
        else:
            gstatus_info = nw_manager.get_group_status(def_id, 
                                                       pool_id)
            if gstatus_info:
                status = gstatus_info.status

        return status

    def add_clicked(self, widget):
        if self.context.managed_server is not None:
            # KLUDGE
            self.context.managed_server.environ.refresh()
            
        def_dlg = NWDefDlg()
        ret = def_dlg.show(
                           "ADD",
                           self.context.nw_manager,
                           self.context.server_pool,
                           self.context.managed_server,
                           None,
                           parent = self.dialog)

        if ret == gtk.RESPONSE_OK:
            new_def = def_dlg.get_new_defn()
            if new_def:
                errs = self.context.nw_manager.add_defn(new_def, 
                                                   self.context.server_pool,
                                                   self.context.managed_server)
                print "dumping group and node Status "
                self.context.nw_manager.dump_group_defn_status()
                self.context.nw_manager.dump_node_defn_status()
                if errs: # Its ugly, if error, delete it.
                    if len(errs) > 0:
                        self.context.nw_manager.remove_defn(new_def,
                                                self.context.server_pool,
                                                self.context.managed_server)
                        showmsg(errs)
                        return
                # update the ui.
                model = self.widgets.nw_view.get_model()
                pool_id, node_id  = get_ids_from_context(self.context)
                status = self.get_status(self.context.nw_manager, 
                                         new_def.id, pool_id, node_id)
                model.append([new_def.name,
                              nw_type_map[new_def.type],
                              new_def.description,
                              new_def.get_definition(),
                              status,
                              new_def.id]
                             )

        

    def remove_clicked(self, widget):
        view = self.widgets.nw_view
        selection = view.get_selection()
        result = selection.get_selected()
        if result is not None: #result could be None
            model, iter = result
            nw_id = model.get_value(iter, self.NW_ID )
            nw_def = self.context.nw_manager.get_defn(nw_id)
            msg = "Remove %s ? " % (nw_def.name,)
            if not confirmation(msg):
                return
            self.context.nw_manager.remove_defn(nw_def, 
                                                self.context.server_pool,
                                                self.context.managed_server)
            self.context.nw_manager.dump_group_defn_status()
            self.context.nw_manager.dump_node_defn_status()
 
            model.remove(iter)
            

    def rename_clicked(self, widget):
        view = self.widgets.nw_view
        selection = view.get_selection()
        result = selection.get_selected()
        if result is not None: #result could be None
            model, iter = result
            nw_name = model.get_value(iter, self.NW_NAME )
            nw_id = model.get_value(iter, self.NW_ID )
            renamedlg = NWRenameDlg()
            ret = renamedlg.show(nw_name, parent = self.dialog)
            if ret != gtk.RESPONSE_OK:
                return

            new_name = renamedlg.get_new_name()
            self.context.nw_manager.rename_defn(nw_id, new_name)
            model.set(iter, self.NW_NAME, new_name)            

    def edit_clicked(self, widget):
        view = self.widgets.nw_view
        selection = view.get_selection()
        result = selection.get_selected()
        if result is not None: #result could be None
            model, iter = result
            nw_id = model.get_value(iter, self.NW_ID )
            def_dlg = NWDefDlg()
            ret = def_dlg.show("EDIT",
                               self.context.nw_manager,
                               self.context.server_pool,
                               self.context.managed_server,
                               nw_id,
                               parent = self.dialog)
            if ret == gtk.RESPONSE_OK:
                new_name = def_dlg.get_new_name()
                new_desc = def_dlg.get_new_desc()
                self.context.nw_manager.rename_defn(nw_id, new_name)
                self.context.nw_manager.update_desc(nw_id, new_desc)
                model.set(iter, self.NW_NAME, new_name)
                model.set(iter, self.NW_DESCRIPTION, new_desc)

    # initialize view and model for the nw list
    def init_nw_list(self):
        textrenderer = gtk.CellRendererText()
        view = self.widgets.nw_view
        columns = [("Name",self.NW_NAME), 
                   #("Type",self.NW_TYPE),  
                   ("Details",self.NW_DEFINITION),
                   ("Description",self.NW_DESCRIPTION),
                   ]
                   #("Status", self.NW_SYNC_STATUS) ] #, "Definition"]
        for c, pos in columns:
            tree_column = gtk.TreeViewColumn(c, textrenderer,
                                            text=pos)
            if pos == self.NW_DESCRIPTION:
                tree_column.set_max_width(100)
                tree_column.set_expand(True)
            if pos == self.NW_NAME:
                tree_column.set_min_width(25)
                tree_column.set_expand(True)
            if pos == self.NW_DEFINITION:
                tree_column.set_min_width(25)
                tree_column.set_expand(True)
            tree_column.set_resizable(True)
            view.append_column(tree_column)        

        # create model
        model = gtk.ListStore(gobject.TYPE_STRING, # NW Name
                              gobject.TYPE_STRING, # Type
                              gobject.TYPE_STRING, # Description
                              gobject.TYPE_STRING, # Definition
                              gobject.TYPE_STRING, # Sync Status
                              gobject.TYPE_STRING, # ID 
                              ) 

        # associate it with the view.
        view.set_model(model)     
        
    # show the public networks available separately.
    def init_pub_nw_list(self):
        textrenderer = gtk.CellRendererText()
        view = self.widgets.pub_nw_view
        columns = [("Name",self.NW_NAME), 
                   ("Details",self.NW_DEFINITION),
                   ]
        for c, pos in columns:
            tree_column = gtk.TreeViewColumn(c, textrenderer,
                                            text=pos)
            if pos == self.NW_NAME:
                tree_column.set_min_width(25)
                tree_column.set_expand(True)
            if pos == self.NW_DEFINITION:
                tree_column.set_min_width(25)
                tree_column.set_expand(True)
            tree_column.set_resizable(True)
            view.append_column(tree_column)        

        # create model
        model = gtk.ListStore(gobject.TYPE_STRING, # NW Name
                              gobject.TYPE_STRING, # Type
                              gobject.TYPE_STRING, # Description
                              gobject.TYPE_STRING, # Definition
                              gobject.TYPE_STRING, # Sync Status
                              gobject.TYPE_STRING, # ID 
                              ) 

        # associate it with the view.
        view.set_model(model)     
        

    def get_widgets_to_hide(self, mode):
        return [self.widgets.pub_nw_view, self.widgets.pub_nw_text]

    def get_widgets_to_disable(self, mode):
        return []

    def validate(self):
        pass

    def scatter(self, context):
        # populate the widgets from the context.
        nw_manager=self.context.nw_manager
        pool_id, node_id = get_ids_from_context(context)
        defns = nw_manager.get_defns(pool_id, node_id)
        
        model = self.widgets.nw_view.get_model()
        model.clear()

        #pub_model=self.widgets.pub_nw_view.get_model()
        #pub_model.clear()
        
        bridge_list = []
        for defn in defns:
#            if defn.type == NwDef.HOST_PRIVATE_NW:
#                m = model
#            else:
#                m = pub_model

            status = self.get_status(nw_manager, defn.id, pool_id, node_id)
            model.append(
                [defn.name,
                 nw_type_map[defn.type],
                 defn.description,
                 defn.get_definition(),
                 status,
                 defn.id]
                )
            if defn.bridge_info and defn.bridge_info.name:
                bridge_list.append(defn.bridge_info.name)

        return # The other bridges are very confusing.

        if self.context.managed_server is not None:
            bridges = self.context.managed_server.get_bridge_info()
            if bridges:
                for b in bridges.itervalues():
                    b_name = b["name"]
                    if b_name not in bridge_list:
                        bridge_info = dynamic_map()
                        bridge_info.name = b_name
                        phy_list = ""
                        if b.get("interfaces") is not None:
                            for i in b.get("interfaces"):
                                if phy_list == "":
                                    phy_list = i
                                else:
                                    phy_list = phy_list + "," + i
                        bridge_info.phy_list = phy_list
                        ipv4_info = dynamic_map()
                        if b.get("network"):
                            ipv4_info.ip_network = b.get("network")
                        nw_id = None
                        nw_type = NwDef.PUBLIC_NW
                        nw_name = "%s network" % (b_name, )
                        nw_desc = nw_name

                        
                        temp_defn = NwDef(nw_id, 
                                          nw_type,
                                          nw_name,
                                          nw_desc,
                                          bridge_info=bridge_info,
                                          ipv4_info = ipv4_info)

                        print "#### ", temp_defn
                        pub_model.append(
                            [temp_defn.name,
                             nw_type_map[temp_defn.type],
                             temp_defn.description,
                             temp_defn.get_definition(),
                             "",
                             temp_defn.id]
                            )

    def gather(self, context):
        pass

    def save(self, context):
        pass

    def show(self, widget, nw_manager, pool, managed_server, parent):
        if managed_server is not None:
            print "MANAGED_SERVER ****** ", managed_server.hostname
            tbl_title = "Currently defined networks on %s :\n" % \
                ( managed_server.hostname,)
            set_value(self.widgets.nw_list_table_hdr, tbl_title)
            self.dialog.set_title("Virtual Networks: %s" % (managed_server.hostname,))
        # set the context
        self.context = dynamic_map();
        self.context.server_pool = pool
        self.context.parent = parent
        self.context.nw_manager = nw_manager
        self.context.managed_server = managed_server
        ret=  self.run_dlg(self.context)
        return ret


class NWRenameDlg(Container):
    """ Class rename nw definition """

    def __init__(self):
        """ Constructor"""
        wtree = gtk.glade.XML(nw_gladefile, "NWRenameDlg")
        self.dialog = get_widget(wtree, "NWRenameDlg")

        self.nw_name = wtree.get_widget("nw_rename_text")
        self.selected_nw_label  = wtree.get_widget("selected_nw_label")
        self.new_nw_name = ""
        
        # setup handlers
        wtree.signal_connect("on_nw_rename_cancel_clicked",
                                 self.on_cancel_clicked)
        wtree.signal_connect("on_nw_rename_ok_clicked",
                                 self.on_ok_clicked)
        self.nw_name.set_activates_default(True)
        self.dialog.set_default_response(gtk.RESPONSE_OK)

        self.init()

    def init(self):
        self.nw_name.set_text("")

    def get_new_name(self):
        return self.new_nw_name

    def show(self, ct_nw_name, parent = None):
        if parent:
            self.dialog.set_transient_for(parent)
        """ Displays rename image dialog"""
        self.ct_nw_name = ct_nw_name
        self.init()

        self.selected_nw_label.set_text("Selected Network : " +
                                        self.ct_nw_name)
        ret = self.dialog.run()
        if ret == gtk.RESPONSE_DELETE_EVENT:
            self.dialog.destroy()

        return ret


    def on_cancel_clicked(self, widget):
       """  Cancel on rename image dialog """
       self.dialog.destroy()

    def on_ok_clicked(self, widget):
       """  Ok  button on rename nw """
       # validate parameters
       self.new_nw_name = self.nw_name.get_text()
       if self.new_nw_name.strip() == "":
           showmsg("Please enter valid Network name.")
           return

       # TBD : If NW name is already in the store, then return.
       
       self.dialog.destroy()



class NWDefDlg(Dlg):
    def __init__(self):
        Dlg.__init__(self)
        self.context=None
        self.ui_init()

    def get_nw_address_space_map(self, context):
        nw_address_space = { "10.1.0.0/24": "10.1.0.0/24",
                             "10.2.0.0/24": "10.2.0.0/24",
                             "10.3.0.0/24": "10.3.0.0/24",
                             "10.4.0.0/24": "10.4.0.0/24",
                             }
        return nw_address_space

    def get_nw_address_space_order(self, context):
        nw_address_space_order = ["10.1.0.0/24", "10.2.0.0/24", "10.3.0.0/24",
                                  "10.4.0.0/24"]
        return nw_address_space_order

    def get_nw_nat_fwding_map(self, context):
        nw_nat_fwding_map = {"Any interface" : "ANY",
                              }
        if self.context.managed_server is not None:
            nics = self.context.managed_server.get_nic_info()
            if nics:
                for nic in nics.itervalues():
                    nic_name = nic["name"]
                    nw_nat_fwding_map[nic_name] = nic_name
                
        return nw_nat_fwding_map

    def get_nw_nat_fwding_order(self, context):
        nw_nat_fwding_order = [ "Any interface",
                                ]
        if self.context.managed_server is not None:
            nics = self.context.managed_server.get_nic_info()
            if nics:
                for nic in nics.itervalues():
                    nic_name = nic["name"]
                    nw_nat_fwding_order.append(nic_name)

        print "ORDER : ", nw_nat_fwding_order
        return nw_nat_fwding_order

    def ui_init(self):
        wtree = gtk.glade.XML(nw_gladefile, "NWDefinitionDlg")
        self.dialog = get_widget(wtree,"NWDefinitionDlg")
 
        # init widget list
        self.init_widgets(wtree, [
                                  'nw_name_label',
                                  'nw_name_entry',


                                  'nw_desc_label',
                                  'nw_desc_entry',

                                  'nw_public_radio',
                                  'nw_host_priv_radio',

                                  'pub_nw_desc_text',
                                  'host_priv_desc_text',

                                  'nw_device_label',
                                  'nw_device_entry',
                                  'nw_device_select_btn',

                                  
                                  'nw_phy_if_label',
                                  'nw_phy_if_entry',
                                  'nw_phy_if_select_btn',

                                  'nw_vlan_label',
                                  'nw_vlan_entry',

                                  'nw_bond_name_label',
                                  'nw_bond_name_entry',
                                  
                                  'nw_isolated_radio',
                                  'nw_nated_radio',

                                  'nw_priv_device_label',
                                  'nw_priv_device_entry',
                                  'nw_priv_device_select_btn',
                                  'nw_priv_device_tip_text',



                                  'nw_address_space_label',
                                  'nw_address_space_combo',

                                  'nw_dhcp_range_label',
                                  'nw_dhcp_range_entry',
                                  
                                  'nw_nat_fwding_label',
                                  'nw_nat_fwding_combo',

                                  ]
                          )

        # widget groups
        self.pub_widgets = [                              
                             'pub_nw_desc_text',
                             
                             'nw_device_label',
                             'nw_device_entry',
                             'nw_device_select_btn',
                             
                             
                             'nw_phy_if_label',
                             'nw_phy_if_entry',
                             'nw_phy_if_select_btn',
                             
                             'nw_vlan_label',
                             'nw_vlan_entry',
                             
                             'nw_bond_name_label',
                             'nw_bond_name_entry',
                             ]

        self.pub_editables = ['nw_public_radio',
                             'nw_device_entry',
                             'nw_device_select_btn',
                             'nw_phy_if_entry',
                             'nw_phy_if_select_btn',
                             ]

        self.private_widgets = ['host_priv_desc_text',
                                
                                'nw_isolated_radio',
                                'nw_nated_radio',

                                'nw_priv_device_label',
                                'nw_priv_device_entry',
                                'nw_priv_device_select_btn',
                                'nw_priv_device_tip_text',
                                
                                'nw_address_space_label',
                                'nw_address_space_combo',
                                
                                'nw_dhcp_range_label',
                                'nw_dhcp_range_entry',
                                
                                'nw_nat_fwding_label',
                                'nw_nat_fwding_combo',
                                
                                ]

        self.private_editables = [ 'nw_host_priv_radio',
                                   'nw_isolated_radio',
                                   'nw_nated_radio',
                                   'nw_priv_device_entry',
                                   'nw_priv_device_select_btn',
                                   'nw_address_space_combo',
                                   'nw_dhcp_range_entry',
                                   'nw_nat_fwding_combo'
                                  ]
        
        self.future_extensions = [ 'nw_vlan_label',
                                   'nw_vlan_entry',
                                   
                                   'nw_bond_name_label',
                                   'nw_bond_name_entry',
                                   ]
                                   

        self.common = [  'nw_name_label',
                         'nw_name_entry',
                         
                         
                         'nw_desc_label',
                         'nw_desc_entry']

        # connect the signal handlers
        signal_map = {"on_nw_name_combo_changed":(cb_wrapper,
                                                  self.name_changed),
                      "on_nw_type_combo_changed":(cb_wrapper,
                                                  self.type_changed),
                                  
                      "on_nw_public_radio_toggled" : (cb_wrapper,
                                                      self.nw_type_changed),
                      "on_nw_isolated_radio_toggled" : (cb_wrapper,
                                                      self.nw_isolated_changed),
                      "on_nw_address_space_combo_changed" : (cb_wrapper,
                                                      self.nw_address_changed),
                      "on_nw_address_space_combo_editing_done" : (cb_wrapper,
                                                      self.nw_address_editing_done),
                      }
        wtree.signal_autoconnect(signal_map)

        # init list views
        # 
                           
    def nw_address_changed(self, widget):
        value = get_value(widget)
        try:
            if value:
                x = IP(value)
                start = x[len(x)/2]
                end = x[-1]
                range = "%s-%s" % (start.strNormal(), end.strNormal())
                set_value(self.widgets.nw_dhcp_range_entry, range)
            else:
                set_value(self.widgets.nw_dhcp_range_entry, "")
            
        except Exception , ex:
            print ex
            set_value(self.widgets.nw_dhcp_range_entry,"")

    # not getting fired!
    def nw_address_editing_done(self, widget):
        print "Editing done", get_value(self.widget)
        
        


    def nw_isolated_changed(self, widget):
        pub_radio = widget
        self.update_widgets(self.context.mode)


    def nw_type_changed(self, widget):
        pub_radio = widget
        self.update_widgets(self.context.mode)
            
    def name_changed(self, widget):
        pass

    # type combo changed
    def type_changed(self, widget):
        pass

    def get_nw_type(self):
        mode = self.context.mode
        if mode == "ADD":
            if self.widgets.nw_public_radio.get_active():
                nw_type = NwDef.PUBLIC_NW # get it from widget
            else:
                nw_type = NwDef.HOST_PRIVATE_NW
        else:
            nw_type = self.context.nw_defn.type
        return nw_type

    
    # Container methods
    def get_widgets_to_hide(self, mode):
        w_to_hide = [self.widgets[w] for w in self.future_extensions]

        ## This release no public n/w management
        w_to_hide = w_to_hide +\
            [ self.widgets[w] for w in self.pub_widgets ] 
        w_to_hide.append (self.widgets.nw_public_radio )
        w_to_hide.append (self.widgets.nw_host_priv_radio )

        is_nated = not self.widgets.nw_isolated_radio.get_active()
        if not is_nated:
            w_to_hide.append(self.widgets.nw_nat_fwding_combo)
            w_to_hide.append(self.widgets.nw_nat_fwding_label)

        w_to_hide.append(self.widgets.nw_priv_device_select_btn)
        return w_to_hide

        if mode != "ADD":
            nw_type = self.context.nw_defn.type
        
            if nw_type == NwDef.PUBLIC_NW:
                w_to_hide = w_to_hide + \
                    [ self.widgets[w] for w in self.private_widgets ]
                w_to_hide.append (self.widgets.nw_host_priv_radio )
            else:
                w_to_hide = w_to_hide +\
                    [ self.widgets[w] for w in self.pub_widgets ] 
                w_to_hide.append (self.widgets.nw_public_radio )

        return w_to_hide

    def get_widgets_to_disable(self, mode):
        nw_type = self.get_nw_type()
        w_to_disable = []
        if mode != "ADD":
            if nw_type == NwDef.PUBLIC_NW :
                w_to_disable =  [ self.widgets[w] for w in self.pub_editables ]
            else:
                w_to_disable =  [ self.widgets[w] for w in self.private_editables ]
                w_to_disable.append(self.widgets.host_priv_desc_text)
                w_to_disable.append(self.widgets.nw_priv_device_tip_text)
        
        return w_to_disable


    def scatter(self, context):
        # populate the widgets from the context.
        nw_manager=self.context.nw_manager

        # init combo boxes
        init_combo(self.widgets.nw_address_space_combo,
                   self.get_nw_address_space_map(context),
                   self.get_nw_address_space_order(context))


        init_combo(self.widgets.nw_nat_fwding_combo,
                   self.get_nw_nat_fwding_map(context),
                   self.get_nw_nat_fwding_order(context))

        
        if context.mode != "ADD":
            nw = context.nw_defn
            dhcp_range_value = None
            if nw.dhcp_info and nw.dhcp_info.dhcp_start and\
                    nw.dhcp_info.dhcp_end:
                dhcp_range_value = nw.dhcp_info.dhcp_start + " - " +\
                    nw.dhcp_info.dhcp_end
            

            for widget, val in (
                ( "nw_name_entry", nw.name),
                ( "nw_desc_entry", nw.description),
                ( "nw_device_entry", nw.bridge_info.name),
                ( "nw_phy_if_entry", nw.bridge_info.phy_list),
                ( "nw_priv_device_entry", nw.bridge_info.name),
                ( "nw_address_space_combo", nw.ipv4_info.ip_network),
                ( "nw_dhcp_range_entry", dhcp_range_value),
                ( "nw_nat_fwding_combo", nw.nat_info.interface),
                ):
                if val:
                    set_value(self.widgets[widget], val)
                else:
                    set_value(self.widgets[widget], "")

            
            set_value(self.widgets.nw_nated_radio, nw.is_nated())
            set_value(self.widgets.nw_isolated_radio, not nw.is_nated())
        else:
            self.widgets.nw_host_priv_radio.set_active(True)
            self.widgets.nw_isolated_radio.set_active(True)
            new_name = self.get_new_private_bridge_name()
            set_value(self.widgets.nw_priv_device_entry, new_name)


    def get_all_known_bridges(self):
        bridge_names = []
        if self.context.managed_server is not None:
            bridges = self.context.managed_server.get_bridge_info()
            if bridges:
                bridge_names = bridge_names + bridges.keys()

        if self.context.nw_manager:
            pool_id, node_id = get_ids_from_context(self.context)
            defns = self.context.nw_manager.get_defns(pool_id, node_id)
            for defn in defns:
                if defn.bridge_info and defn.bridge_info.name:
                    n = defn.bridge_info.name
                    if n not in bridge_names:
                        bridge_names.append(n)

        return bridge_names

    # go through definitions and actual bridges on the 
    # machine to generate a new name.
            
    def get_new_bridge_name(self, template):
        new_name = ""
        bridge_names = self.get_all_known_bridges()
        # convention name pbr0-pbrN
        for i in range(0,1000):
            name = template % (i,)
            if name in bridge_names:
                continue
            else:
                new_name = name
                break

        return new_name

    def get_new_private_bridge_name(self):
        return self.get_new_bridge_name("pbr%d")
    def get_new_public_bridge_name(self):
        return self.get_new_bridge_name("br%d")

    def validate(self):

        errmsgs = []
        

        priv_widget_desc=  [('nw_priv_device_entry', "Network bridge device"),
                            ('nw_address_space_combo',"Address space"),
                            ('nw_dhcp_range_entry', "DHCP address range"),
                            ('nw_nat_fwding_combo', "NAT Forwarding")
                            ]
        pub_widget_desc= [ ("nw_device_entry", "Network bridge device"),
                           ("nw_phy_if_entry", "Physical Netowrk interface"),
                           ]
        common_desc = [ ("nw_name_entry", "Network name"),
                        ("nw_desc_entry", "Network description")
                        ]
        if self.context.mode == "ADD" : # no edit planned
            nw_type = self.get_nw_type()
            if nw_type  == NwDef.PUBLIC_NW:
                widget_desc = common_desc + pub_widget_desc 
            else:
                widget_desc = common_desc + priv_widget_desc

            for w_name, name in widget_desc:
                    v = get_value(self.widgets[w_name])
                    if not get_value(self.widgets.nw_nated_radio):
                        if w_name == "nw_nat_fwding_combo":
                            continue
                    if not v:
                        errmsgs.append("%s is required." % (name,))
                                     
            if nw_type == NwDef.HOST_PRIVATE_NW:
                nw_dhcp_range = get_value(self.widgets.nw_dhcp_range_entry)
                if nw_dhcp_range:
                    r = nw_dhcp_range.split("-")
                    if len(r) !=2:
                        errmsgs.append("DHCP should be in start-end format. e.g. 192.168.1.128 - 192.168.1.254")
                
            priv_bridge_name = get_value(self.widgets.nw_priv_device_entry)
            if priv_bridge_name in self.get_all_known_bridges():
                errmsgs.append("Bridge (%s) already exist, please choose different name." % (priv_bridge_name))
            
        else:
            for w_name, name in common_desc:
                    v = get_value(self.widgets[w_name])
                    if not v:
                        errmsgs.append("%s is required." % (name,))

        return errmsgs


    def gather(self, context):
        mode = self.context.mode
        if mode == "ADD":
            nw_id = None
            nw_type= self.get_nw_type()
            nw_name = get_value(self.widgets.nw_name_entry)
            nw_desc = get_value(self.widgets.nw_desc_entry)
            if nw_type == NwDef.PUBLIC_NW:
                nw_device = get_value( self.widgets.nw_device_entry)
                nw_phy_if = get_value( self.widgets.nw_phy_if_entry )
                bridge_info = dynamic_map()
                bridge_info.name = nw_device
                bridge_info.phy_list = nw_phy_if
                self.context.new_nw_def = NwDef(nw_id, 
                                                nw_type,
                                                nw_name,
                                                nw_desc,
                                                bridge_info=bridge_info)

            else:
                nw_device = get_value( self.widgets.nw_priv_device_entry)
                nw_address_space = \
                    get_value(self.widgets.nw_address_space_combo)
                nw_dhcp_range = get_value(self.widgets.nw_dhcp_range_entry)
                nw_nat_fwding = get_value(self.widgets.nw_nat_fwding_combo)
                
                bridge_info = dynamic_map()
                bridge_info.name = nw_device

                ipv4_info = dynamic_map()
                ipv4_info.ip_network = nw_address_space

                # assign first address in the range to the 
                # bridge
                ip = IP(nw_address_space)
                bridge_info.ip_address = ip[1].strNormal()
                bridge_info.netmask = ip.netmask().strNormal()
                
                dhcp_info = dynamic_map()
                r = nw_dhcp_range.split("-")
                if len(r) == 2:
                    dhcp_info.dhcp_start = r[0].strip()
                    dhcp_info.dhcp_end = r[1].strip()
                
                nat_info = dynamic_map()
                nat_info.interface = nw_nat_fwding

                self.context.new_nw_def = NwDef(nw_id, 
                                                nw_type,
                                                nw_name,
                                                nw_desc,
                                                bridge_info=bridge_info,
                                                ipv4_info=ipv4_info,
                                                dhcp_info=dhcp_info,
                                                nat_info=nat_info
                                                )
                
            print "New definition ", self.context.new_nw_def
        else: # Edit mode
            self.context.new_nw_name = get_value(self.widgets.nw_name_entry)
            self.context.new_nw_desc = get_value(self.widgets.nw_desc_entry)


    def save(self, context):
        # All work done in gather.
        # caller will get the new definition using get_new_defn
        print "save called"
 
    def get_new_name(self):
        return self.context.new_nw_name
    
    def get_new_desc(self):
        return self.context.new_nw_desc


    def get_new_defn(self):
        return self.context.new_nw_def

    def show(self, mode, 
             nw_manager, server_pool, managed_server=None, 
             nw_id=None,
             parent=None):
        # set the context
        self.context = dynamic_map();
        self.context.mode = mode
        self.context.server_pool = server_pool
        self.context.parent = parent
        self.context.nw_manager = nw_manager
        self.context.nw_id = nw_id
        self.context.nw_defn = nw_manager.get_defn(nw_id)
        self.context.managed_server = managed_server
        
        ret = self.run_dlg(self.context)
        return ret





