1
0
mirror of https://github.com/systemd/systemd synced 2024-07-08 20:15:55 +00:00

storagetm: add new systemd-storagetm component

This implements a "storage target mode", similar to what MacOS provides
since a long time as "Target Disk Mode":

        https://en.wikipedia.org/wiki/Target_Disk_Mode

This implementation is relatively simple:

1. a new generic target "storage-target-mode.target" is added, which
   when booted into defines the target mode.

2. a small tool and service "systemd-storagetm.service" is added which
   exposes a specific device or all devices as NVMe-TCP devices over the
   network.  NVMe-TCP appears to be hot shit right now how to expose
   block devices over the network. And it's really simple to set up via
   configs, hence our code is relatively short and neat.

The idea is that systemd-storagetm.target can be extended sooner or
later, for example to expose block devices also as USB mass storage
devices and similar, in case the system has "dual mode" USB controller
that can also work as device, not just as host. (And people could also
plug in sharing as NBD, iSCSI, whatever they want.)

How to use this? Boot into your system with a kernel cmdline of
"rd.systemd.unit=storage-target-mode.target ip=link-local", and you'll see on
screen the precise "nvme connect" command line to make the relevant
block devices available locally on some other machine. This all requires
that the target mode stuff is included in the initrd of course. And the
system will the stay in the initrd forever.

Why bother? Primarily three use-cases:

1. Debug a broken system: with very few dependencies during boot get
   access to the raw block device of a broken machine.

2. Migrate from system to another system, by dd'ing the old to the new
   directly.

3. Installing an OS remotely on some device (for example via Thunderbolt
   networking)

(And there might be more, for example the ability to boot from a
laptop's disk on another system)

Limitations:

1. There's no authentication/encryption. Hence: use this on local links
   only.

2. NVMe target mode on Linux supports r/w operation only. Ideally, we'd
   have a read-only mode, for security reasons, and default to it.

Future love:

1. We should have another mode, where we simply expose the homed LUKS
   home dirs like that.

2. Some lightweight hookup with plymouth, to display a (shortened)
   version of the info we write to the console.

To test all this, just run:

    mkosi --kernel-command-line-extra="rd.systemd.unit=storage-target-mode.target" qemu
This commit is contained in:
Lennart Poettering 2023-10-27 14:25:49 +02:00
parent 3b516db71d
commit 1761066b13
7 changed files with 1116 additions and 1 deletions

View File

@ -1533,6 +1533,8 @@ have = get_option('sysupdate').require(
error_message : 'fdisk and openssl required').allowed()
conf.set10('ENABLE_SYSUPDATE', have)
conf.set10('ENABLE_STORAGETM', get_option('storagetm'))
have = get_option('importd').require(
conf.get('HAVE_LIBCURL') == 1 and
conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and
@ -2196,10 +2198,11 @@ subdir('src/systemctl')
subdir('src/sysupdate')
subdir('src/sysusers')
subdir('src/sysv-generator')
subdir('src/storagetm')
subdir('src/timedate')
subdir('src/timesync')
subdir('src/tpm2-setup')
subdir('src/tmpfiles')
subdir('src/tpm2-setup')
subdir('src/tty-ask-password-agent')
subdir('src/update-done')
subdir('src/update-utmp')
@ -2793,6 +2796,7 @@ foreach tuple : [
['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1],
['sysupdate'],
['sysusers'],
['storagetm'],
['timedated'],
['timesyncd'],
['tmpfiles'],

View File

@ -158,6 +158,8 @@ option('quotacheck', type : 'boolean',
description : 'support for the quotacheck tools')
option('sysusers', type : 'boolean',
description : 'support for the sysusers configuration')
option('storagetm', type : 'boolean',
description : 'support for Storage Target Mode')
option('tmpfiles', type : 'boolean',
description : 'support for tmpfiles.d')
option('importd', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },

11
src/storagetm/meson.build Normal file
View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
executables += [
libexec_template + {
'name' : 'systemd-storagetm',
'conditions' : [
'ENABLE_STORAGETM',
],
'sources' : files('storagetm.c'),
},
]

1047
src/storagetm/storagetm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -559,6 +559,14 @@ units = [
'conditions' : ['ENABLE_SYSUSERS'],
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-storagetm.service.in',
'conditions' : ['ENABLE_STORAGETM'],
},
{
'file' : 'storage-target-mode.target',
'conditions' : ['ENABLE_STORAGETM'],
},
{
'file' : 'systemd-time-wait-sync.service.in',
'conditions' : ['ENABLE_TIMESYNCD'],

View File

@ -0,0 +1,16 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Storage Target Mode
Documentation=man:systemd.special(7)
Wants=systemd-storagetm.service systemd-udevd.service systemd-udev-trigger.service systemd-networkd.service systemd-network-generator.service systemd-journald.socket systemd-journald-dev-log.socket
Conflicts=rescue.service rescue.target
After=systemd-storagetm.service systemd-udevd.service systemd-udev-trigger.service systemd-networkd.service systemd-network-generator.service systemd-journald.socket systemd-journald-dev-log.socket rescue.service rescue.target
AllowIsolate=yes

View File

@ -0,0 +1,27 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Storage Target Mode (NVMe-TCP)
Documentation=man:systemd-storagetm.service(8)
ConditionVirtualization=!container
DefaultDependencies=no
Wants=modprobe@nvmet_tcp.service modprobe@thunderbolt_net.service sys-kernel-config.mount
After=modprobe@nvmet_tcp.service modprobe@thunderbolt_net.service sys-kernel-config.mount
Conflicts=shutdown.target
Before=shutdown.target
FailureAction=reboot
SuccessAction=reboot
[Service]
Type=notify
RemainAfterExit=yes
StandardInput=tty
StandardOutput=tty
ExecStart={{LIBEXECDIR}}/systemd-storagetm --all