Logo Search packages:      
Sourcecode: uec-provisioning version File versions  Download package

uec.py

#!/usr/bin/python
#
#    uec.py - a basic cgi-bin script for triggering UEC installations
#
#    Copyright (C) 2010 Canonical Ltd.
#
#    Authors: Thierry Carrez <thierry.carrez@canonical.com>
#             Dustin Kirkland <kirkland@canonical.com>
#             Chris Cheney <chris.cheney@canonical.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, version 3 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import os, shutil
import subprocess
import cgi, yaml

# Send out headers
print "Content-Type: text/html\n\n"
print "<html>"
print "<body>"

# Redirect errors to HTML doc
sys.stderr = sys.stdout

# Load CGI fields and configuration
f = cgi.FieldStorage()
hosts_cfg = yaml.load(open("/etc/uec-provisioning/hosts.cfg", "r"))
mirrors_cfg = yaml.load(open("/etc/uec-provisioning/mirrors.cfg", "r"))
webui_cfg = yaml.load(open("/etc/uec-provisioning/webui.cfg", "r"))

mac = {}
try:
      for h in hosts_cfg['hosts']:
            mac[h['ip']] = h['mac']
except:
      print("<b>ERROR</b>: No hosts configured in <code>/etc/uec-provisioning/hosts.cfg</code>")
      sys.exit(0)

#----

# If called with done, unlink file
if f.getfirst('done'):
      try:
            print("Finishing install for %s" % mac[os.environ["REMOTE_ADDR"]])
            os.unlink(os.path.join(webui_cfg['tftp_dir'],"pxelinux.cfg","01-"+mac[os.environ["REMOTE_ADDR"]].replace(":","-")))
      except KeyError:
            print("Unknown IP")
      sys.exit(0)

#----

# If no ip given, send out form
# TODO: Autoselect UDEB based on local repo contents
if f.getfirst('ip') is None:
      print "<form>"
      print "<h2>Host</h2>"
      print "<select name=ip>"
      for i in hosts_cfg["hosts"]:
            print("<option value=\""+i['ip']+"\">"+i['hostname']+"</option>")
      print "</select>"

      print """
<h2>Services</h2>
<input type="checkbox" name="clc" value="1">CLC<br>
<input type="checkbox" name="wc"  value="1">WC<br>
<input type="checkbox" name="cc"  value="1">CC<br>
<input type="checkbox" name="sc"  value="1">SC<br>
<input type="checkbox" name="nc"  value="1">NC<br>
<input type="checkbox" name="manual"  value="1">Manual Installation<br>
"""

      cluster_name = "cluster1"
      if webui_cfg.has_key('cluster_name'):
            cluster_name = webui_cfg['cluster_name']

      if webui_cfg.has_key('ip_range'):
            ip_range = webui_cfg['ip_range']
      else:
            p1 = subprocess.Popen("/usr/lib/uec-provisioning/ip_helper range", shell=True, stdout=subprocess.PIPE)
            output = p1.communicate()[0]
            ip_range = output.rstrip("\n\r")

      print "<h2>Eucalyptus Configuration</h2>"
      print "IP Range: <input name=\"ip_range\" value=\"" + ip_range + "\"<br>"
      print "Cluster Name: <input name=\"cluster_name\" value=\"" + cluster_name + "\"><br>"

      # need to know how to have this fail properly if there are no mirrors defined in file...
      print """
<h2>Mirror Selection</h2>
<select name=mirror>
"""
      print("<option value=\"default\">default</option>")
      if mirrors_cfg.has_key('mirrors'):
            for i in mirrors_cfg["mirrors"]:
                  sel=""
                  if i.has_key('default') and i['default']:
                        sel=" selected "
                  print("<option value=\""+i['name']+ "\"" + 
                        sel +">"+i['name']+"</option>")
      print "</select>"

      print """
<h2>Partition Setup</h2>
<input type="checkbox" name="lvm-full-disk" value="1" checked>Erase disk - Use LVM for full disk<br>
"""

      print """
<h2>Account Setup</h2>
User Fullname: <input name="user-fullname" value="Ubuntu User"><br>
Username: <input name="username" value="ubuntu"><br>
Password: <input name="user-password" value="ubuntu"><br>
<input type="checkbox" name="allow-password-weak" value="true" checked>Allow Weak Password<br>
"""

      if webui_cfg.has_key('developer') and webui_cfg['developer'] == 1:
            print """
<h2>Version</h2>
<input type="checkbox" name="localdeb" value="1">Enable local repository<br>
<input name="euca_udeb" value="1.6.2~bzr1189-0ubuntu2~ppa2"><br>
"""

      print """
<h2>Additional Packages</h2>
<input type="text" name="packages" value="openssh-server">
"""

      print """
<h2>Install</h2>
<input type="submit" name="submit" value="Begin installation">
"""

      print """
</form>
</body>
</html>
"""
      sys.exit(0)

