else:
from fcntl import F_GETFL, F_SETFL
-PYMOD_DIR = ["/usr/lib/lustre/python", "/usr/lib64/lustre/python"]
+PYMOD_DIR = ["/usr/lib64/lustre/python", "/usr/lib/lustre/python"]
def development_mode():
base = os.path.dirname(sys.argv[0])
print string.strip(s)
def debug(*args):
+ # apparently, (non)execution of the following line affects mds device
+ # startup order (e.g. two mds's using loopback devices), so always do it.
+ msg = string.join(map(str,args))
if config.verbose:
- msg = string.join(map(str,args))
print msg
# ack, python's builtin int() does not support '0x123' syntax.
self.port = port
self.net_type = net_type
self.flags = ''
+ if config.allow_unprivileged_port:
+ self.flags = '-p'
def pidfile(self):
return "/var/run/%s-%d.pid" % (self.command, self.port)
def add_peer(self, net_type, nid, hostaddr, port):
""" noop """
-# if net_type in ('tcp','openib','ra') and not config.lctl_dump:
+# if net_type in ('tcp','openib','ra','cray_kern_nal') and not config.lctl_dump:
# cmds = """
# network %s
# add_peer %s %s %d
def connect(self, srv):
self.add_uuid(srv.net_type, srv.nid_uuid, srv.nid)
-# if srv.net_type in ('tcp','openib','iib','vib','ra') and not config.lctl_dump:
-# if srv.hostaddr[0]:
-# hostaddr = string.split(srv.hostaddr[0], '/')[0]
-# self.add_peer(srv.net_type, srv.nid, hostaddr, srv.port)
+# if config.lctl_dump:
+# return
+#
+# if srv.net_type in ('tcp',):
+# host = socket.gethostname()
+# node_list = []
+# if config.node:
+# node_list.append(config.node)
+# else:
+# if len(host) > 0:
+# node_list.append(host)
+# node_list.append('localhost')
+#
+# node_db = None
+# for h in node_list: # we are quite sure we can find the node_db
+# node_db = toplustreDB.lookup_name(h, 'node')
+# if node_db:
+# break
+#
+# hostaddr = None
+# for netuuid in node_db.get_networks():
+# localnet = toplustreDB.lookup(netuuid)
+# localnet = Network(localnet)
+# if localnet.net_type != 'tcp':
+# continue # only tcp understands multiple hostaddrs
+#
+# # always true for tcp network
+# if localnet.hostaddr[0] and srv.hostaddr[0]:
+# for lnet in localnet.hostaddr:
+# for pnet in srv.hostaddr:
+# if srv.netmatch(lnet, pnet) != 0:
+# hostaddr = string.split(pnet, '/')[0]
+# #find one is enough, should break the top-most loop
+# break
+# if hostaddr: break
+# else: # can't find a match
+# hostaddr = string.split(srv.hostaddr[0], '/')[0]
+# break
+#
+# self.add_peer(srv.net_type, srv.nid, hostaddr, srv.port)
+#
+# if srv.net_type in ('openib','iib','vib','ra'):
+# self.add_peer(srv.net_type, srv.nid, srv.hostaddr[0], srv.port)
# Recover a device
def recover(self, dev_name, new_conn):
def abort_recovery(self, name):
cmds = """
ignore_errors
- device %s
+ device $%s
abort_recovery
quit""" % (name)
self.run(cmds)
panic("Unable to build fs:", dev, string.join(out))
# enable hash tree indexing on fsswe
if fstype in ('ext3', 'extN', 'ldiskfs'):
- htree = 'echo "feature FEATURE_C5" | debugfs -w'
+ htree = 'tune2fs -O dir_index'
(ret, out) = run (htree, dev)
if ret:
panic("Unable to enable htree:", dev)
loop='/dev/loop'
return loop
-# find loop device assigned to thefile
+# find loop device assigned to the file
def find_loop(file):
loop = loop_base()
for n in xrange(0, MAX_LOOP_DEVICES):
# don't need a real nid for config log - client will replace (bug5619)
if config.record:
local = "54321"
- elif net_type in ('tcp','openib','iib','vib','ra'):
+ elif net_type in ('tcp','openib','iib','vib','ra','cray_kern_nal'):
if ':' in wildcard:
iface, star = string.split(wildcard, ':')
local = if2addr(iface)
- if not local:
- panic("unable to determine ip for:", wildcard)
+ elif net_type == 'vib':
+ local = if2addr('ipoib0')
else:
host = socket.gethostname()
local = socket.gethostbyname(host)
+ if not local:
+ panic("unable to determine ip for:", wildcard)
elif net_type == 'elan':
# awk '/NodeId/ { print $2 }' 'sys_get_elan_position_file()'
f = sys_get_elan_position_file()
def sys_get_branch():
"""Returns kernel release"""
- try:
- fp = open('/proc/sys/kernel/osrelease')
- lines = fp.readlines()
- fp.close()
-
- for l in lines:
- version = string.split(l)
- a = string.split(version[0], '.')
- return a[0] + '.' + a[1]
- except IOError, e:
- log(e)
- return ""
+ return os.uname()[2][:3]
def mod_loaded(modname):
"""Check if a module is already loaded. Look in /proc/modules for it."""
ip = string.split(hostaddr, '/')[0]
lctl.del_interface(self.net_type, ip)
+ def my_inet_aton(self, net):
+ split = net.split('.')
+ if len(split) != 4:
+ raise ValueError, "Invalid IPv4 address %s" % net
+
+ naddr = 0
+ i = 0
+ for n in split:
+ try:
+ naddr = naddr + int(n) * (256 ** (3-i))
+ except:
+ raise ValueError, "Invalid IPv4 address %s" % net
+ i = i + 1
+ return naddr
+
+ def tointAddr(self, net):
+ """convert a net address/mask into (numeric-address, bitmap-mask)"""
+ try:
+ addr, mask = string.split(net, '/')
+ except:
+ addr = net
+ mask = 24 #eeb told me that kernel uses this value by default
+
+ try:
+ mask = int(mask)
+ assert(mask >= 1 and mask <= 32)
+ mask = bitmap_32(mask)
+ except:
+ try:
+ mask = self.my_inet_aton(mask)
+ except:
+ raise ValueError("Invalid netmask %s" % str(mask))
+
+ try:
+ addr = socket.gethostbyname(addr)
+ naddr = self.my_inet_aton(addr)
+ except:
+ raise ValueError("Invalid host %s" % addr)
+
+ return (naddr, mask)
+
+ def netmatch(self, net1, net2):
+ # XXX this is only valid for IPv4 address
+ try:
+ addr1, mask1 = self.tointAddr(net1)
+ addr2, mask2 = self.tointAddr(net2)
+ except:
+ return 0
+
+ if addr1 & mask1 == addr2 & mask2:
+ return 1
+ return 0
+
+def bitmap_32(n):
+ """n should be in [1, 32]"""
+ if n < 0 or n > 32:
+ raise ValueError("A number between 1 and 32 is expected. (not %d)" % n)
+ return (-1) << (32-n)
+
class RouteTable(Module):
def __init__(self,db):
Module.__init__(self, 'ROUTES', db)
self.stripe_off = self.db.get_val_int('stripeoffset', 0)
self.pattern = self.db.get_val_int('stripepattern', 0)
self.devlist = []
- self.stripe_cnt = 0
+ self.stripe_cnt = self.db.get_val_int('stripecount', 1)
self.osclist = []
self.desc_uuid = self.uuid
self.uuid = generate_client_uuid(self.name)
self.fs_name = fs_name
+ # settings below here won't be seen by the MDSDEV code!
if config_only:
self.config_only = 1
return
index = index + 1
if self.osclist == []:
panic('No OSCs configured for LOV')
- self.stripe_cnt = self.db.get_val_int('stripecount', len(self.devlist))
+ debug('dbg LOV __init__:', self.osclist, self.devlist, self.stripe_cnt)
def prepare(self):
debug('dbg LOV prepare')
lctl.lov_add_obd(self.name, self.uuid, target_uuid, index, gen)
def cleanup(self):
- for (osc, index, gen, active) in self.osclist:
- target_uuid = osc.target_uuid
- if is_prepared(osc.name):
- lctl.lov_del_obd(self.name, self.uuid, target_uuid, index, gen)
- osc.cleanup()
if is_prepared(self.name):
Module.cleanup(self)
+ for (osc, index, gen, active) in self.osclist:
+ osc.cleanup()
if self.config_only:
panic("Can't clean up config_only LOV ", self.name)
self.devpath = self.db.get_val('devpath','')
self.size = self.db.get_val_int('devsize', 0)
self.journal_size = self.db.get_val_int('journalsize', 0)
+
self.fstype = self.db.get_val('fstype', '')
+ if sys_get_branch() == '2.4' and self.fstype == 'ldiskfs':
+ self.fstype = 'ext3'
+ elif sys_get_branch() == '2.6' and self.fstype == 'ext3':
+ self.fstype = 'ldiskfs'
+
self.nspath = self.db.get_val('nspath', '')
self.mkfsoptions = '-i 4096 ' + self.db.get_val('mkfsoptions', '')
self.mountfsoptions = self.db.get_val('mountfsoptions', '')
self.active = 1
else:
self.active = 0
- if self.active and config.group and config.group != mds.get_val('group'):
+ if self.active and config.group and config.group != mds.get_val('group', mds.get_val('name')):
self.active = 0
self.inode_size = self.db.get_val_int('inodesize', 0)
if (lov.stripe_cnt > 0):
stripe_count = lov.stripe_cnt
else:
- stripe_count = len(lov.devlist)
+ stripe_count = 1
if stripe_count > 77:
self.inode_size = 4096
elif stripe_count > 34:
self.inode_size = 2048
elif stripe_count > 13:
self.inode_size = 1024
- elif stripe_count > 2:
- self.inode_size = 512
+ #elif stripe_count < 3:
+ # self.inode_size = 256
else:
- self.inode_size = 256
+ self.inode_size = 512
+
+ debug('stripe_count %d, inode_size %d', stripe_count, self.inode_size)
self.target_dev_uuid = self.uuid
self.uuid = target_uuid
noexec_opt = ('', '-n')
ret, out = run (sys.argv[0],
noexec_opt[old_noexec == 1],
- " -v --record --nomod",
+ " --record --nomod",
"--record_log", client_name,
"--record_device", self.name,
"--node", client_name,
self.size = self.db.get_val_int('devsize', 0)
self.journal_size = self.db.get_val_int('journalsize', 0)
self.inode_size = self.db.get_val_int('inodesize', 0)
- self.mkfsoptions = '-i 16384 ' + self.db.get_val('mkfsoptions', '')
+ self.mkfsoptions = self.db.get_val('mkfsoptions', '')
+ # Allocate fewer inodes on large OST devices. Most filesystems
+ # can be much more aggressive than this, but by default we can't.
+ if self.size > 1000000:
+ self.mkfsoptions = '-i 16384 ' + self.mkfsoptions
self.mountfsoptions = self.db.get_val('mountfsoptions', '')
+
self.fstype = self.db.get_val('fstype', '')
+ if sys_get_branch() == '2.4' and self.fstype == 'ldiskfs':
+ self.fstype = 'ext3'
+ elif sys_get_branch() == '2.6' and self.fstype == 'ext3':
+ self.fstype = 'ldiskfs'
+
self.nspath = self.db.get_val('nspath', '')
target_uuid = self.db.get_first_ref('target')
ost = self.db.lookup(target_uuid)
self.active = 1
else:
self.active = 0
- if self.active and config.group and config.group != ost.get_val('group'):
+ if self.active and config.group and config.group != ost.get_val('group', ost.get_val('name')):
self.active = 0
self.target_dev_uuid = self.uuid
self.target_name = tgtdb.getName()
self.target_uuid = tgtdb.getUUID()
self.db = tgtdb
- self.backup_targets = []
+ self.backup_targets = []
self.tgt_dev_uuid = get_active_target(tgtdb)
if not self.tgt_dev_uuid:
('subsystem', "Set the portals debug subsystem", PARAM),
('gdb_script', "Fullname of gdb debug script", PARAM, default_gdb_script()),
('debug_path', "Path to save debug dumps", PARAM, default_debug_path()),
+ ('allow_unprivileged_port', "Allow connections from unprivileged ports"),
# Client recovery options
('recover', "Recover a device"),
('group', "The group of devices to configure or cleanup", PARAM),