Chris Hunt
Chris Hunt

Reputation: 4030

How can I dynamically mount an external USB hard drive in RancherOS?

Like the title states, I have RancherOS installed on a baremetal host and want to dynamically handle addition/removal of an external USB hard drive. It should be accessible as a bind mount for other containers.

Upvotes: 1

Views: 1482

Answers (1)

Chris Hunt
Chris Hunt

Reputation: 4030

You can do something like this:

# udev_config.yml
write_files:
- path: /etc/udev/rules.d/99-media-Storage-usb-drive.rules
  container: udev
  permissions: "0644"
  owner: root
  content: |
    ATTRS{ID_FS_UUID}!="161E-5755", GOTO="media_Storage_usb_drive_exit"
    ACTION=="add", \
      RUN{program}+="/usr/bin/udev-mount.sh -o nodev,noexec,nosuid,uid=1100,gid=5000,umask=007 $root/$name /media/Storage"
    ACTION=="remove", \
      RUN{program}+="/usr/bin/udev-umount.sh /media/Storage"
    LABEL="media_Storage_usb_drive_exit"
- path: /usr/bin/udev-mount.sh
  container: udev
  permissions: "0755"
  owner: root
  content: |
    #!/bin/sh
    set -e
    eval path=\${$#}
    system-docker exec console /usr/bin/mkdir -p "$path"
    system-docker exec console /usr/bin/mount "$@"
- path: /usr/bin/udev-umount.sh
  container: udev
  permissions: "0755"
  owner: root
  content: |
    #!/bin/sh
    system-docker exec console /usr/bin/umount "$@"

Then execute

sudo ros config merge -i udev_config.yml && sudo ros service restart udev

You can unplug and plug in your device or if you know your DEVNAME (see below) e.g. /dev/sdb1, execute

sudo system-docker exec udev udevadm trigger --action=add /dev/sdb1

There are several parts to this:

Dynamically taking action on hardware addition/removal

udev is a common tool for this job. udev(7) has information on its configuration.

In the example above:

ATTRS{ID_FS_UUID}!="161E-5755", GOTO="media_Storage_usb_drive_exit"
ACTION=="add", \
  RUN{program}+="/usr/bin/udev-mount.sh -o nodev,noexec,nosuid,uid=1100,gid=5000,umask=007 $root/$name /media/Storage"
ACTION=="remove", \
  RUN{program}+="/usr/bin/udev-umount.sh /media/Storage"
LABEL="media_Storage_usb_drive_exit"

In other examples online you may see KERNEL used, but this can be fragile as the specific name associated with an external device is not static. Here we use ID_FS_UUID. This and the other attributes associated with your device can be found by executing udevadm info /dev/sdb1 (as an example). It's important to use something that won't be overwritten or may be used by another hard drive. Other important information from this command includes DEVPATH and DEVNAME.

Configuring udev in RancherOS.

The configuration above would usually be placed into /etc/udev/rules.d/, but we need to put it in the correct /etc/udev/rules.d/.

In RancherOS the udev daemon (udevd) runs as a container, visible by executing:

sudo ros service ps

or

sudo system-docker ps

RancherOS system containers can be configured using cloud-config. We can write files into system containers using the write_files directive as demonstrated above.

Making mounts available to the console and other spawned docker containers.

By default the udev container doesn't share media volumes so we run the provided scripts which execute mount inside the console system container. It has the properties we need:

  • mount and umount available (unlike the docker container)
  • media-volumes mounted

Notes

  1. Be careful with paths in RUN commands, as non-absolute paths will be resolved relative to /usr/lib/udev/.
  2. You can view attributes of your device by executing udevadm info <device path> e.g. udevadm info /dev/sdb1.
  3. You can test your udev configuration in the console container (the default container that spawns when you ssh into RancherOS) you can place the file in /etc/udev/rules.d/ and test using e.g. udevadm test --action=add <DEVPATH>
  4. The logs for udevd are accessible via dmesg (per rancher/os#2253). udevadm --log-priority=debug sets the log level dynamically

Upvotes: 1

Related Questions