def setUp(self): self.srv1 = Server(Utils.HOSTNAME, ['%s@tcp' % Utils.HOSTNAME]) self.disk1 = Utils.make_disk() self.disk2 = Utils.make_disk() self.fs = FileSystem('testfs') self.fs.local_server = self.srv1
def testAllServers(self): """test Target.allservers()""" fs1 = FileSystem('allsrvr') srv1 = Server('foo1', ['foo1@tcp']) srv2 = Server('foo2', ['foo2@tcp']) tgt = fs1.new_target(srv1, 'ost', 0, '/dev/null') tgt.add_server(srv2) self.assertEqual(list(iter(tgt.allservers())), [srv1, srv2])
def test_unique_id(self): """test target.uniqueid()""" fs1 = FileSystem('uniqueid') srv1 = Server('foo1', ['foo1@tcp']) tgt1 = fs1.new_target(srv1, 'ost', 0, '/dev/null') fs2 = FileSystem('uniqueid') srv2 = Server('foo1', ['foo1@tcp']) tgt2 = fs2.new_target(srv2, 'ost', 0, '/dev/null') self.assertEqual(tgt2.uniqueid(), tgt1.uniqueid())
def test_uniqueid_diff_mountpath(self): """test client.uniqueid() (diff mount_path)""" fs1 = FileSystem('uniqueid') srv1 = Server('foo1', ['foo1@tcp']) client1 = fs1.new_client(srv1, '/foo1') fs2 = FileSystem('uniqueid') srv2 = Server('foo1', ['foo1@tcp']) client2 = fs2.new_client(srv2, '/foo2') self.assertNotEqual(client1.uniqueid(), client2.uniqueid())
def test_unique_id(self): """test client.uniqueid()""" fs1 = FileSystem('uniqueid') srv1 = Server('foo1', ['foo1@tcp']) client1 = fs1.new_client(srv1, '/foo') fs2 = FileSystem('uniqueid') srv2 = Server('foo1', ['foo1@tcp']) client2 = fs2.new_client(srv2, '/foo') self.assertEqual(client1.uniqueid(), client2.uniqueid())
def setUp(self): self._fs = FileSystem('complex') # Router (foo0) self._fs.new_router(Server('foo0', ['foo0@tcp'])) # MGS (foo1) self._fs.new_target(Server('foo1', ['foo1@tcp']), 'mgt', 0, '/dev/mgt') # OSTs (foo3) srv3 = Server('foo3', ['foo3@tcp']) self._fs.new_target(srv3, 'ost', 0, '/dev/ost0') self._fs.new_target(srv3, 'ost', 1, '/dev/ost1') # MDT (foo2) self._fs.new_target(Server('foo2', ['foo2@tcp']), 'mdt', 0, '/dev/mdt')
def setUp(self): fs1 = FileSystem('allsrvr') self.srv1 = Server('foo1', ['foo1@tcp']) self.srv2 = Server('foo2', ['foo2@tcp']) self.srv3 = Server('foo3', ['foo3@tcp']) self.srv1name = str(self.srv1.hostname) self.srv2name = str(self.srv2.hostname) self.srv3name = str(self.srv3.hostname) self.tgt = fs1.new_target(self.srv1, 'ost', 0, '/dev/null') self.tgt.add_server(self.srv2) self.tgt.add_server(self.srv3)
def setUp(self): self.fs = FileSystem('proxy') self.srv1 = Server(Utils.HOSTNAME, ["%s@tcp" % Utils.HOSTNAME]) disk = Utils.makeTempFilename() self.tgt = self.fs.new_target(self.srv1, 'mgt', 0, disk) self.act = self.fs._proxy_action('start', self.srv1.hostname, self.fs.components) self.info = StartTarget(self.tgt).info() def fakeprepare(action): return [action.fakecmd] self.act._prepare_cmd = types.MethodType(fakeprepare, self.act)
def testHaNode(self): """test failover servers""" fs = FileSystem('nonreg') srv = Server('foo1', ['foo1@tcp']) tgt = Target(fs, srv, 0, '/dev/null') self.assertEqual(tgt.server, srv) self.assertEqual(len(tgt.failservers), 0) # Could not switch to an undefined failnode self.assertFalse(tgt.failover(NodeSet("foo1"))) self.assertEqual(tgt.server, srv) # Add a failserver and switch to it foo2 = Server('foo2', ['foo2@tcp']) tgt.add_server(foo2) self.assertEqual(list(tgt.failservers), [foo2]) self.assertTrue(tgt.failover(NodeSet("foo2"))) self.assertEqual(tgt.server, foo2) # Add a 2nd failserver and switch to it foo3 = Server('foo3', ['foo3@tcp']) tgt.add_server(foo3) self.assertEqual(list(tgt.failservers), [foo2, foo3]) self.assertTrue(tgt.failover(NodeSet("foo3"))) self.assertEqual(tgt.server, foo3) # Switch with more than 1 candidate but only one exist self.assertTrue(tgt.failover(NodeSet("bar,foo2"))) self.assertEqual(tgt.server, foo2) # Could not switch if more than one node matches self.assertRaises(ComponentError, Target.failover, tgt, NodeSet("foo[2,3]"))
def testServers(self): """test ComponentGroup.servers()""" fs = FileSystem('comp') grp = ComponentGroup() grp.add(Component(fs, Server('foo1', ['foo1@tcp']))) grp.add(Component(fs, Server('foo2', ['foo2@tcp']))) self.assertEqual(str(grp.servers()), "foo[1-2]")
def testGenericComponent(self): """test ComponentGroup simple methods""" fs = FileSystem('comp') grp = ComponentGroup() self.assertEqual(len(grp), 0) comp = Component(fs, Server('foo', ['foo@tcp'])) comp.TYPE = 'A' # add() grp.add(comp) # __len__ self.assertEqual(len(grp), 1) # __str__ self.assertEqual(str(grp), 'comp-A') # __getitem__ self.assertEqual(grp[comp.uniqueid()], comp) # __contains__ self.assertTrue(comp in grp) # __iter__ self.assertEqual(list(iter(grp)), [ comp ]) # Could not add() twice the same component try: grp.add(comp) except KeyError as error: txt = "'A component with id comp-A-foo@tcp already exists.'" self.assertEqual(str(error), txt)
def test_unique_id_failover(self): """test target.uniqueid()""" fs1 = FileSystem('uniqueid') srv1a = Server('foo1', ['foo1@tcp']) srv1b = Server('foo2', ['foo2@tcp']) tgt1 = fs1.new_target(srv1a, 'ost', 0, '/dev/null') tgt1.add_server(srv1b) fs2 = FileSystem('uniqueid') srv2a = Server('foo1', ['foo1@tcp']) srv2b = Server('foo2', ['foo2@tcp']) tgt2 = fs2.new_target(srv2a, 'ost', 0, '/dev/null') tgt2.add_server(srv2b) tgt2.failover(NodeSet('foo2')) print tgt2.uniqueid() self.assertEqual(tgt2.uniqueid(), tgt1.uniqueid())
def testAllServers(self): """test ComponentGroup.allservers()""" fs = FileSystem('comp') grp = ComponentGroup() grp.add(Target(fs, Server('foo1', ['foo1@tcp']), 0, '/dev/sda')) comp = Target(fs, Server('foo2', ['foo2@tcp']), 1, '/dev/sda') grp.add(comp) comp.add_server(Server('foo3', ['foo3@tcp0'])) self.assertEqual(str(grp.allservers()), "foo[1-3]")
class FileSystemTest(unittest.TestCase): def setUp(self): self.srv1 = Server(Utils.HOSTNAME, ['%s@tcp' % Utils.HOSTNAME]) self.disk1 = Utils.make_disk() self.disk2 = Utils.make_disk() self.fs = FileSystem('testfs') self.fs.local_server = self.srv1 def tearDown(self): self.fs.stop() @Utils.rootonly def test_start_failover(self): """start on a failover node""" srv2 = Server('fakenode', ['127.0.0.2@tcp']) mgt = self.fs.new_target(self.srv1, 'mgt', 0, self.disk1.name) mdt = self.fs.new_target(self.srv1, 'mdt', 0, self.disk2.name) mdt.add_server(srv2) self.assertEqual(self.fs.format(), set([OFFLINE])) # For a simpler test environment, simulate local node is the failover # node. # This could be improved when --servicenode will be supported. Format # will be possible directly in failover configuration (no need to # reconfig anymore). mdt.state = None mdt.defaultserver = srv2 mdt.failservers = ServerGroup() mdt.add_server(self.srv1) # Fail over this local node (-F HOSTNAME -n HOSTNAME) mdt.failover(self.srv1.hostname) srv2.action_enabled = False # Start should succeed and detect migration self.assertEqual(self.fs.start(), set([MIGRATED])) self.assertEqual(mgt.state, MOUNTED) self.assertEqual(mdt.state, MIGRATED)
class FileSystemTest(unittest.TestCase): def setUp(self): self.srv1 = Server(Utils.HOSTNAME, ['%s@tcp' % Utils.HOSTNAME]) self.disk1 = Utils.make_disk() self.disk2 = Utils.make_disk() self.fs = FileSystem('testfs') self.fs.local_server = self.srv1 def tearDown(self): self.fs.stop() @Utils.rootonly def test_start_failover(self): """start on a failover node""" srv2 = Server('fakenode', ['127.0.0.2@tcp']) mgt = self.fs.new_target(self.srv1, 'mgt', 0, self.disk1.name) mdt = self.fs.new_target(self.srv1, 'mdt', 0, self.disk2.name) mdt.add_server(srv2) self.assertEqual(self.fs.format(), OFFLINE) # For a simpler test environment, simulate local node is the failover # node. # This could be improved when --servicenode will be supported. Format # will be possible directly in failover configuration (no need to # reconfig anymore). mdt.state = None mdt.defaultserver = srv2 mdt.failservers = ServerGroup() mdt.add_server(self.srv1) # Fail over this local node (-F HOSTNAME -n HOSTNAME) mdt.failover(self.srv1.hostname) srv2.action_enabled = False # Start should succeed and detect migration self.assertEqual(self.fs.start(), MIGRATED) self.assertEqual(mgt.state, MOUNTED) self.assertEqual(mdt.state, MIGRATED)
def testLabels(self): """test ComponentGroup.labels()""" fs = FileSystem('comp') grp = ComponentGroup() comp = Component(fs, Server('foo1', ['foo1@tcp'])) comp.TYPE = 'A' grp.add(comp) comp = Component(fs, Server('foo2', ['foo2@tcp'])) comp.TYPE = 'B' grp.add(comp) self.assertEqual(str(grp.labels()), 'comp-A,comp-B')
def testUpdate(self): """test ComponentGroup.update()""" fs = FileSystem('comp') grp1 = ComponentGroup() comp1 = Component(fs, Server('foo1', ['foo1@tcp'])) grp1.add(comp1) grp2 = ComponentGroup() comp2 = Component(fs, Server('foo2', ['foo2@tcp'])) grp2.add(comp2) grp1.update(grp2) self.assertEqual(len(grp1), 2) self.assertTrue(comp1 in grp1) self.assertTrue(comp2 in grp1)
def testOr(self): """test ComponentGroup.__or__()""" fs = FileSystem('comp') grp1 = ComponentGroup() comp1 = Component(fs, Server('foo1', ['foo1@tcp'])) grp1.add(comp1) grp2 = ComponentGroup() comp2 = Component(fs, Server('foo2', ['foo2@tcp'])) grp2.add(comp2) merge = grp1|grp2 self.assertEqual(len(merge), 2) self.assertTrue(comp1 in merge) self.assertTrue(comp2 in merge)
def test_install_unreachable(self): """install on unreachable nodes raises an error""" fs = FileSystem('testfs') badsrv1 = Server('badnode1', ['127.0.0.2@tcp']) badsrv2 = Server('badnode2', ['127.0.0.3@tcp']) fs.new_target(badsrv1, 'mgt', 0, '/dev/fakedev') fs.new_client(badsrv2, '/testfs') try: fs.install(fs_config_file=Utils.makeTempFilename()) except FSRemoteError, ex: self.assertEqual(str(ex.nodes), 'badnode[1-2]') self.assertEqual(ex.rc, 1) # Partial comparison to support RHEL5 OpenSSH output self.assertTrue(str(ex).startswith("badnode[1-2]: Copy failed: ")) self.assertTrue( str(ex).endswith("badnode[1-2]: Name or service not" " known\nlost connection [rc=1]"))
def testManaged(self): """test ComponentGroup.managed()""" fs = FileSystem('comp') grp = ComponentGroup() comp1 = Component(fs, Server('foo1', ['foo1@tcp']), mode="external") grp.add(comp1) comp2 = Component(fs, Server('foo2', ['foo2@tcp'])) grp.add(comp2) comp3 = Component(fs, Server('foo3', ['foo3@tcp']), enabled=False) grp.add(comp3) comp4 = Component(fs, Server('foo4', ['foo4@tcp'])) grp.add(comp4) offgrp = grp.managed() self.assertEqual(len(offgrp), 2) self.assertTrue(comp2 in offgrp) self.assertTrue(comp4 in offgrp)
class ComplexFillTests(unittest.TestCase): def setUp(self): self._fs = FileSystem('complex') # Router (foo0) self._fs.new_router(Server('foo0', ['foo0@tcp'])) # MGS (foo1) self._fs.new_target(Server('foo1', ['foo1@tcp']), 'mgt', 0, '/dev/mgt') # OSTs (foo3) srv3 = Server('foo3', ['foo3@tcp']) self._fs.new_target(srv3, 'ost', 0, '/dev/ost0') self._fs.new_target(srv3, 'ost', 1, '/dev/ost1') # MDT (foo2) self._fs.new_target(Server('foo2', ['foo2@tcp']), 'mdt', 0, '/dev/mdt') def test_sorting(self): """fill with 2 different sortings""" tbl = TextTable(fmt="%4fsname %node") tbl.show_header = False key = lambda t: t.TYPE table_fill(tbl, self._fs, key) self.assertEqual(str(tbl), 'c... foo2\nc... foo1\nc... foo3\nc... foo0') tbl = TextTable(fmt="%4fsname %node") tbl.show_header = False key = lambda t: t.DISPLAY_ORDER table_fill(tbl, self._fs, key) self.assertEqual(str(tbl), 'c... foo0\nc... foo1\nc... foo2\nc... foo3') def test_format_group(self): """fill with group field in format""" tbl = TextTable(fmt="%3type %count") tbl.show_header = False table_fill(tbl, self._fs) self.assertEqual(str(tbl), 'MDT 1\nMGT 1\nOST 2\nROU 1') def test_support(self): """fill with a support filter""" tbl = TextTable(fmt="%3type %node %count") tbl.show_header = False table_fill(tbl, self._fs, None, supports='dev') self.assertEqual(str(tbl), 'MGT foo1 1\nMDT foo2 1\nOST foo3 2')
def test_install_unreachable(self): """install on unreachable nodes raises an error""" fs = FileSystem('testfs') badsrv1 = Server('badnode1', ['127.0.0.2@tcp']) badsrv2 = Server('badnode2', ['127.0.0.3@tcp']) fs.new_target(badsrv1, 'mgt', 0, '/dev/fakedev') fs.new_client(badsrv2, '/testfs') try: fs.install(fs_config_file=Utils.makeTempFilename()) except FSRemoteError, ex: self.assertEqual(str(ex.nodes), 'badnode[1-2]') self.assertEqual(ex.rc, 1) # Partial comparison to support RHEL5 OpenSSH output self.assertTrue(str(ex).startswith("badnode[1-2]: Copy failed: ")) self.assertTrue(str(ex).endswith("badnode[1-2]: Name or service not" " known\nlost connection [rc=1]"))
def test_managed_active(self): """test ComponentGroup.managed() with active option""" fs = FileSystem('active') grp = ComponentGroup() srv = Server('foo1', ['foo1@tcp']) comp1 = Component(fs, srv) comp1.TYPE = 'A' grp.add(comp1) comp2 = Component(fs, srv, active='no') comp2.TYPE = 'B' grp.add(comp2) comp3 = Component(fs, srv, active='nocreate') comp3.TYPE = 'C' grp.add(comp3) comp4 = Component(fs, srv, active='no', mode='external') comp4.TYPE = 'D' grp.add(comp4) self.assertEqual(str(grp.managed()), 'active-A,active-C') self.assertEqual(str(grp.managed(inactive=True)), 'active-A,active-B,active-C,active-D')
def testGroupBy(self): """test ComponentGroup.groupby()""" fs = FileSystem('comp') grp = ComponentGroup() comp1 = Component(fs, Server('foo1', ['foo1@tcp']), mode="external") grp.add(comp1) comp2 = Component(fs, Server('foo2', ['foo2@tcp'])) grp.add(comp2) comp3 = Component(fs, Server('foo3', ['foo3@tcp']), mode="external") grp.add(comp3) comp4 = Component(fs, Server('foo4', ['foo4@tcp'])) grp.add(comp4) results = [[mode, list(comps)] for mode, comps in grp.groupby(attr='_mode')] self.assertEqual(len(results), 2) self.assertEqual(results[0][0], "external") self.assertTrue(comp1 in results[0][1]) self.assertTrue(comp3 in results[0][1]) self.assertEqual(results[1][0], "managed") self.assertTrue(comp2 in results[1][1]) self.assertTrue(comp4 in results[1][1])
def testFilterSupports(self): """test ComponentGroup.filter(supports and key)""" fs = FileSystem('comp') grp = ComponentGroup() comp1 = Component(fs, Server('foo1', ['foo1@tcp'])) comp1.state = MOUNTED grp.add(comp1) comp2 = Component(fs, Server('foo2', ['foo2@tcp'])) comp2.state = OFFLINE grp.add(comp2) comp3 = Component(fs, Server('foo3', ['foo3@tcp'])) comp3.state = MOUNTED grp.add(comp3) comp4 = Component(fs, Server('foo4', ['foo4@tcp'])) comp4.state = OFFLINE grp.add(comp4) offgrp = grp.filter(supports='is_external', key=lambda comp: comp.state == OFFLINE) self.assertEqual(len(offgrp), 2) self.assertTrue(comp2 in offgrp) self.assertTrue(comp4 in offgrp)
def test_unique_id_failover(self): """test target.uniqueid()""" fs1 = FileSystem('uniqueid') srv1a = Server('foo1', ['foo1@tcp']) srv1b = Server('foo2', ['foo2@tcp']) tgt1 = fs1.new_target(srv1a, 'ost', 0, '/dev/null') tgt1.add_server(srv1b) fs2 = FileSystem('uniqueid') srv2a = Server('foo1', ['foo1@tcp']) srv2b = Server('foo2', ['foo2@tcp']) tgt2 = fs2.new_target(srv2a, 'ost', 0, '/dev/null') tgt2.add_server(srv2b) tgt2.failover(NodeSet('foo2')) self.assertEqual(tgt2.uniqueid(), tgt1.uniqueid())
def testGroupByServer(self): """test ComponentGroup.groupbyserver()""" fs = FileSystem('comp') grp = ComponentGroup() srv1 = Server('foo1', ['foo1@tcp']) srv2 = Server('foo2', ['foo2@tcp']) comp1 = Component(fs, srv1) comp1.TYPE = 'A' grp.add(comp1) comp2 = Component(fs, srv2) comp2.TYPE = 'B' grp.add(comp2) comp3 = Component(fs, srv1) comp3.TYPE = 'C' grp.add(comp3) comp4 = Component(fs, srv2) comp4.TYPE = 'D' grp.add(comp4) key = lambda c: c.TYPE results = [[srv, sorted(comps, key=key)] for srv, comps in grp.groupbyserver()] self.assertEqual(len(results), 2) self.assertTrue([srv1, [comp1, comp3]] in results) self.assertTrue([srv2, [comp2, comp4]] in results)
def test_group_by_all_servers(self): """test ComponentGroup.groupbyallservers()""" fs = FileSystem('comp') grp = ComponentGroup() srv1 = Server('foo1', ['foo1@tcp']) srv2 = Server('foo2', ['foo2@tcp']) comp1 = Target(fs, srv1, 0, '/dev/sda') comp1.add_server(srv2) grp.add(comp1) comp2 = Target(fs, srv2, 1, '/dev/sdb') comp2.add_server(srv1) grp.add(comp2) comp3 = Target(fs, srv1, 2, '/dev/sdc') comp3.add_server(srv2) grp.add(comp3) comp4 = Target(fs, srv2, 3, '/dev/sdd') comp4.add_server(srv1) grp.add(comp4) key = lambda c: c.TYPE results = [[srv, sorted(comps, key=key)] for srv, comps in grp.groupbyallservers()] self.assertEqual(len(results), 2) self.assertTrue([srv1, [comp1, comp2, comp3, comp4]] in results) self.assertTrue([srv2, [comp1, comp2, comp3, comp4]] in results)
def setUp(self): self._fs = FileSystem('foofs') Globals().replace('color', 'auto')
class ActionsTest(unittest.TestCase): def setUp(self): self.fs = FileSystem('action') self.srv1 = Server("localhost", ["localhost@tcp"]) self.srv2 = Server("localhost2", ["localhost2@tcp"]) def tearDown(self): del Globals()['lustre_version'] def check_cmd(self, action, cmdline): """Check `action' prepare_cmd() return the provided cmdline.""" self.assertEqual(' '.join(action._prepare_cmd()), cmdline) # # Router # def test_start_router(self): """test command line start router""" rtr = self.fs.new_router(self.srv1) action = StartRouter(rtr) self.assertEquals(sorted(action.needed_modules()), []) self.check_cmd(action, "/sbin/modprobe ptlrpc") def test_stop_router(self): """test command line stop router""" rtr = self.fs.new_router(self.srv1) action = StopRouter(rtr) self.check_cmd(action, "lustre_rmmod") # # Client # def test_start_client_simple(self): """test command line start client (mgs one nid)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = StartClient(client) self.assertEquals(sorted(action.needed_modules()), ['lustre']) self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre localhost@tcp:/action /foo') def test_start_client_two_nids(self): """test command line start client (mgs two nids)""" srv = Server('localhost', ['localhost@tcp','localhost@o2ib']) self.fs.new_target(srv, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = StartClient(client) self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre localhost@tcp,localhost@o2ib:/action /foo') def test_start_client_mgs_failover(self): """test command line start client (mgs failover)""" mgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mgt.add_server(self.srv2) client = self.fs.new_client(self.srv1, "/foo") action = StartClient(client) self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre localhost@tcp:localhost2@tcp:/action /foo') def test_start_client_mount_options(self): """test command line start client (mount options)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo", mount_options="acl") action = StartClient(client) self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre -o acl localhost@tcp:/action /foo') def test_start_client_addl_options(self): """test command line start client (addl options)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = StartClient(client, addopts='user_xattr') self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre -o user_xattr localhost@tcp:/action /foo') def test_start_client_both_options(self): """test command line start client (both options)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo", mount_options="acl") action = StartClient(client, addopts='user_xattr') self.check_cmd(action, 'mkdir -p "/foo" && ' + '/bin/mount -t lustre -o acl,user_xattr localhost@tcp:/action /foo') def test_startstop_client_custom_vars(self): """test command line start/stop client (custom vars)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') # fs_name mtpt = '/action' client = self.fs.new_client(self.srv1, "/$fs_name") action = StartClient(client) self.check_cmd(action, 'mkdir -p "%s" && ' \ '/bin/mount -t lustre localhost@tcp:/action %s' % (mtpt, mtpt)) action = StopClient(client) self.check_cmd(action, 'umount %s' % mtpt) # label mtpt = '/action-client' client = self.fs.new_client(self.srv1, "/$label") action = StartClient(client) self.check_cmd(action, 'mkdir -p "%s" && ' \ '/bin/mount -t lustre localhost@tcp:/action %s' % (mtpt, mtpt)) action = StopClient(client) self.check_cmd(action, 'umount %s' % mtpt) # type mtpt = '/client' client = self.fs.new_client(self.srv1, "/client") action = StartClient(client) self.check_cmd(action, 'mkdir -p "%s" && ' \ '/bin/mount -t lustre localhost@tcp:/action %s' % (mtpt, mtpt)) action = StopClient(client) self.check_cmd(action, 'umount %s' % mtpt) def test_stop_client_simple(self): """test command line stop client (simple)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = StopClient(client) self.check_cmd(action, 'umount /foo') def test_stop_client_addopts(self): """test command line stop client (addl opts)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = StopClient(client, addopts='-f') self.check_cmd(action, 'umount -f /foo') # # Target # def test_fsck(self): """test command line fsck""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Fsck(tgt) self.check_cmd(action, 'e2fsck -f -C2 /dev/root -y') def test_fsck_addopts(self): """test command line fsck (addl options)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Fsck(tgt, addopts='-v') self.check_cmd(action, 'e2fsck -f -C2 /dev/root -v') def test_fsck_addopts_placeholders(self): """test command line fsck (addl options with placeholders)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Fsck(tgt, addopts='--ostdb /mnt/db/%label.db') self.check_cmd(action, 'e2fsck -f -C2 /dev/root --ostdb /mnt/db/MGS.db') # XXX: All full_check() calls should be replaced by a real call to the # method dedicated action for the Target. def test_start_target_modules_v2_1x(self): Globals().replace('lustre_version', '2.1') tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = StartTarget(tgt) self.assertEquals(sorted(action.needed_modules()), ['ldiskfs', 'lustre']) def test_start_target_modules_v2_4x(self): Globals().replace('lustre_version', '2.4') tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = StartTarget(tgt) self.assertEquals(sorted(action.needed_modules()), ['fsfilt_ldiskfs', 'lustre']) def test_start_target_modules_v2_5x(self): Globals().replace('lustre_version', '2.5') tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = StartTarget(tgt) self.assertEquals(sorted(action.needed_modules()), ['ldiskfs', 'lustre']) def test_start_target(self): """test command line start target""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre /dev/root /mnt/action/mgt/0') def test_start_target_addopts(self): """test command line start target (addl options)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt, addopts='abort_recov') self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre -o abort_recov /dev/root /mnt/action/mgt/0') def test_start_target_mount_options(self): """test command line start target (mount_options)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt, mount_options={'mgt': 'abort_recov'}) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre -o abort_recov /dev/root /mnt/action/mgt/0') def test_start_target_mount_options_none(self): """test command line start target (mount_options missing)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt, mount_options={'mdt': 'abort_recov'}) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre /dev/root /mnt/action/mgt/0') action = StartTarget(tgt, mount_options={'mgt': None}) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre /dev/root /mnt/action/mgt/0') def test_start_target_both_options(self): """test command line start target (both options)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt, addopts='ro', mount_options={'mgt': 'abort_recov'}) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre -o abort_recov,ro /dev/root /mnt/action/mgt/0') def test_start_target_jdev(self): """test command line start target (with journal)""" dev = Utils.config_options('noformat_dev') jdev = Utils.config_options('noformat_jdev') majorminor = os.stat(jdev).st_rdev tgt = self.fs.new_target(self.srv1, 'mgt', 0, dev, jdev) tgt.full_check(mountdata=False) action = StartTarget(tgt) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre -o journal_dev=%#x %s /mnt/action/mgt/0' % (majorminor, dev)) def test_start_target_file_device(self): """test command line start target (file device)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/etc/passwd') tgt.full_check(mountdata=False) action = StartTarget(tgt) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt/0" && ' + '/bin/mount -t lustre -o loop /etc/passwd /mnt/action/mgt/0') def test_start_target_mount_paths(self): """test command line start target (mount paths)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = StartTarget(tgt, mount_paths={'mgt': '/mnt/mypath'}) self.check_cmd(action, 'mkdir -p "/mnt/mypath" && ' + '/bin/mount -t lustre /dev/root /mnt/mypath') def test_start_target_custom_mount_paths(self): """test command line start target (custom mount paths)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) # fs_name action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$fs_name/mgt'}) self.check_cmd(action, 'mkdir -p "/mnt/action/mgt" && ' + '/bin/mount -t lustre /dev/root /mnt/action/mgt') # index action = StartTarget(tgt, mount_paths={'mgt': '/mnt/mgt/$index'}) self.check_cmd(action, 'mkdir -p "/mnt/mgt/0" && ' + '/bin/mount -t lustre /dev/root /mnt/mgt/0') # type action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$type/$index'}) self.check_cmd(action, 'mkdir -p "/mnt/mgt/0" && ' + '/bin/mount -t lustre /dev/root /mnt/mgt/0') # label action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$label'}) self.check_cmd(action, 'mkdir -p "/mnt/MGS"' + ' && /bin/mount -t lustre /dev/root /mnt/MGS') # dev action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$fs_name-$dev'}) self.check_cmd(action, 'mkdir -p "/mnt/action-root"' + ' && /bin/mount -t lustre /dev/root /mnt/action-root') # No jdev action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$fs_name-$jdev'}) self.check_cmd(action, 'mkdir -p "/mnt/action-$jdev"' + ' && /bin/mount -t lustre /dev/root /mnt/action-$jdev') # Bad variable, leave it as-is action = StartTarget(tgt, mount_paths={'mgt': '/mnt/$bad'}) self.check_cmd(action, 'mkdir -p "/mnt/$bad" && ' + '/bin/mount -t lustre /dev/root /mnt/$bad') # jdev tgt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root', '/dev/loop0') tgt.full_check(mountdata=False) action = StartTarget(tgt, mount_paths={'mdt': '/mnt/$jdev'}) self.check_cmd(action, 'mkdir -p "/mnt/loop0" && ' + '/bin/mount -t lustre -o journal_dev=0x700 /dev/root /mnt/loop0') # Stop def test_stop_target(self): """test command line stop target""" dev = Utils.config_options('noformat_dev') tgt = self.fs.new_target(self.srv1, 'mgt', 0, dev) tgt.full_check(mountdata=False) action = StopTarget(tgt) self.check_cmd(action, 'umount %s' % dev) def test_stop_target_addopts(self): """test command line stop target (addl options)""" dev = Utils.config_options('noformat_dev') tgt = self.fs.new_target(self.srv1, 'mgt', 0, dev) tgt.full_check(mountdata=False) action = StopTarget(tgt, addopts='-l') self.check_cmd(action, 'umount -l %s' % dev) def test_stop_target_file_device(self): """test command line stop target (file device)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/etc/passwd') tgt.full_check(mountdata=False) action = StopTarget(tgt) self.check_cmd(action, 'umount -d /etc/passwd') # Format def check_cmd_format(self, action, cmdline): """Helper method to check cmdline for format actions""" self.check_cmd(action, 'mkfs.lustre --reformat --quiet "--fsname=action" ' + cmdline) def test_format_target(self): """test command line format (MGT)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt) self.assertEquals(sorted(action.needed_modules()), ['ldiskfs']) self.check_cmd_format(action, '--mgs /dev/root') def test_format_target_loopback(self): """test command line format (MGT in loopback)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/etc/passwd') tgt.full_check(mountdata=False) action = Format(tgt) size = os.stat('/etc/passwd').st_size / 1024 self.check_cmd_format(action, '--mgs --device-size=%d /etc/passwd' % size) def test_format_target_jdev(self): """test command line format (MGT with jdev and mkfsoptions)""" jdev = Utils.config_options('noformat_jdev') tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root', jdev) tgt.full_check(mountdata=False) action = Format(tgt, mkfs_options={'mgt': '-m 2'}) jaction = JournalFormat(tgt.journal) self.check_cmd(jaction, 'mke2fs -q -F -O journal_dev -b 4096 %s' % jdev) self.check_cmd_format(action, '--mgs ' '"--mkfsoptions=-j -J device=%s -m 2" /dev/root' % jdev) def test_format_target_mdt(self): """test command line format (MDT)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" /dev/root') def test_format_target_mdt_options(self): """test command line format (MDT with addl options)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, addopts='-v') self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" -v /dev/root') def test_format_target_mdt_quota_v1x(self): """test command line format v1.x (MDT with quota)""" Globals().replace('lustre_version', '1.6') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, quota=True, quota_type='ug') self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" "--param=mdt.quota_type=ug" /dev/root') def test_format_target_mdt_quota_v2x(self): """test command line format v2.x (MDT with quota)""" Globals().replace('lustre_version', '2.0.0.1') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, quota=True, quota_type='ug') self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" "--param=mdd.quota_type=ug" /dev/root') def test_format_target_mdt_quota_v24(self): """test command line format v2.4 and above (MDT with quota)""" Globals().replace('lustre_version', '2.4') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, quota=True, quota_type='ug') self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" /dev/root') def test_format_target_mdt_striping(self): """test command line format (MDT with striping)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, stripecount=2, stripesize=2097152) self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" --param=lov.stripecount=2 ' + '--param=lov.stripesize=2097152 /dev/root') def test_format_target_mdt_mkfsoptions(self): """test command line format (MDT with mkfsoptions)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, mkfs_options={'mdt': '-m 2'}) self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" "--mkfsoptions=-m 2" /dev/root') def test_format_target_mdt_param(self): """test command line format (MDT with param)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'mdt', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, format_params={'mdt': 'foo'}) self.check_cmd_format(action, '--mdt --index=0 ' + '"--mgsnode=localhost@tcp" "--param=foo" /dev/root') def test_format_target_ost(self): """test command line format (OST)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'ost', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" /dev/root') def test_format_target_ost_quota_v2x(self): """test command line format v2.x (OST with quota)""" Globals().replace('lustre_version', '2.0.0.1') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'ost', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, quota=True, quota_type='ug') self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" "--param=ost.quota_type=ug" /dev/root') def test_format_target_ost_quota_v24(self): """test command line format v2.4 and above (OST with quota)""" Globals().replace('lustre_version', '2.4') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv2, 'ost', 0, '/dev/root') tgt.full_check(mountdata=False) action = Format(tgt, quota=True, quota_type='ug') self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" /dev/root') def test_format_target_ost_failnode(self): """test command line format (OST with failnode)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root') tgt.add_server(self.srv2) tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" "--failnode=localhost2@tcp" /dev/root') def test_format_target_ost_two_failnodes(self): """test command line format (OST with 2 failnodes)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root') tgt.add_server(self.srv2) tgt.add_server(Server('localhost3', ['localhost3@tcp'])) tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" "--failnode=localhost2@tcp" ' + '"--failnode=localhost3@tcp" /dev/root') def test_format_target_ost_bad_network(self): """test command line format (OST with a bad network)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='bad netw') tgt.add_server(self.srv2) action = Format(tgt) self.assertRaises(ValueError, action._prepare_cmd) def test_format_target_ost_failnodes_network(self): """test command line format (OST with 2 failnodes and network)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='tcp') tgt.add_server(self.srv2) tgt.add_server(Server('localhost3', ['localhost3@o2ib'])) tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" "--failnode=localhost2@tcp" ' + '--network=tcp /dev/root') def test_format_target_network_zero(self): """test command line format (network with zero suffix)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') tgt = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='o2ib0') tgt.add_server(self.srv2) tgt.add_server(Server('localhost3', ['localhost3@o2ib'])) tgt.full_check(mountdata=False) action = Format(tgt) self.check_cmd_format(action, '--ost --index=0 ' + '"--mgsnode=localhost@tcp" "--failnode=localhost3@o2ib" ' + '--network=o2ib0 /dev/root') # Tunefs def check_cmd_tunefs(self, action, cmdline): """Helper method to check cmdline for tunefs actions""" self.check_cmd(action, 'tunefs.lustre --erase-params --quiet ' + cmdline) def test_tunefs_mgs_writeconf(self): """test command line tunefs writeconf (MGT)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Tunefs(tgt, writeconf=True) self.assertEquals(sorted(action.needed_modules()), ['ldiskfs']) self.check_cmd_tunefs(action, '--writeconf /dev/root') def test_tunefs_mgs_addl(self): """test command line tunefs addl options (MGT)""" tgt = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Tunefs(tgt, addopts='-v') self.check_cmd_tunefs(action, '-v /dev/root') def test_tunefs_mdt(self): """test command line tunefs (MDT)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mdt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root') action = Tunefs(mdt) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" /dev/root') def test_tunefs_ost(self): """test command line tunefs (OST)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root') action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" /dev/root') def test_tunefs_mdt_striping(self): """test command line tunefs striping (MDT)""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mdt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root') action = Tunefs(mdt, stripecount=2, stripesize=2097152) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '--param=lov.stripecount=2 ' + '--param=lov.stripesize=2097152 /dev/root') def test_tunefs_target_quota_v1x(self): """test command line tunefs quota (v1.x)""" Globals().replace('lustre_version', '1.6') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mdt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root') action = Tunefs(mdt, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--param=mdt.quota_type=ug" /dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/sdb') action = Tunefs(ost, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--param=ost.quota_type=ug" /dev/sdb') def test_tunefs_target_quota_v2x(self): """test command line tunefs quota (v2.x)""" Globals().replace('lustre_version', '2.0.0.1') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mdt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root') action = Tunefs(mdt, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--param=mdd.quota_type=ug" /dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/sdb') action = Tunefs(ost, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--param=ost.quota_type=ug" /dev/sdb') def test_tunefs_target_quota_v24(self): """test command line tunefs quota (v2.4 and above)""" Globals().replace('lustre_version', '2.4') self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') mdt = self.fs.new_target(self.srv1, 'mdt', 0, '/dev/root') action = Tunefs(mdt, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/sdb') action = Tunefs(ost, quota=True, quota_type='ug') self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '/dev/sdb') def test_tunefs_target_failnode(self): """test command line tunefs failnode""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root') ost.add_server(self.srv2) action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--failnode=localhost2@tcp" /dev/root') def test_tunefs_target_network(self): """test command line tunefs network""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='tcp') ost.add_server(self.srv2) ost.add_server(Server('localhost3', ['localhost3@o2ib'])) action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--failnode=localhost2@tcp" --network=tcp /dev/root') def test_tunefs_target_network_zero(self): """test command line tunefs network with zero suffix""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='o2ib0') ost.add_server(self.srv2) ost.add_server(Server('localhost3', ['localhost3@o2ib'])) action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--failnode=localhost3@o2ib" --network=o2ib0 /dev/root') def test_tunefs_target_network_zero2(self): """test command line tunefs network without zero suffix""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='o2ib') ost.add_server(self.srv2) ost.add_server(Server('localhost3', ['localhost3@o2ib0'])) action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--failnode=localhost3@o2ib0" --network=o2ib /dev/root') def test_tunefs_target_network_zero3(self): """test command line tunefs network with non-zero suffix""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root', network='o2ib1') ost.add_server(self.srv2) ost.add_server(Server('localhost3', ['localhost3@o2ib1'])) action = Tunefs(ost) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--failnode=localhost3@o2ib1" --network=o2ib1 /dev/root') def test_tunefs_target_format_params(self): """test command line tunefs format params""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') ost = self.fs.new_target(self.srv1, 'ost', 0, '/dev/root') action = Tunefs(ost, format_params={'ost': 'foo'}) self.check_cmd_tunefs(action, '"--mgsnode=localhost@tcp" ' + '"--param=foo" /dev/root') # Execute def test_simple_execute(self): """test simple execute""" mgs = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Execute(mgs, addopts="foo") self.check_cmd(action, "foo") def test_execute_target(self): """test execute with target fields""" mgs = self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') action = Execute(mgs, addopts="fsck %device") self.check_cmd(action, "fsck /dev/root") def test_execute_client(self): """test execute with client fields""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo", "ro") action = Execute(client, addopts="mount %mntpath %mntopts") self.check_cmd(action, "mount /foo ro") def test_execute_client_bad_fields(self): """test execute with client and dev fields""" self.fs.new_target(self.srv1, 'mgt', 0, '/dev/root') client = self.fs.new_client(self.srv1, "/foo") action = Execute(client, addopts="mount %device") self.check_cmd(action, "mount ") def test_execute_router(self): """test execute with router fields""" rtr = self.fs.new_router(self.srv1) action = Execute(rtr, addopts="start %fsname") self.check_cmd(action, "start action") # # Proxy # def _create_proxy(self, **kwargs): """Instanciate a FSProxyAction with a fake progpath for tests.""" action = FSProxyAction(self.fs, 'dummy', 'foo', **kwargs) action.progpath = 'nosetests' return action def test_simple_proxy(self): """test proxy with minimal arguments""" action = self._create_proxy(debug=False) self.check_cmd(action, 'nosetests dummy -f action -R') def test_proxy_debug(self): """test proxy with debug""" action = self._create_proxy(debug=True) self.check_cmd(action, 'nosetests dummy -f action -R -d') def test_proxy_comps(self): """test proxy with a component list""" self.fs.new_router(self.srv1) self.fs.new_client(self.srv1, "/foo") action = self._create_proxy(debug=False, comps=self.fs.components) self.check_cmd(action, 'nosetests dummy -f action -R' ' -l action-client,action-router') def test_proxy_comps_addopts(self): """test proxy with a component list and additional options""" self.fs.new_router(self.srv1) self.fs.new_client(self.srv1, "/foo") action = self._create_proxy(debug=False, comps=self.fs.components, addopts="-y") self.check_cmd(action, "nosetests dummy -f action -R" " -l action-client,action-router -o '-y'") def test_proxy_comps_failover(self): """test proxy with a component list and failover""" self.fs.new_router(self.srv1) self.fs.new_client(self.srv1, "/foo") action = self._create_proxy(debug=False, comps=self.fs.components, failover=NodeSet('failnode')) self.check_cmd(action, "nosetests dummy -f action -R" " -l action-client,action-router -F 'failnode'") def test_proxy_comps_mountdata_never(self): """test proxy with a component list and mountdata=never""" action = self._create_proxy(debug=False, mountdata='never') self.check_cmd(action, "nosetests dummy -f action -R" " --mountdata=never") def test_proxy_comps_mountdata_auto(self): """test proxy with a component list and mountdata=auto""" action = self._create_proxy(debug=False, mountdata='auto') self.check_cmd(action, "nosetests dummy -f action -R") def test_proxy_fanout(self): """test proxy with fanout""" action = self._create_proxy(debug=False, fanout=18) self.check_cmd(action, 'nosetests dummy -f action -R --fanout=18') def test_proxy_dryrun(self): """test proxy with dryrun""" action = self._create_proxy(debug=False, dryrun=True) self.check_cmd(action, 'nosetests dummy -f action -R --dry-run')
def test_allservers(self): """test client.allservers()""" fs = FileSystem('foo') srv = Server('foo1', ['foo1@tcp']) client = fs.new_client(srv, '/foo') self.assertEqual(str(client.allservers().nodeset()), 'foo1')
def setUp(self): self.fs = FileSystem('action') self.srv1 = Server("localhost", ["localhost@tcp"]) self.srv2 = Server("localhost2", ["localhost2@tcp"])
class ProxyTest(unittest.TestCase): def setUp(self): self.fs = FileSystem('proxy') self.srv1 = Server(Utils.HOSTNAME, ["%s@tcp" % Utils.HOSTNAME]) disk = Utils.makeTempFilename() self.tgt = self.fs.new_target(self.srv1, 'mgt', 0, disk) self.act = self.fs._proxy_action('start', self.srv1.hostname, self.fs.components) self.info = StartTarget(self.tgt).info() def fakeprepare(action): return [action.fakecmd] self.act._prepare_cmd = types.MethodType(fakeprepare, self.act) def test_exec_fail(self): """simulate unable to run python""" self.act.fakecmd = '/bin/false' self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual( list(self.fs.proxy_errors.messages())[0], "Remote action start failed: No response") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_ERROR) def test_start_crash(self): """send a start message then crashes""" msg = shine_msg_pack(evtype='comp', info=self.info, status='start') self.act.fakecmd = 'echo "%s"; echo BAD; exit 1' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual( list(self.fs.proxy_errors.messages())[0], "Remote action start failed: \nBAD\n") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_ERROR) def test_start_ok(self): """send a start and done message""" msgs = [] msgs.append( shine_msg_pack(evtype='comp', info=self.info, status='start')) self.tgt.state = MOUNTED msgs.append( shine_msg_pack(evtype='comp', info=self.info, status='done')) self.act.fakecmd = 'echo "%s"' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_OK) def test_crash_after_start_ok(self): """send a start and done message and then crashes""" msgs = [] msgs.append( shine_msg_pack(evtype='comp', info=self.info, status='start')) self.tgt.state = MOUNTED msgs.append( shine_msg_pack(evtype='comp', info=self.info, status='done')) self.act.fakecmd = 'echo "%s"; echo Oops; exit 1' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual( list(self.fs.proxy_errors.messages())[0], "Remote action start failed: \n\nOops\n") self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_ERROR) def test_bad_object(self): """send a done message which fails update due to bad property""" msg = shine_msg_pack(evtype='comp', info=self.info, status='done') def buggy_update(self, other): self.wrong_property = other.wrong_property self.tgt.update = types.MethodType(buggy_update, self.tgt) self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual( str(list(self.fs.proxy_errors.messages())[0]), "Cannot read message (check Shine and ClusterShell " "version): 'MGT' object has no attribute " "'wrong_property'") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_OK) def test_cannot_unpickle(self): """send a forged message which fails due to bad pickle content""" msg = "%s%d:%s" % (SHINE_MSG_MAGIC, SHINE_MSG_VERSION, binascii.b2a_base64('bad content')) self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual( str(list(self.fs.proxy_errors.messages())[0]), "Cannot unpickle message (check Shine and ClusterShell" " versions): pop from empty list") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_OK) def test_compat_compname(self): """message with compname value is backward compatible""" msgs = [] msgs.append( shine_msg_pack(compname=self.tgt.TYPE, action='start', status='start', comp=self.tgt)) self.tgt.state = MOUNTED msgs.append( shine_msg_pack(compname=self.tgt.TYPE, action='start', status='done', comp=self.tgt)) self.act.fakecmd = 'echo "%s"' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_OK) def test_compat_msg_v2(self): """message shine version 2 is compatible""" class CustomEH(EventHandler): def __init__(eh): EventHandler.__init__(eh) eh.event = None def event_callback(eh, evtype, **kwargs): if kwargs['info'].actname != 'proxy': self.assertEqual(eh.event, None) eh.event = kwargs # v2-style message: # comp=mgt, action=start, status=failed, rc=1, message='fake error' msg = "SHINE:2:ev_starttarget_failed:gAJ9cQAoVQRjb21wcQFjU2hpbmUuTHV" \ "zdHJlLlRhcmdldApNR1QKcQIpgXEDfXEEKFUNZGVmYXVsdHNlcnZlcnEFY1No" \ "aW5lLkx1c3RyZS5TZXJ2ZXIKU2VydmVyCnEGKYFxB31xCChVBG5pZHNxCV1xC" \ "lUIZm9vQHRjcDBxC2FVCGhvc3RuYW1lcQxjQ2x1c3RlclNoZWxsLk5vZGVTZX" \ "QKTm9kZVNldApxDSmBcQ59cQ8oVQhfdmVyc2lvbnEQSwJVCV9hdXRvc3RlcHE" \ "RTlUHX2xlbmd0aHESSwBVCV9wYXR0ZXJuc3ETfXEUVQNmb29xFU5zdWJ1YlUG" \ "bW50ZGV2cRZVCC9kZXYvc2R6cRdVA3RhZ3EYTlUbX0NvbXBvbmVudF9fcnVub" \ "mluZ19hY3Rpb25zcRldcRpVC3N0YXR1c19pbmZvcRtOVQVpbmRleHEcSwBVDm" \ "FjdGlvbl9lbmFibGVkcR2IVQpsZGRfc3ZuYW1lcR5OVQVncm91cHEfTlUHbmV" \ "0d29ya3EgTlUKX2xkZF9mbGFnc3EhSwBVBV9tb2RlcSJVB21hbmFnZWRxI1UJ" \ "ZGV2X2lzYmxrcSSJVQNkZXZxJWgXVQZzZXJ2ZXJxJmgHVQpsZGRfZnNuYW1lc" \ "SdOVQVzdGF0ZXEoTlUEamRldnEpTlUIZGV2X3NpemVxKksAVQtmYWlsc2Vydm" \ "Vyc3ErY1NoaW5lLkx1c3RyZS5TZXJ2ZXIKU2VydmVyR3JvdXAKcSwpgXEtfXE" \ "uVQVfbGlzdHEvXXEwc2J1YlUHbWVzc2FnZXExVQpmYWtlIGVycm9ycTJVAnJj" \ "cTNLAXUu" self.fs.hdlr = CustomEH() self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.assertEqual(self.fs.hdlr.event['info'].actname, 'start') self.assertEqual(self.fs.hdlr.event['status'], 'failed') self.assertEqual(self.fs.hdlr.event['result'].retcode, 1) self.assertEqual(self.fs.hdlr.event['result'].message, 'fake error') self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.act.status(), ACT_OK)
def setUp(self): self.eh = self.ActionEH() self.fs = FileSystem('action', event_handler=self.eh)
class DisplayTest(unittest.TestCase): def setUp(self): self._fs = FileSystem('display') # Router (foo0) self._fs.new_router(Server('foo0', ['foo0@tcp'])) # MGS (foo1) self._fs.new_target(Server('foo1', ['foo1@tcp']), 'mgt', 0, '/dev/mgt') # OSTs (foo3) srv3 = Server('foo3', ['foo3@tcp']) self._fs.new_target(srv3, 'ost', 0, '/dev/ost0') self._fs.new_target(srv3, 'ost', 1, '/dev/ost1') # MDT (foo2) self._fs.new_target(Server('foo2', ['foo2@tcp']), 'mdt', 0, '/dev/mdt') # Client (foo0) self._fs.new_client(Server('foo0', ['foo0@tcp']), '/foo') def test_view_custom(self): """display with a custom format""" opts = DummyOptions(color='never', header=True, fmt='%type %node') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual(txt, """= FILESYSTEM STATUS (display) = TYPE NODE ---- ---- ROU foo0 MGT foo1 MDT foo2 OST foo3 CLI foo0""") def test_view_fs(self): """display with fs view""" opts = DummyOptions(color='never', header=True, view='fs', fmt=None) cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual(txt, """= FILESYSTEM STATUS (display) = TYPE # STATUS NODES ---- - ------ ----- ROU 1 unknown foo0 MGT 1 unknown foo1 MDT 1 unknown foo2 OST 2 unknown foo3 CLI 1 unknown foo0""") def test_view_target(self): """display with target view""" opts = DummyOptions(color='never', header=True, view='target') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual(txt, """========== FILESYSTEM TARGETS (display) ========= TARGET TYPE IDX SERVERS DEVICE STATUS ------ ---- --- ------- ------ ------ MGS MGT 0 foo1 /dev/mgt unknown display-MDT0000 MDT 0 foo2 /dev/mdt unknown display-OST0000 OST 0 foo3 /dev/ost0 unknown display-OST0001 OST 1 foo3 /dev/ost1 unknown""") def test_view_target_with_supports(self): """display with target view with a force 'supports'""" opts = DummyOptions(color='never', header=True, view='target') cmd = DummyCommand(opts) txt = display(cmd, self._fs, supports='status') self.assertEqual(txt, """========== FILESYSTEM TARGETS (display) ========= TARGET TYPE IDX SERVERS DEVICE STATUS ------ ---- --- ------- ------ ------ MGS MGT 0 foo1 /dev/mgt unknown display-MDT0000 MDT 0 foo2 /dev/mdt unknown display-OST0000 OST 0 foo3 /dev/ost0 unknown display-OST0001 OST 1 foo3 /dev/ost1 unknown""") def test_view_disk(self): """display with disk view""" opts = DummyOptions(color='never', header=True, view='disk') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual(txt, """======================== FILESYSTEM DISKS (display) ======================== DEVICE SERVERS DEV_SIZE TYPE INDEX LABEL FLAGS FSNAME STATUS ------ ------- -------- ---- ----- ----- ----- ------ ------ /dev/mgt foo1 0 MGT 0 MGS display unknown /dev/mdt foo2 0 MDT 0 display-MDT0000 display unknown /dev/ost0 foo3 0 OST 0 display-OST0000 display unknown /dev/ost1 foo3 0 OST 1 display-OST0001 display unknown""" ) def test_color(self): """display with fs view and colors""" opts = DummyOptions(color='always', header=True, view='fs') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual(txt, """=\x1b[34m FILESYSTEM STATUS (display) \x1b[0m= \x1b[34mTYPE # STATUS NODES\x1b[0m ---- - ------ ----- ROU 1 unknown foo0 MGT 1 unknown foo1 MDT 1 unknown foo2 OST 2 unknown foo3 CLI 1 unknown foo0""")
class SimpleFillTests(unittest.TestCase): def setUp(self): self._fs = FileSystem('foofs') Globals().replace('color', 'auto') def _fmt_str(self, fmt, txt): tbl = TextTable(fmt) tbl.show_header = False table_fill(tbl, self._fs) self.assertEqual(str(tbl), txt) def test_empty_fs(self): """fill with an empty filesystem""" tbl = TextTable() table_fill(tbl, self._fs, None) self.assertEqual(len(tbl), 0) def test_bad_field(self): """fill with bad field name""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') tbl = TextTable('%badname') self.assertRaises(DisplayError, table_fill, tbl, self._fs) def test_missing_field(self): """fill with an irrelevant field""" self._fs.new_router(Server('foo', ['foo@tcp'])) self._fmt_str('%index', '-') def test_simple_fs(self): """fill with a MGT only filesystem""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%fsname %node", 'foofs foo') def test_simple_fs_group_fields(self): """fill with a MGT only filesystem with group fields""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%fsname %node %count %labels %nodes", 'foofs foo 1 MGS foo') def test_common_fields(self): """fill with component common fields""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str( "%fsname %label %node %status %statusonly %type %servers", 'foofs MGS foo unknown unknown MGT foo') def test_status_evicted(self): """fill with status/statusonly field with different values""" client = self._fs.new_client(Server('foo', ['foo@tcp']), '/foo') client.proc_states['evicted'] = 1 client.state = MOUNTED self._fmt_str("%status | %statusonly", "mounted (evicted=1) | mounted") def test_target_fields(self): """fill with target fields""" tgt = self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo', '/dev/jfoo', tag='footag', network="tcp") tgt.add_server(Server('foo2', ['foo2@tcp'])) tgt.journal.dev_size = 123 fmt = "%device %2flags %hanodes %1index %jdev %3jsize" self._fmt_str(fmt, '/dev/foo foo2 0 /dev/jfoo 123') fmt = "%3network %tag %servers" self._fmt_str(fmt, 'tcp footag foo,foo2') def test_size_field(self): """fill with different dev size""" tgt = self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') tgt.dev_size = 123 self._fmt_str('%size', '123') # KB tgt.dev_size = 123456 self._fmt_str('%size', '120.6KB') # MB tgt.dev_size = 123456789 self._fmt_str('%size', '117.7MB') # GB tgt.dev_size = 12345678901 self._fmt_str('%size', '11.5GB') # TB tgt.dev_size = 1024**4 self._fmt_str('%size', '1.0TB') def test_journal_fields(self): """fill using journal fields with no journal""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%jdev %jsize", '') def test_client_fields(self): """fill with client fields""" self._fs.new_client(Server('foo', ['foo@tcp']), '/mnt/foo', 'ro') self._fmt_str("%mntpath %mntopts", '/mnt/foo ro')
class SimpleFillTests(unittest.TestCase): def setUp(self): self._fs = FileSystem('foofs') Globals().replace('color', 'auto') def _fmt_str(self, fmt, txt): tbl = TextTable(fmt) tbl.show_header = False table_fill(tbl, self._fs) self.assertEqual(str(tbl), txt) def test_empty_fs(self): """fill with an empty filesystem""" tbl = TextTable() table_fill(tbl, self._fs, None) self.assertEqual(len(tbl), 0) def test_bad_field(self): """fill with bad field name""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') tbl = TextTable('%badname') self.assertRaises(DisplayError, table_fill, tbl, self._fs) def test_missing_field(self): """fill with an irrelevant field""" self._fs.new_router(Server('foo', ['foo@tcp'])) self._fmt_str('%index', '-') def test_simple_fs(self): """fill with a MGT only filesystem""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%fsname %node", 'foofs foo') def test_simple_fs_group_fields(self): """fill with a MGT only filesystem with group fields""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%fsname %node %count %labels %nodes", 'foofs foo 1 MGS foo') def test_common_fields(self): """fill with component common fields""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%fsname %label %node %status %statusonly %type %servers", 'foofs MGS foo unknown unknown MGT foo') def test_status_evicted(self): """fill with status/statusonly field with different values""" client = self._fs.new_client(Server('foo', ['foo@tcp']), '/foo') client.proc_states['evicted'] = 1 client.state = MOUNTED self._fmt_str("%status | %statusonly", "mounted (evicted=1) | mounted") def test_target_fields(self): """fill with target fields""" tgt = self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo', '/dev/jfoo', tag='footag', network="tcp") tgt.add_server(Server('foo2', ['foo2@tcp'])) tgt.journal.dev_size = 123 fmt = "%device %2flags %hanodes %1index %jdev %3jsize" self._fmt_str(fmt, '/dev/foo foo2 0 /dev/jfoo 123') fmt = "%3network %tag %servers" self._fmt_str(fmt, 'tcp footag foo,foo2') def test_size_field(self): """fill with different dev size""" tgt = self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') tgt.dev_size = 123 self._fmt_str('%size', '123') # KB tgt.dev_size = 123456 self._fmt_str('%size', '120.6KB') # MB tgt.dev_size = 123456789 self._fmt_str('%size', '117.7MB') # GB tgt.dev_size = 12345678901 self._fmt_str('%size', '11.5GB') # TB tgt.dev_size = 1024**4 self._fmt_str('%size', '1.0TB') def test_journal_fields(self): """fill using journal fields with no journal""" self._fs.new_target(Server('foo', ['foo@tcp']), 'mgt', 0, '/dev/foo') self._fmt_str("%jdev %jsize", '') def test_client_fields(self): """fill with client fields""" self._fs.new_client(Server('foo', ['foo@tcp']), '/mnt/foo', 'ro') self._fmt_str("%mntpath %mntopts", '/mnt/foo ro')
class PrepareTest(unittest.TestCase): """Verify graph from _prepare()""" def setUp(self): self.fs = FileSystem('prepare') self.remotesrv = Server('remote', ['remote@tcp']) self.localsrv = Server(Utils.HOSTNAME, ['%s@tcp' % Utils.HOSTNAME]) self.fs.local_server = self.localsrv def test_simple_local_action(self): """prepare a simple action on a local component""" comp = self.fs.new_target(self.localsrv, 'mgt', 0, '/dev/fakedev') graph = self.fs._prepare('start') self.assertEqual(_graph2obj(graph), [[[{'NAME': 'start', 'comp': comp}], [{'NAME': 'load modules'}, {'NAME': 'load modules'}]]]) self.assertEqual(graph[0][1][0]._modname, 'lustre') def test_simple_remote_action(self): """prepare a simple action on a remote component""" self.fs.new_target(self.remotesrv, 'mgt', 0, '/dev/fakedev') graph = self.fs._prepare('start') self.assertEqual(_graph2obj(graph), [[[{'NAME': 'proxy', 'action': 'start'}]]]) self.assertEqual(str(graph[0][0][0].nodes), 'remote') def test_proxy_tunings(self): """prepare is ok with or without tunings""" self.fs.new_target(self.remotesrv, 'mgt', 0, '/dev/fakedev') # Without tunings graph = self.fs._prepare('dummy', tunings=None) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'proxy', 'action': 'dummy'}]]]) self.assertEqual(str(graph[0][0][0].nodes), 'remote') # With tunings graph = self.fs._prepare('dummy', tunings=FakeTunings()) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'install', 'config_file': 'foo'}, {'NAME': 'proxy', 'action': 'dummy'}]]]) self.assertEqual(str(graph[0][0][1].nodes), 'remote') def test_local_tunings(self): """prepare is ok with or without tunings""" comp = self.fs.new_target(self.localsrv, 'mgt', 0, '/dev/fakedev') # Without tunings graph = self.fs._prepare('start', tunings=None) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'start', 'comp': comp}], [{'NAME': 'load modules'}, {'NAME': 'load modules'}]]]) self.assertEqual(graph[0][1][0]._modname, 'lustre') # With tunings graph = self.fs._prepare('start', tunings=FakeTunings()) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'start', 'comp': comp}], [{'NAME': 'load modules'}, {'NAME': 'load modules'}], []]]) self.assertEqual(graph[0][1][0]._modname, 'lustre') self.assertEqual(graph[0][2].NAME, 'tune') def test_need_unload(self): """prepare handles need_unload correctly""" comp = self.fs.new_target(self.localsrv, 'mgt', 0, '/dev/fakedev') # Without module unload graph = self.fs._prepare('stop', need_unload=False) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'stop', 'comp': comp}]]]) # With module unload graph = self.fs._prepare('stop', need_unload=True) self.assertEqual(_graph2obj(graph), [[[{'NAME': 'stop', 'comp': comp}], {'NAME': 'unload modules'}]])
class DisplayTest(unittest.TestCase): def setUp(self): self._fs = FileSystem('display') # Router (foo0) self._fs.new_router(Server('foo0', ['foo0@tcp'])) # MGS (foo1) self._fs.new_target(Server('foo1', ['foo1@tcp']), 'mgt', 0, '/dev/mgt') # OSTs (foo3) srv3 = Server('foo3', ['foo3@tcp']) self._fs.new_target(srv3, 'ost', 0, '/dev/ost0') self._fs.new_target(srv3, 'ost', 1, '/dev/ost1') # MDT (foo2) self._fs.new_target(Server('foo2', ['foo2@tcp']), 'mdt', 0, '/dev/mdt') # Client (foo0) self._fs.new_client(Server('foo0', ['foo0@tcp']), '/foo') def test_view_custom(self): """display with a custom format""" opts = DummyOptions(color='never', header=True, fmt='%type %node') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual( txt, """= FILESYSTEM STATUS (display) = TYPE NODE ---- ---- ROU foo0 MGT foo1 MDT foo2 OST foo3 CLI foo0""") def test_view_fs(self): """display with fs view""" opts = DummyOptions(color='never', header=True, view='fs', fmt=None) cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual( txt, """= FILESYSTEM STATUS (display) = TYPE # STATUS NODES ---- - ------ ----- ROU 1 unknown foo0 MGT 1 unknown foo1 MDT 1 unknown foo2 OST 2 unknown foo3 CLI 1 unknown foo0""") def test_view_target(self): """display with target view""" opts = DummyOptions(color='never', header=True, view='target') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual( txt, """================ FILESYSTEM TARGETS (display) ================ TARGET TYPE IDX NODE PRIMARY SERVERS DEVICE STATUS ------ ---- --- ---- ------- ------- ------ ------ MGS MGT 0 foo1 foo1 foo1 /dev/mgt unknown display-MDT0000 MDT 0 foo2 foo2 foo2 /dev/mdt unknown display-OST0000 OST 0 foo3 foo3 foo3 /dev/ost0 unknown display-OST0001 OST 1 foo3 foo3 foo3 /dev/ost1 unknown""") def test_view_target_with_supports(self): """display with target view with a force 'supports'""" opts = DummyOptions(color='never', header=True, view='target') cmd = DummyCommand(opts) txt = display(cmd, self._fs, supports='status') self.assertEqual( txt, """================ FILESYSTEM TARGETS (display) ================ TARGET TYPE IDX NODE PRIMARY SERVERS DEVICE STATUS ------ ---- --- ---- ------- ------- ------ ------ MGS MGT 0 foo1 foo1 foo1 /dev/mgt unknown display-MDT0000 MDT 0 foo2 foo2 foo2 /dev/mdt unknown display-OST0000 OST 0 foo3 foo3 foo3 /dev/ost0 unknown display-OST0001 OST 1 foo3 foo3 foo3 /dev/ost1 unknown""") def test_view_disk(self): """display with disk view""" opts = DummyOptions(color='never', header=True, view='disk') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual( txt, """======================== FILESYSTEM DISKS (display) ======================== DEVICE SERVERS DEV_SIZE TYPE INDEX LABEL FLAGS FSNAME STATUS ------ ------- -------- ---- ----- ----- ----- ------ ------ /dev/mgt foo1 0 MGT 0 MGS display unknown /dev/mdt foo2 0 MDT 0 display-MDT0000 display unknown /dev/ost0 foo3 0 OST 0 display-OST0000 display unknown /dev/ost1 foo3 0 OST 1 display-OST0001 display unknown""" ) def test_color(self): """display with fs view and colors""" opts = DummyOptions(color='always', header=True, view='fs') cmd = DummyCommand(opts) txt = display(cmd, self._fs) self.assertEqual( txt, """=\x1b[34m FILESYSTEM STATUS (display) \x1b[0m= \x1b[34mTYPE # STATUS NODES\x1b[0m ---- - ------ ----- ROU 1 unknown foo0 MGT 1 unknown foo1 MDT 1 unknown foo2 OST 2 unknown foo3 CLI 1 unknown foo0""")
def instantiate_lustrefs(fs_conf, target_types=None, nodes=None, excluded=None, failover=None, indexes=None, labels=None, groups=None, event_handler=None): """ Instantiate shine Lustre filesystem classes from configuration. """ # Arguments interpretation assert indexes is None or isinstance(indexes, RangeSet) assert labels is None or isinstance(labels, NodeSet) _SERVERS.clear() # Create file system instance fs = FileSystem(fs_conf.get_fs_name(), event_handler) # Create attached file system targets... for cf_target in fs_conf.iter_targets(): server = _get_servers(cf_target.get_nodename(), fs_conf) # retrieve config variables cf_t_type = cf_target.get_type() cf_t_mode = cf_target.get_mode() cf_t_index = cf_target.get_index() cf_t_dev = cf_target.get_dev() cf_t_jdev = cf_target.get_jdev() cf_t_group = cf_target.get_group() cf_t_tag = cf_target.get_tag() cf_t_net = cf_target.get_network() # filter on target types, indexes, groups and nodes target_action_enabled = True if (target_types is not None and cf_t_type not in target_types) or \ (indexes is not None and cf_t_index not in indexes) or \ (groups is not None and \ (cf_t_group is None or cf_t_group not in groups)): target_action_enabled = False target = fs.new_target(server, cf_t_type, cf_t_index, cf_t_dev, cf_t_jdev, cf_t_group, cf_t_tag, target_action_enabled, cf_t_mode, cf_t_net) # Now the device is instanciated, we could check label name if labels is not None and target.label not in labels: target.action_enabled = False # add failover hosts for ha_node in cf_target.ha_nodes(): server = _get_servers(ha_node, fs_conf) target.add_server(server) # Change current server if failover nodes are used. if failover and len(failover) and target.action_enabled: target.action_enabled = target.failover(failover) # Now that server is set, check explicit nodes and exclusion if (nodes is not None and target.server.hostname not in nodes) or \ (excluded is not None and target.server.hostname in excluded): target.action_enabled = False # Create attached file system clients... for client_node, mount_path, mount_options in fs_conf.iter_clients(): server = _get_servers(client_node, fs_conf) # filter on target types and nodes client_action_enabled = True if (target_types is not None and 'client' not in target_types) or \ (nodes is not None and server.hostname not in nodes) or \ (excluded is not None and server.hostname in excluded): client_action_enabled = False client = fs.new_client(server, mount_path, mount_options, \ client_action_enabled) # Now the device is instanciated, we could check label name if (labels is not None and client.label not in labels): client.action_enabled = False # Create attached file system routers... for router_node in fs_conf.iter_routers(): server = _get_servers(router_node, fs_conf) # filter on target types and nodes router_action_enabled = True if (target_types is not None and 'router' not in target_types) or \ (nodes is not None and server.hostname not in nodes) or \ (excluded is not None and server.hostname in excluded): router_action_enabled = False router = fs.new_router(server, router_action_enabled) # Now the device is instanciated, we could check label name if (labels is not None and router.label not in labels): router.action_enabled = False return fs
def setUp(self): self.fs = FileSystem('prepare') self.remotesrv = Server('remote', ['remote@tcp']) self.localsrv = Server(Utils.HOSTNAME, ['%s@tcp' % Utils.HOSTNAME]) self.fs.local_server = self.localsrv
class ProxyTest(unittest.TestCase): def setUp(self): self.fs = FileSystem('proxy') self.srv1 = Server(Utils.HOSTNAME, ["%s@tcp" % Utils.HOSTNAME]) disk = Utils.makeTempFilename() self.tgt = self.fs.new_target(self.srv1, 'mgt', 0, disk) self.act = self.fs._proxy_action('start', self.srv1.hostname, self.fs.components) self.info = StartTarget(self.tgt).info() def fakeprepare(action): return [action.fakecmd] self.act._prepare_cmd = types.MethodType(fakeprepare, self.act) def test_exec_fail(self): """simulate unable to run python""" self.act.fakecmd = '/bin/false' self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual(list(self.fs.proxy_errors.messages())[0], "Remote action start failed: No response") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_ERROR) def test_start_crash(self): """send a start message then crashes""" msg = shine_msg_pack(evtype='comp', info=self.info, status='start') self.act.fakecmd = 'echo "%s"; echo BAD; exit 1' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual(list(self.fs.proxy_errors.messages())[0], "Remote action start failed: \nBAD\n") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_ERROR) def test_start_ok(self): """send a start and done message""" msgs = [] msgs.append(shine_msg_pack(evtype='comp', info=self.info, status='start')) self.tgt.state = MOUNTED msgs.append(shine_msg_pack(evtype='comp', info=self.info, status='done')) self.act.fakecmd = 'echo "%s"' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_OK) def test_crash_after_start_ok(self): """send a start and done message and then crashes""" msgs = [] msgs.append(shine_msg_pack(evtype='comp', info=self.info, status='start')) self.tgt.state = MOUNTED msgs.append(shine_msg_pack(evtype='comp', info=self.info, status='done')) self.act.fakecmd = 'echo "%s"; echo Oops; exit 1' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual(list(self.fs.proxy_errors.messages())[0], "Remote action start failed: \n\nOops\n") self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_ERROR) def test_bad_object(self): """send a done message which fails update due to bad property""" msg = shine_msg_pack(evtype='comp', info=self.info, status='done') def buggy_update(self, other): self.wrong_property = other.wrong_property self.tgt.update = types.MethodType(buggy_update, self.tgt) self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual(str(list(self.fs.proxy_errors.messages())[0]), "Cannot read message (check Shine and ClusterShell " "version): 'MGT' object has no attribute " "'wrong_property'") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_OK) def test_cannot_unpickle(self): """send a forged message which fails due to bad pickle content""" msg = "%s%d:%s" % (SHINE_MSG_MAGIC, SHINE_MSG_VERSION, binascii.b2a_base64('bad content')) self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 1) self.assertEqual(str(list(self.fs.proxy_errors.messages())[0]), "Cannot unpickle message (check Shine and ClusterShell" " versions): pop from empty list") self.assertEqual(self.tgt.state, RUNTIME_ERROR) self.assertEqual(self.act.status(), ACT_OK) def test_compat_compname(self): """message with compname value is backward compatible""" msgs = [] msgs.append(shine_msg_pack(compname=self.tgt.TYPE, action='start', status='start', comp=self.tgt)) self.tgt.state = MOUNTED msgs.append(shine_msg_pack(compname=self.tgt.TYPE, action='start', status='done', comp=self.tgt)) self.act.fakecmd = 'echo "%s"' % '\n'.join(msgs) self.act.launch() self.fs._run_actions() self.fs._check_errors([MOUNTED], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.tgt.state, MOUNTED) self.assertEqual(self.act.status(), ACT_OK) def test_compat_msg_v2(self): """message shine version 2 is compatible""" class CustomEH(EventHandler): def __init__(eh): EventHandler.__init__(eh) eh.event = None def event_callback(eh, evtype, **kwargs): if kwargs['info'].actname != 'proxy': self.assertEqual(eh.event, None) eh.event = kwargs # v2-style message: # comp=mgt, action=start, status=failed, rc=1, message='fake error' msg = "SHINE:2:ev_starttarget_failed:gAJ9cQAoVQRjb21wcQFjU2hpbmUuTHV" \ "zdHJlLlRhcmdldApNR1QKcQIpgXEDfXEEKFUNZGVmYXVsdHNlcnZlcnEFY1No" \ "aW5lLkx1c3RyZS5TZXJ2ZXIKU2VydmVyCnEGKYFxB31xCChVBG5pZHNxCV1xC" \ "lUIZm9vQHRjcDBxC2FVCGhvc3RuYW1lcQxjQ2x1c3RlclNoZWxsLk5vZGVTZX" \ "QKTm9kZVNldApxDSmBcQ59cQ8oVQhfdmVyc2lvbnEQSwJVCV9hdXRvc3RlcHE" \ "RTlUHX2xlbmd0aHESSwBVCV9wYXR0ZXJuc3ETfXEUVQNmb29xFU5zdWJ1YlUG" \ "bW50ZGV2cRZVCC9kZXYvc2R6cRdVA3RhZ3EYTlUbX0NvbXBvbmVudF9fcnVub" \ "mluZ19hY3Rpb25zcRldcRpVC3N0YXR1c19pbmZvcRtOVQVpbmRleHEcSwBVDm" \ "FjdGlvbl9lbmFibGVkcR2IVQpsZGRfc3ZuYW1lcR5OVQVncm91cHEfTlUHbmV" \ "0d29ya3EgTlUKX2xkZF9mbGFnc3EhSwBVBV9tb2RlcSJVB21hbmFnZWRxI1UJ" \ "ZGV2X2lzYmxrcSSJVQNkZXZxJWgXVQZzZXJ2ZXJxJmgHVQpsZGRfZnNuYW1lc" \ "SdOVQVzdGF0ZXEoTlUEamRldnEpTlUIZGV2X3NpemVxKksAVQtmYWlsc2Vydm" \ "Vyc3ErY1NoaW5lLkx1c3RyZS5TZXJ2ZXIKU2VydmVyR3JvdXAKcSwpgXEtfXE" \ "uVQVfbGlzdHEvXXEwc2J1YlUHbWVzc2FnZXExVQpmYWtlIGVycm9ycTJVAnJj" \ "cTNLAXUu" self.fs.hdlr = CustomEH() self.act.fakecmd = 'echo "%s"' % msg self.act.launch() self.fs._run_actions() self.assertEqual(self.fs.hdlr.event['info'].actname, 'start') self.assertEqual(self.fs.hdlr.event['status'], 'failed') self.assertEqual(self.fs.hdlr.event['result'].retcode, 1) self.assertEqual(self.fs.hdlr.event['result'].message, 'fake error') self.fs._check_errors([OFFLINE], self.fs.components) self.assertEqual(len(self.fs.proxy_errors), 0) self.assertEqual(self.act.status(), ACT_OK)