From ac4dcca44cbaad4a43557ace40fa674339b80f89 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sun, 12 May 2024 19:40:08 +0200 Subject: [PATCH] Add Tramp method "nspawn" * doc/misc/tramp.texi: Adapt some markups. (Inline methods) : Add. (Default Host): Mention default host for "nspawn". (Customizing Methods): Remove tramp-nspawn. (Password handling): Add "nspawn". * etc/NEWS: New Tramp method "nspawn". * lisp/net/tramp-compat.el (tramp-nspawn): Warn, if that package is used. * lisp/net/tramp-container.el (tramp-nspawn-program): New defcustom. (tramp-nspawn-method): New defconst. (tramp-nspawn--completion-function, tramp-enable-nspawn-method): New defuns. * lisp/net/tramp.el (tramp-local-host-regexp): Add OpenSUSE host names. (cherry picked from commit e53e8b4cf44be0fac0eb92c816b2c7915533e283) --- doc/misc/tramp.texi | 95 ++++++++++++++++++++----------------- etc/NEWS | 8 ++-- lisp/net/tramp-compat.el | 3 ++ lisp/net/tramp-container.el | 64 +++++++++++++++++++++++-- lisp/net/tramp.el | 6 ++- 5 files changed, 124 insertions(+), 52 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 7ec9746eb8b..8a375254eff 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -973,7 +973,12 @@ supports changing the remote login shell @command{/bin/sh}. Check the @samp{Share SSH connections if possible} control for that session. +@end table + +@noindent +The following methods allow to access containers in different ways: +@table @asis @item @option{docker} @cindex method @option{docker} @cindex @option{docker} method @@ -1032,6 +1037,14 @@ name, as returned by @samp{apptainer instance list}. This is an optional method, @ref{Optional methods}. It does not support user names. +@item @option{nspawn} +@cindex method @option{nspawn} +@cindex @option{nspawn} method + +Integration of @code{systemd-nspawn} instances. The host name is the +instance name, as returned by @samp{machinectl list --all}. + +This is an optional method, @ref{Optional methods}. @end table @@ -1256,9 +1269,9 @@ domain name). An example: @trampfn{smb,daniel%BIZARRE@@melancholia,/daniel$$/.emacs} @end example -where user @code{daniel} connects as a domain user to the SMB host -@code{melancholia} in the MS Windows domain @code{BIZARRE} to edit -@file{.emacs} located in the home directory (share @code{daniel$}). +where user @samp{daniel} connects as a domain user to the SMB host +@samp{melancholia} in the MS Windows domain @samp{BIZARRE} to edit +@file{.emacs} located in the home directory (share @samp{daniel$}). Alternatively, for local WINS users (as opposed to domain users), substitute the domain name with the name of the local host in @@ -1268,9 +1281,9 @@ UPPERCASE as shown here: @trampfn{smb,daniel%MELANCHOLIA@@melancholia,/daniel$$/.emacs} @end example -where user @code{daniel} connects as local user to the SMB host -@code{melancholia} in the local domain @code{MELANCHOLIA} to edit -@file{.emacs} located in the home directory (share @code{daniel$}). +where user @samp{daniel} connects as local user to the SMB host +@samp{melancholia} in the local domain @samp{MELANCHOLIA} to edit +@file{.emacs} located in the home directory (share @samp{daniel$}). The domain name and user name are optional for @command{smbclient} authentication. When user name is not specified, @command{smbclient} @@ -1702,8 +1715,8 @@ follows: @end group @end lisp -With all defaults set, @samp{@trampfn{-,,}} will connect @value{tramp} -to John's home directory on @code{target} via @code{ssh}. +With all defaults set, @file{@trampfn{-,,}} will connect @value{tramp} +to John's home directory on @samp{target} via method @option{ssh}. @end defopt @defopt tramp-default-host-alist @@ -1712,6 +1725,10 @@ allows multiple default host values based on access method or user name combinations. The alist can hold multiple values. While @code{tramp-default-host} is sufficient in most cases, some methods, like @option{adb}, require defaults overwritten. + +The default host name for @option{nspawn} is @samp{.host}. Therefore, +@file{@trampfn{nspawn,,}} and @file{@trampfn{sudo,,}} have the same +effect. @end defopt @@ -1938,17 +1955,6 @@ Access of a hadoop/hdfs file system. A file is accessed via the user that you want to use, and @samp{node} is the name of the hadoop server. -@item tramp-nspawn -@cindex method @option{nspawn} -@cindex @option{nspawn} method -Access to environments provided by systemd-nspawn. A file is accessed -via @file{@trampfn{nspawn,user@@container,/path/to/file}}, where -@samp{user} is the (optional) user that you want to use, and -@samp{container} is the container to connect to. systemd-nspawn and -its container utilities often require super user access to run, use -multi-hop file names with @option{doas} or @option{sudo} to raise your -privileges. - @item vagrant-tramp @cindex method @option{vagrant} @cindex @option{vagrant} method @@ -2118,11 +2124,12 @@ file name syntax, must be appended to the machine and login items: machine melancholia#4711 port davs login daniel%BIZARRE password geheim @end example -For the methods @option{doas}, @option{sudo} and @option{sudoedit} the -password of the user requesting the connection is needed, and not the -password of the target user@footnote{On the local host, @code{run0} -uses a graphical password agent.}. If these connections happen on the -local host, an entry with the local user and local host is used: +For the methods @option{doas}, @option{sudo}, @option{sudoedit} and +@option{nspawn} the password of the user requesting the connection is +needed, and not the password of the target user@footnote{On the local +host, @code{run0} uses a graphical password agent.}. If these +connections happen on the local host, an entry with the local user and +local host is used: @example machine @var{host} port sudo login @var{user} password secret @@ -2701,8 +2708,8 @@ its execution of @command{/bin/sh} on the remote host because Bourne shell does not recognize the export command as entered in @file{.profile}. -Likewise, (@code{~}) character in paths will cause errors because -Bourne shell does not do (@code{~}) character expansions. +Likewise, (@samp{~}) character in paths will cause errors because +Bourne shell does not do (@samp{~}) character expansions. One approach to avoiding these incompatibilities is to make all commands in @file{~/.shrc} and @file{~/.profile} Bourne shell @@ -3417,7 +3424,7 @@ configuration option will be selected, it can be @t{"--standard"} or @t{"--paranoia"}. See the @samp{encfs(1)} man page for details. However, @value{tramp} must adapt these configuration sets. The -@code{chainedNameIV} configuration option must be disabled; otherwise +@option{chainedNameIV} configuration option must be disabled; otherwise @value{tramp} couldn't handle file name encryption transparently. @end defopt @@ -3536,7 +3543,7 @@ on the remote host @var{host}, using the method @var{method}. @table @file @item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}.emacs For the file @file{.emacs} located in the home directory, on the host -@code{melancholia}, using method @code{ssh}. +@samp{melancholia}, using method @option{ssh}. @item @value{prefix}ssh@value{postfixhop}melancholia.danann.net@value{postfix}.emacs For the file @file{.emacs} specified using the fully qualified domain name of @@ -3546,12 +3553,12 @@ the host. For the file @file{.emacs} specified using the @file{~}, which is expanded. @item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}~daniel/.emacs -For the file @file{.emacs} located in @code{daniel}'s home directory -on the host, @code{melancholia}. The @file{~} construct is +For the file @file{.emacs} located in @samp{daniel}'s home directory +on the host, @samp{melancholia}. The @file{~} construct is expanded to the home directory of that user on the remote host. @item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}/etc/squid.conf -For the file @file{/etc/squid.conf} on the host @code{melancholia}. +For the file @file{/etc/squid.conf} on the host @samp{melancholia}. @end table @@ -3569,8 +3576,8 @@ different name using the proper syntax will override this default behavior: @file{@trampfn{method,user@@host,path/to/file}}. @file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file -@file{.emacs} in @code{daniel}'s home directory on the host, -@code{melancholia}, accessing via method @code{ssh}. +@file{.emacs} in @samp{daniel}'s home directory on the host, +@samp{melancholia}, accessing via method @option{ssh}. For specifying port numbers, affix @file{#} to the host name. For example: @file{@trampfn{ssh,daniel@@melancholia#42,.emacs}}. @@ -3603,8 +3610,8 @@ names. Beside the @code{default} value, @var{syntax} can be This remote file name syntax is similar to the syntax used by Ange FTP@. A remote file name has the form -@code{@value{prefix}user@@host@value{postfix}path/to/file}. The -@code{user@@} part is optional, and the method is determined by +@file{@value{prefix}user@@host@value{postfix}path/to/file}. The +@samp{user@@} part is optional, and the method is determined by @ref{Default Method}. @item @code{separate} @@ -3615,8 +3622,8 @@ A remote file name has the form @include trampver.texi This remote file name syntax originated in the XEmacs text editor. A remote file name has the form -@code{@trampfn{method,user@@host,path/to/file}}. The @code{method} -and @code{user@@} parts are optional. +@file{@trampfn{method,user@@host,path/to/file}}. The @samp{method} +and @samp{user@@} parts are optional. @clear separate @set unified @include trampver.texi @@ -3799,12 +3806,12 @@ Ad-hoc proxies can take patterns @code{%h} or @code{%u} like in @code{tramp-default-proxies-alist}. The following file name expands to user @samp{root} on host @samp{remotehost}, starting with an @option{ssh} session on host @samp{remotehost}: -@samp{@trampfn{ssh@value{postfixhop}%h|su,remotehost,}}. +@file{@trampfn{ssh@value{postfixhop}%h|su,remotehost,}}. On the other hand, if a trailing hop does not specify a host name, the host name of the previous hop is reused. Therefore, the following file name is equivalent to the previous example: -@samp{@trampfn{ssh@value{postfixhop}remotehost|su,,}}. +@file{@trampfn{ssh@value{postfixhop}remotehost|su,,}}. @defopt tramp-completion-multi-hop-methods When this list includes the last method in a multi-hop connection, the @@ -3831,8 +3838,8 @@ The buffer must either visit a file, or a directory @defopt tramp-file-name-with-method The method @code{tramp-revert-buffer-with-sudo} shows an alternate -buffer. It defaults to @code{sudo}, other valid methods are -@code{su}, @code{doas}, @code{run0}, and @code{ksu}. +buffer. It defaults to @option{sudo}, other valid methods are +@option{su}, @option{doas}, @option{run0}, and @option{ksu}. @lisp (customize-set-variable 'tramp-file-name-with-method "doas") @@ -4066,7 +4073,7 @@ follows in the local @file{.emacs} file: local host that the remote host can redirect X11 window interactions. If querying for a recognizable name is not possible for whatever reason, then replace @code{(getenv "DISPLAY")} with a -hard-coded, fixed name. Note that using @code{:0} for X11 display name +hard-coded, fixed name. Note that using @samp{:0} for X11 display name here will not work as expected. @vindex ForwardX11@r{, ssh option} @@ -4638,7 +4645,7 @@ specifies the target to be applied for renaming buffer file names from source via @code{tramp-rename-files}. @code{source} is a regular expressions, which matches a remote file name. @code{target} must be a directory name, which could be remote (including remote directories -@value{tramp} infers by default, such as @samp{@trampfn{method,user@@host,}}). +@value{tramp} infers by default, such as @file{@trampfn{method,user@@host,}}). @code{target} can contain the patterns @code{%m}, @code{%u} or @code{%h}, which are replaced by the method name, user name or host @@ -4667,7 +4674,7 @@ ssh@value{postfixhop}%h@value{postfix}") @end lisp routes all connections to a host in @samp{company.org} via -@samp{@trampfn{ssh,multi.hop,}}, which might be useful when using +@file{@trampfn{ssh,multi.hop,}}, which might be useful when using Emacs outside the company network. @lisp diff --git a/etc/NEWS b/etc/NEWS index c1827b3d19a..5239175b71f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1177,9 +1177,11 @@ This connection method is similar to "sudo", but it uses the These are the external methods counterparts of "docker" and "podman". +++ -*** New optional connection methods "toolbox", "flatpak" and "apptainer". -They allow accessing system containers provided by Toolbox, sandboxes -provided by Flatpak, or instances managed by Apptainer. +*** New optional connection methods for containers. +Tere are new optional connection methods "toolbox", "flatpak", +"apptainer" and "nspawn". They allow accessing system containers +provided by Toolbox, sandboxes provided by Flatpak, instances managed by +Apptainer, or accessing systemd-based light-weight containers.. +++ *** Connection method "kubernetes" supports now optional container name. diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index d7492be63f2..26c2049fbae 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -55,6 +55,9 @@ (with-eval-after-load 'kubernetes-tramp (warn (concat "Package `kubernetes-tramp' has been obsoleted, " "please use integrated package `tramp-container'"))) +(with-eval-after-load 'tramp-nspawn + (warn (concat "Package `tramp-nspawn' has been obsoleted, " + "please use integrated package `tramp-container'"))) ;; For not existing functions, obsolete functions, or functions with a ;; changed argument list, there are compiler warnings. We want to diff --git a/lisp/net/tramp-container.el b/lisp/net/tramp-container.el index 902fc6a451b..3d15d71d709 100644 --- a/lisp/net/tramp-container.el +++ b/lisp/net/tramp-container.el @@ -81,8 +81,8 @@ ;; C-x C-f /flatpak:SANDBOX:/path/to/file ;; ;; Where: -;; SANDBOX is the running sandbox to connect to. -;; It could be an application ID, an instance ID, or a PID. +;; SANDBOX is the running sandbox to connect to. +;; It could be an application ID, an instance ID, or a PID. ;; ;; ;; @@ -91,7 +91,17 @@ ;; C-x C-f /apptainer:INSTANCE:/path/to/file ;; ;; Where: -;; INSTANCE is the running instance to connect to. +;; INSTANCE is the running instance to connect to. +;; +;; +;; +;; Open a file on a running systemd-nspawn container: +;; +;; C-x C-f /nspawn:USER@CONTAINER:/path/to/file +;; +;; Where: +;; USER is the user on the container to connect as (optional) +;; CONTAINER is the container to connect to ;;; Code: @@ -159,6 +169,13 @@ If it is nil, the default context will be used." :type '(choice (const "apptainer") (string))) +(defcustom tramp-nspawn-program "machinectl" + "Name of the machinectl program." + :group 'tramp + :version "30.1" + :type '(choice (const "machinectl") + (string))) + ;;;###tramp-autoload (defconst tramp-docker-method "docker" "Tramp method name to use to connect to Docker containers.") @@ -193,6 +210,10 @@ This is for out-of-band connections.") (defconst tramp-apptainer-method "apptainer" "Tramp method name to use to connect to Apptainer instances.") +;;;###tramp-autoload +(defconst tramp-nspawn-method "nspawn" + "Tramp method name to use to connect to systemd-nspawn containers.") + ;;;###tramp-autoload (defmacro tramp-skeleton-completion-function (method &rest body) "Skeleton for `tramp-*-completion-function' with multi-hop support. @@ -416,6 +437,21 @@ see its function help for a description of the format." lines))) (mapcar (lambda (name) (list nil name)) names)))) +(defun tramp-nspawn--completion-function (method) + "List systemd-nspawn containers available for connection. + +This function is used by `tramp-set-completion-function', please +see its function help for a description of the format." + (tramp-skeleton-completion-function method + (when-let ((raw-list + (shell-command-to-string (concat program " list --all -q"))) + ;; Ignore header line. + (lines (cdr (split-string raw-list "\n"))) + (first-words (mapcar (lambda (line) (car (split-string line))) + lines)) + (machines (seq-take-while (lambda (name) name) first-words))) + (mapcar (lambda (m) (list nil m)) machines)))) + ;;;###tramp-autoload (defvar tramp-default-remote-shell) ;; Silence byte compiler. @@ -580,6 +616,28 @@ see its function help for a description of the format." tramp-apptainer-method `((tramp-apptainer--completion-function ,tramp-apptainer-method)))) +;; todo: check tramp-async-args and tramp-direct-async +;;;###tramp-autoload +(defun tramp-enable-nspawn-method () + "Enable connection to nspawn containers." + (add-to-list 'tramp-methods + `(,tramp-nspawn-method + (tramp-login-program ,tramp-nspawn-program) + (tramp-login-args (("shell") + ("-q") + ("--uid" "%u") + ("%h"))) + (tramp-remote-shell ,tramp-default-remote-shell) + (tramp-remote-shell-login ("-l")) + (tramp-remote-shell-args ("-i" "-c")))) + + (add-to-list 'tramp-default-host-alist `(,tramp-nspawn-method nil ".host")) + (add-to-list 'tramp-completion-multi-hop-methods tramp-nspawn-method) + + (tramp-set-completion-function + tramp-nspawn-method + `((tramp-nspawn--completion-function ,tramp-nspawn-method)))) + ;; Default connection-local variables for Tramp. (defconst tramp-kubernetes-connection-local-default-variables diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index ffef051cbe3..6cfc2f722d4 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -562,11 +562,13 @@ host runs a restricted shell, it shall be added to this list, too." ;; Fedora. "localhost4" "localhost6" ;; Ubuntu. - "ip6-localhost" "ip6-loopback")) + "ip6-localhost" "ip6-loopback" + ;; OpenSUSE. + "ipv6-localhost" "ipv6-loopback")) eos) "Host names which are regarded as local host. If the local host runs a chrooted environment, set this to nil." - :version "29.3" + :version "30.1" :type '(choice (const :tag "Chrooted environment" nil) (regexp :tag "Host regexp"))) -- 2.39.5