-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

First and foremost, the bonding stuff discussed today sounds great and
is something that I'd be interested in helping with and using.

Before we dig too far into that, however, I want to post up something
I've been meaning to finish for the past month or so but just haven't
had the time to flesh it out completely.  I'd like to get it applied
(assuming others think it's a good patch :D) before we go tearing up the
interface code even more.

The attached patch adds support for generic interface names, and as a
side-effect allows an arbitrary number of interfaces to be assigned to a
system.  This work looks to be a pre-requisite for the bonding examples
anyways, so it should prove useful.

More information is available in the commit log of the patch.

As always, suggestions / gripes / feedback / patches are welcome!

- --
John Eckersberg
Systems Administrator, CIS
Red Hat, Inc.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkjZlPIACgkQdxt4pd4ztYuBegCfTgcny9hdoLovwWD/UU+QPOwW
QBEAoICMHcU/ji+0teuihbNitB1Pwr+k
=ZuJ9
-----END PGP SIGNATURE-----
>From f39dbead3f8f9f6de9b734e1856e66e8035e2f04 Mon Sep 17 00:00:00 2001
From: John Eckersberg <[EMAIL PROTECTED]>
Date: Tue, 23 Sep 2008 20:41:53 -0400
Subject: [PATCH] * Add new functions __get_default_interface and 
set_default_interface
   to the System class.

* Add new setting 'default_interface' to automatically name the
  interface used when creating new systems.  Defaults to 'intf0' for
  backwards compatibility.  I suspect most people will want to set
  this to 'eth0'.

* Modify the printable method of System to always print the default
  interface first and mark it as the default

* Modify cli_system to add two new options:
  * --delete-interface
  * --default-interface

* Whatever interface is set as the default cannot be deleted.

These changes allow for an arbitrary number of interfaces to be added
to a system, as well as allows for the interfaces to be named
something more meaningful than intf0-7.

TODO
----
*** The WebUI is NOT updated by this patch and needs fixed! ***

* Allow default_interface to be set at profile level

* Add method to fetch system interfaces over XMLRPC.  I want to query
  my cobbler server in my Puppet exernal nodes script to build out
  interface configuration.  YMMV.
---
 cobbler/item_system.py        |   69 +++++++++++++++++++++++++++-------------
 cobbler/modules/cli_system.py |   19 ++++++++---
 cobbler/settings.py           |    1 +
 config/settings               |    5 +++
 4 files changed, 65 insertions(+), 29 deletions(-)

diff --git a/cobbler/item_system.py b/cobbler/item_system.py
index c83e74b..4d8796a 100644
--- a/cobbler/item_system.py
+++ b/cobbler/item_system.py
@@ -45,6 +45,7 @@ class System(item.Item):
         self.kernel_options_post  = {}
         self.ks_meta              = {}    
         self.interfaces           = {}
+        self.default_interface    = self.settings.default_interface
         self.netboot_enabled      = True
         self.depth                = 2
         self.mgmt_classes         = []              
@@ -61,12 +62,10 @@ class System(item.Item):
 
     def delete_interface(self,name):
         """
-        Used to remove an interface.  Not valid for intf0.
+        Used to remove an interface.  Not valid for the default interface.
         """
-        if name == "intf0":
-            raise CX(_("the first interface cannot be deleted"))
-        if self.interfaces.has_key(name):
-            del self.interfaces[name]
+        if self.interfaces.has_key(name) and self.default_interface != name:
+                del self.interfaces[name]
         else:
             # NOTE: raising an exception here would break the WebUI as 
currently implemented
             return False
@@ -74,9 +73,8 @@ class System(item.Item):
         
 
     def __get_interface(self,name):
-
-        if name not in [ "intf0", "intf1", "intf2", "intf3", "intf4", "intf5", 
"intf6", "intf7" ]:
-            raise CX(_("internal error: invalid key for interface lookup or 
storage, must be 'intfX' where x is 0..7"))
+        if name is None:
+            return self.__get_default_interface()
 
         if not self.interfaces.has_key(name):
             self.interfaces[name] = {
@@ -91,6 +89,12 @@ class System(item.Item):
             }
         return self.interfaces[name]
 
+    def __get_default_interface(self):
+        if self.default_interface != "":
+            return self.__get_interface(self.default_interface)
+        else:
+            raise CX(_("no default interface defined"))
+
     def from_datastruct(self,seed_data):
 
         # load datastructures from previous and current versions of cobbler
@@ -110,6 +114,7 @@ class System(item.Item):
         self.netboot_enabled      = self.load_item(seed_data, 
'netboot_enabled', True)
         self.server               = self.load_item(seed_data, 'server', 
'<<inherit>>')
         self.mgmt_classes         = self.load_item(seed_data, 'mgmt_classes', 
[])
+        self.default_interface    = self.load_item(seed_data, 
'default_interface', self.settings.default_interface)
 
         # virt specific 
         self.virt_path   = self.load_item(seed_data, 'virt_path', 
'<<inherit>>') 
@@ -182,7 +187,7 @@ class System(item.Item):
         Set the name.  If the name is a MAC or IP, and the first MAC and/or IP 
is not defined, go ahead
         and fill that value in.  
         """
-        intf = self.__get_interface("intf0")
+        intf = self.__get_default_interface()
 
 
         if self.name not in ["",None] and self.parent not in ["",None] and 
self.name == self.parent:
@@ -211,14 +216,14 @@ class System(item.Item):
         self.server = server
         return True
 
-    def get_mac_address(self,interface="intf0"):
+    def get_mac_address(self,interface):
         """
         Get the mac address, which may be implicit in the object name or 
explicit with --mac-address.
         Use the explicit location first.
         """
 
-
         intf = self.__get_interface(interface)
+
         if intf["mac_address"] != "":
             return intf["mac_address"]
         # obsolete, because we should have updated the mac field already with 
set_name (?)
@@ -227,13 +232,14 @@ class System(item.Item):
         else:
             return None
 
-    def get_ip_address(self,interface="intf0"):
+    def get_ip_address(self,interface):
         """
         Get the IP address, which may be implicit in the object name or 
explict with --ip-address.
         Use the explicit location first.
         """
 
         intf = self.__get_interface(interface)
+
         if intf["ip_address"] != "": 
             return intf["ip_address"]
         else:
@@ -258,22 +264,28 @@ class System(item.Item):
                 return True
         return False
 
-    def set_dhcp_tag(self,dhcp_tag,interface="intf0"):
+    def set_default_interface(self,interface):
+        if self.interfaces.has_key(interface):
+            self.default_interface = interface
+        else:
+            raise CX(_("invalid interface (%s)") % interface)
+
+    def set_dhcp_tag(self,dhcp_tag,interface):
         intf = self.__get_interface(interface)
         intf["dhcp_tag"] = dhcp_tag
         return True
 
-    def set_hostname(self,hostname,interface="intf0"):
+    def set_hostname(self,hostname,interface):
         intf = self.__get_interface(interface)
         intf["hostname"] = hostname
         return True
 
-    def set_static(self,truthiness,interface="intf0"):
+    def set_static(self,truthiness,interface):
         intf = self.__get_interface(interface)
         intf["static"] = utils.input_boolean(truthiness)
         return True
 
-    def set_ip_address(self,address,interface="intf0"):
+    def set_ip_address(self,address,interface):
         """
         Assign a IP or hostname in DHCP when this MAC boots.
         Only works if manage_dhcp is set in /etc/cobbler/settings
@@ -284,24 +296,24 @@ class System(item.Item):
            return True
         raise CX(_("invalid format for IP address (%s)") % address)
 
-    def set_mac_address(self,address,interface="intf0"):
+    def set_mac_address(self,address,interface):
         intf = self.__get_interface(interface)
         if address == "" or utils.is_mac(address):
            intf["mac_address"] = address
            return True
         raise CX(_("invalid format for MAC address (%s)" % address))
 
-    def set_gateway(self,gateway,interface="intf0"):
+    def set_gateway(self,gateway,interface):
         intf = self.__get_interface(interface)
         intf["gateway"] = gateway
         return True
 
-    def set_subnet(self,subnet,interface="intf0"):
+    def set_subnet(self,subnet,interface):
         intf = self.__get_interface(interface)
         intf["subnet"] = subnet
         return True
     
-    def set_virt_bridge(self,bridge,interface="intf0"):
+    def set_virt_bridge(self,bridge,interface):
         intf = self.__get_interface(interface)
         intf["virt_bridge"] = bridge
         return True
@@ -414,6 +426,7 @@ class System(item.Item):
            'kernel_options_post'   : self.kernel_options_post,
            'depth'                 : self.depth,
            'interfaces'            : self.interfaces,
+           'default_interface'     : self.default_interface,
            'ks_meta'               : self.ks_meta,
            'kickstart'             : self.kickstart,
            'netboot_enabled'       : self.netboot_enabled,
@@ -451,9 +464,21 @@ class System(item.Item):
         buf = buf + _("virt ram              : %s\n") % self.virt_ram
         buf = buf + _("virt type             : %s\n") % self.virt_type
 
+        # list the default interface first
+        name = self.default_interface
+        x    = self.interfaces[name]
+        buf = buf + _("interface        : %s (default)\n") % (name)
+        buf = buf + _("  mac address    : %s\n") % x.get("mac_address","")
+        buf = buf + _("  ip address     : %s\n") % x.get("ip_address","")
+        buf = buf + _("  hostname       : %s\n") % x.get("hostname","")
+        buf = buf + _("  gateway        : %s\n") % x.get("gateway","")
+        buf = buf + _("  subnet         : %s\n") % x.get("subnet","")
+        buf = buf + _("  virt bridge    : %s\n") % x.get("virt_bridge","")
+        buf = buf + _("  dhcp tag       : %s\n") % x.get("dhcp_tag","")
+        buf = buf + _("  is static?     : %s\n") % x.get("static",False)
 
-        counter = 0
         for (name,x) in self.interfaces.iteritems():
+            if name == self.default_interface: continue
             buf = buf + _("interface        : %s\n") % (name)
             buf = buf + _("  mac address    : %s\n") % x.get("mac_address","")
             buf = buf + _("  ip address     : %s\n") % x.get("ip_address","")
@@ -463,8 +488,6 @@ class System(item.Item):
             buf = buf + _("  virt bridge    : %s\n") % x.get("virt_bridge","")
             buf = buf + _("  dhcp tag       : %s\n") % x.get("dhcp_tag","")
             buf = buf + _("  is static?     : %s\n") % x.get("static",False)
-            counter = counter + 1
-         
 
         return buf
 
diff --git a/cobbler/modules/cli_system.py b/cobbler/modules/cli_system.py
index 7d5a032..3ffd7cd 100644
--- a/cobbler/modules/cli_system.py
+++ b/cobbler/modules/cli_system.py
@@ -29,7 +29,7 @@ sys.path.insert(0, mod_path)
 
 from utils import _, get_random_mac
 import commands
-import cexceptions
+from cexceptions import *
 
 
 class SystemFunction(commands.CobblerFunction):
@@ -54,9 +54,11 @@ class SystemFunction(commands.CobblerFunction):
             p.add_option("--hostname",        dest="hostname",      help="ex: 
server.example.org")
 
             if not self.matches_args(args,["find"]):
-                p.add_option("--interface",       dest="interface", help="edit 
this interface # (0-7, default 0)")
+                p.add_option("--interface",       dest="interface", help="edit 
this interface")
+                p.add_option("--delete-interface", dest="delete_interface", 
metavar="INTERFACE", help="delete the selected interface")
+                p.add_option("--default-interface", dest="default_interface", 
metavar="INTERFACE", help="set INTERFACE as the system default")
             p.add_option("--image",           dest="image",         
help="inherit values from this image, not compatible with --profile")
-            p.add_option("--ip",              dest="ip",            help="ex: 
192.168.1.55, for static IP or dynamic reservation, (RECOMMENDED)")
+            p.add_option("--ip",              dest="ip",            help="ex: 
192.168.1.55, (RECOMMENDED)")
             p.add_option("--kickstart",       dest="kickstart",     
help="override profile kickstart template")
             p.add_option("--kopts",           dest="kopts",         help="ex: 
'noipv6'")
             p.add_option("--kopts-post",      dest="kopts_post",    help="ex: 
'clocksource=pit'")
@@ -130,9 +132,9 @@ class SystemFunction(commands.CobblerFunction):
         if self.options.virt_path:       
obj.set_virt_path(self.options.virt_path)
 
         if self.options.interface:
-            my_interface = "intf%s" % self.options.interface
+            my_interface = self.options.interface
         else:
-            my_interface = "intf0"
+            my_interface = None
 
         if self.options.hostname:    obj.set_hostname(self.options.hostname, 
my_interface)
         if self.options.mac:
@@ -146,7 +148,12 @@ class SystemFunction(commands.CobblerFunction):
         if self.options.dhcp_tag:    obj.set_dhcp_tag(self.options.dhcp_tag, 
my_interface)
         if self.options.virt_bridge: 
obj.set_virt_bridge(self.options.virt_bridge, my_interface)
         if self.options.static:      obj.set_static(self.options.static, 
my_interface)
-              
+
+        if self.options.delete_interface:
+            success = obj.delete_interface(self.options.delete_interface)
+            if not success:
+                raise CX(_('interface does not exist or is the default 
interface (%s)') % self.options.delete_interface)
+        if self.options.default_interface: 
obj.set_default_interface(self.options.default_interface)
 
         if self.options.owners:       obj.set_owners(self.options.owners)
         if self.options.mgmt_classes: 
obj.set_mgmt_classes(self.options.mgmt_classes)
diff --git a/cobbler/settings.py b/cobbler/settings.py
index fd2af0a..d652e4a 100644
--- a/cobbler/settings.py
+++ b/cobbler/settings.py
@@ -34,6 +34,7 @@ DEFAULTS = {
     "allow_duplicate_ips"         : 0,
     "bind_bin"                    : "/usr/sbin/named",
     "cobbler_master"              : '',
+    "default_interface"           : 'intf0',
     "default_kickstart"           : "/etc/cobbler/default.ks",
     "default_virt_bridge"         : "xenbr0",
     "default_virt_type"           : "auto",
diff --git a/config/settings b/config/settings
index 9ac6cec..67ea1a3 100644
--- a/config/settings
+++ b/config/settings
@@ -20,6 +20,11 @@ allow_duplicate_ips: 0
 # the path to BIND's executable for this distribution.
 bind_bin: /usr/sbin/named
 
+# name of the default interface when creating a new system.
+# this is intf0 for backwards-compatibility; you may want to
+# specify something else (e.g. eth0) to be more meaningful
+default_interface: intf0
+
 # if no kickstart is specified, use this template (FIXME)
 default_kickstart: /etc/cobbler/default.ks
 
-- 
1.5.5.1

_______________________________________________
cobbler mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/cobbler

Reply via email to