示例#1
0
    def run(self, args):

        host = args[0]

        rows = self.owner.call('list.host.interface', [host, 'expanded=True'])

        udev_output = ""

        for row in rows:

            mac = row['mac']
            ip = row['ip']
            device = row['interface']
            netmask = row['mask']
            subnet = row['network']
            module = row['module']
            options = row['options']
            channel = row['channel']
            gateway = row['gateway']
            vlanid = row['vlan']
            default = row['default']

            if ip and not subnet:
                Warn(
                    f'WARNING: skipping interface "{device}" on host "{host}" - '
                    'interface has an IP but no network')
                continue

            # If we don't have a device, we don't need a config file
            if not device:
                continue

            mtu = None
            if subnet:
                subnetInfo = self.owner.call('list.network', [subnet])
                mtu = subnetInfo[0]['mtu']

            # Host attributes can override the subnets tables
            # definition of the netmask.

            x = self.owner.getHostAttr(host, 'network.%s.netmask' % subnet)
            if x:
                netmask = x

            optionlist = []
            if options:
                optionlist = shlex.split(options)
            if 'noreport' in optionlist:
                continue  # don't do anything if noreport set

            if device == 'ipmi':
                self.owner.addOutput(
                    host,
                    '<stack:file stack:name="/etc/sysconfig/ipmi" stack:perms="500">'
                )
                self.owner.writeIPMI(host, ip, channel, netmask, gateway,
                                     vlanid)
                self.owner.addOutput(host, '</stack:file>')

                # ipmi is special, skip the standard stuff
                continue

            if device and device[0:4] != 'vlan':
                #
                # output a script to update modprobe.conf
                #
                self.writeModprobe(host, device, module, optionlist)

            if self.owner.interface:
                if self.owner.interface == device:
                    self.writeConfig(host, mac, ip, device, netmask, vlanid,
                                     mtu, optionlist, channel, default)
            else:
                s = '<stack:file stack:name="'
                s += '/etc/sysconfig/network-scripts/ifcfg-'
                s += '%s">' % (device)

                self.owner.addOutput(host, s)
                self.owner.addOutput(host, '# AUTHENTIC STACKI')
                self.writeConfig(host, mac, ip, device, netmask, vlanid, mtu,
                                 optionlist, channel, default)
                self.owner.addOutput(host, '</stack:file>')

                ib_re = re.compile('^ib[0-9]+$')
                if not ib_re.match(device):
                    udev_output += 'SUBSYSTEM=="net", '
                    udev_output += 'ACTION=="add", '
                    udev_output += 'DRIVERS=="?*", '
                    udev_output += 'ATTR{address}=="%s", ' % mac
                    udev_output += 'ATTR{type}=="1", '
                    udev_output += 'KERNEL=="eth*", '
                    udev_output += 'NAME="%s"\n\n' % device

        if udev_output:
            self.owner.addOutput(
                host,
                '<stack:file stack:name="/etc/udev/rules.d/70-persistent-net.rules">'
            )
            self.owner.addOutput(host, udev_output)
            self.owner.addOutput(host, '</stack:file>')
