diff options
Diffstat (limited to 'cobbler/item_system.py')
-rw-r--r-- | cobbler/item_system.py | 222 |
1 files changed, 165 insertions, 57 deletions
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 } |