#----

# If we are here, we were called with ip
ip = f.getfirst('ip')
print ("Booting %s(%s) with the following preseed:<br>" % (ip, mac[ip]))

# Write pxelinux config
pxe = open(os.path.join(webui_cfg['tftp_dir'],"pxelinux.cfg","01-%s" % mac[ip].replace(":","-")), "w")
pxe.write("default linux\n")
pxe.write("prompt 1\n")
pxe.write("timeout 20\n")
pxe.write("label linux\n")
pxe.write("\tkernel ubuntu-installer/amd64/linux\n")
pxe.write("\tappend priority=critical %s url=http://%s/preseed/preseed-%s initrd=ubuntu-installer/amd64/initrd.gz root=/dev/rd/0 rw DEBCONF_DEBUG=developer --\n" % (webui_cfg['extra_kern_opt'],webui_cfg['preseed_host'], mac[ip]))
pxe.close()

# Copy preseed model
preseed = os.path.join(webui_cfg['preseed_dir'],"preseed-"+mac[ip])
shutil.copyfile(os.path.join(webui_cfg['preseed_dir'],"preseed"),preseed)
preseed_file = open(preseed, "a")

# Mirror to use
if (f.getfirst('mirror') != "default"):
      for i in mirrors_cfg['mirrors']:
            if i['name'] == f.getfirst('mirror'):
                  preseed_file.write("d-i mirror/country string manual\n")
                  preseed_file.write("d-i mirror/http/directory string %s\n" % i['ubuntu-dir'])
                  preseed_file.write("d-i mirror/http/hostname string %s\n" % i['ubuntu-host'])
                  preseed_file.write("d-i mirror/http/proxy string\n")
                  preseed_file.write("d-i apt-setup/services-select multiselect security\n")
                  preseed_file.write("d-i apt-setup/security_host string %s\n" % i['security-host'])
                  preseed_file.write("d-i apt-setup/security_path string %s\n" % i['security-dir'])
else:
      print("<b>Using default (non-local) mirror.</b><br>")

# Partition the disk
if (f.getfirst('lvm-full-disk')):
      print("<b>Erase disk - Use LVM for full disk</b><br>")
      preseed_file.write("d-i partman/default_filesystem string ext3\n")
      preseed_file.write("d-i partman/choose_partition select finish\n")
      preseed_file.write("d-i partman/confirm boolean true\n")
      preseed_file.write("d-i partman/confirm_nooverwrite boolean true\n")
      preseed_file.write("d-i partman/confirm_write_new_label boolean true\n")
      preseed_file.write("d-i partman-auto/disk string\n")
      preseed_file.write("d-i partman-auto/method string lvm\n")
      preseed_file.write("d-i partman-lvm/device_remove_lvm boolean true\n")
      preseed_file.write("d-i partman-lvm/confirm boolean true\n")
      preseed_file.write("d-i partman-md/device_remove_md boolean true\n")
else:
      print("<b>No paritioning scheme selected. You must provide your own partitioning preseed data.</b><br>")

# User account setup
if (f.getfirst('user-fullname')):
      preseed_file.write("d-i passwd/user-fullname string %s\n" % f.getfirst('user-fullname'))
if (f.getfirst('user-password')):
      preseed_file.write("d-i passwd/user-password password %s\n" % f.getfirst('user-password'))
      preseed_file.write("d-i passwd/user-password-again password %s\n" % f.getfirst('user-password'))