示例#2
0
    def run(self, args):

        host = args[0]

        bond_reg = re.compile('bond[0-9]+')
        udev_output = ""

        result = self.owner.call('list.host.interface',
                                 ['expanded=true', host])
        for o in result:
            interface = o['interface']
            default = str2bool(o['default'])
            ip = o['ip']
            netname = o['network']
            vlanid = o['vlan']
            mac = o['mac']
            if mac:
                mac = mac.lower()
            channel = o['channel']
            options = o['options']
            netmask = o['mask']
            gateway = o['gateway']

            startmode = None
            bootproto = 'static'

            if ip and not netname:
                Warn(
                    f'WARNING: skipping interface "{interface}" on host "{o["host"]}" - '
                    'interface has an IP but no network')
                continue

            if netname and ip and netmask:
                net = ipaddress.IPv4Network('%s/%s' % (ip, netmask),
                                            strict=False)
                broadcast = str(net.broadcast_address)
                network = str(net.network_address)
            else:
                broadcast = None
                network = None

            if options:
                options = shlex.split(o['options'])
            else:
                options = []

            if 'noreport' in options:
                continue  # don't do anything if noreport set

            ib_re = re.compile('^ib[0-9]+$')
            if mac:
                if not ib_re.match(interface) and interface != 'ipmi':
                    udev_output += 'SUBSYSTEM=="net", '
                    udev_output += 'ACTION=="add", '
                    udev_output += 'DRIVERS=="?*", '
                    udev_output += 'ATTR{address}=="%s", ' % mac
                    udev_output += 'ATTR{type}=="1", '
                    udev_output += 'KERNEL=="eth*", '
                    udev_output += 'NAME="%s"\n\n' % interface

            if not interface:
                continue

            if interface == 'ipmi':
                ipmisetup = '/tmp/ipmisetup'
                self.owner.addOutput(
                    host, '<stack:file stack:name="%s">' % ipmisetup)
                self.owner.writeIPMI(host, ip, channel, netmask, gateway,
                                     vlanid)
                self.owner.addOutput(host, '</stack:file>')
                self.owner.addOutput(host, 'chmod 500 %s' % ipmisetup)
                continue

            if len(interface.split(':')) == 2:
                #
                # virtual interface configuration
                #
                self.owner.addOutput(
                    host,
                    '<stack:file stack:mode="append" stack:name="/etc/sysconfig/network/ifcfg-%s">'
                    % interface.split(':')[0])

                self.owner.addOutput(host, '# AUTHENTIC STACKI')

                vnum = interface.split(':')[1]
                if ip:
                    self.owner.addOutput(host, 'IPADDR%s=%s' % (vnum, ip))
                if netmask:
                    self.owner.addOutput(host,
                                         'NETMASK%s=%s' % (vnum, netmask))
                if network:
                    self.owner.addOutput(host,
                                         'NETWORK%s=%s' % (vnum, network))
                if broadcast:
                    self.owner.addOutput(host,
                                         'BROADCAST%s=%s' % (vnum, broadcast))

                self.owner.addOutput(host, 'LABEL%s=%s' % (vnum, vnum))

            else:
                self.owner.addOutput(
                    host,
                    '<stack:file stack:name="/etc/sysconfig/network/ifcfg-%s">'
                    % interface)

                self.owner.addOutput(host, '# AUTHENTIC STACKI')

                if vlanid and self.owner.host_based_routing(
                        host, interface, vlanid):
                    parent_device = interface.strip().split('.')[0]
                    self.owner.addOutput(host,
                                         'ETHERDEVICE=%s' % parent_device)
                    self.owner.addOutput(host, 'VLAN=yes')
                    startmode = 'auto'
                else:
                    self.owner.addOutput(host, 'USERCONTROL=no')

                dhcp = 'dhcp' in options

                if dhcp:
                    bootproto = 'dhcp'
                    if default:
                        self.owner.addOutput(host,
                                             'DHCLIENT_SET_HOSTNAME="yes"')
                        self.owner.addOutput(
                            host, 'DHCLIENT_SET_DEFAULT_ROUTE="yes"')
                    else:
                        self.owner.addOutput(host,
                                             'DHCLIENT_SET_HOSTNAME="no"')
                        self.owner.addOutput(
                            host, 'DHCLIENT_SET_DEFAULT_ROUTE="no"')

                if 'onboot=no' in options:
                    startmode = 'manual'
                elif ip or dhcp or channel or 'bridge' in options:
                    #
                    # if there is an IP address, or this
                    # interface should DHCP, or anything in
                    # the 'channel' field (e.g., this is a
                    # bridged or bonded interface), or if 'bridge'
                    # is in the options, then turn this interface on
                    #
                    startmode = 'auto'

                if not dhcp:
                    if ip:
                        self.owner.addOutput(host, 'IPADDR=%s' % ip)
                    if netmask:
                        self.owner.addOutput(host, 'NETMASK=%s' % netmask)
                    if network:
                        self.owner.addOutput(host, 'NETWORK=%s' % network)
                    if broadcast:
                        self.owner.addOutput(host, 'BROADCAST=%s' % broadcast)

                if mac:
                    self.owner.addOutput(host, 'HWADDR=%s' % mac.strip())

                #
                # bonded interface, e.g., 'bond0'
                #
                if bond_reg.match(interface):
                    #
                    # if a 'bond*' device is present, then always make
                    # sure it is enabled on boot.
                    #
                    startmode = 'auto'

                    self.owner.addOutput(host, 'BONDING_MASTER=yes')

                    #
                    # find the interfaces that are part of this bond
                    #
                    i = 0
                    for p in result:
                        if p['channel'] == interface:
                            self.owner.addOutput(
                                host,
                                'BONDING_SLAVE%d="%s"' % (i, p['interface']))
                            i = i + 1

                    #
                    # Check if there are bonding options set
                    #
                    for opt in options:
                        if opt.startswith('bonding-opts='):
                            i = opt.find('=')
                            bo = opt[i + 1:]
                            self.owner.addOutput(
                                host, 'BONDING_MODULE_OPTS="%s"' % bo)
                            break

                #
                # check if this is part of a bonded channel
                #
                if channel and bond_reg.match(channel):
                    startmode = 'auto'
                    bootproto = 'none'

                if not startmode:
                    startmode = 'off'

                self.owner.addOutput(host, 'STARTMODE=%s' % startmode)
                self.owner.addOutput(host, 'BOOTPROTO=%s' % bootproto)

                #
                # if this is a bridged interface, then go look for the
                # physical interface this bridge is associated with
                #
                if 'bridge' in options:
                    for p in result:
                        if p['channel'] == interface:
                            self.owner.addOutput(host, 'BRIDGE=yes')
                            self.owner.addOutput(host, 'BRIDGE_FORWARDDELAY=0')
                            self.owner.addOutput(host, 'BRIDGE_STP=off')
                            self.owner.addOutput(
                                host, 'BRIDGE_PORTS=%s' % p['interface'])
                            break

            self.owner.addOutput(host, '\n')
            self.owner.addOutput(host, '</stack:file>')

        if udev_output:
            self.owner.addOutput(
                host,
                '<stack:file stack:name="/etc/udev/rules.d/70-persistent-net.rules">'
            )
            self.owner.addOutput(host, udev_output)
            self.owner.addOutput(host, '</stack:file>')
