python-kerberos + urllib2

(Wow, old post sitting in my draft box for eons.  Might be useful to someone …)

At work, I’ve been working on getting the planet RSS aggregator to work w/ mod_auth_kerb + wordpress-mu. Thankfully, I found this quite useful post:
http://selenic.com/pipermail/mercurial/2008-June/019776.html

With this very useful snippet of code:
http://selenic.com/pipermail/mercurial/attachments/20080624/ec728dbb/attachment.py

#!/usr/bin/python

# urllib2 with kerberos proof of concept
# Copyright 2008 Lime Spot LLC

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# A copy of the GNU General Public License can be found at
# .

import re
import logging
import sys
import urllib2 as u2

import kerberos as k

def getLogger():
log = logging.getLogger(“http_negotiate_auth_handler”)
handler = logging.StreamHandler()
formatter = logging.Formatter(‘%(asctime)s %(levelname)s %(message)s’)
handler.setFormatter(formatter)
log.addHandler(handler)
return log

log = getLogger()

class HTTPNegotiateAuthHandler(u2.BaseHandler):
“””auth handler for urllib2 that does HTTP Negotiate Authentication
“””

rx = re.compile(‘(?:.*,)*\s*Negotiate\s*([^,]*),?’, re.I)
handler_order = 480 # before Digest auth

def negotiate_value(self, headers):
authreq = headers.get(‘www-authenticate’, None)

if authreq:
mo = HTTPNegotiateAuthHandler.rx.search(authreq)
if mo:
return mo.group(1)
else:
log.debug(“regex failed on: %s” % authreq)

else:
log.debug(“www-authenticate header not found”)

return None

def __init__(self):
self.retried = 0
self.context = None

def generate_request_header(self, req, headers):
neg_value = self.negotiate_value(headers)
if neg_value is None:
self.retried = 0
return None

if self.retried >= 5:
raise HTTPError(req.get_full_url(), 401, “negotiate auth failed”,
headers, None)

self.retried += 1

log.debug(“req.get_host() returned %s” % req.get_host())
result, self.context = k.authGSSClientInit(“HTTP@%s” % req.get_host())

if result < 1:
log.warning(“authGSSClientInit returned result %d” % result)
return None

log.debug(“authGSSClientInit() succeeded”)

result = k.authGSSClientStep(self.context, neg_value)

if result < 0:
log.warning(“authGSSClientStep returned result %d” % result)
return None

log.debug(“authGSSClientStep() succeeded”)

response = k.authGSSClientResponse(self.context)
log.debug(“authGSSClientResponse() succeeded”)

return “Negotiate %s” % response

def authenticate_server(self, headers):
neg_value = self.negotiate_value(headers)
if neg_value is None:
log.critical(“mutual auth failed. No negotiate header”)
return None

if k.authGSSClientStep(self.context, neg_value) < 1:
log.critical(“mutual auth failed: authGSSClientStep returned result %d” % result)

def clean_context(self):
if self.context is not None:
k.authGSSClientClean(self.context)

def http_error_401(self, req, fp, code, msg, headers):
log.debug(“inside http_error_401″)
try:
neg_hdr = self.generate_request_header(req, headers)

if neg_hdr is None:
log.debug(“neg_hdr was None”)
return None

req.add_unredirected_header(‘Authorization’, neg_hdr)
resp = self.parent.open(req)

self.authenticate_server(resp.info())

return resp

finally:
self.clean_context()

def test():
log.setLevel(logging.DEBUG)
log.info(“starting test”)
opener = u2.build_opener()
opener.add_handler(HTTPNegotiateAuthHandler())
resp = opener.open(sys.argv[1])
print dir(resp), resp.info(), resp.code

if __name__ == ‘__main__’:
test()

Packages to come, and hopefully I’ll get the patch pushed upstream soon.

Moving iPhoto onto a portable hard drive…

Found this gem:

http://support.apple.com/kb/HT1229

Moving ~110gb off of Janel’s laptop and onto more easily expandable storage.

wordpress-mu-2.8.5.2 RPMs available

I rolled 2.8.5.2 out for wpmu yesterday; updates haven’t hit yet, but you should be able to snag packages from koji.  Some security and bug fixes in there.

I still need to file a ticket to get it into F12, since it’s getting a little late to make a change there.

Centralized Home Storage

The Problem

A few months ago, my wife started running out of room on her Mac Book Pro. I’d purchased her a nice little Western Digital USB drive to use as her Time Machine backup target, but now she needed to start using it for her primary digital photo storage.  I considered looking into replacing her laptop’s internal drive, but that seemed more of a band-aid than anything else.

