mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-09-17 15:27:58 +00:00
Drop luet, image extractor, drop build code and multiarch images (#20)
Co-authored-by: Mauro Morales <mauro.morales@spectrocloud.com>
This commit is contained in:
@@ -499,17 +499,6 @@ func FindFileWithPrefix(fs v1.FS, path string, prefixes ...string) (string, erro
|
||||
|
||||
var errInvalidArch = fmt.Errorf("invalid arch")
|
||||
|
||||
func ArchToGolangArch(arch string) (string, error) {
|
||||
switch strings.ToLower(arch) {
|
||||
case cnst.Archx86:
|
||||
return cnst.ArchAmd64, nil
|
||||
case cnst.ArchArm64:
|
||||
return cnst.ArchArm64, nil
|
||||
default:
|
||||
return "", errInvalidArch
|
||||
}
|
||||
}
|
||||
|
||||
func GolangArchToArch(arch string) (string, error) {
|
||||
switch strings.ToLower(arch) {
|
||||
case cnst.ArchAmd64:
|
||||
|
@@ -60,6 +60,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
// We also use the real fs
|
||||
memLog = &bytes.Buffer{}
|
||||
logger = v1.NewBufferLogger(memLog)
|
||||
logger.SetLevel(log.DebugLevel)
|
||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||
|
||||
config = conf.NewConfig(
|
||||
@@ -95,12 +96,10 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
It("Goes over extra paths", func() {
|
||||
d, err := utils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile(fmt.Sprintf("%s/extra.yaml", d), []byte{}, os.ModePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
config.Logger.SetLevel(log.DebugLevel)
|
||||
|
||||
Expect(utils.RunStage(config, "luke", strict, d)).To(BeNil())
|
||||
Expect(memLog.String()).To(ContainSubstring(fmt.Sprintf("Executing %s/extra.yaml", d)))
|
||||
Expect(memLog.String()).To(ContainSubstring(d))
|
||||
Expect(memLog).To(ContainSubstring("luke"))
|
||||
Expect(memLog).To(ContainSubstring("luke.before"))
|
||||
Expect(memLog).To(ContainSubstring("luke.after"))
|
||||
|
@@ -18,8 +18,6 @@ package utils_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -1126,154 +1124,4 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(err.Error()).To(ContainSubstring("Cleanup error 3"))
|
||||
})
|
||||
})
|
||||
Describe("VHD utils", Label("vhd"), func() {
|
||||
It("creates a valid header", func() {
|
||||
tmpDir, _ := utils.TempDir(fs, "", "")
|
||||
f, _ := fs.OpenFile(filepath.Join(tmpDir, "test.vhd"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||
utils.RawDiskToFixedVhd(f)
|
||||
_ = f.Close()
|
||||
f, _ = fs.Open(filepath.Join(tmpDir, "test.vhd"))
|
||||
info, _ := f.Stat()
|
||||
// Should only have the footer in teh file, hence 512 bytes
|
||||
Expect(info.Size()).To(BeNumerically("==", 512))
|
||||
// Dump the header from the file into our VHDHeader
|
||||
buff := make([]byte, 512)
|
||||
_, _ = f.ReadAt(buff, info.Size()-512)
|
||||
_ = f.Close()
|
||||
|
||||
header := utils.VHDHeader{}
|
||||
err := binary.Read(bytes.NewBuffer(buff[:]), binary.BigEndian, &header)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Just check the fields that we know the value of, that should indicate that the header is valid
|
||||
Expect(hex.EncodeToString(header.DiskType[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.Features[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.DataOffset[:])).To(Equal("ffffffffffffffff"))
|
||||
Expect(hex.EncodeToString(header.CreatorApplication[:])).To(Equal("656c656d"))
|
||||
})
|
||||
Describe("CHS calculation", func() {
|
||||
It("limits the number of sectors", func() {
|
||||
tmpDir, _ := utils.TempDir(fs, "", "")
|
||||
f, _ := fs.Create(filepath.Join(tmpDir, "test.vhd"))
|
||||
// This size would make the chs calculation break, but we have a guard for it
|
||||
f.Truncate(500 * 1024 * 1024 * 1024)
|
||||
f.Close()
|
||||
f, _ = fs.OpenFile(filepath.Join(tmpDir, "test.vhd"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||
utils.RawDiskToFixedVhd(f)
|
||||
_ = f.Close()
|
||||
f, _ = fs.Open(filepath.Join(tmpDir, "test.vhd"))
|
||||
info, _ := f.Stat()
|
||||
// Dump the header from the file into our VHDHeader
|
||||
buff := make([]byte, 512)
|
||||
_, _ = f.ReadAt(buff, info.Size()-512)
|
||||
_ = f.Close()
|
||||
|
||||
header := utils.VHDHeader{}
|
||||
err := binary.Read(bytes.NewBuffer(buff[:]), binary.BigEndian, &header)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Just check the fields that we know the value of, that should indicate that the header is valid
|
||||
Expect(hex.EncodeToString(header.DiskType[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.Features[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.DataOffset[:])).To(Equal("ffffffffffffffff"))
|
||||
// cylinders which is (totalSectors / sectorsPerTrack) / heads
|
||||
// and totalsectors is 65535 * 16 * 255 due to hitting the max sector
|
||||
// This turns out to be 65535 or ffff in hex or [2]byte{255,255}
|
||||
Expect(hex.EncodeToString(header.DiskGeometry[:2])).To(Equal("ffff"))
|
||||
Expect(header.DiskGeometry[2]).To(Equal(uint8(16))) // heads
|
||||
Expect(header.DiskGeometry[3]).To(Equal(uint8(255))) // sectors per track
|
||||
})
|
||||
// The tests below test the different routes that the chs calculation can take to get the disk geometry
|
||||
// it's all based on number of sectors, so we have to try with different known sizes to see if the
|
||||
// geometry changes are properly reflected on the final VHD header
|
||||
It("sets the disk geometry correctly based on sector number", func() {
|
||||
tmpDir, _ := utils.TempDir(fs, "", "")
|
||||
f, _ := fs.Create(filepath.Join(tmpDir, "test.vhd"))
|
||||
// one route of the chs calculation
|
||||
f.Truncate(1 * 1024 * 1024)
|
||||
f.Close()
|
||||
f, _ = fs.OpenFile(filepath.Join(tmpDir, "test.vhd"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||
utils.RawDiskToFixedVhd(f)
|
||||
_ = f.Close()
|
||||
f, _ = fs.Open(filepath.Join(tmpDir, "test.vhd"))
|
||||
info, _ := f.Stat()
|
||||
// Dump the header from the file into our VHDHeader
|
||||
buff := make([]byte, 512)
|
||||
_, _ = f.ReadAt(buff, info.Size()-512)
|
||||
_ = f.Close()
|
||||
|
||||
header := utils.VHDHeader{}
|
||||
err := binary.Read(bytes.NewBuffer(buff[:]), binary.BigEndian, &header)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Just check the fields that we know the value of, that should indicate that the header is valid
|
||||
Expect(hex.EncodeToString(header.DiskType[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.Features[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.DataOffset[:])).To(Equal("ffffffffffffffff"))
|
||||
// should not be the max value
|
||||
Expect(hex.EncodeToString(header.DiskGeometry[:2])).ToNot(Equal("ffff"))
|
||||
Expect(header.DiskGeometry[2]).To(Equal(uint8(4))) // heads
|
||||
Expect(header.DiskGeometry[3]).To(Equal(uint8(17))) // sectors per track
|
||||
})
|
||||
It("sets the disk geometry correctly based on sector number", func() {
|
||||
tmpDir, _ := utils.TempDir(fs, "", "")
|
||||
f, _ := fs.Create(filepath.Join(tmpDir, "test.vhd"))
|
||||
// one route of the chs calculation
|
||||
f.Truncate(1 * 1024 * 1024 * 1024)
|
||||
f.Close()
|
||||
f, _ = fs.OpenFile(filepath.Join(tmpDir, "test.vhd"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||
utils.RawDiskToFixedVhd(f)
|
||||
_ = f.Close()
|
||||
f, _ = fs.Open(filepath.Join(tmpDir, "test.vhd"))
|
||||
info, _ := f.Stat()
|
||||
// Dump the header from the file into our VHDHeader
|
||||
buff := make([]byte, 512)
|
||||
_, _ = f.ReadAt(buff, info.Size()-512)
|
||||
_ = f.Close()
|
||||
|
||||
header := utils.VHDHeader{}
|
||||
err := binary.Read(bytes.NewBuffer(buff[:]), binary.BigEndian, &header)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Just check the fields that we know the value of, that should indicate that the header is valid
|
||||
Expect(hex.EncodeToString(header.DiskType[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.Features[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.DataOffset[:])).To(Equal("ffffffffffffffff"))
|
||||
// should not be the max value
|
||||
Expect(hex.EncodeToString(header.DiskGeometry[:2])).ToNot(Equal("ffff"))
|
||||
Expect(header.DiskGeometry[2]).To(Equal(uint8(16))) // heads
|
||||
Expect(header.DiskGeometry[3]).To(Equal(uint8(63))) // sectors per track
|
||||
})
|
||||
It("sets the disk geometry correctly based on sector number", func() {
|
||||
tmpDir, _ := utils.TempDir(fs, "", "")
|
||||
f, _ := fs.Create(filepath.Join(tmpDir, "test.vhd"))
|
||||
// another route of the chs calculation
|
||||
f.Truncate(220 * 1024 * 1024)
|
||||
f.Close()
|
||||
f, _ = fs.OpenFile(filepath.Join(tmpDir, "test.vhd"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||
utils.RawDiskToFixedVhd(f)
|
||||
_ = f.Close()
|
||||
f, _ = fs.Open(filepath.Join(tmpDir, "test.vhd"))
|
||||
info, _ := f.Stat()
|
||||
// Dump the header from the file into our VHDHeader
|
||||
buff := make([]byte, 512)
|
||||
_, _ = f.ReadAt(buff, info.Size()-512)
|
||||
_ = f.Close()
|
||||
|
||||
header := utils.VHDHeader{}
|
||||
err := binary.Read(bytes.NewBuffer(buff[:]), binary.BigEndian, &header)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Just check the fields that we know the value of, that should indicate that the header is valid
|
||||
Expect(hex.EncodeToString(header.DiskType[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.Features[:])).To(Equal("00000002"))
|
||||
Expect(hex.EncodeToString(header.DataOffset[:])).To(Equal("ffffffffffffffff"))
|
||||
// should not be the max value
|
||||
Expect(hex.EncodeToString(header.DiskGeometry[:2])).ToNot(Equal("ffff"))
|
||||
Expect(header.DiskGeometry[2]).To(Equal(uint8(16))) // heads
|
||||
Expect(header.DiskGeometry[3]).To(Equal(uint8(31))) // sectors per track
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
155
pkg/utils/vhd.go
155
pkg/utils/vhd.go
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
Copyright © 2022 SUSE LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"math"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
uuidPkg "github.com/distribution/distribution/uuid"
|
||||
)
|
||||
|
||||
// This file contains utils to work with VHD disks
|
||||
|
||||
type VHDHeader struct {
|
||||
Cookie [8]byte // Cookies are used to uniquely identify the original creator of the hard disk image
|
||||
Features [4]byte // This is a bit field used to indicate specific feature support.
|
||||
// Can be 0x00000000 (no features), 0x00000001 (Temporary, candidate for deletion on shutdown) or 0x00000002 (Reserved)
|
||||
FileFormatVersion [4]byte // Divided into a major/minor version and matches the version of the specification used in creating the file.
|
||||
DataOffset [8]byte // For fixed disks, this field should be set to 0xFFFFFFFF.
|
||||
Timestamp [4]byte // Sstores the creation time of a hard disk image. This is the number of seconds since January 1, 2000 12:00:00 AM in UTC/GMT.
|
||||
CreatorApplication [4]byte // Used to document which application created the hard disk.
|
||||
CreatorVersion [4]byte // This field holds the major/minor version of the application that created the hard disk image.
|
||||
CreatorHostOS [4]byte // This field stores the type of host operating system this disk image is created on.
|
||||
OriginalSize [8]byte // This field stores the size of the hard disk in bytes, from the perspective of the virtual machine, at creation time. Info only
|
||||
CurrentSize [8]byte // This field stores the current size of the hard disk, in bytes, from the perspective of the virtual machine.
|
||||
DiskGeometry [4]byte // This field stores the cylinder, heads, and sectors per track value for the hard disk.
|
||||
DiskType [4]byte // Fixed = 2, Dynamic = 3, Differencing = 4
|
||||
Checksum [4]byte // This field holds a basic checksum of the hard disk footer. It is just a one’s complement of the sum of all the bytes in the footer without the checksum field.
|
||||
UniqueID [16]byte // This is a 128-bit universally unique identifier (UUID).
|
||||
SavedState [1]byte // This field holds a one-byte flag that describes whether the system is in saved state. If the hard disk is in the saved state the value is set to 1
|
||||
Reserved [427]byte // This field contains zeroes.
|
||||
}
|
||||
|
||||
func newVHDFixed(size uint64) VHDHeader {
|
||||
header := VHDHeader{}
|
||||
hexToField("00000002", header.Features[:])
|
||||
hexToField("00010000", header.FileFormatVersion[:])
|
||||
hexToField("ffffffffffffffff", header.DataOffset[:])
|
||||
t := uint32(time.Now().Unix() - 946684800)
|
||||
binary.BigEndian.PutUint32(header.Timestamp[:], t)
|
||||
hexToField("656c656d", header.CreatorApplication[:]) // Cos
|
||||
hexToField("73757365", header.CreatorHostOS[:]) // SUSE
|
||||
binary.BigEndian.PutUint64(header.OriginalSize[:], size)
|
||||
binary.BigEndian.PutUint64(header.CurrentSize[:], size)
|
||||
// Divide size into 512 to get the total sectors
|
||||
totalSectors := float64(size / 512)
|
||||
geometry := chsCalculation(uint64(totalSectors))
|
||||
binary.BigEndian.PutUint16(header.DiskGeometry[:2], uint16(geometry.cylinders))
|
||||
header.DiskGeometry[2] = uint8(geometry.heads)
|
||||
header.DiskGeometry[3] = uint8(geometry.sectorsPerTrack)
|
||||
hexToField("00000002", header.DiskType[:]) // Fixed 0x00000002
|
||||
hexToField("00000000", header.Checksum[:])
|
||||
uuid := uuidPkg.Generate()
|
||||
copy(header.UniqueID[:], uuid.String())
|
||||
generateChecksum(&header)
|
||||
return header
|
||||
}
|
||||
|
||||
// generateChecksum generates the checksum of the vhd header
|
||||
// Lifted from the official VHD Format Spec
|
||||
func generateChecksum(header *VHDHeader) {
|
||||
buffer := new(bytes.Buffer)
|
||||
_ = binary.Write(buffer, binary.BigEndian, header)
|
||||
checksum := 0
|
||||
bb := buffer.Bytes()
|
||||
for counter := 0; counter < 512; counter++ {
|
||||
checksum += int(bb[counter])
|
||||
}
|
||||
binary.BigEndian.PutUint32(header.Checksum[:], uint32(^checksum))
|
||||
}
|
||||
|
||||
// hexToField decodes an hex to bytes and copies it to the given header field
|
||||
func hexToField(hexs string, field []byte) {
|
||||
h, _ := hex.DecodeString(hexs)
|
||||
copy(field, h)
|
||||
}
|
||||
|
||||
// chs is a simple struct to represent the cylinders/heads/sectors for a given sector count
|
||||
type chs struct {
|
||||
cylinders uint
|
||||
heads uint
|
||||
sectorsPerTrack uint
|
||||
}
|
||||
|
||||
// chsCalculation calculates the cylinders, headers and sectors per track for a given sector count
|
||||
// Exactly the same code on the official VHD format spec
|
||||
func chsCalculation(sectors uint64) chs {
|
||||
var sectorsPerTrack,
|
||||
heads,
|
||||
cylinderTimesHeads,
|
||||
cylinders float64
|
||||
totalSectors := float64(sectors)
|
||||
|
||||
if totalSectors > 65535*16*255 {
|
||||
totalSectors = 65535 * 16 * 255
|
||||
}
|
||||
|
||||
if totalSectors >= 65535*16*63 {
|
||||
sectorsPerTrack = 255
|
||||
heads = 16
|
||||
cylinderTimesHeads = math.Floor(totalSectors / sectorsPerTrack)
|
||||
} else {
|
||||
sectorsPerTrack = 17
|
||||
cylinderTimesHeads = math.Floor(totalSectors / sectorsPerTrack)
|
||||
heads = math.Floor((cylinderTimesHeads + 1023) / 1024)
|
||||
if heads < 4 {
|
||||
heads = 4
|
||||
}
|
||||
if (cylinderTimesHeads >= (heads * 1024)) || heads > 16 {
|
||||
sectorsPerTrack = 31
|
||||
heads = 16
|
||||
cylinderTimesHeads = math.Floor(totalSectors / sectorsPerTrack)
|
||||
}
|
||||
if cylinderTimesHeads >= (heads * 1024) {
|
||||
sectorsPerTrack = 63
|
||||
heads = 16
|
||||
cylinderTimesHeads = math.Floor(totalSectors / sectorsPerTrack)
|
||||
}
|
||||
}
|
||||
|
||||
cylinders = cylinderTimesHeads / heads
|
||||
|
||||
return chs{
|
||||
cylinders: uint(cylinders),
|
||||
heads: uint(heads),
|
||||
sectorsPerTrack: uint(sectorsPerTrack),
|
||||
}
|
||||
}
|
||||
|
||||
// RawDiskToFixedVhd will write the proper header to a given os.File to convert it from a simple raw disk to a Fixed VHD
|
||||
// RawDiskToFixedVhd makes no effort into opening/closing/checking if the file exists
|
||||
func RawDiskToFixedVhd(diskFile *os.File) {
|
||||
info, _ := diskFile.Stat()
|
||||
size := uint64(info.Size())
|
||||
header := newVHDFixed(size)
|
||||
_ = binary.Write(diskFile, binary.BigEndian, header)
|
||||
}
|
Reference in New Issue
Block a user