#!/usr/bin/env python # # Copyright (C) 2002 Cluster File Systems, Inc. # Author: Robert Read # This file is part of Lustre, http://www.lustre.org. # # Lustre is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public # License as published by the Free Software Foundation. # # Lustre 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Lustre; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # For all the OST/MDSs that are primary on the --primary node, set # them to be active on --active if that OST is available on --active. # # Make the active node the active node for all devices it shares with the # old. The bulk of this code is for figuring out which devices to # change, and what to change them to. # XXX add error checking # XXX make this code less ugly import sys, getopt, types import string, os import ldap from stat import S_IROTH, S_IRGRP PYMOD_DIR = "/usr/lib/lustre/python" def development_mode(): base = os.path.dirname(sys.argv[0]) if os.access(base+"/Makefile.am", os.R_OK): return 1 return 0 if not development_mode(): sys.path.append(PYMOD_DIR) import Lustre PARAM = Lustre.Options.PARAM lactive_options = [ ('ldapurl',"LDAP server URL", PARAM, "ldap://localhost"), ('config', "Cluster config name used for LDAP query", PARAM), ('group', "The group of devices to update", PARAM), ('active', "The active node name", PARAM), ('pwfile', "File containing password", PARAM), ] def fatal(*args): msg = string.join(map(str,args)) print "! " + msg sys.exit(1) cl = Lustre.Options("lactive","", lactive_options) config, args = cl.parse(sys.argv[1:]) if not (config.group or config.active): fatal("Must specify both group and active node.") if not config.config: fatal("Missing config") if config.pwfile: try: pwperm = os.stat(config.pwfile)[0] pwreadable = pwperm & (S_IRGRP | S_IROTH) if pwreadable: if pwreadable == (S_IRGRP | S_IROTH): readable_by = "group and others" elif pwreadable == S_IRGRP: readable_by = "group" else: readable_by = "others" print "WARNING: Password file %s is readable by %s" % ( config.pwfile, readable_by) pwfile = open(config.pwfile, "r") pw = string.strip(pwfile.readline()) pwfile.close() except Exception, e: fatal("Can't read secret from pwfile %s: %s" % (config.pwfile, e)) else: print "no pwfile specified, binding anonymously" pw = "" base = "config=%s,fs=lustre" % (config.config,) db = Lustre.LustreDB_LDAP('', {}, base=base, pw = pw, url = config.ldapurl) active_node = db.lookup_name(config.active) if not active_node: fatal(config.active, "node not found in database.") devices = db.get_group(config.group) if len(devices) < 0: fatal("no devices found for group", config.group) # for all devices in group # lookup device in active node # update the active device for tgtuuid in devices: active_uuid = db.get_active_dev(tgtuuid) new_active_uuid = active_node.get_tgt_dev(tgtuuid) if active_uuid != new_active_uuid: print ("%s: changing active %s to %s:%s" % (tgtuuid, active_uuid, config.active, new_active_uuid)) db.update_active(tgtuuid, new_active_uuid)