228 lines
8 KiB
Python
Executable file
228 lines
8 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# hardware-reinstall - Prepare a physical box in FI for re-install.
|
|
# (c) 2012 Red Hat, Inc.
|
|
# Ricky Elrod <codeblock@fedoraproject.org>
|
|
# GPLv2+
|
|
|
|
import os
|
|
import sys
|
|
import urllib
|
|
import socket
|
|
import subprocess
|
|
import shlex
|
|
import platform
|
|
from optparse import OptionParser
|
|
|
|
parser = OptionParser(
|
|
description='Prepare a physical box in FI for re-install.')
|
|
parser.add_option('-n',
|
|
'--noop',
|
|
action='store_true',
|
|
help="Don't actually modify/download anything, just "
|
|
"output stuff.")
|
|
parser.add_option('-y',
|
|
'--yes',
|
|
action='store_true',
|
|
default=False,
|
|
dest="yes",
|
|
help="Don't prompt to confirm, just do it.")
|
|
parser.add_option('--ip',
|
|
help="Override the IP of the box (passed to Grubby)")
|
|
parser.add_option('--gw',
|
|
help="Override the Gateway of the box (passed to Grubby)",
|
|
dest='gateway')
|
|
parser.add_option('--nm',
|
|
help="Override the Netmask of the box (passed to Grubby)",
|
|
dest='netmask')
|
|
parser.add_option('--dns',
|
|
help="Comma-delimited list of DNS resolvers (passed to "
|
|
"Grubby)",
|
|
dest='dns_resolvers')
|
|
parser.add_option('--ks-file',
|
|
help="Set the kickstart file to use (default:"
|
|
"hardware-rhel-6-nohd)",
|
|
default='hardware-rhel-6-nohd',
|
|
dest='ks_file')
|
|
(options, args) = parser.parse_args()
|
|
|
|
if options.yes and options.noop:
|
|
print "Don't ask AND don't do anything? Cmon"
|
|
sys.exit(1)
|
|
|
|
# 0. Get our hostname/primary ip
|
|
# Get our primary IP by resolving our hostname.
|
|
if options.ip:
|
|
if not options.netmask:
|
|
print 'You gave a custom IP and should specify a custom netmask too.'
|
|
sys.exit(1)
|
|
primary_ip = options.ip
|
|
else:
|
|
primary_ip = socket.gethostbyname(socket.gethostname())
|
|
|
|
# so - anaconda sometimes doesn't seem to listen to our dns
|
|
# when fetching kickstarts, etc - so if we give the ip of the host
|
|
# if we're in 10.5.X network (phx2) then things just work.
|
|
if primary_ip.startswith('10.5.'):
|
|
basehost = "http://10.5.126.23/"
|
|
else:
|
|
basehost = "http://infrastructure.fedoraproject.org/"
|
|
|
|
arch = platform.machine()
|
|
VMLINUZ_URL = '%srepo/rhel/RHEL6-%s/images/pxeboot/vmlinuz' % (basehost, arch)
|
|
INITRD_URL = '%srepo/rhel/RHEL6-%s/images/pxeboot/initrd.img' % (basehost,
|
|
arch)
|
|
|
|
# 1. Grab initrd and vmlinuz and throw them in /boot
|
|
# FIXME - more error catching here
|
|
if not options.noop:
|
|
print 'Fetching vmlinuz'
|
|
urllib.urlretrieve(VMLINUZ_URL, "/boot/vmlinuz-install")
|
|
|
|
print 'Fetching initrd'
|
|
urllib.urlretrieve(INITRD_URL, "/boot/initrd-install.img")
|
|
|
|
|
|
# 2. Find our network info.
|
|
if options.netmask:
|
|
primary_netmask = options.netmask
|
|
|
|
# We still have to get the MAC address, of the primary NIC
|
|
# even if we specify a custom IP/NM.
|
|
cmd = subprocess.Popen('/sbin/ifconfig', stdout=subprocess.PIPE)
|
|
stdout = cmd.communicate()[0]
|
|
i = 0
|
|
lines = stdout.split("\n")
|
|
for line in lines:
|
|
if socket.gethostbyname(socket.gethostname()) in line:
|
|
# Somewhere between EL6 and F17, ifconfig output has changed.
|
|
# We accommodate for both.
|
|
if ':' in line:
|
|
# We are EL6
|
|
if not options.netmask:
|
|
# inet addr:10.5.127.51 Bcast:10.5.127.255 Mask:255.255.255.0
|
|
primary_netmask = line.split('Mask:')[1]
|
|
|
|
# On EL6 MAC addr is always one line before the IP address line
|
|
primary_mac = lines[i - 1].split('HWaddr ')[1]
|
|
else:
|
|
# We are likely something newer
|
|
if not options.netmask:
|
|
# inet 10.10.10.113 netmask 255.255.255.0 broadcast
|
|
# 10.10.10.255 # (cont. from above comment)
|
|
primary_netmask = line.split('netmask ')[1].split(' ')[0]
|
|
|
|
# On newer things, life gets harder. We have to continue
|
|
# parsing lines until we get one with 'ether ' in it.
|
|
# The range is the line we're on now -> the last line.
|
|
for y in xrange(i, len(lines) - 1):
|
|
if 'ether ' in lines[y]:
|
|
primary_mac = lines[y].split('ether ')[1].split(' ')[0]
|
|
break
|
|
break
|
|
i += 1
|
|
|
|
# Gateway
|
|
if options.gateway:
|
|
primary_gateway = options.gateway
|
|
else:
|
|
cmd = subprocess.Popen(['/sbin/ip', 'route'], stdout=subprocess.PIPE)
|
|
stdout = cmd.communicate()[0]
|
|
for line in stdout.split("\n"):
|
|
if 'default' in line:
|
|
# default via 10.10.10.1 dev wlan0 proto static
|
|
primary_gateway = line.split('via ')[1].split(' ')[0]
|
|
break
|
|
|
|
# And DNS servers
|
|
if options.dns_resolvers:
|
|
dns_resolvers = options.dns_resolvers
|
|
else:
|
|
dns_servers = []
|
|
with open('/etc/resolv.conf', 'r') as f:
|
|
for line in f.readlines():
|
|
if 'nameserver' in line:
|
|
dns = line.split(' ')
|
|
if len(dns) == 2:
|
|
dns_servers.append(dns[1].strip())
|
|
dns_resolvers = ','.join(dns_servers)
|
|
|
|
print '-' * 30
|
|
print 'Primary IP: ' + primary_ip
|
|
print 'Primary Netmask: ' + primary_netmask
|
|
print 'Primary Gateway: ' + primary_gateway
|
|
print 'Primary MAC Address: ' + primary_mac
|
|
print 'DNS Resolvers: ' + dns_resolvers
|
|
print '-' * 30
|
|
|
|
# 3. Construct the grubby line.
|
|
# grubby --add-kernel=/boot/vmlinuz-install \
|
|
# --args="ks=http://infrastructure.fedoraproject.org/\
|
|
# repo/rhel/ks/hardware-rhel-6-nohd \
|
|
# repo=http://infrastructure.fedoraproject.org/repo/rhel/RHEL6-x86_64/ \
|
|
# ksdevice=link ip=$IP gateway=$GATEWAY netmask=$NETMASK dns=$DNS" \
|
|
# --title="install el6" --initrd=/boot/initrd-install.img
|
|
grubby_command = '/sbin/grubby --add-kernel=/boot/vmlinuz-install ' \
|
|
'--args="ks=%srepo/rhel/ks/%s ksdevice=%s ' \
|
|
'ip=%s gateway=%s netmask=%s dns=%s repo=%srepo/rhel/RHEL6-x86_64/" ' \
|
|
'--title="install el6" --initrd=/boot/initrd-install.img' % (basehost,
|
|
options.ks_file,
|
|
primary_mac,
|
|
primary_ip,
|
|
primary_gateway,
|
|
primary_netmask,
|
|
dns_resolvers,
|
|
basehost)
|
|
|
|
print 'This grubby command seems like it will work:'
|
|
print '-' * 30
|
|
print grubby_command
|
|
print '-' * 30
|
|
print 'Check the command and be sure that it looks correct.'
|
|
|
|
if not options.noop:
|
|
if not options.yes:
|
|
print 'Type yes to continue, anything else to abort.'
|
|
print 'By continuing, I will run the above command.'
|
|
if raw_input('> ') != 'yes':
|
|
print 'Removing downloaded files.'
|
|
os.unlink('/boot/vmlinuz-install')
|
|
os.unlink('/boot/initrd-install.img')
|
|
print 'Aborting.'
|
|
sys.exit(1)
|
|
|
|
cmd = subprocess.Popen(shlex.split(grubby_command),
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE)
|
|
stdout, stderr = cmd.communicate()
|
|
if stdout:
|
|
print stdout
|
|
if stderr:
|
|
print "[STDERR output]"
|
|
print stderr
|
|
|
|
if not options.yes:
|
|
raw_input(
|
|
'Examine the above output, if it looks sane, press enter to '
|
|
'continue.')
|
|
print 'The next command I will run is:'
|
|
print 'echo "savedefault --default=0 --once" | grub --batch'
|
|
|
|
if not options.noop:
|
|
cmd = subprocess.Popen(['/sbin/grub', '--batch'],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT)
|
|
stdout = cmd.communicate(input='savedefault --default=0 --once\n')
|
|
print stdout[0]
|
|
|
|
print 'Done.'
|
|
print 'When you are ready, run: `shutdown -r now` to reboot.'
|
|
print 'Go here:'
|
|
print 'http://infrastructure.fedoraproject.org/infra/docs/kickstarts.txt'
|
|
print 'And control-f for "Installation" (no quotes). Continue from there.'
|
|
|
|
if options.noop:
|
|
print '-' * 30
|
|
print 'Script was run in "no-op" mode - none of the above commands ' \
|
|
'actually ran.'
|
|
print '-' * 30
|