summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-10-08 15:47:48 -0400
committerMichael DeHaan <mdehaan@redhat.com>2007-10-08 15:47:48 -0400
commit56fc6d73fea2d8224c92a8f03b860fd0b7761f0f (patch)
tree36343c25d6cb07414ed44462e562039bd8761050
parenta856c9fbf9cc9d9da777b95059219638d3636344 (diff)
downloadthird_party-cobbler-56fc6d73fea2d8224c92a8f03b860fd0b7761f0f.tar.gz
third_party-cobbler-56fc6d73fea2d8224c92a8f03b860fd0b7761f0f.tar.xz
third_party-cobbler-56fc6d73fea2d8224c92a8f03b860fd0b7761f0f.zip
In process of making NICs seperate data structures in cobbler, which requires seperate accessors
and templating. This is all to allow multiple NICs in koan. Stil needs changes in sync code and possibly other places.
-rw-r--r--CHANGELOG3
-rw-r--r--cobbler/action_litesync.py2
-rw-r--r--cobbler/action_sync.py7
-rwxr-xr-xcobbler/cobbler.py25
-rw-r--r--cobbler/item_system.py222
-rw-r--r--cobbler/utils.py21
-rw-r--r--docs/cobbler.pod18
7 files changed, 228 insertions, 70 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 93b2219..39a8ec7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,7 +2,8 @@ Cobbler CHANGELOG
(all entries mdehaan@redhat.com unless noted otherwise)
* Mon Oct 08 2007 - 0.6.3
-- Replace @@server@@ in repo config files
+- Be able to define and use Multiple NICs per system
+- Use server address not @@server in repo config files
* Fri Sep 28 2007 - 0.6.2
- cobbler repo auto-add to discover yum repos automatically
diff --git a/cobbler/action_litesync.py b/cobbler/action_litesync.py
index d86962f..61b4ee5 100644
--- a/cobbler/action_litesync.py
+++ b/cobbler/action_litesync.py
@@ -113,9 +113,11 @@ class BootLiteSync:
self.sync.rmfile(os.path.join(self.settings.webdir, "systems", name))
# delete contents of kickstarts_sys/$name in webdir
system_record = self.systems.find(name=name)
+ # FIXME: make this understand multiple interfaces
filename = utils.get_config_filename(system_record)
self.sync.rmtree(os.path.join(self.settings.webdir, "kickstarts_sys", filename))
+ # FIXME: make this understand multiple interfaces
if not system_record.is_pxe_supported():
# no need to go any further with PXE cleanup
return
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index 9cd7b46..03716d4 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -460,7 +460,6 @@ class BootSync:
meta = utils.blender(False, s)
kickstart_path = utils.find_kickstart(meta["kickstart"])
if kickstart_path and os.path.exists(kickstart_path):
- # pxe_fn = utils.get_config_filename(s)
copy_path = os.path.join(self.settings.webdir,
"kickstarts_sys", # system kickstarts go here
s.name
@@ -602,6 +601,8 @@ class BootSync:
distro = profile.get_conceptual_parent()
if distro is None:
raise CX(_("profile %(profile)s references a missing distro %(distro)s") % { "profile" : system.profile, "distro" : profile.distro})
+
+ # FIXME: make this understand multiple interfaces:
f1 = utils.get_config_filename(system)
# tftp only
@@ -615,12 +616,13 @@ class BootSync:
if system.get_ip_address() == None:
print _("Warning: Itanium system object (%s) needs an IP address to PXE") % system.name
-
+ # FIXME: make this understand multiple interfaces
filename = "%s.conf" % utils.get_config_filename(system)
f2 = os.path.join(self.settings.tftpboot, filename)
f3 = os.path.join(self.settings.webdir, "systems", f1)
+ # FIXME: make this understand multiple interfaces
if system.netboot_enabled and system.is_pxe_supported():
if distro.arch in [ "x86", "x86_64", "standard"]:
self.write_pxe_file(f2,system,profile,distro,False)
@@ -720,7 +722,6 @@ class BootSync:
if kickstart_path is not None and kickstart_path != "":
if system is not None and kickstart_path.startswith("/"):
- # pxe_fn = utils.get_config_filename(system)
kickstart_path = "http://%s/cblr/kickstarts_sys/%s/ks.cfg" % (self.settings.server, system.name)
elif kickstart_path.startswith("/") or kickstart_path.find("/cobbler/kickstarts/") != -1:
kickstart_path = "http://%s/cblr/kickstarts/%s/ks.cfg" % (self.settings.server, profile.name)
diff --git a/cobbler/cobbler.py b/cobbler/cobbler.py
index 1fa6821..38c971c 100755
--- a/cobbler/cobbler.py
+++ b/cobbler/cobbler.py
@@ -494,6 +494,7 @@ class BootCLI:
"""
Create/Edit a system: 'cobbler system edit --name='foo' ...
"""
+ # This copy/paste is heinous evil, please forgive me.
commands = {
'--name' : lambda(a) : sys.set_name(a),
'--newname' : lambda(a) : True,
@@ -502,18 +503,30 @@ class BootCLI:
'--kopts' : lambda(a) : sys.set_kernel_options(a),
'--ksmeta' : lambda(a) : sys.set_ksmeta(a),
'--hostname' : lambda(a) : sys.set_hostname(a),
- '--pxe-address' : lambda(a) : sys.set_ip_address(a), # deprecated
- '--ip-address' : lambda(a) : sys.set_ip_address(a),
- '--ip' : lambda(a) : sys.set_ip_address(a), # alias
- '--mac-address' : lambda(a) : sys.set_mac_address(a),
- '--mac' : lambda(a) : sys.set_mac_address(a), # alias
+ '--ip' : lambda(a) : sys.set_ip_address(a,interface=0),
+ '--mac' : lambda(a) : sys.set_mac_address(a,interface=0),
+ '--gateway' : lambda(a) : sys.set_mac_address(a,interface=0),
+ '--subnet' : lambda(a) : sys.set_mac_address(a,interface=0),
+ '--virt-bridge' : lambda(a) : sys.set_mac_address(a,interface=0),
'--kickstart' : lambda(a) : sys.set_kickstart(a),
- '--kick-start' : lambda(a) : sys.set_kickstart(a),
'--netboot-enabled' : lambda(a) : sys.set_netboot_enabled(a),
'--virt-path' : lambda(a) : sys.set_virt_path(a),
'--virt-type' : lambda(a) : sys.set_virt_type(a),
'--dhcp-tag' : lambda(a) : sys.set_dhcp_tag(a)
}
+
+ # add some command aliases for additional interfaces. The default commands
+ # only operate on the first, which are all many folks will need.
+ for count in range(0,7):
+ commands["--hostname%d" % count] = lambda(a) : sys.set_hostname(a,interface=count)
+ commands["--ip%d" % count] = lambda(a) : sys.set_ip_address(a,interface=count)
+ commands["--mac%d" % count] = lambda(a) : sys.set_mac_address(a,interface=0)
+ commands["--gateway%d" % count] = lambda(a) : sys.set_gateway(a,interface=0)
+ commands["--subnet%d" % count] = lambda(a) : sys.set_subnet(a,interface=0)
+ commands["--virt-bridge%d" % count] = lambda(a) : sys.set_virt_bridge(a,interface=0)
+ commands["--dhcp-tag%d" % count] = lambda(a) : sys.set_dhcp_tag(a,interface=0)
+
+
def on_ok():
self.api.systems().add(sys, with_copy=True)
return self.apply_args(args,commands,on_ok)
diff --git a/cobbler/item_system.py b/cobbler/item_system.py
index 03a8f69..1a130f3 100644
--- a/cobbler/item_system.py
+++ b/cobbler/item_system.py
@@ -34,12 +34,14 @@ class System(item.Item):
self.profile = (None, '<<inherit>>')[is_subobject]
self.kernel_options = ({}, '<<inherit>>')[is_subobject]
self.ks_meta = ({}, '<<inherit>>')[is_subobject]
- self.ip_address = ("", '<<inherit>>')[is_subobject]
- self.mac_address = ("", '<<inherit>>')[is_subobject]
+
+ # these are obsolete:
+ # self.ip_address = ("", '<<inherit>>')[is_subobject]
+ # self.mac_address = ("", '<<inherit>>')[is_subobject]
+ # self.hostname = ("", '<<inheirt>>')[is_subobject]
+
self.netboot_enabled = (1, '<<inherit>>')[is_subobject]
- self.hostname = ("", '<<inheirt>>')[is_subobject]
self.depth = 2
- self.dhcp_tag = "default"
self.kickstart = "<<inherit>>" # use value in profile
self.virt_path = "<<inherit>>" # use value in profile
self.virt_type = "<<inherit>>" # use value in profile
@@ -55,20 +57,68 @@ class System(item.Item):
self.kickstart = self.load_item(seed_data, 'kickstart', '<<inherit>>')
self.virt_path = self.load_item(seed_data, 'virt_path', '<<inherit>>')
self.virt_type = self.load_item(seed_data, 'virt_type', '<<inherit>>')
- self.dhcp_tag = self.load_item(seed_data, 'dhcp_tag', 'default')
+
+ # backwards compat, this is now a per-NIC setting
+ __dhcp_tag = self.load_item(seed_data, 'dhcp_tag', 'default')
# backwards compat, load --ip-address from two possible sources.
# the old --pxe-address was a bit of a misnomer, new value is --ip-address
-
- oldvar = self.load_item(seed_data, 'pxe_address')
- if oldvar == "": # newer version, yay
- self.ip_address = self.load_item(seed_data, 'ip_address')
+ # though the ultimate trick is that we don't even use this parameter anymore for
+ # storage reasons. We now use self.interfaces which is an array of hashes.
+ __oldvar = self.load_item(seed_data, 'pxe_address', "")
+ if __oldvar == "": # newer version, yay
+ __ip_address = self.load_item(seed_data, 'ip_address', "")
else:
- self.ip_address = oldvar
-
+ __ip_address = __oldvar
+
+ # the following two parameters are also here for backwards compatibility reasons
+ __hostname = self.load_item(seed_data, 'hostname', "")
+ __mac_address = self.load_item(seed_data, 'mac_address', "")
+
+ # now load the new-style interface definition data structure
+ self.interfaces = self.load_item(seed_data, 'interfaces', [])
+
+ # now backfill the interface structure with any old values
+ # backwards compatibility here is complex/ugly though we don't want to
+ # break anyone. So this code needs to stay here.
+ if __hostname is not None or
+ __mac_address is not None or
+ __ip_address is not None:
+ insert_item = {}
+ if __hostname is not None and __hostname != "":
+ insert_item["hostname"] = __hostname
+ if __mac_address is not None and __mac_address != "":
+ insert_item["mac_address"] = __mac_address
+ if __ip_address is not None and __ip_address != "":
+ insert_item["ip_address"] = __ip_address
+ if __dhcp_tag is not None and __dhcp_tag != "":
+ insert_item["dhcp_tag"] = __dhcp_tag
+ self.interfaces.append(insert_item)
+
+ # now if no interfaces are STILL defined, add in one only under certain
+ # conditions .. this emulates legacy behavior in the new interface format
+ if __mac_address == "" and utils.is_mac(self.name):
+ self.interfaces.append({
+ "mac_address" : self.name
+ })
+ elif __ip_address == "" and utils.is_ip(self.name):
+ self.interfaces.append({
+ "ip_address" : self.ip_address
+ })
+
+ # now for each interface, if any fields are missing, add them.
+ for x in self.interfaces:
+ x.setdefault("mac_address","")
+ x.setdefault("ip_address","")
+ x.setdefault("netmask","")
+ x.setdefault("hostname","")
+ x.setdefault("gateway","")
+ x.setdefault("virt_bridge","")
+ x.setdefault("dhcp_tag","default")
+
+ # question: is there any case where we'd want to PXE-enable one interface
+ # but not another. answer: probably not.
self.netboot_enabled = self.load_item(seed_data, 'netboot_enabled', 1)
- self.hostname = self.load_item(seed_data, 'hostname')
- self.mac_address = self.load_item(seed_data, 'mac_address')
# backwards compatibility -- convert string entries to dicts for storage
# this allows for better usage from the API.
@@ -78,16 +128,7 @@ class System(item.Item):
if self.ks_meta != "<<inherit>>" and type(self.ks_meta) != dict:
self.set_ksmeta(self.ks_meta)
- # backwards compatibility -- if name is an IP or a MAC, set appropriate fields
- # this will only happen once, as part of an upgrade path ...
- # Explanation -- older cobbler's figured out the MAC and IP
- # from the system name, newer cobblers allow arbitrary naming but can tell when the
- # name is an IP or a MAC and use that if that info is not supplied.
- if self.mac_address == "" and utils.is_mac(self.name):
- self.mac_address = self.name
- elif self.ip_address == "" and utils.is_ip(self.name):
- self.ip_address = self.name
return self
@@ -117,33 +158,41 @@ class System(item.Item):
return True
- def get_mac_address(self):
+ def get_mac_address(self,interface=0):
"""
Get the mac address, which may be implicit in the object name or explicit with --mac-address.
Use the explicit location first.
"""
- if self.mac_address != "":
- return self.mac_address
- elif utils.is_mac(self.name):
+
+ if len(self.interfaces) -1 < interface:
+ raise CX(_("internal error: probing an interface that does not exist"))
+
+ intf = self.interfaces[interface]
+ if intf["mac_address"] != "":
+ return intf["mac_address"]
+ elif utils.is_mac(self.name) and interface == 0:
return self.name
else:
- # no one ever set it, but that might be ok depending on usage.
return None
- def get_ip_address(self):
+ def get_ip_address(self,interface=0):
"""
Get the IP address, which may be implicit in the object name or explict with --ip-address.
Use the explicit location first.
"""
- if self.ip_address != "":
- return self.ip_address
- elif utils.is_ip(self.name):
+
+ if len(self.interfaces) -1 < interface:
+ raise CX(_("internal error: probing an interface that does not exist"))
+
+ intf = self.interfaces[interface]
+ if intf["ip_address"] != "":
+ return intf["ip_address"]
+ elif utils.is_ip(self.name) and interface == 0:
return self.name
else:
- # no one ever set it, but that might be ok depending on usage.
return None
- def is_pxe_supported(self):
+ def is_pxe_supported(self,interface=0):
"""
Can only add system PXE records if a MAC or IP address is available, else it's a koan
only record. Actually Itanium goes beyond all this and needs the IP all of the time
@@ -151,39 +200,83 @@ class System(item.Item):
"""
if self.name == "default":
return True
- mac = self.get_mac_address()
- ip = self.get_ip_address()
+ counter = 0
+ mac = self.get_mac_address(counter)
+ ip = self.get_ip_address(counter)
if mac is None and ip is None:
return False
return True
- def set_dhcp_tag(self,dhcp_tag):
- self.dhcp_tag = dhcp_tag
+ def __get_interface(self,interface=0,enforcing=False):
+ if not ( interface <= len(self.interfaces) -1 ):
+ if enforcing:
+ raise CX(_("internal error: accessing interface that does not exist: %s" % interface))
+ else:
+ # if there are two interfaces and the API requests the fifth, that's an error.
+ # you can't set an interface that is more than +1 away from the current count.
+ # FIXME: this may cause problems.
+ # FIXME: there should be a function that generates this.
+ new_item = {
+ "hostname" : "",
+ "ip_address" : "",
+ "mac_address" : "",
+ "subnet" : "",
+ "netmask" : "",
+ "virt_bridge" : "",
+ "dhcp_tag" : ""
+ }
+ self.interfaces.append(new_item)
+ return new_item
+
+ return self.interfaces[interface]
+
+ def set_dhcp_tag(self,dhcp_tag,interface=0):
+ intf = self.__get_interface(interface)
+ intf["dhcp_tag"] = dhcp_tag
return True
- def set_hostname(self,hostname):
- self.hostname = hostname
+ def set_hostname(self,hostname,interface=0):
+ intf = self.__get_interface(interface)
+ intf["hostname"] = hostname
return True
- def set_ip_address(self,address):
+ def set_ip_address(self,address,interface=0):
"""
Assign a IP or hostname in DHCP when this MAC boots.
Only works if manage_dhcp is set in /var/lib/cobbler/settings
"""
+ # FIXME: interface
+ intf = self.__get_interface(interface)
if utils.is_ip(address):
- self.ip_address = address
+ intf["ip_address"] = address
return True
raise CX(_("invalid format for IP address"))
- def set_mac_address(self,address):
+ def set_mac_address(self,address,interface=0):
+ # FIXME: interface
+ intf = self.__get_interface(interface)
if utils.is_mac(address):
- self.mac_address = address
+ intf["mac_address"] = address
return True
raise CX(_("invalid format for MAC address"))
- def set_pxe_address(self,address):
- # backwards compatibility for API users:
- return self.set_ip_address(address)
+ def set_gateway(self,gateway,interface=0):
+ # FIXME: validate + interface
+ intf = self.__get_interface(interface)
+ intf["gateway"] = gateway
+ return True
+
+ def set_subnet(self,subnet,interface=0):
+ # FIXME: validate + interface
+ intf = self.__get_interface(interface)
+ intf["subnet"] = subnet
+ return True
+
+ def set_virt_bridge(self,bridge,interface=0):
+ # FIXME: validate + interface
+ intf = self.__get_interface(interface)
+ intf["bridge"] = bridge
+ return True
def set_profile(self,profile_name):
"""
@@ -272,16 +365,17 @@ class System(item.Item):
'profile' : self.profile,
'kernel_options' : self.kernel_options,
'ks_meta' : self.ks_meta,
- 'ip_address' : self.ip_address,
+ #'ip_address' : self.ip_address,
'netboot_enabled' : self.netboot_enabled,
- 'hostname' : self.hostname,
- 'mac_address' : self.mac_address,
+ #'hostname' : self.hostname,
+ #'mac_address' : self.mac_address,
'parent' : self.parent,
'depth' : self.depth,
'kickstart' : self.kickstart,
'virt_type' : self.virt_type,
'virt_path' : self.virt_path,
- 'dhcp_tag' : self.dhcp_tag
+ #'dhcp_tag' : self.dhcp_tag,
+ 'interfaces' : self.interfaces
}
def printable(self):
@@ -289,16 +383,27 @@ class System(item.Item):
buf = buf + _("profile : %s\n") % self.profile
buf = buf + _("kernel options : %s\n") % self.kernel_options
buf = buf + _("ks metadata : %s\n") % self.ks_meta
- buf = buf + _("ip address : %s\n") % self.get_ip_address()
- buf = buf + _("mac address : %s\n") % self.get_mac_address()
- buf = buf + _("hostname : %s\n") % self.hostname
- buf = buf + _("pxe info set? : %s\n") % self.is_pxe_supported()
- buf = buf + _("config id : %s\n") % utils.get_config_filename(self)
+
buf = buf + _("netboot enabled? : %s\n") % self.netboot_enabled
buf = buf + _("kickstart : %s\n") % self.kickstart
buf = buf + _("virt type : %s\n") % self.virt_type
buf = buf + _("virt path : %s\n") % self.virt_path
- buf = buf + _("dhcp tag : %s\n") % self.dhcp_tag
+
+ counter = 0
+ for x in self.interfaces:
+ buf = buf + _(" -----------\n")
+ buf = buf + _("interface : #%d\n") % counter + 1
+ 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 + _(" config id : %s\n") % utils.get_config_filename(self,counter)
+ counter = counter + 1
+
+
return buf
def remote_methods(self):
@@ -316,6 +421,9 @@ class System(item.Item):
'netboot-enabled' : self.set_netboot_enabled,
'virt-path' : self.set_virt_path,
'virt-type' : self.set_virt_type,
- 'dhcp-tag' : self.set_dhcp_tag
+ 'dhcp-tag' : self.set_dhcp_tag,
+ 'gateway' : self.set_gateway,
+ 'virt-bridge' : self.set_virt_bridge,
+ 'subnet' : self.set_subnet
}
diff --git a/cobbler/utils.py b/cobbler/utils.py
index 2feee70..a2cefbb 100644
--- a/cobbler/utils.py
+++ b/cobbler/utils.py
@@ -55,7 +55,7 @@ def get_host_ip(ip):
results = out.read()
return results.split(" ")[-1][0:8]
-def get_config_filename(sys):
+def get_config_filename(sys,interface=0):
"""
The configuration file for each system pxe uses is either
a form of the MAC address of the hex version of the IP. If none
@@ -64,10 +64,14 @@ def get_config_filename(sys):
system.is_pxe_supported()). This same file is used to store
system config information in the Apache tree, so it's still relevant.
"""
+
+ if interface > len(sys.interfaces) -1:
+ raise CX(_("internal error: probing an interface that does not exist"))
+
if sys.name == "default":
return "default"
- mac = sys.get_mac_address()
- ip = sys.get_ip_address()
+ mac = sys.get_mac_address(nterface)
+ ip = sys.get_ip_address(interface)
if mac != None:
return "01-" + "-".join(mac.split(":")).lower()
elif ip != None:
@@ -308,6 +312,17 @@ def flatten(data):
data["repos"] = " ".join(data["repos"])
if data.has_key("rpm_list") and type(data["rpm_list"]) == list:
data["rpm_list"] = " ".join(data["rpm_list"])
+ if data.has_key("interfaces"):
+ # make interfaces accessible without Cheetah-voodoo in the templates
+ # EXAMPLE: $ip == $ip0, $ip1, $ip2 and so on.
+ counter = 0
+ for x in data["interfaces"]:
+ data["%s%d" % (x,counter)] = data["interfaces"][x]
+ # just to keep templates backwards compatibile
+ if counter == 0:
+ data[x] = data["interfaces"][x]
+ counter = counter + 1
+
return data
def __consolidate(node,results):
diff --git a/docs/cobbler.pod b/docs/cobbler.pod
index 8326987..0962278 100644
--- a/docs/cobbler.pod
+++ b/docs/cobbler.pod
@@ -204,6 +204,8 @@ already looks like a mac address, this is inferred from the system name and does
MAC addresses have the format AA:BB:CC:DD:EE:FF.
+If you would like to specify additional MACs, use --mac0=x, --mac1=y and so on.
+
=item ip
If cobbler is configured to generate a DHCP configuratition (see advanced section), use this
@@ -214,6 +216,8 @@ Example: ---ip=192.168.1.50
Note for Itanium users: this setting is always required for IA64 regardless of whether DHCP management is enabled.
+If you would like to specify additional IPs, use --ip0=x, --ip1=y and so on.
+
=item hostname
If using the DHCP configuration feature (see advanced section) with dnsmasq, use this to define a hostname for the system to
@@ -222,6 +226,18 @@ basically ignored.
Example: --hostname=mycomputer.example.com
+If you would like to specify additional hostnames, use --hostname0=x, --hostname1=y and so on.
+
+=item --gateway and --subnet
+
+If you are using static IP configurations, you may find it useful to store gateway and subnet
+information inside of cobbler. These variables are not used internally by cobbler, but are
+made available in cobbler templates, which are described later in this document and on the Wiki.
+For DHCP configurations, these parameters should be left blank.
+
+To describe gateway and subnet information for multiple intefaces, use --gateway0=x, --gateway1=y
+and so on. Subnets work the same way.
+
=item --kickstart
(optional) While it is recommended that the --kickstart parameter is only used within for the "profile add" command, there are scenarios when an install base switching to cobbler may have kickstarts created on a per-system basis (one kickstart for each system, nothing shared) and may not want to immediately make use of the cobbler templating system. This allows specifing a kickstart for use on a per-system basis. Creation of a parent profile is still required. If the kickstart is a filesystem location, it will still be treated as a cobbler template.
@@ -237,6 +253,8 @@ If you are setting up a PXE environment with multiple subnets/gateways, and are
By default, the dhcp tag for all systems is "default" and means that in the DHCP template files the systems will expand out where $insert_cobbler_systems_definitions is found in the DHCP template. However, you may want certain systems to expand out in other places in the file. Setting --dhcp-tag=subnet2 for instance, will cause that system to expand out where $insert_cobbler_system_definitions_subnet2 is found, allowing you to insert directives to specify different subnets (or other parameters) before the DHCP configuration entries for those particular systems.
+If your system has multiple network interfaces, use --dhcp-tag0=x, --dhcp-tag1=y and so on.
+
=end
=head2 ADDING A REPOSITORY TO MIRROR