Skip to content

Commit

Permalink
feat: update ISO VolumeID with Talos version
Browse files Browse the repository at this point in the history
Put Talos version in the ISO volume ID and volumeset ID.

Volume ID is restricted on valid characters, while volumeset ID is not
restricted (Unicode).

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
xerc authored and smira committed Aug 13, 2024
1 parent 9a33dce commit 2bf924c
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ image-%: ## Builds the specified image. Valid options are aws, azure, digital-oc
@docker pull $(REGISTRY_AND_USERNAME)/imager:$(IMAGE_TAG)
@for platform in $(subst $(,),$(space),$(PLATFORM)); do \
arch=$$(basename "$${platform}") && \
docker run --rm -t -v /dev:/dev -v $(PWD)/$(ARTIFACTS):/secureboot:ro -v $(PWD)/$(ARTIFACTS):/out --network=host --privileged $(REGISTRY_AND_USERNAME)/imager:$(IMAGE_TAG) $* --arch $$arch $(IMAGER_ARGS) ; \
docker run --rm -t -v /dev:/dev -v $(PWD)/$(ARTIFACTS):/secureboot:ro -v $(PWD)/$(ARTIFACTS):/out -e SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) --network=host --privileged $(REGISTRY_AND_USERNAME)/imager:$(IMAGE_TAG) $* --arch $$arch $(IMAGER_ARGS) ; \
done

images-essential: image-aws image-azure image-gcp image-metal secureboot-installer ## Builds only essential images used in the CI (AWS, GCP, and Metal).
Expand Down
20 changes: 15 additions & 5 deletions pkg/imager/iso/grub.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,16 @@ func CreateGRUB(printf func(string, ...any), options GRUBOptions) error {

printf("creating ISO image")

return grubMkrescue(options.OutPath, options.ScratchDir)
return grubMkrescue(options)
}

func grubMkrescue(isoPath, scratchPath string) error {
func grubMkrescue(options GRUBOptions) error {
args := []string{
"--compress=xz",
"--output=" + isoPath,
scratchPath,
"--output=" + options.OutPath,
"--verbose",
options.ScratchDir,
"--",
}

if epoch, ok, err := utils.SourceDateEpoch(); err != nil {
Expand All @@ -105,12 +107,20 @@ func grubMkrescue(isoPath, scratchPath string) error {
}

args = append(args,
"--",
"-volume_date", "all_file_dates", fmt.Sprintf("=%d", epoch),
"-volume_date", "uuid", time.Unix(epoch, 0).Format("2006010215040500"),
)
}

if quirks.New(options.Version).SupportsISOLabel() {
label := Label(options.Version, false)

args = append(args,
"-volid", VolumeID(label),
"-volset-id", label,
)
}

_, err := cmd.Run("grub-mkrescue", args...)
if err != nil {
return fmt.Errorf("failed to create ISO: %w", err)
Expand Down
37 changes: 37 additions & 0 deletions pkg/imager/iso/iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,40 @@

// Package iso contains functions for creating ISO images.
package iso

import "strings"

// VolumeID returns a valid volume ID for the given label.
func VolumeID(label string) string {
// builds a valid volume ID: 32 chars out of [A-Z0-9_]
label = strings.ToUpper(label)
label = strings.Map(func(r rune) rune {
switch {
case r >= 'A' && r <= 'Z':
return r
case r >= '0' && r <= '9':
return r
case r == '_' || r == '-' || r == '.':
return '_'
default:
return -1
}
}, label)

if len(label) > 32 {
label = label[:32]
}

return label
}

// Label returns an ISO full label for a given version.
func Label(version string, secureboot bool) string {
label := "Talos-"

if secureboot {
label += "SB-"
}

return label + version
}
40 changes: 40 additions & 0 deletions pkg/imager/iso/iso_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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 iso_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/siderolabs/talos/pkg/imager/iso"
)

func TestVolumeID(t *testing.T) {
t.Parallel()

for _, test := range []struct {
in string

out string
}{
{
in: "Talos-v1.7.6",

out: "TALOS_V1_7_6",
},
{
in: "Talos-v1.7.6-beta.0",

out: "TALOS_V1_7_6_BETA_0",
},
} {
t.Run(test.in, func(t *testing.T) {
t.Parallel()

assert.Equal(t, test.out, iso.VolumeID(test.in))
})
}
}
39 changes: 28 additions & 11 deletions pkg/imager/iso/uefi.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
"os"
"path/filepath"
"text/template"
"time"

"github.com/siderolabs/go-cmd/pkg/cmd"

"github.com/siderolabs/talos/pkg/imager/utils"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/imager/quirks"
"github.com/siderolabs/talos/pkg/makefs"
)

Expand Down Expand Up @@ -185,19 +187,34 @@ func CreateUEFI(printf func(string, ...any), options UEFIOptions) error {

printf("creating ISO image")

if _, err := cmd.Run(
"xorriso",
"-as",
"mkisofs",
"-V",
"Talos Secure Boot ISO",
"-e",
"efiboot.img",
args := []string{
"-as", "mkisofs",
"-e", "efiboot.img",
"-no-emul-boot",
"-o",
options.OutPath,
"-o", options.OutPath,
options.ScratchDir,
); err != nil {
"--",
}

if epoch, ok, err := utils.SourceDateEpoch(); err != nil {
return err
} else if ok {
args = append(args,
"-volume_date", "all_file_dates", fmt.Sprintf("=%d", epoch),
"-volume_date", "uuid", time.Unix(epoch, 0).Format("2006010215040500"),
)
}

if quirks.New(options.Version).SupportsISOLabel() {
label := Label(options.Version, true)

args = append(args,
"-volid", VolumeID(label),
"-volset-id", label,
)
}

if _, err := cmd.Run("xorriso", args...); err != nil {
return err
}

Expand Down
12 changes: 12 additions & 0 deletions pkg/machinery/imager/quirks/quirks.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ func (q Quirks) UseZSTDCompression() bool {
return q.v.GTE(minVersionZstd)
}

var minVersionISOLabel = semver.MustParse("1.8.0")

// SupportsISOLabel returns true if the Talos version supports setting the ISO label.
func (q Quirks) SupportsISOLabel() bool {
// if the version doesn't parse, we assume it's latest Talos
if q.v == nil {
return true
}

return q.v.GTE(minVersionISOLabel)
}

var minVersionMultidoc = semver.MustParse("1.5.0")

// SupportsMultidoc returns true if the Talos version supports multidoc machine configs.
Expand Down

0 comments on commit 2bf924c

Please sign in to comment.