Mac is pretty, and very GUI, but getting real data about what’s going on can be a PITA.
Want to know how to list the luns and storage controllers that your Mac client can see?
fibreconfig -l
(and you can rescan with -r!). Note the english spelling of fibre.
–Jason
When did I last run FSCK?
aka ‘how long has it been since I ran fsck?’
Answer: run ‘tune2fs -l <device>’ and look at
Mount count: 2
Maximum mount count: 36
Last checked: Tue Sep 6 23:12:36 2011
Check interval: 15552000 (6 months)
Next check after: Sun Mar 4 23:12:36 2012
If the mount count = max mount count, you’re due for an FSCK. If you’re booting after the ‘Check interval’, (which is helpfully calculated for you on the ‘Next check after:’ line), you’re due for an FSCK.
Knowing if your scheduled reboot will take several hours in order to run the FSCK? Priceless.
PIPA letter to Georgia Senators
(Not directly Sysadmin related, but important none the less. Here are letters I’m sending to my Senators, both of whom are co-sponsors of the PIPA or Protect IP Act)
Please use these as templates or replace <NAME> and <ADDRESS> with the appropriate values.
###########################################################################
The Honorable Saxby Chambliss
416 Russell Senate Office Building
United States Senate
Washington DC 20510
Dear Senator:
My name is <NAME> and my address is <ADDRESS>. I am writing you because I am deeply disappointed that you are not only supporting the Protect IP Act (aka PIPA, aka S.968), but are actually a co-sponsor of the proposed legislation.
As written, PIPA would destroy the progress of the Internet over the past 15 years. You well know how important that growth has been to the country as a whole, and Atlanta/Columbus/Savannah in particular. The entire ‘Web 2.0′ movement is founded on user generated content as well as enabling small entities (businesses and persons) to work together and build amazing things. The provisions of PIPA would work to destroy this foundation by significantly decreasing due process for ‘take down’ requests, while drastically increasing the ‘damage radius’ of such requests (such as forcing Ad-networks, search engines, DNS servers, etc to ‘delist’ entire sites for having a single bit of infringing content.)
No one denies that intellectual property piracy is a real problem. There are possible legal remedies to these challenges, however PIPA is a very dangerous solution to these problems.
Please retract your support and sponsorship of the PIPA (S.968) immediately.
Thank you,
<NAME>
###########################################################################
The Honorable Johnny Isakson
131 Russell Senate Office Building
United States Senate
Washington DC 20510
Dear Senator:
My name is <NAME> and my address is <ADDRESS>. I am writing you because I am deeply disappointed that you are not only supporting the Protect IP Act (aka PIPA, aka S.968), but are actually a co-sponsor of the proposed legislation.
As written, PIPA would destroy the progress of the Internet over the past 15 years. You well know how important that growth has been to the country as a whole, and Atlanta/Columbus/Savannah in particular. The entire ‘Web 2.0′ movement is founded on user generated content as well as enabling small entities (businesses and persons) to work together and build amazing things. The provisions of PIPA would work to destroy this foundation by significantly decreasing due process for ‘take down’ requests, while drastically increasing the ‘damage radius’ of such requests (such as forcing Ad-networks, search engines, DNS servers, etc to ‘delist’ entire sites for having a single bit of infringing content.)
No one denies that intellectual property piracy is a real problem. There are possible legal remedies to these challenges, however PIPA is a very dangerous solution to these problems.
Please retract your support and sponsorship of the PIPA (S.968) immediately.
Thank you,
<NAME>
boo.
(double boo for not posting anything in nearly 6 months)
From what I can tell, Xen 3.0.3 (shipped with CentOS / RHEL 5) does NOT support NPIV for SAN attached storage. Looks like it works just fine with CentOS 6 though. The frustrating thing is that all the pieces are there for it to work… /sys/class/scsi_host/host?/vport_create and _destroy work as they should, you can zone storage to the new vports… you just can’t present the lun form:
npiv:
to the guest.
boo. SysOps will upgrade the xen stuff next year at some point.
Follow up from an earlier post
Turns out to be a known issue. hooray.
http://oss.oracle.com/ol5/docs/RELEASE-NOTES-U6-en
–Jason
If any of you run SSL sites…
Use this tool to check the SSL config.
You’ll be happy.
linux multipath is making me tired.
So, I’ve got a multipath setup that claims to be working:
# multipath -ll
vrp (360060e8010053b90052fb06900000190) dm-8 HITACHI,DF600F
size=70G features=’0′ hwhandler=’0′ wp=rw
`-+- policy=’round-robin 0′ prio=1 status=active
|- 6:0:0:0 sdc 8:32 active ready running
`- 5:0:0:0 sdb 8:16 active ready running
sweet right?
Until you test it. For some reason, the above setup isn’t ’round-robin’, it’s only using one path. If you kill the inactive link (unplug, port disable, whatever), it works fine. Reconnect, and it recovers. If you kill the active link, well, the world blows up on you (read-only file system, etc).
The above is with Oracle Enterprise Linux 5.6 (aka oracle unbreakable linux) and device-mapper-multipath-0.4.9-23.0.8.el5 (which is the latest supported version AFAICT). I’ll update or post again when/if I get this solved.
lvresize is my friend
Everyone is fearful of resizing volumes.
Linux has made it pretty easy though, provided you’re using LVM (lvm2 that is), and ext3 filesystems. Tested on Redhat 5.6 (aka Oracle Enterprise Linux aka CentOS). One command which will grow or shrink both the volume and the file system.
lvresize!
Note: if you’re resizing down (shrinking), you’ll need to umount the shrinking volume first. If it is mounted, it’ll ask you to do it for you.
Say you need to move 20GB from /home, to /var, and they’re in the same VG:
umount /home lvresize --resizefs -L -20G /dev/mapper/localdisks-home lvresize --resizefs -L +20G /dev/mapper/localdisk-var mount /home
Done! (though the shrink command will take a little bit of time to finish)
tcpdump and error 1448
If you use tcpdump, and see ‘reply ERR 1448′, you’re hitting a bug in tcpdump. Use tshark instead.
Tcpdump isn’t reassembling NFS packets correctly.
FYI
Create Luns in an AMS2500 easily.
If you’re like me, you’ve got an AMS2000 series (2100, 2300, 2500) array, and you’re using HDP pools, since they’re SO MUCH EASIER than regular RAID groups.
If you’re also like me, you’re using SNM2[1] to manage this thing, and it is an amazingly slow GUI. But SNM2 has a CLI! So that’s better, right? Sorta… you have to log in with each command you want to run…
So I’ve written a python script which creates LU[2] of specified size. You can download my lu-maker.py here, or you can look at it below.
–Jason
[1] Storage Navigator Modular 2
[2] or LUNS (not presented to the hosts yet), or LDEV’s if you’re from USP land…
#!/usr/bin/python import os import os.path import subprocess import sys import time unit = 'tc3ams2500' user = 'my_username_you_silly_boy' passwd = 'my_password_you_silly_boy' def usage() : """print usage information and exit""" print "USAGE:" print "%s -p <pool#> size1 [size2 ... sizeN] [-p <pool#> size1 ...] ..." % sys.argv[0] print 'a size can be either:' print '"100" for 100gb or' print '"10x50" for creating ten different 50gb luns' sys.exit(-1) def whereis(program): """Validate if a program is in your $PATH variable""" for path in os.environ.get('PATH', '').split(':'): if os.path.exists(os.path.join(path, program)) and \ not os.path.isdir(os.path.join(path, program)): return os.path.join(path, program) return None def isint(arg) : """Validate if a string passed on the command line is an integer.""" try : int(arg) except ValueError : return False return True def validsize(arg) : """validate if an argument is a valid size argument. Either it must be an integer (indicating a size of one lun) or it must be in the form #x# or <number>x<number> which indicates a count of luns to be created of a specific size. For example: 10x50 would mean 10 luns of size 50gb should be created """ if isint(arg) : return True elif 'x' in arg : try : count, size = arg.split('x') except : return False if isint(count) and isint(size) : return True return False def parsesize(arg) : """once a size specification is validated, it can be more easily parsed. Run as a generator to yeild the right number of sizes """ if isint(arg) : yield arg else : count,size = arg.split('x') for i in range(int(count)) : yield size def runcmd(cmdstr, dashy=False) : """run command abstracts away the subprocess module, and the vagarities of the SNM2 CLI. Deals with the login prompt and the password prompt. if dashy is True, also respond the a third question with a 'y\n' to deal with 'are you sure' type prompts. """ sleeptime = .2 cmdlist = cmdstr.split() if whereis(cmdlist[0]) == None : print "%s is not found in $PATH" % cmdlist[0] sys.exit(-1) p = subprocess.Popen( cmdlist, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE ) time.sleep(sleeptime) p.stdin.write(user + '\n') time.sleep(sleeptime) p.stdin.write(passwd + '\n') if dashy : time.sleep(sleeptime) p.stdin.write('y\n') stdout, stderr = p.communicate() return stdout, stderr, p.returncode def parselus(output) : """Takes the output of auluref, and finds any gaps in the list of LU's, and also gives the next free lu number. First parse the output, then find the gaps, then add 1 to the top lu number in existance, and return the holelist, and the next free. """ lulist = [] holelist = [] last = 0 for line in (line for line in output.split(os.linesep)) : uline = line.strip() words = uline.split() if len(words) > 0 and isint(words[0]) : lu = int(words[0]) lulist.append(lu) #find the gaps in lulist: last = 0 holelist = [] for lu in lulist : while True : tlast = last last += 1 if tlast >= lu : break holelist.append(tlast) return holelist, lulist[-1] + 1 def genlunumbers() : """Creates a generator to yield the next available lu number. First tries to fill any holes, and then just adds to the top. Uses auluref as a datasource. """ cmdstr = "auluref -unit %s" % unit stdout, stderr, returncode = runcmd(cmdstr) holelist, next = parselus(stdout) for lu in holelist : yield str(lu) lu = next while True : yield str(lu) lu += 1 def getpools() : """uses audppool to list the available DP pools. Used to validate if the passed pool numbers are valid. NOTE: The format of the audppool command is a little crazy. Short version of what follows: if the first 10 chars of any line start with a number (if the 10 chars are run through .split(), it's a valid pool. """ cmdstr = "audppool -unit %s -refer" % unit stdout, stderr, returncode = runcmd(cmdstr) poollist = [] for line in (line for line in stdout.split(os.linesep)) : uline = line[:10] words = uline.split() if len(words) == 0 : continue if isint(words[0]) : poollist.append(words[0]) return poollist def makelun(pool, size, lu) : """Actually makes a given lun in a specified pool, with a given size. """ #auluadd -unit tc3ams2500 [ -lu lun ] -dppoolno pool -size size + 'g' cmdstr = "auluadd -unit %s -lu %s -dppoolno %s -size %s" % (unit, lu, pool, size + 'g') print "making LU number %s from pool %s of size %s" % (lu, pool, size) #stdout, stderr, returncode = runcmd(cmdstr, dashy=True) print "NOTE: program currently nutered. Uncomment above line (and \ncomment out this line) to activate.\n I would normally run this command: \n", cmdstr def main() : """ Main: calls getpool, parses the command line arguments (in a way I'm not fully happy with). The last three lines make the luns. """ poollist = getpools() lunlist = [] #parse cmdline, build list of pool,size pairs if sys.argv[1] != '-p' : print 'must specify -p <pool number> first' usage() if isint(sys.argv[2]) and sys.argv[2] in poollist : pool = sys.argv[2] else : print 'pool number %s must be a valid pool number' % sys.argv[2] print 'valid pools are %s' % poollist usage() if validsize(sys.argv[3]) : for size in parsesize(sys.argv[3]) : lunlist.append( (pool, size) ) else : print 'invalid size specification: %s' % sys.argv[3] usage() nextispool = False for arg in sys.argv[4:] : if nextispool : if isint(arg) and arg in poollist : pool = arg nextispool = False else : print 'pool number %s must be a valid pool number' % sys.argv[2] print 'valid pools are %s' % poollist usage() elif arg == '-p' : nextispool = True elif validsize(arg) : for size in parsesize(arg) : lunlist.append( (pool,size) ) else : 'unknown error with arg %s' % arg usage() lu = genlunumbers() for pool,size in lunlist : makelun(pool, size, lu.next()) if __name__ == '__main__' : main()