示例#3
0
    def run(self, param, args):
        text = []
        self.beginOutput()
        text.append('<stack:file stack:name="/etc/hosts">')
        text.append(stack.text.DoNotEdit())
        text.append('#  Site additions go in /etc/hosts.local\n')
        text.append('127.0.0.1\tlocalhost.localdomain\tlocalhost\n')
        zones = {}
        aliases = {}

        # Populate the zone map : network->zone
        for row in self.call('list.network'):
            zones[row['network']] = row['zone']

        # Populate the host -> interface -> aliases map
        for row in self.call('list.host.interface.alias'):
            host = row['host']
            interface = row['interface']
            if host not in aliases:
                aliases[host] = {}
            if interface not in aliases[host]:
                aliases[host][interface] = []
            aliases[host][interface].append(row['alias'])

        hosts = {}

        # Get a list of all interfaces and populate the host map
        # host -> interfaces.
        # {"hostname":[
        #	{"ip":"1.2.3.4", "interface":"eth0", "zone":"domain.com","default":True/None, "shortname":True/False},
        #	{"ip":"2.3.4.5", "interface":"eth1", "zone":"domain2.com","default":True/None, "shortname":True/False},
        #	]}
        interfaces = self.call('list.host.interface')
        for row in interfaces:
            if not row['ip']:
                continue
            if not row['network']:
                Warn(
                    f'WARNING: skipping interface "{row["interface"]}" on host "{row["host"]}" - '
                    'interface has an IP but no network')
                continue

            # Each interface dict contains interface name,
            # zone, whether the interface is the default one,
            # and whether the shortname should be assigned
            # to that interface
            host = row['host']
            if host not in hosts:
                hosts[host] = []
            h = {}
            h['ip'] = row['ip']
            h['name'] = row['name']
            h['interface'] = row['interface']
            h['zone'] = zones[row['network']]
            h['default'] = row['default']
            h['shortname'] = False
            if 'options' in row and row['options']:
                options = shlex.split(row['options'])
                for option in options:
                    if option.strip() == 'shortname':
                        h['shortname'] = True

            if self.validateHostInterface(host, h, aliases):
                hosts[host].append(h)

        processed = {}

        for host in hosts:
            # Check if any interface for the host has
            # shortname set to true
            shortname_exists = False
            l = list(filter(lambda x: x['shortname'], hosts[host]))
            if len(l):
                shortname_exists = True

            # For each interface in the host, get ip, zone, and names,
            # default, and shortname info
            for row in hosts[host]:
                ip = row['ip']
                zone = row['zone']
                default = row['default']
                interface = row['interface']
                shortname = row['shortname']
                names = []

                # Get the FQDN
                if zone:
                    names.append('%s.%s' % (host, zone))

                    if row['name']:
                        name_fqdn = f"{row['name']}.{zone}"
                        if name_fqdn not in names:
                            names.append(name_fqdn)

                # If shortname for an interface is set to true,
                # set this interface to have the shortname
                if shortname_exists and shortname:
                    names.append(host)

                    if row['name'] and row['name'] not in names:
                        names.append(row['name'])

                # If shortname is not set for any interface
                # set the default interface to have the shortname
                if default and not shortname_exists:
                    names.append(host)

                    if row['name'] and row['name'] not in names:
                        names.append(row['name'])

                # Add any interface specific aliases
                if host in aliases:
                    if interface in aliases[host]:
                        for alias in aliases[host].get(interface):
                            names.append(alias)

                # check if this is duplicate entry:
                if ip in processed:
                    if processed[ip]['names'] == ' '.join(names):
                        continue

                # Write it all
                text.append('%s\t%s' % (ip, ' '.join(names)))

                if ip not in processed:
                    processed[ip] = {}
                processed[ip]['names'] = '\t'.join(names)

        # Finally, add the hosts.local file to the list
        hostlocal = '/etc/hosts.local'
        if os.path.exists(hostlocal):
            f = open(hostlocal, 'r')
            text.append('\n# Imported from /etc/hosts.local\n')
            h = f.read()
            text.append(h)
            f.close()

        text.append('</stack:file>')
        self.addOutput(None, '\n'.join(text))
        self.endOutput(padChar='', trimOwner=True)
