Skip to content

Commit

Permalink
feat: generate iqn and nqn files
Browse files Browse the repository at this point in the history
Generate deterministic IQN and NQN files based on `machine-id`.

Fixes: #10009

Signed-off-by: Noel Georgi <[email protected]>
  • Loading branch information
frezbo committed Jan 20, 2025
1 parent 399d53b commit f33d9f2
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 5 deletions.
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ END
COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh
RUN <<END
cleanup.sh /rootfs
mkdir -pv /rootfs/{boot/EFI,etc/cri/conf.d/hosts,lib/firmware,usr/etc,usr/local/share,usr/share/zoneinfo/Etc,mnt,system,opt,.extra}
mkdir -pv /rootfs/{boot/EFI,etc/{iscsi,nvme,cri/conf.d/hosts},lib/firmware,usr/etc,usr/local/share,usr/share/zoneinfo/Etc,mnt,system,opt,.extra}
mkdir -pv /rootfs/{etc/kubernetes/manifests,etc/cni/net.d,etc/ssl/certs,usr/libexec/kubernetes,/usr/local/lib/kubelet/credentialproviders,etc/selinux/targeted/contexts/files}
mkdir -pv /rootfs/opt/{containerd/bin,containerd/lib}
END
Expand All @@ -750,7 +750,7 @@ COPY --chmod=0644 hack/lvm.conf /rootfs/etc/lvm/lvm.conf
COPY --chmod=0644 --from=base /src/pkg/machinery/version/os-release /rootfs/etc/os-release
RUN <<END
ln -s /usr/share/zoneinfo/Etc/UTC /rootfs/etc/localtime
touch /rootfs/etc/{extensions.yaml,resolv.conf,hosts,machine-id,cri/conf.d/cri.toml,cri/conf.d/01-registries.part,cri/conf.d/20-customization.part,cri/conf.d/base-spec.json,ssl/certs/ca-certificates,selinux/targeted/contexts/files/file_contexts}
touch /rootfs/etc/{extensions.yaml,resolv.conf,hosts,machine-id,cri/conf.d/cri.toml,cri/conf.d/01-registries.part,cri/conf.d/20-customization.part,cri/conf.d/base-spec.json,ssl/certs/ca-certificates,selinux/targeted/contexts/files/file_contexts,iscsi/initiatorname.iscsi,nvme/{hostid,hostnqn}}
ln -s ca-certificates /rootfs/etc/ssl/certs/ca-certificates.crt
ln -s /etc/ssl /rootfs/etc/pki
ln -s /etc/ssl /rootfs/usr/share/ca-certificates
Expand Down Expand Up @@ -812,7 +812,7 @@ END
COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh
RUN <<END
cleanup.sh /rootfs
mkdir -pv /rootfs/{boot/EFI,etc/cri/conf.d/hosts,lib/firmware,usr/etc,usr/local/share,usr/share/zoneinfo/Etc,mnt,system,opt,.extra}
mkdir -pv /rootfs/{boot/EFI,etc/{iscsi,nvme,cri/conf.d/hosts},lib/firmware,usr/etc,usr/local/share,usr/share/zoneinfo/Etc,mnt,system,opt,.extra}
mkdir -pv /rootfs/{etc/kubernetes/manifests,etc/cni/net.d,etc/ssl/certs,usr/libexec/kubernetes,/usr/local/lib/kubelet/credentialproviders,etc/selinux/targeted/contexts/files}
mkdir -pv /rootfs/opt/{containerd/bin,containerd/lib}
END
Expand All @@ -827,7 +827,7 @@ COPY --chmod=0644 hack/lvm.conf /rootfs/etc/lvm/lvm.conf
COPY --chmod=0644 --from=base /src/pkg/machinery/version/os-release /rootfs/etc/os-release
RUN <<END
ln -s /usr/share/zoneinfo/Etc/UTC /rootfs/etc/localtime
touch /rootfs/etc/{extensions.yaml,resolv.conf,hosts,machine-id,cri/conf.d/cri.toml,cri/conf.d/01-registries.part,cri/conf.d/20-customization.part,cri/conf.d/base-spec.json,ssl/certs/ca-certificates,selinux/targeted/contexts/files/file_contexts}
touch /rootfs/etc/{extensions.yaml,resolv.conf,hosts,machine-id,cri/conf.d/cri.toml,cri/conf.d/01-registries.part,cri/conf.d/20-customization.part,cri/conf.d/base-spec.json,ssl/certs/ca-certificates,selinux/targeted/contexts/files/file_contexts,iscsi/initiatorname.iscsi,nvme/{hostid,hostnqn}}
ln -s /etc/ssl /rootfs/etc/pki
ln -s ca-certificates /rootfs/etc/ssl/certs/ca-certificates.crt
ln -s /etc/ssl /rootfs/usr/share/ca-certificates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (ctrl *NodeIdentityController) Run(ctx context.Context, r controller.Runtim

return err
}); err != nil {
return fmt.Errorf("error modifying resolv.conf: %w", err)
return fmt.Errorf("error modifying machine-id: %w", err)
}