I’d tried using a HP Media Vault (MV2010) for network storage previously, but without significant hacking, I would be limited to ~300gb of mirrored space.  With the wife likely to be getting a DSLR in the near future, and my desire to start backing up all the videos I’ve been taking lately, the existing hardware seemed to be a deal-breaker.

The Strategy

Still, centralized storage seemed to be the right way to go for long-term scaling.  I took stock of what was available to me around the house:

  1. Gigabit wired network
  2. Wireless-N WiFi router (Linksys WRT610N)
  3. Older multi-core Linux machine
  4. 4 spare SATA drives

I was reluctant to try just another NAS machine; given that I had a machine to turn into a dedicated home server, Direct-Attached-Storage (DAS) seemed to make more sense.  Not only would I be less likely to run into embedded-OS pains, but the more modular approach would help future upgrade plans.

The next question to answer was technology would connect the server to the drives?  USB 2.0 would be far too slow, and version 3 is still a ways out, and likely to have some painful initial costs.  The remaining choices were eSATA and Serial-Attached-Storage (SAS).

eSATA has become a fairly commodity-level technology; it seems particularly tied to the expansion of DVRs that utilize it for local storage expansion.  When you’re dealing w/ a single external device, there are zero cons to going this route, but I was envisioning an expandable array, maxing out at perhaps 8 devices.  Most eSATA implementations would utilize port-multiplication, and here’s the eSATA gotcha:  you end up dividing the effective bandwidth of your cable.  With projected workloads including virtualization and multimedia-streaming, I didn’t want to incur those penalties.

SAS is a standard both for connectors and cables, as well as drives, but most folks use commodity SATA drives with SAS controllers.  Using cheap SAS-SATA connectors, you can drive up to 4 SATA devices off of one multi-lane SAS connection.  You can even use specialized hardware (edge and fan-out expanders) to vastly increase the number of devices supported.  The only downside is that SAS is a new technology, with not a ton of hardware or driver support out there.

The Hardware

After crunching some numbers in a Google Docs spreadsheet, I took the plunge and ordered:

The total ended up being about $330 USD (I purchased an open-box ARC-1300 for ~$100, regularly ~$160).  This will get the array started for the 4 devices I already have; I’ll eventually need to order another controller card and cable to support the eventual final 4 hard drives.

Here’s a shot of the case w/ the cover off:

addonics tower (cover off)

The build quality is excellent; beveled edges everywhere meant very few nicks and gouges for my fingers… always appreciated :)

Adding in the extra multilane-to-SATA bridge board proved trivial; I just removed one of the SCSI punch-outs on the back of the case, and screwed the board in place.  As you can see, not much to the board itself:

ad4saml multilane connector

I’m also using an existing SATA drive cage to temporarily keep costs down; I’ll migrate to 8 external mobile racks as future budget permits:

supermicro sata 5x raid cage

I ran into one annoyance–the multilane cable did not like the screw-holes on the bridge board:

highpoint cable + bridge mismatch

Some cursing and 5 minutes with a small set of pliers later, the issue was fixed:acceptor screws removed

Operating System & Drivers

Recent versions (2.6.32+?) of the Linux kernel support the areca 1300 card via the mvsas driver.  Thankfully, Red Hat has backported the majority of the driver to RHEL 5.4; I only had to add the following patch to get the driver to recognize the card and the attached drives:

diff -up ./mvsas.c.orig ./mvsas.c
— ./mvsas.c.orig      2009-11-01 08:18:41.000000000 -0500
+++ ./mvsas.c   2009-11-01 08:18:41.000000000 -0500
@@ -69,6 +69,9 @@

#define  SAS_PROTOCOL_ALL SAS_PROTO_ALL