示例#4
0
    def writeDhcpDotConf(self):
        self.addOutput('', '<stack:file stack:name="/etc/dhcp/dhcpd.conf">')

        self.addOutput('', stack.text.DoNotEdit())
        self.addOutput('', '%s' % header)

        # Build a dictionary of DHCPD server addresses
        # for each subnet that serves PXE (DHCP).

        servers = {}
        for row in self.db.select(
                """
			s.name, n.ip from nodes nd, subnets s, networks n
			where s.pxe=TRUE and nd.name=%s
			and n.node=nd.id and s.id=n.subnet
		""", (self.db.getHostname(), )):
            servers[row[0]] = row[1]
            servers['default'] = row[1]

        if len(servers) > 2:
            del servers['default']

        shared_networks = {}
        for (netname, network, netmask, gateway, zone,
             device) in self.db.select(
                 """
			s.name, s.address, s.mask, s.gateway, s.zone, n.device
			from subnets s, networks n
			where pxe=TRUE and node=(select id from nodes where name=%s)
			and subnet=s.id
		""", (self.db.getHostname(), )):

            if self.os == 'sles':
                device = device.split('.')[0].split(':')[0]
                dhchp_settings = (netname, network, netmask, gateway, zone)
                if device in shared_networks:
                    if dhchp_settings not in shared_networks[device]:
                        shared_networks[device].append(dhchp_settings)
                else:
                    shared_networks[device] = [dhchp_settings]

            else:
                self.addOutput('',
                               '\nsubnet %s netmask %s {' % (network, netmask))

                self.addOutput('', '\tdefault-lease-time\t\t1200;')
                self.addOutput('', '\tmax-lease-time\t\t\t1200;')

                ipnetwork = ipaddress.IPv4Network(network + '/' + netmask)
                self.addOutput('', '\toption routers\t\t\t%s;' % gateway)
                self.addOutput('', '\toption subnet-mask\t\t%s;' % netmask)
                self.addOutput(
                    '', '\toption broadcast-address\t%s;' %
                    ipnetwork.broadcast_address)
                self.addOutput('', '}\n')
        #
        # if sles, add shared_network block to interfaces with multiple subnets
        #
        if self.os == 'sles':
            for device in shared_networks.keys():
                sn = shared_networks[device]
                if len(sn) == 1:
                    for (netname, network, netmask, gateway, zone) in sn:
                        self.addOutput(
                            '',
                            '\nsubnet %s netmask %s {' % (network, netmask))

                        self.addOutput('', '\tdefault-lease-time\t\t1200;')
                        self.addOutput('', '\tmax-lease-time\t\t\t1200;')

                        ipnetwork = ipaddress.IPv4Network(network + '/' +
                                                          netmask)
                        self.addOutput('',
                                       '\toption routers\t\t\t%s;' % gateway)
                        self.addOutput('',
                                       '\toption subnet-mask\t\t%s;' % netmask)
                        self.addOutput(
                            '', '\toption broadcast-address\t%s;' %
                            ipnetwork.broadcast_address)
                        self.addOutput('', '}\n')
                else:
                    self.addOutput('', '\nshared-network %s {' % device)
                    for (netname, network, netmask, gateway, zone) in sn:
                        self.addOutput(
                            '',
                            '\n\tsubnet %s netmask %s {' % (network, netmask))

                        self.addOutput('', '\t\tdefault-lease-time\t\t1200;')
                        self.addOutput('', '\t\tmax-lease-time\t\t\t1200;')

                        ipnetwork = ipaddress.IPv4Network(network + '/' +
                                                          netmask)
                        self.addOutput('',
                                       '\t\toption routers\t\t\t%s;' % gateway)
                        self.addOutput(
                            '', '\t\toption subnet-mask\t\t%s;' % netmask)
                        self.addOutput(
                            '', '\t\toption broadcast-address\t%s;' %
                            ipnetwork.broadcast_address)
                        self.addOutput('', '\t}\n')
                    self.addOutput('', '}\n')

        data = {}
        for host in self.call('list.host'):
            data[host['host']] = []

        host_devices = {}
        interfaces = self.call('list.host.interface')
        for interface in interfaces:
            host = interface['host']
            mac = interface['mac']
            ip = interface['ip']
            device = interface['interface']
            channel = interface['channel']

            other_interfaces = [
                iface['interface'] for iface in interfaces
                if iface['host'] == host and iface['interface'] != device
            ]

            if channel:
                if device == 'ipmi' and not ip:
                    Warn(
                        f'WARNING: skipping IPMI interface on host "{host}" - interface has a channel but no IP'
                    )
                    continue
                elif device != 'ipmi' and channel not in other_interfaces:
                    Warn(
                        f'WARNING: skipping interface "{device}" on host "{host}" - '
                        f'interface has channel "{channel}" that does not match any other interface on the host'
                    )
                    continue
            if host in host_devices:
                if device in host_devices[host]:
                    Warn(
                        f'WARNING: skipping interface "{device}" on host "{host}" - duplicate interface detected'
                    )
                    continue
                else:
                    host_devices[host].append(device)
            elif host:
                host_devices[host] = [device]

            if host and mac:
                data[host].append((mac, ip, device))

        for name in data.keys():
            kickstartable = self.str2bool(
                self.getHostAttr(name, 'kickstartable'))
            aws = self.str2bool(self.getHostAttr(name, 'aws'))
            mac = None
            ip = None
            dev = None

            #
            # look for a physical private interface that has an
            # IP address assigned to it.
            #
            for (mac, ip, dev) in data[name]:
                if not ip:
                    try:
                        ip = self.resolve_ip(name, dev)
                    except IndexError:
                        Warn(
                            f'WARNING: skipping interface "{device}" on host "{host}" - duplicate interface detected'
                        )
                        continue
                netname = None
                if ip:
                    r = self.db.select(
                        """
						s.name from subnets s, networks nt, nodes n
						where nt.node=n.id and n.name=%s
						and nt.subnet=s.id and s.pxe=TRUE and nt.ip=%s
					""", (name, ip))

                    if r:
                        (netname, ) = r[0]
                if ip and mac and dev and netname and not aws:
                    self.addOutput('',
                                   '\nhost %s.%s.%s {' % (name, netname, dev))
                    self.addOutput('', '\toption host-name\t"%s";' % name)

                    self.addOutput('', '\thardware ethernet\t%s;' % mac)
                    self.addOutput('', '\tfixed-address\t\t%s;' % ip)

                    if kickstartable:

                        self.addOutput('', filename)
                        server = servers.get(netname)
                        if not server:
                            server = servers.get('default')

                        self.addOutput('', '\tserver-name\t\t"%s";' % server)
                        self.addOutput('', '\tnext-server\t\t%s;' % server)

                    self.addOutput('', '}')

        self.addOutput('', '</stack:file>')