if !ctrl.identityEstablished {
Expand Down
99 changes: 99 additions & 0 deletions internal/app/machined/pkg/controllers/files/iqn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package files

import (
"context"
"fmt"

"github.com/cosi-project/runtime/pkg/controller"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/siderolabs/gen/optional"
"go.uber.org/zap"

clusteradapter "github.com/siderolabs/talos/internal/app/machined/pkg/adapters/cluster"
runtimetalos "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/resources/cluster"
"github.com/siderolabs/talos/pkg/machinery/resources/files"
)

// IQNController creates an EtcFileSpec for the iSCSI Qualified Name (IQN) file.
type IQNController struct {
V1Alpha1Mode runtimetalos.Mode
}

// Name implements controller.Controller interface.
func (ctrl *IQNController) Name() string {
return "files.IQNController"
}

// Inputs implements controller.Controller interface.
func (ctrl *IQNController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: cluster.NamespaceName,
Type: cluster.IdentityType,
ID: optional.Some(cluster.LocalIdentity),
Kind: controller.InputWeak,
},
}
}

// Outputs implements controller.Controller interface.
func (ctrl *IQNController) Outputs() []controller.Output {
return []controller.Output{
{
Type: files.EtcFileSpecType,
Kind: controller.OutputShared,
},
}
}

// Run implements controller.Controller interface.
func (ctrl *IQNController) Run(ctx context.Context, r controller.Runtime, _ *zap.Logger) error {
// Skip the controller if we're running in a container.
if ctrl.V1Alpha1Mode == runtimetalos.ModeContainer {
return nil
}

for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}

// get the local node identity
localIdentity, err := safe.ReaderGetByID[*cluster.Identity](ctx, r, cluster.LocalIdentity)
if err != nil {
if state.IsNotFoundError(err) {
continue
}

return fmt.Errorf("failed to get machine-id etcfile status: %w", err)
}

machineID, err := clusteradapter.IdentitySpec(localIdentity.TypedSpec()).ConvertMachineID()
if err != nil {
return fmt.Errorf("failed to convert identity to machine ID: %w", err)
}

if err := safe.WriterModify(ctx, r, files.NewEtcFileSpec(files.NamespaceName, "iscsi/initiatorname.iscsi"),
func(r *files.EtcFileSpec) error {
spec := r.TypedSpec()

// Fri Nov 3 16:19:12 2017 -0700 is the date of the first commit in the talos repository.
spec.Contents = []byte(fmt.Sprintf("InitiatorName=iqn.2017.11.dev.talos:%s\n", machineID))
spec.Mode = 0o600
spec.SelinuxLabel = constants.EtcSelinuxLabel

return nil
}); err != nil {
return fmt.Errorf("error modifying resource: %w", err)
}
}
}
120 changes: 120 additions & 0 deletions internal/app/machined/pkg/controllers/files/nqn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package files

