Various cleanup bits, always use the version from lsb_release instead of hardcoding
This commit is contained in:
parent
4d6176bc13
commit
fa0302e5aa
@ -1,12 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.5.0)
|
||||
project(snapd-installation-monitor)
|
||||
|
||||
# Enable CMake features
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
# Find required Qt6 components
|
||||
find_package(Qt6 COMPONENTS Widgets DBus REQUIRED)
|
||||
|
||||
# Set C++ standard
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Add the main application executable
|
||||
add_executable(snapd-installation-monitor main.cpp)
|
||||
target_link_libraries(snapd-installation-monitor Qt6::Widgets Qt6::DBus)
|
||||
|
@ -10,11 +10,11 @@ import (
|
||||
)
|
||||
|
||||
// cleanUpFiles removes partial, old, and orphaned snap and assertion files from the download and assertions directories.
|
||||
func cleanUpFiles(snapsDir, assertionsDir, seedYaml string) {
|
||||
func cleanUpFiles(snapsDir string, assertionsDir string) {
|
||||
verboseLog("Starting cleanup process...")
|
||||
|
||||
// Load the seed.yaml data
|
||||
seedData := loadSeedData(seedYaml)
|
||||
seedData := loadSeedData()
|
||||
|
||||
// Create a map of valid snap and assertion files based on seed.yaml
|
||||
validSnaps := make(map[string]bool)
|
||||
|
@ -12,15 +12,6 @@ import (
|
||||
"github.com/snapcore/snapd/store"
|
||||
)
|
||||
|
||||
// Seed structure for seed.yaml
|
||||
type seed struct {
|
||||
Snaps []struct {
|
||||
Name string `yaml:"name"`
|
||||
Channel string `yaml:"channel"`
|
||||
File string `yaml:"file"`
|
||||
} `yaml:"snaps"`
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
storeClient *store.Store
|
||||
@ -30,6 +21,7 @@ var (
|
||||
processedSnaps = make(map[string]bool)
|
||||
snapSizeMap = make(map[string]float64)
|
||||
totalSnapSize float64
|
||||
seedYaml string
|
||||
)
|
||||
|
||||
type SnapInfo struct {
|
||||
@ -61,14 +53,14 @@ func main() {
|
||||
// Define directories based on the seed directory
|
||||
snapsDir := filepath.Join(seedDirectory, "snaps")
|
||||
assertionsDir := filepath.Join(seedDirectory, "assertions")
|
||||
seedYaml := filepath.Join(seedDirectory, "seed.yaml")
|
||||
seedYaml = filepath.Join(seedDirectory, "seed.yaml")
|
||||
|
||||
// Setup directories and seed.yaml
|
||||
initializeDirectories(snapsDir, assertionsDir)
|
||||
initializeSeedYaml(seedYaml)
|
||||
initializeSeedYaml()
|
||||
|
||||
// Load existing snaps from seed.yaml
|
||||
existingSnapsInYaml := loadExistingSnaps(seedYaml)
|
||||
existingSnapsInYaml := loadExistingSnaps()
|
||||
|
||||
// Populate currentSnaps based on existing snaps
|
||||
for snapName := range existingSnapsInYaml {
|
||||
@ -133,7 +125,7 @@ func main() {
|
||||
cleanUpCurrentSnaps(assertionsDir, snapsDir)
|
||||
|
||||
// Update seed.yaml with the current required snaps
|
||||
if err := updateSeedYaml(snapsDir, seedYaml, currentSnaps); err != nil {
|
||||
if err := updateSeedYaml(snapsDir, currentSnaps); err != nil {
|
||||
log.Fatalf("Failed to update seed.yaml: %v", err)
|
||||
}
|
||||
|
||||
@ -143,7 +135,7 @@ func main() {
|
||||
if err := validateSeed(seedYaml); err != nil {
|
||||
log.Fatalf("Seed validation failed: %v", err)
|
||||
}
|
||||
cleanUpFiles(snapsDir, assertionsDir, seedYaml)
|
||||
cleanUpFiles(snapsDir, assertionsDir)
|
||||
|
||||
// Mark "Finalizing" as complete
|
||||
if progressTracker != nil {
|
||||
@ -155,11 +147,21 @@ func main() {
|
||||
func collectSnapsToProcess(snapsDir, assertionsDir string) ([]SnapDetails, error) {
|
||||
var snapsToProcess []SnapDetails
|
||||
|
||||
versionID, err := getVersionID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultChannel := "latest/stable/ubuntu-" + versionID
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fallbackChannel := "latest/stable"
|
||||
for snapEntry := range requiredSnaps {
|
||||
// Extract channel if specified, default to "stable"
|
||||
parts := strings.SplitN(snapEntry, "=", 2)
|
||||
channel := "latest/stable/ubuntu-25.04"
|
||||
channel := defaultChannel
|
||||
if len(parts) == 2 {
|
||||
channel = parts[1]
|
||||
}
|
||||
@ -173,9 +175,10 @@ func collectSnapsToProcess(snapsDir, assertionsDir string) ([]SnapDetails, error
|
||||
|
||||
// Append only those snaps that need updates
|
||||
for _, snapDetails := range snapList {
|
||||
verboseLog("Processing snap: %s with result: %v", snapDetails.InstanceName, snapDetails.Result)
|
||||
verboseLog("Processing snap: %s", snapDetails.InstanceName)
|
||||
if len(snapDetails.Result.Deltas) > 0 {
|
||||
for _, delta := range snapDetails.Result.Deltas {
|
||||
verboseLog("Delta found for %s from %d to %d", snapDetails.InstanceName, delta.FromRevision, delta.ToRevision)
|
||||
snapSize := float64(delta.Size)
|
||||
snapSizeMap[snapDetails.Result.Info.SuggestedName] = snapSize
|
||||
totalSnapSize += snapSize
|
||||
|
@ -32,6 +32,7 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
|
||||
|
||||
var result *store.SnapActionResult
|
||||
var err error
|
||||
workingChannel := ""
|
||||
|
||||
// Fetch or refresh snap information
|
||||
if oldSnap == nil || oldSnap.SnapID == "" || oldSnap.Revision.N == 0 {
|
||||
@ -41,18 +42,25 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
|
||||
result, err = fetchOrRefreshSnapInfo(snapName, nil, fallbackChannel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
workingChannel = fallbackChannel
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
workingChannel = channel
|
||||
}
|
||||
} else {
|
||||
verboseLog("Old snap info: %s %d", oldSnap.SnapID, oldSnap.Revision.N)
|
||||
result, err = fetchOrRefreshSnapInfo(snapName, oldSnap, channel)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "snap has no updates available") {
|
||||
result, err = fetchOrRefreshSnapInfo(snapName, nil, channel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
workingChannel = channel
|
||||
}
|
||||
} else if strings.Contains(err.Error(), "no snap revision available as specified") {
|
||||
result, err = fetchOrRefreshSnapInfo(snapName, oldSnap, fallbackChannel)
|
||||
@ -61,14 +69,20 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
|
||||
result, err = fetchOrRefreshSnapInfo(snapName, nil, fallbackChannel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
workingChannel = fallbackChannel
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
workingChannel = fallbackChannel
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
workingChannel = channel
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,9 +92,10 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
|
||||
|
||||
info := result.Info
|
||||
newSnap := &store.CurrentSnap{
|
||||
InstanceName: snapName,
|
||||
SnapID: info.SnapID,
|
||||
Revision: snap.Revision{N: info.Revision.N},
|
||||
InstanceName: snapName,
|
||||
SnapID: info.SnapID,
|
||||
Revision: snap.Revision{N: info.Revision.N},
|
||||
TrackingChannel: workingChannel,
|
||||
}
|
||||
snapInCurrentSnaps, oldRevision := isSnapInCurrentSnaps(snapName)
|
||||
if snapInCurrentSnaps {
|
||||
@ -176,7 +191,7 @@ func fetchOrRefreshSnapInfo(snapName string, currentSnap *store.CurrentSnap, cha
|
||||
results, _, err := storeClient.SnapAction(ctx, includeSnap, actions, nil, nil, nil)
|
||||
if err != nil {
|
||||
verboseLog("SnapAction error for %s: %v", snapName, err)
|
||||
if strings.Contains(err.Error(), "snap has no updates available") && currentSnap != nil {
|
||||
if (strings.Contains(err.Error(), "snap has no updates available") || strings.Contains(err.Error(), "no snap revision available as specified")) && currentSnap != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("snap action failed for %s: %w", snapName, err)
|
||||
@ -232,6 +247,12 @@ func findPreviousSnap(downloadDir, assertionsDir, snapName string) (string, *sto
|
||||
assertFilePath := filepath.Join(assertionsDir, strings.Replace(file.Name(), ".snap", ".assert", 1))
|
||||
currentSnap = parseSnapInfo(assertFilePath, snapName)
|
||||
currentSnap.Revision.N = revision
|
||||
trackingChannel, err := getChannelName(snapName)
|
||||
if err != nil {
|
||||
verboseLog("Failed to get existing channel name for %s", snapName)
|
||||
continue
|
||||
}
|
||||
currentSnap.TrackingChannel = "latest/" + trackingChannel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,42 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/snapcore/snapd/store"
|
||||
)
|
||||
|
||||
type seed struct {
|
||||
Snaps []struct {
|
||||
Name string `yaml:"name"`
|
||||
Channel string `yaml:"channel"`
|
||||
File string `yaml:"file"`
|
||||
} `yaml:"snaps"`
|
||||
}
|
||||
|
||||
// getChannelName returns the channel name for a specific snap name
|
||||
func getChannelName(snapName string) (string, error) {
|
||||
file, err := ioutil.ReadFile(seedYaml)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read seed.yaml: %w", err)
|
||||
}
|
||||
|
||||
var seedData seed
|
||||
if err := yaml.Unmarshal(file, &seedData); err != nil {
|
||||
return "", fmt.Errorf("failed to parse seed.yaml: %w", err)
|
||||
}
|
||||
|
||||
for _, snap := range seedData.Snaps {
|
||||
if snap.Name == snapName {
|
||||
return snap.Channel, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("snap %s not found in seed.yaml", snapName)
|
||||
}
|
||||
|
||||
// initializeSeedYaml ensures that seed.yaml exists; if not, creates it.
|
||||
func initializeSeedYaml(seedYaml string) {
|
||||
func initializeSeedYaml() {
|
||||
if _, err := os.Stat(seedYaml); os.IsNotExist(err) {
|
||||
file, err := os.Create(seedYaml)
|
||||
if err != nil {
|
||||
@ -23,7 +52,7 @@ func initializeSeedYaml(seedYaml string) {
|
||||
}
|
||||
|
||||
// loadSeedData loads seed data from seed.yaml
|
||||
func loadSeedData(seedYaml string) seed {
|
||||
func loadSeedData() seed {
|
||||
file, err := ioutil.ReadFile(seedYaml)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read seed.yaml: %v", err)
|
||||
@ -38,7 +67,7 @@ func loadSeedData(seedYaml string) seed {
|
||||
}
|
||||
|
||||
// loadExistingSnaps loads snaps from seed.yaml into a map
|
||||
func loadExistingSnaps(seedYaml string) map[string]bool {
|
||||
func loadExistingSnaps() map[string]bool {
|
||||
file, err := ioutil.ReadFile(seedYaml)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read seed.yaml: %v", err)
|
||||
@ -58,7 +87,7 @@ func loadExistingSnaps(seedYaml string) map[string]bool {
|
||||
}
|
||||
|
||||
// updateSeedYaml updates the seed.yaml file with the current required snaps
|
||||
func updateSeedYaml(snapsDir, seedYaml string, currentSnaps []*store.CurrentSnap) error {
|
||||
func updateSeedYaml(snapsDir string, currentSnaps []*store.CurrentSnap) error {
|
||||
// Log the snaps to be written
|
||||
verboseLog("CurrentSnaps to be written to seed.yaml:")
|
||||
for _, snapInfo := range currentSnaps {
|
||||
@ -92,7 +121,7 @@ func updateSeedYaml(snapsDir, seedYaml string, currentSnaps []*store.CurrentSnap
|
||||
File string `yaml:"file"`
|
||||
}{
|
||||
Name: snapInfo.InstanceName,
|
||||
Channel: "stable", // Assuming 'stable' channel; modify as needed
|
||||
Channel: strings.Replace(snapInfo.TrackingChannel, "latest/", "", -1),
|
||||
File: snapFileName,
|
||||
}
|
||||
seedData.Snaps = append(seedData.Snaps, snapData)
|
||||
|
@ -148,3 +148,28 @@ func verifySnapIntegrity(filePath, expectedChecksum string) bool {
|
||||
}
|
||||
return checksumMatches
|
||||
}
|
||||
|
||||
// Get the raw VERSION_ID from /etc/os-release to use for branch detection
|
||||
func getVersionID() (string, error) {
|
||||
file, err := os.Open("/etc/os-release")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open /etc/os-release: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "VERSION_ID=") {
|
||||
// Remove the prefix and any surrounding quotes
|
||||
versionID := strings.Trim(strings.SplitN(line, "=", 2)[1], `"`)
|
||||
return versionID, nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", fmt.Errorf("error reading /etc/os-release: %w", err)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("VERSION_ID not found in /etc/os-release")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user