if (f.getfirst('username')):
      preseed_file.write("d-i passwd/username string %s\n" % f.getfirst('username'))
if (f.getfirst('allow-password-weak')):
      preseed_file.write("d-i user-setup/allow-password-weak boolean %s\n" % f.getfirst('allow-password-weak'))

# Additional packages
if (f.getfirst('packages')):
      preseed_file.write("d-i pkgsel/include string %s\n" % f.getfirst('packages'))

# UEC specific
preseed_file.write("d-i base-installer/kernel/override-image string linux-server\n")
preseed_file.write("d-i debian-installer/splash boolean false\n")
preseed_file.write("d-i pkgsel/install-language-support boolean false\n")
preseed_file.write("d-i pkgsel/language-pack-patterns string\n")

# Add values for local deb
if webui_cfg.has_key('developer') and webui_cfg['developer'] == 1:
      # Check if localdeb exists
      if (f.getfirst('localdeb')):
            euca_udeb = f.getfirst('euca_udeb')
            location = '%s/%s/eucalyptus-udeb_%s_amd64.udeb' % (webui_cfg['localdeb_dir'], webui_cfg['localdeb_dist'],euca_udeb)
            if (not os.path.exists(location)):
                  print "<b>ERROR: %s doesn't exist</b>\n" % euca_udeb
            else:
                  preseed_file.write("d-i preseed/early_command string anna net-retriever && wget %s/%s/eucalyptus-udeb_%s_amd64.udeb && udpkg --unpack eucalyptus-udeb_%s_amd64.udeb\n" % (webui_cfg['localdeb'], webui_cfg['localdeb_dist'], euca_udeb, euca_udeb))
                  preseed_file.write("d-i apt-setup/local0/repository string %s/ %s/\n" % (webui_cfg['localdeb'], webui_cfg['localdeb_dist']))
                  preseed_file.write("d-i apt-setup/local0/comment string Local\n") 
                  preseed_file.write("d-i apt-setup/local0/key string %s\n" % webui_cfg['localdeb_key']) 

# Add values for services
services = ""
if (f.getfirst('nc')):
      services += "node, "
      preseed_file.write("d-i anna/choose_modules string eucalyptus-udeb\n")
if (f.getfirst('clc')):
      services += "cloud, "
      preseed_file.write("d-i anna/choose_modules string eucalyptus-udeb\n")
if (f.getfirst('wc')):
      services += "walrus, "
      preseed_file.write("d-i anna/choose_modules string eucalyptus-udeb\n")
if (f.getfirst('cc')):
      services += "cluster, "
      preseed_file.write("d-i anna/choose_modules string eucalyptus-udeb\n")
      preseed_file.write("eucalyptus-udeb eucalyptus/publicips string %s\n" % f.getfirst('ip_range'))
      preseed_file.write("eucalyptus-common eucalyptus/cluster-name string %s\n" % f.getfirst('cluster_name'))
if (f.getfirst('sc')):
      services += "storage, "
      preseed_file.write("d-i anna/choose_modules string eucalyptus-udeb\n")

if services.endswith(", "):
      services = services[:-2]
if (services != ""):
      preseed_file.write("eucalyptus-udeb eucalyptus/install-mode multiselect %s\n" % services)

# Script specific
preseed_file.write("d-i preseed/late_command string wget http://%s%s?done=1\n" % (os.environ["SERVER_NAME"], os.environ["SCRIPT_NAME"]))

# Add extra_preseed from configuration, if any
if webui_cfg.has_key('extra_preseed'):
      for line in webui_cfg['extra_preseed']:
            preseed_file.write(line+"\n")

preseed_file.close()

# Send wake on LAN
# TODO: avoid system call
os.system("powerwake %s" % mac[ip])

# Dump preseed for review
print("<pre>")
preseed_file=open(preseed,"r")
for line in preseed_file:
      print(line[:-1])
preseed_file.close()
print('''
</pre>
</body>
</html>
''')

Generated by  Doxygen 1.6.0   Back to index