add DebianTemplateManager

This commit is contained in:
Max Erenberg 2022-06-25 05:52:08 -04:00
parent 083788ab92
commit f84ace7700
9 changed files with 143 additions and 22 deletions

View File

@ -188,7 +188,7 @@ func (c *CloudBuilder) createNewTemplate(
newVersion, codename string, distroInfo *DistroInfo,
) (template *cloudstack.Template, err error) {
distroManager := distroInfo.manager
templatePath, err := distroManager.DownloadTemplate(codename)
templatePath, err := distroManager.DownloadTemplate(newVersion, codename)
if err != nil {
return
}
@ -219,6 +219,15 @@ func (c *CloudBuilder) versionStringCompare(version1, version2 string) int {
func (c *CloudBuilder) Start() (err error) {
distrosInfo := map[string]DistroInfo{
"debian": DistroInfo{
name: "Debian",
manager: distros.NewDebianTemplateManager(c.cfg),
// This is the latest version available in CloudStack 4.16;
// using a custom OS type caused issues with the ethernet
// interface not being detected
osDescription: "Debian GNU/Linux 11 (64-bit)",
user: "debian",
},
"ubuntu": DistroInfo{
name: "Ubuntu",
manager: distros.NewUbuntuTemplateManager(c.cfg),
@ -261,7 +270,9 @@ func (c *CloudBuilder) Start() (err error) {
Msg("Existing version is up to date, skipping")
continue
}
log.Info().Str("distro", distro).Msg("Existing template is out of date, creating a new one")
log.Info().
Str("distro", distroLower).
Msg("Existing template is out of date, creating a new one")
var template *cloudstack.Template
template, err = c.createNewTemplate(newVersion, codename, &distroInfo)

View File

@ -3,7 +3,6 @@ package distros
import (
"errors"
"fmt"
"math"
"net/http"
"regexp"
"strconv"
@ -58,13 +57,12 @@ func (mgr *AlmaLinuxTemplateManager) GetLatestVersion() (version string, codenam
return
}
func (mgr *AlmaLinuxTemplateManager) DownloadTemplate(codename string) (path string, err error) {
version := codename
func (mgr *AlmaLinuxTemplateManager) DownloadTemplate(version, codename string) (path string, err error) {
floatVersion, err := strconv.ParseFloat(version, 64)
if err != nil {
return
}
majorVersion := int(math.Floor(floatVersion))
majorVersion := int(floatVersion)
filename := fmt.Sprintf("AlmaLinux-%d-GenericCloud-latest.x86_64.qcow2", majorVersion)
url := fmt.Sprintf("https://mirror.csclub.uwaterloo.ca/almalinux/%s/cloud/x86_64/images/%s", version, filename)
return mgr.DownloadTemplateGeneric(filename, url)

96
pkg/distros/debian.go Normal file
View File

@ -0,0 +1,96 @@
package distros
import (
"bufio"
"errors"
"fmt"
"net/http"
"regexp"
"github.com/rs/zerolog/log"
"libguestfs.org/guestfs"
"git.csclub.uwaterloo.ca/cloud/cloudbuild/pkg/config"
)
type DebianTemplateManager struct {
TemplateManager
}
// NewDebianTemplateManager returns a DebianTemplateManager with the given
// config values.
func NewDebianTemplateManager(cfg *config.Config) *DebianTemplateManager {
logger := log.With().Str("distro", "debian").Logger()
debianTemplateManager := DebianTemplateManager{
TemplateManager{
cfg: cfg,
logger: &logger,
impl: nil,
},
}
debianTemplateManager.TemplateManager.impl = &debianTemplateManager
return &debianTemplateManager
}
func (mgr *DebianTemplateManager) GetLatestVersion() (version string, codename string, err error) {
// We're only interested in the major version (integer part)
versionPattern := regexp.MustCompile("^Version: (\\d+)(?:\\.\\d)?$")
codenamePattern := regexp.MustCompile("^Codename: ([a-z-]+)$")
resp, err := http.Get("https://mirror.csclub.uwaterloo.ca/debian/dists/stable/InRelease")
if err != nil {
return
}
defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
if version == "" {
submatches := versionPattern.FindStringSubmatch(scanner.Text())
if submatches != nil {
version = submatches[1]
}
}
if codename == "" {
submatches := codenamePattern.FindStringSubmatch(scanner.Text())
if submatches != nil {
codename = submatches[1]
}
}
if version != "" && codename != "" {
break
}
}
if version == "" {
err = errors.New("Could not determine latest version of Debian")
}
return
}
func (mgr *DebianTemplateManager) DownloadTemplate(version, codename string) (path string, err error) {
filename := fmt.Sprintf("debian-%s-genericcloud-amd64.qcow2", version)
url := fmt.Sprintf("https://cloud.debian.org/images/cloud/%s/latest/%s", codename, filename)
return mgr.DownloadTemplateGeneric(filename, url)
}
func (mgr *DebianTemplateManager) HasSELinuxEnabled() bool {
return false
}
func (mgr *DebianTemplateManager) GetIpv6ScriptsTemplateData() map[string]string {
return map[string]string{
"networkService": "networking.service",
"networkTarget": "network.target",
}
}
func (mgr *DebianTemplateManager) PerformDistroSpecificModifications(handle *guestfs.Guestfs) (err error) {
if err = mgr.setChronyOptions(handle, "/etc/chrony/chrony.conf"); err != nil {
return
}
if err = mgr.setDhclientOptions(handle); err != nil {
return
}
if err = mgr.replaceDebianMirrorUrls(handle); err != nil {
return
}
return
}

View File

@ -92,8 +92,7 @@ func (mgr *FedoraTemplateManager) GetLatestVersion() (version string, codename s
return
}
func (mgr *FedoraTemplateManager) DownloadTemplate(codename string) (path string, err error) {
version := codename
func (mgr *FedoraTemplateManager) DownloadTemplate(version, codename string) (path string, err error) {
pattern := regexp.MustCompile(fmt.Sprintf("^Fedora-Cloud-Base-%s-\\d+(\\.\\d+)?\\.x86_64\\.qcow2$", version))
imagesUrl := fmt.Sprintf("https://mirror.csclub.uwaterloo.ca/fedora/linux/releases/%s/Cloud/x86_64/images/", version)
resp, err := http.Get(imagesUrl)

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -ex
ip -brief link show | while read interface _; do
if [ $interface = lo ]; then
continue
fi
sysctl net.ipv6.conf.$interface.accept_ra=0
sysctl net.ipv6.conf.$interface.accept_dad=0
done
ip -6 -brief addr show dynamic | \
while read iface _ addrs; do
for addr in $addrs; do
ip addr del dev $iface $addr
done
done
ip -6 route show proto ra | grep -E -o "^default via [a-f0-9:]+ dev [a-z0-9]+" | \
while read line; do
ip route del $line
done

View File

@ -16,7 +16,7 @@ ip -6 -brief addr show dynamic | \
done
done
ip -6 route show proto ra | \
ip -6 route show proto ra | grep -E -o "^default via [a-f0-9:]+ dev [a-z0-9]+" | \
while read line; do
ip route del $line
done

View File

@ -1,9 +0,0 @@
#!/bin/bash
set -ex
while read interface _; do
if [ $interface = lo ]; then
continue
fi
sysctl net.ipv6.conf.$interface.accept_ra=0
sysctl net.ipv6.conf.$interface.accept_dad=0
done < <(ip -brief link show)

View File

@ -48,9 +48,9 @@ type ITemplateManager interface {
// GetLatestVersion returns the version number and codename of the
// latest version of particular OS (e.g. version="22.04", codename="jammy")
GetLatestVersion() (version string, codename string, err error)
// DownloadTemplate downloads a VM template for a given OS codename
// and returns the path to where it was downloaded
DownloadTemplate(codename string) (path string, err error)
// DownloadTemplate downloads a VM template for a given OS version and
// codename, and returns the path to where it was downloaded
DownloadTemplate(version, codename string) (path string, err error)
// ModifyTemplate makes custom modifications to the downloaded VM template
ModifyTemplate(filename string) error
}
@ -255,6 +255,8 @@ func (mgr *TemplateManager) setupIpv6Scripts(handle *guestfs.Guestfs, templateDa
scripts := []string{"99_csclub_ipv6_addr.sh"}
if templateData["networkService"] == "NetworkManager.service" {
scripts = append(scripts, "98_csclub_disable_nm_ipv6.sh")
} else {
scripts = append(scripts, "98_csclub_disable_ipv6_ra.sh")
}
scriptDir := "/var/lib/cloud/scripts/per-boot"
if err = handle.Mkdir_p(scriptDir); err != nil {

View File

@ -50,6 +50,7 @@ func (mgr *UbuntuTemplateManager) GetLatestVersion() (version string, codename s
if err != nil {
return
}
defer resp.Body.Close()
buf, err := io.ReadAll(resp.Body)
if err != nil {
return
@ -72,7 +73,7 @@ func (mgr *UbuntuTemplateManager) GetLatestVersion() (version string, codename s
// DownloadTemplate downloads the cloud image for the given Ubuntu codename,
// and returns the filename to which it was written.
func (mgr *UbuntuTemplateManager) DownloadTemplate(codename string) (path string, err error) {
func (mgr *UbuntuTemplateManager) DownloadTemplate(version, codename string) (path string, err error) {
filename := fmt.Sprintf("%s-server-cloudimg-amd64-disk-kvm.img", codename)
url := fmt.Sprintf("https://cloud-images.ubuntu.com/%s/current/%s", codename, filename)
return mgr.DownloadTemplateGeneric(filename, url)