From 24a426e80ca856dbc9f905a663ad66c551356de9 Mon Sep 17 00:00:00 2001 From: Andrew Brestick Date: Tue, 15 Jul 2008 16:24:20 +0000 Subject: experimental breadboard plugin git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@4793 ce84e21b-d406-0410-9b95-82705330c041 --- src/lib/Server/Plugins/BB.py | 170 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 src/lib/Server/Plugins/BB.py (limited to 'src/lib/Server') 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 + + -- cgit v1.2.3-1-g7c22