‘Simple’ were the requirements for this evening: When I plug in my USB drive into my Openstack(ubuntu) server, i want it to automatically start backing up vm-harddisks.
Well, that sounds easy. But ubuntu doesn’t always assign the same device-node to my usb drive. Sometimes its /dev/sdc1 and sometimes its /dev/sdb1 … so first order of business is to get ubuntu to assign the same device node, and mount point to my usb disk.
UDEV
So after some research, i found this very straight-forward method to achieve just what i wanted. ‘udev’ is a nifty little tool that can map a device to the same device-node.
How? You can tell it some unique properties of the device, and if it matches those properties, you can tell it which device-node (or symlink to assign). And finally, we can tell it to mount the device node to a static mount-point when the device is plugged in.
- Find a set of attributes unique to this device
- Use custom udev-rules to assign a static device-node when these properties are seen
- Use kernel events to mount this device-node to a static mount-point
1. Find a set of attributes unique to this device
We’re looking for details about our USB drive – unique details. First lets find our current usb device-node using disk.
root@core ~# fdisk -l | grep "^/dev/"
/dev/sda1 * 122880 999423 438272 83 Linux
/dev/sda2 1001472 39061503 19030016 8e Linux LVM
/dev/sdb1 2 488397167 244198583 b W95 FAT32
/dev/sdd1 2 976773167 488386583 b W95 FAT32
The USB drive I’m interested in is ‘/dev/sdd1’ . So lets find out some unique attributes to identify this same exact device every time.
There is a very good tutorial on udev rules here. Or you can simply walk all the available properties using the command
‘ udevadm info –attribute-walk –name=/dev/sdd1’
The unique properties I picked for my device are :
SUBSYSTEM==”block”, ATTRS{serial}==”20150128002380F”
2. Creating custom udev-rules
Now, whenever the above properties match, i want my device-node to be /dev/nascopy.
So i just create a new ‘udev-rule’ under a new file /etc/udev/rules.d/99-custom.rules
( why did I use this name? See the link on udev rules above. The author has explained this in detail )
Now this file reads:
SUBSYSTEM==”block”,ATTRS{serial}==”20150128002380F”, SYMLINK+=”nascopy”
Now tail /var/log/syslog and plug in your USB drive . It will get assigned to /dev/nascopy. Unplug , and it will disappear.
3. Auto-Mounting, and Backups
This part is easy. The same udev also listens to kernel events “add/remove” and can fire an action when the USB device is added/removed.
To identify the USB device we have to provide info about the ENV of the device that was added/removed.
In this case, since we assigned the name ‘nascopy’, the ‘DEVLINKS’ env variable has the word ‘nascopy’ in it. So we can use that as a filter to trigger an action (namely mount the device, and kick off backups). So here is an extra line for my 99-custom.rules:
ACTION==”add”, ENV{DEVLINKS}==”nascopy“, RUN+=”/bin/mkdir /nascopy”, RUN+=”/bin/mount /dev/nascopy /nascopy”
This basically says => When a device is added , and its DEVLINKS matches “nascopy” then create a mount-point and mount it.
The full custom.rules file looks like this:
root@core ~#
root@core ~# cat /etc/udev/rules.d/80-custom.rules
SUBSYSTEM=="block",ATTRS{serial}=="20150128002380F", SYMLINK+="nascopy"
ACTION=="add", ENV{DEVLINKS}=="<em>nascopy</em>", RUN+="/bin/mkdir /nascopy", RUN+="/bin/mount /dev/nascopy /nascopy"
ACTION=="remove", ENV{DEVLINKS}=="<em>nascopy</em>", RUN+="/bin/umount /nascopy", RUN+="/bin/rmdir /nascopy"
( To get other ENV details, run “udevadm monitor –environment –udev” while plugging in the device. )
And thats it. With other RUN+ commands, you can kick off an rsync (which is incidentally what I’m doing)