+#define PCI_DEVICE_ID_ARECA_1300       0×1300
+#define PCI_DEVICE_ID_ARECA_1320       0×1320
+
/* driver compile-time configuration */
enum driver_configuration {
MVS_TX_RING_SZ          = 1024, /* TX ring size (12-bit) */
@@ -482,6 +485,8 @@ enum chip_flavors {
chip_6320,
chip_6440,
chip_6485,
+        chip_1300,
+        chip_1320
};

enum port_type {
@@ -678,6 +683,8 @@ static const struct mvs_chip_info mvs_ch
[chip_6320] =           { 2, 16, 9  },
[chip_6440] =           { 4, 16, 9  },
[chip_6485] =           { 8, 32, 10 },
+        [chip_1300] =           { 4, 16, 9  },
+        [chip_1320] =           { 4, 64, 9  },
};

static struct scsi_host_template mvs_sht = {
@@ -2816,6 +2823,8 @@ static struct pci_device_id __devinitdat
},
{ PCI_VDEVICE(MARVELL, 0×6440), chip_6440 },
{ PCI_VDEVICE(MARVELL, 0×6485), chip_6485 },
+       { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
+       { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },

{ }     /* terminate list */
};

RAID & LVM Configuration

When I was doing my initial research, I was very interested in the Drobo Pro; its RAID-6′ish configuration and aesthetic design were pretty compelling.  The $1500 USD price-tag, on the other hand, was not.

At this point, given how ridiculously cheap SATA drives are, I’m just going to use a combination of RAID1 and LVM.  Yes, I know, RAID6 could be pretty compelling, but I’ve got sets of mis-matched drives, so pairing them up based upon capacity seems like the smartest move for now.

For every two-drive set, I’ll create a new /dev/mdX device using mdadm.

mdadm –create /dev/md0 –level=raid1 –raid-devices=2 /dev/sdb /dev/sdc

mdadm –create /dev/md1 –level=raid1 –raid-devices=2 /dev/sdd /dev/sde

Each mdX device will then be added in turn to a vg_storage LVM volume group.  I’ll spin logical volumes off that volume group as needed.

[root@localhost ~]# vgscan
Reading all physical volumes.  This may take a while…
Found volume group “vg_system” using metadata type lvm2
[root@localhost ~]# lvscan
ACTIVE            ‘/dev/vg_system/lv_root’ [68.59 GB] inherit
ACTIVE            ‘/dev/vg_system/lv_swap’ [5.81 GB] inherit
[root@localhost ~]# pvcreate /dev/md0
Physical volume “/dev/md0″ successfully created
[root@localhost ~]# pvcreate /dev/md1
Physical volume “/dev/md1″ successfully created
[root@localhost ~]# pvscan
PV /dev/sda2 VG vg_system lvm2 [74.41 GB / 0 free]
PV /dev/md0 lvm2 [149.05 GB]
PV /dev/md1 lvm2 [279.46 GB]
Total: 3 [502.92 GB] / in use: 1 [74.41 GB] / in no VG: 2 [428.51 GB]
[root@localhost ~]# vgcreate vg_storage /dev/md0 /dev/md1
Volume group “vg_storage” successfully created
[root@localhost ~]# vgdisplay vg_storage
— Volume group —
VG Name vg_storage
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 2
Act PV 2
VG Size 428.50 GB
PE Size 4.00 MB
Total PE 109697
Alloc PE / Size 0 / 0
Free PE / Size 109697 / 428.50 GB
VG UUID AN7IqW-UBsQ-D55g-vUmh-z6h0-wC49-l09oaz

So, I now have ~430GB of storage available for new logical volumes!

I’ll probably pick up 2 x 1TB drives at some point to replace the old SATA-I device (md0); that’ll be a future post on migrating physical volumes out of an LVM volume group :)

Logical Volumes & Filesystems

I did some research on alternative filesystems, such as ZFS or btrfs, but they don’t seem quite ready yet.  Once btrfs gets RAID-6 and is declared production ready, then about the only other thing I’d like to see is some of the storage-virtualization functionality present in the Drobo Pro.  For now, though, ext3 logical volumes on the infrastructure defined above should more than meet my needs.

wordpress-mu-2.8.2 rpm’s in Fedora 12

Just rolled wordpress-mu-2.8.2 into Fedora 12 stream; I’m going to play around w/ it a bit; if it works well, I’ll probably extend it to F11 & F10.

Includes some XSS security fixes coming out of the Black Hat conference.

Need storage enclosure…

So, Janel filled up her laptop’s hard drive. I got her one of those little Western Digital external usb drives, and it’s nice and all, but we really are starting to need centralized storage for the house.

I’ve got a number of old drives, and even a 5-bay raid array to hold them in, but no actual case to hold it all in.

Ideally, I’d like something that’s about mini-tower-sized or less, and just holds the drives, fan, and power supply. Would be happy w/ ESATA, regular SATA, or SAS connections.

Something like this tower from addonics: http://www.addonics.com/products/raid_system/st_series.asp

Anyone have recommendations?

gregdek has a posse!

So, apparently, there was a poster of this in downtown Toronto.  I need to turn this into a t-shirt.

Follow

Get every new post delivered to your Inbox.