summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Brestick <brestick@mcs.anl.gov>2008-07-15 16:24:20 +0000
committerAndrew Brestick <brestick@mcs.anl.gov>2008-07-15 16:24:20 +0000
commit24a426e80ca856dbc9f905a663ad66c551356de9 (patch)
tree924eec48cc5b8322954f4d639855af7161fd0135
parentbc0f8dead7dd4e98643ee7bd3a1a50011d8c29a9 (diff)
downloadbcfg2-24a426e80ca856dbc9f905a663ad66c551356de9.tar.gz
bcfg2-24a426e80ca856dbc9f905a663ad66c551356de9.tar.bz2
bcfg2-24a426e80ca856dbc9f905a663ad66c551356de9.zip
experimental breadboard plugin
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@4793 ce84e21b-d406-0410-9b95-82705330c041
-rw-r--r--src/lib/Server/Plugins/BB.py170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/lib/Server/Plugins/BB.py b/src/lib/Server/Plugins/BB.py
new file mode 100644
index 000000000..e7f016a76
--- /dev/null
+++ b/src/lib/Server/Plugins/BB.py
@@ -0,0 +1,170 @@
+'''BB Plugin'''
+
+import Bcfg2.Server.Plugin
+import lxml.etree
+import sys, os
+from socket import gethostbyname
+
+PROFILE_MAP = {"ubuntu-i386":"compute-node",
+ "ubuntu-amd64":"compute-node-amd64",
+ "fc6":"fc6-compute-node",
+ "peta":"pvfs-server",
+ "bbsto":"fileserver",
+ "bblogin":"head-node"}
+
+
+class BB(Bcfg2.Server.Plugin.GeneratorPlugin,
+ Bcfg2.Server.Plugin.StructurePlugin,
+ Bcfg2.Server.Plugins.Metadata.Metadata,
+ Bcfg2.Server.Plugin.DirectoryBacked):
+ '''BB Plugin handles bb node configuration'''
+
+ __name__ = 'BB'
+
+ def __init__(self, core, datastore):
+ Bcfg2.Server.Plugin.GeneratorPlugin.__init__(self, core, datastore)
+ try:
+ Bcfg2.Server.Plugin.DirectoryBacked.__init__(self, self.data, self.core.fam)
+ except OSError, ioerr:
+ self.logger.error("Failed to load BB repository from %s" % (self.data))
+ self.logger.error(ioerr)
+ raise Bcfg2.Server.Plugin.PluginInitError
+ Bcfg2.Server.Plugins.Metadata.Metadata.__init__(self, core, datastore, False)
+ print self.addresses
+ self.Entries = {'ConfigFile':{'/etc/security/limits.conf':self.gen_limits,
+ '/root/.ssh/authorized_keys':self.gen_root_keys,
+ '/etc/sudoers':self.gen_sudoers,
+ '/etc/dhcp3/dhcpd.conf':self.gen_dhcpd}}
+ self.nodes = {}
+
+ def gen_dhcpd(self, entry, metadata):
+ '''Generate dhcpd.conf'''
+ entry.text = "host %s {\n" % metadata.hostname
+ host = metadata.hostname.split('.')[0]
+ if self.nodes[host].has_key('loader'):
+ entry.text += " filename %s;\n" % self.nodes[host]['loader']
+ entry.text += " hardware ethernet %s;\n" % (self.nodes[host]
+ ['mac'])
+ try:
+ entry.text += " fixed-address %s;\n}" % \
+ gethostbyname(metadata.hostname)
+ except:
+ sys.stderr.write("LOOKUP failed for %s\n" % (metadata.hostname))
+ perms = {'owner':'root', 'group':'root', 'perms':'644'}
+ [entry.attrib.__setitem__(key, value) for (key, value)
+ in perms.iteritems()]
+
+ def gen_root_keys(self, entry, metadata):
+ '''Build /root/.ssh/authorized_keys entry'''
+ users = self.get_users(metadata)
+ rdata = self.entries
+ entry.text = "".join([rdata["%s.key" % user].data for user
+ in users if rdata.has_key("%s.key" % user)])
+ perms = {'owner':'root', 'group':'root', 'perms':'0600'}
+ [entry.attrib.__setitem__(key, value) for (key, value)
+ in perms.iteritems()]
+
+ def gen_sudoers(self, entry, metadata):
+ '''Build /etc/sudoers entry'''
+ users = self.get_users(metadata)
+ entry.text = self.entries['static.sudoers'].data
+ entry.text += "".join(["%s ALL=(ALL) ALL\n" % user
+ for user in users])
+ perms = {'owner':'root', 'group':'root', 'perms':'0440'}
+ [entry.attrib.__setitem__(key, value) for (key, value)
+ in perms.iteritems()]
+
+ def gen_limits(self, entry, metadata):
+ '''Build /etc/security/limits.conf entry'''
+ users = self.get_users(metadata)
+ entry.text = self.entries["static.limits.conf"].data
+ perms = {'owner':'root', 'group':'root', 'perms':'0600'}
+ [entry.attrib.__setitem__(key, value) for (key, value) in perms.iteritems()]
+ entry.text += "".join(["%s hard maxlogins 1024\n" % uname for uname in users])
+ if "*" not in users:
+ entry.text += "* hard maxlogins 0\n"
+
+ def get_users(self, metadata):
+ '''Get users associated with a specific host'''
+ users = []
+ for host, host_dict in self.nodes.iteritems():
+ if host == metadata.hostname.split('.')[0]:
+ if host_dict.has_key('user'):
+ if host_dict['user'] != "none":
+ users.append(host_dict['user'])
+ return users
+
+ def BuildStructures(self, metadata):
+ '''Update build/boot state when client gets configuration'''
+ try:
+ host_attr = self.nodes[metadata.hostname.split('.')[0]]
+ except KeyError:
+ self.logger.error("failed to find metadata for host %s"
+ % metadata.hostname)
+ return []
+ if host_attr['action'].startswith("build"):
+ # make new action string
+ action = ""
+ if host_attr['action'] == "build":
+ action = "boot"
+ else:
+ action = host_attr['action'].replace("build", "boot", 1)
+ # write changes to file
+ bb_tree = lxml.etree.parse(self.entries["bb.xml"])
+ nodes = bb_tree.getroot().findall(".//Node")
+ for node in nodes:
+ if node.attrib['name'] == metadata.hostname.split('.')[0]:
+ node.attrib['action'] = action
+ break
+ bb_tree.write("%s/%s" % (self.data, 'bb.xml'))
+ return []
+
+ def HandleEvent(self, event=None):
+ '''Handle events'''
+ Bcfg2.Server.Plugin.DirectoryBacked.HandleEvent(self, event)
+ # send events to groups.xml back to Metadata plugin
+ if event and "groups.xml" == event.filename:
+ Bcfg2.Server.Plugins.Metadata.Metadata.HandleEvent(self, event)
+ # handle events to bb.xml
+ if event and "bb.xml" == event.filename:
+ bb_tree = lxml.etree.parse(self.entries["bb.xml"])
+ root = bb_tree.getroot()
+ elements = root.findall(".//Node")
+ for node in elements:
+ host = node.attrib['name']
+ node_dict = node.attrib
+ if node.findall("Interface"):
+ node_dict['mac'] = node.findall("Interface")[0].attrib['mac']
+ # populate self.clients dict
+ full_hostname = host + ".mcs.anl.gov"
+ profile = ""
+ # need to translate image/action into profile name
+ if "ubuntu" in node_dict['action']:
+ if "amd64" in node_dict['action']:
+ profile = PROFILE_MAP["ubuntu-amd64"]
+ else:
+ profile = PROFILE_MAP["ubuntu-i386"]
+ elif "fc6" in node_dict['action']:
+ profile = PROFILE_MAP["fc6"]
+ elif "peta" in host:
+ profile = PROFILE_MAP["peta"]
+ elif "bbsto" in host:
+ profile = PROFILE_MAP["bbsto"]
+ elif "bblogin" in host:
+ profile = PROFILE_MAP["head-node"]
+ else:
+ profile = "basic"
+ self.clients[full_hostname] = profile
+ # check links in tftpboot
+ mac = node_dict['mac'].replace(':','-').lower()
+ linkname = "/tftpboot/pxelinux.cfg/01-%s" % (mac)
+ self.nodes[host] = node_dict
+ try:
+ if os.readlink(linkname) != node_dict['action']:
+ os.unlink(linkname)
+ os.symlink(node_dict['action'], linkname)
+ except OSError:
+ self.logger.error("failed to find link for mac address %s" % mac)
+ continue
+
+