import (
"context"
"fmt"

"github.com/cosi-project/runtime/pkg/controller"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/google/uuid"
"github.com/siderolabs/gen/optional"
"go.uber.org/zap"

clusteradapter "github.com/siderolabs/talos/internal/app/machined/pkg/adapters/cluster"
runtimetalos "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/resources/cluster"
"github.com/siderolabs/talos/pkg/machinery/resources/files"
)

// NQNController creates an EtcFileSpec for the NVMe Qualified Name (NQN) and HostID file.
type NQNController struct {
V1Alpha1Mode runtimetalos.Mode
}

// Name implements controller.Controller interface.
func (ctrl *NQNController) Name() string {
return "files.NQNController"
}

// Inputs implements controller.Controller interface.
func (ctrl *NQNController) Inputs() []controller.Input {
return []controller.Input{
{
Namespace: cluster.NamespaceName,
Type: cluster.IdentityType,
ID: optional.Some(cluster.LocalIdentity),
Kind: controller.InputWeak,
},
}
}

// Outputs implements controller.Controller interface.
func (ctrl *NQNController) Outputs() []controller.Output {
return []controller.Output{
{
Type: files.EtcFileSpecType,
Kind: controller.OutputShared,
},
}
}

// Run implements controller.Controller interface.
//
//nolint:gocyclo
func (ctrl *NQNController) Run(ctx context.Context, r controller.Runtime, _ *zap.Logger) error {
// Skip the controller if we're running in a container.
if ctrl.V1Alpha1Mode == runtimetalos.ModeContainer {
return nil
}

for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}

// get the local node identity
localIdentity, err := safe.ReaderGetByID[*cluster.Identity](ctx, r, cluster.LocalIdentity)
if err != nil {
if state.IsNotFoundError(err) {
continue
}

return fmt.Errorf("failed to get machine-id etcfile status: %w", err)
}

machineID, err := clusteradapter.IdentitySpec(localIdentity.TypedSpec()).ConvertMachineID()
if err != nil {
return fmt.Errorf("failed to convert identity to machine ID: %w", err)
}

hostID, err := uuid.FromBytes(machineID[:16])
if err != nil {
return fmt.Errorf("failed to convert machine-id to UUID: %w", err)
}

if err := safe.WriterModify(ctx, r, files.NewEtcFileSpec(files.NamespaceName, "nvme/hostid"),
func(r *files.EtcFileSpec) error {
spec := r.TypedSpec()

spec.Contents = []byte(hostID.String())
spec.Mode = 0o600
spec.SelinuxLabel = constants.EtcSelinuxLabel

return nil
}); err != nil {
return fmt.Errorf("error modifying resource: %w", err)
}

if err := safe.WriterModify(ctx, r, files.NewEtcFileSpec(files.NamespaceName, "nvme/hostnqn"),
func(r *files.EtcFileSpec) error {
spec := r.TypedSpec()

// Fri Nov 3 16:19:12 2017 -0700 is the date of the first commit in the talos repository.
spec.Contents = []byte(fmt.Sprintf("nqn.2017.11.dev.talos:uuid:%s", hostID.String()))
spec.Mode = 0o600
spec.SelinuxLabel = constants.EtcSelinuxLabel

return nil
}); err != nil {
return fmt.Errorf("error modifying resource: %w", err)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error
EtcPath: "/etc",
ShadowPath: constants.SystemEtcPath,
},
&files.IQNController{
V1Alpha1Mode: ctrl.v1alpha1Runtime.State().Platform().Mode(),
},
&files.NQNController{
V1Alpha1Mode: ctrl.v1alpha1Runtime.State().Platform().Mode(),
},
&hardware.PCIDevicesController{
V1Alpha1Mode: ctrl.v1alpha1Runtime.State().Platform().Mode(),
},
Expand Down

0 comments on commit f33d9f2

Please sign in to comment.