Commit 6fd59cda authored by Roman Alifanov's avatar Roman Alifanov

init: kernel support

parent fcf864a7
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
) )
func GetPackageInfo(name string) InfoResponse { func GetPackageInfo(name string) InfoResponse {
conn := sudbus.GetConnection() conn := sudbus.GetSystemConnection()
reply, err := conn.Proxy.CallSync( reply, err := conn.Proxy.CallSync(
context.Background(), context.Background(),
......
...@@ -2,6 +2,7 @@ package apm ...@@ -2,6 +2,7 @@ package apm
import ( import (
"encoding/xml" "encoding/xml"
"time"
) )
type LocalizedText struct { type LocalizedText struct {
...@@ -108,12 +109,147 @@ type EventData struct { ...@@ -108,12 +109,147 @@ type EventData struct {
Transaction string `json:"transaction,omitempty"` Transaction string `json:"transaction,omitempty"`
} }
type PackageChanges struct {
ExtraInstalled []string `json:"extraInstalled"`
UpgradedPackages []string `json:"upgradedPackages"`
NewInstalledPackages []string `json:"newInstalledPackages"`
RemovedPackages []string `json:"removedPackages"`
UpgradedCount int `json:"upgradedCount"`
NewInstalledCount int `json:"newInstalledCount"`
RemovedCount int `json:"removedCount"`
NotUpgradedCount int `json:"-"`
DownloadSize uint64 `json:"downloadSize"`
InstallSize uint64 `json:"installSize"`
}
type InfoResponse struct { type InfoResponse struct {
Message string `json:"message"` Message string `json:"message"`
PackageInfo Package `json:"packageInfo"` PackageInfo Package `json:"packageInfo"`
} }
// KERNEL
type KernelInfo struct {
PackageName string `json:"packageName"`
Flavour string `json:"flavour"`
Version string `json:"version"`
VersionInstalled string `json:"versionInstalled"`
Release string `json:"release"`
BuildTime time.Time `json:"buildTime"`
IsInstalled bool `json:"isInstalled"`
IsRunning bool `json:"isRunning"`
FullVersion string `json:"fullVersion"`
AgeInDays int `json:"ageInDays"`
}
type FullKernelInfo struct {
PackageName string `json:"packageName"`
Flavour string `json:"flavour"`
Version string `json:"version"`
VersionInstalled string `json:"versionInstalled"`
Release string `json:"release"`
FullVersion string `json:"fullVersion"`
IsInstalled bool `json:"isInstalled"`
IsRunning bool `json:"isRunning"`
AgeInDays int `json:"ageInDays"`
BuildTime string `json:"buildTime"`
InstalledModules []InstalledKernelModuleInfo `json:"installedModules,omitempty"`
}
type ShortKernelInfo struct {
Version string `json:"version"`
VersionInstalled string `json:"versionInstalled"`
Flavour string `json:"flavour"`
FullVersion string `json:"fullVersion"`
IsInstalled bool `json:"isInstalled"`
IsRunning bool `json:"isRunning"`
}
type InstalledKernelModuleInfo struct {
Name string `json:"name"`
PackageName string `json:"packageName"`
}
type KernelModuleInfo struct {
Name string `json:"name"`
IsInstalled bool `json:"isInstalled"`
PackageName string `json:"packageName"`
}
type KernelUpgradePreview struct {
Changes *PackageChanges `json:"changes"`
SelectedModules []string `json:"selectedModules"`
MissingModules []string `json:"missingModules"`
}
type ListKernelsResponse struct {
Message string `json:"message"`
Kernels []FullKernelInfo `json:"kernels"`
}
type GetCurrentKernelResponse struct {
Message string `json:"message"`
Kernel FullKernelInfo `json:"kernel"`
}
type InstallUpdateKernelResponse struct {
Message string `json:"message"`
Kernel FullKernelInfo `json:"kernel"`
Preview *KernelUpgradePreview `json:"preview,omitempty"`
}
type KernelWithReasons struct {
Kernel KernelInfo `json:"kernel"`
Reasons []string `json:"reasons"`
}
type CleanOldKernelsResponse struct {
Message string `json:"message"`
RemoveKernels []KernelInfo `json:"removeKernels"`
KeptKernels []KernelWithReasons `json:"keptKernels"`
Preview *PackageChanges `json:"preview,omitempty"`
}
type ListKernelModulesResponse struct {
Message string `json:"message"`
Kernel FullKernelInfo `json:"kernel"`
Modules KernelModuleInfo `json:"modules"`
}
type InstallKernelModulesResponse struct {
Message string `json:"message"`
Kernel FullKernelInfo `json:"kernel"`
Preview PackageChanges `json:"preview,omitempty"`
}
type RemoveKernelModulesResponse struct {
Message string `json:"message"`
Kernel FullKernelInfo `json:"kernel"`
Preview *PackageChanges `json:"preview,omitempty"`
}
// misc
type InfoRootResponse struct { type InfoRootResponse struct {
Data InfoResponse `json:"data"` Data InfoResponse `json:"data"`
Error bool `json:"error"` Error bool `json:"error"`
} }
type UpdateKernelRootResponse struct {
Data struct {
Kernel FullKernelInfo `json:"kernel"`
Preview KernelUpgradePreview `json:"preview"`
Message string `json:"message"`
} `json:"data"`
Error bool `json:"error"`
}
type CheckUpgradeRootResponse struct {
Data struct {
Info PackageChanges `json:"info"`
Message string `json:"message"`
} `json:"data"`
Error bool `json:"error"`
}
...@@ -12,10 +12,10 @@ type Connection struct { ...@@ -12,10 +12,10 @@ type Connection struct {
Proxy *gio.DBusProxy Proxy *gio.DBusProxy
} }
var conn *Connection var systemConn *Connection
func GetConnection() *Connection { func GetSystemConnection() *Connection {
if conn == nil { if systemConn == nil {
c, err := gio.BusGetSync(context.Background(), gio.BusTypeSystem) c, err := gio.BusGetSync(context.Background(), gio.BusTypeSystem)
if err != nil { if err != nil {
log.Fatal("DBus connect:", err) log.Fatal("DBus connect:", err)
...@@ -34,10 +34,40 @@ func GetConnection() *Connection { ...@@ -34,10 +34,40 @@ func GetConnection() *Connection {
log.Fatal("DBus proxy:", err) log.Fatal("DBus proxy:", err)
} }
conn = &Connection{ systemConn = &Connection{
Conn: c, Conn: c,
Proxy: proxy, Proxy: proxy,
} }
} }
return conn return systemConn
}
var kernelConn *Connection
func GetKernelConnection() *Connection {
if kernelConn == nil {
c, err := gio.BusGetSync(context.Background(), gio.BusTypeSystem)
if err != nil {
log.Fatal("DBus connect:", err)
}
proxy, err := gio.NewDBusProxyForBusSync(
context.Background(),
gio.BusTypeSystem,
gio.DBusProxyFlagsNone,
nil,
"org.altlinux.APM",
"/org/altlinux/APM",
"org.altlinux.APM.kernel",
)
if err != nil {
log.Fatal("DBus proxy:", err)
}
kernelConn = &Connection{
Conn: c,
Proxy: proxy,
}
}
return kernelConn
} }
...@@ -20,36 +20,15 @@ type UpdaterSource interface { ...@@ -20,36 +20,15 @@ type UpdaterSource interface {
) error ) error
} }
type PackageChanges struct {
ExtraInstalled []string `json:"extraInstalled"`
UpgradedPackages []string `json:"upgradedPackages"`
NewInstalledPackages []string `json:"newInstalledPackages"`
RemovedPackages []string `json:"removedPackages"`
UpgradedCount int `json:"upgradedCount"`
NewInstalledCount int `json:"newInstalledCount"`
RemovedCount int `json:"removedCount"`
NotUpgradedCount int `json:"-"`
DownloadSize uint64 `json:"downloadSize"`
InstallSize uint64 `json:"installSize"`
}
type Response struct {
Data struct {
Info PackageChanges `json:"info"`
Message string `json:"message"`
} `json:"data"`
Error bool `json:"error"`
}
type UpdatesSources map[string]UpdaterSource type UpdatesSources map[string]UpdaterSource
func NewUpdatesSources() UpdatesSources { func NewUpdatesSources() UpdatesSources {
conn := sudbus.GetConnection() systemConn := sudbus.GetSystemConnection()
kernelConn := sudbus.GetKernelConnection()
return UpdatesSources{ return UpdatesSources{
"System": &SystemUpdatesSource{Proxy: conn.Proxy, Conn: conn.Conn}, "System": &SystemUpdatesSource{Proxy: systemConn.Proxy, Conn: systemConn.Conn},
// "Kernel": &KernelUpdatesSource{conn: conn, obj: obj}, "Kernel": &KernelUpdatesSource{Proxy: kernelConn.Proxy, Conn: kernelConn.Conn},
} }
} }
...@@ -149,10 +128,126 @@ func (s *SystemUpdatesSource) GetPackageChanges() PackageChanges { ...@@ -149,10 +128,126 @@ func (s *SystemUpdatesSource) GetPackageChanges() PackageChanges {
panic("DBus CheckUpgrade error: " + err.Error()) panic("DBus CheckUpgrade error: " + err.Error())
} }
var parsed Response var parsed CheckUpgradeRootResponse
if err := json.Unmarshal([]byte(reply.ChildValue(0).String()), &parsed); err != nil { if err := json.Unmarshal([]byte(reply.ChildValue(0).String()), &parsed); err != nil {
panic("Failed to parse CheckUpgrade: " + err.Error()) panic("Failed to parse CheckUpgrade: " + err.Error())
} }
return parsed.Data.Info return parsed.Data.Info
} }
type KernelUpdatesSource struct {
Proxy *gio.DBusProxy
Conn *gio.DBusConnection
}
func (s *KernelUpdatesSource) RunUpgrade(
onDone func(),
onLog func(EventData),
) error {
stopSignals := make(chan struct{})
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
subID := s.Conn.SignalSubscribe(
"org.altlinux.APM",
"org.altlinux.APM",
"Notification",
"/org/altlinux/APM",
"",
gio.DBusSignalFlagsNone,
func(conn *gio.DBusConnection,
senderName string,
objectPath string,
interfaceName string,
signalName string,
parameters *glib.Variant) {
select {
case <-stopSignals:
return
default:
}
raw := parameters.ChildValue(0).String()
var data EventData
if err := json.Unmarshal([]byte(raw), &data); err == nil {
glib.IdleAdd(func() { onLog(data) })
} else {
fmt.Println("JSON decode error:", err)
}
},
)
<-stopSignals
s.Conn.SignalUnsubscribe(subID)
}()
go func() {
defer wg.Done()
args := glib.NewVariantTuple([]*glib.Variant{
glib.NewVariantString(""),
glib.NewVariantArray(glib.NewVariantType("s"), []*glib.Variant{}),
glib.NewVariantBoolean(false),
glib.NewVariantBoolean(false),
glib.NewVariantString("Ximper System Updater"),
})
_, err := s.Proxy.CallSync(
context.Background(),
"UpdateKernel",
args,
gio.DBusCallFlagsNone,
-1,
)
if err != nil {
log.Println("Upgrade error:", err)
}
close(stopSignals)
glib.IdleAdd(onDone)
}()
wg.Wait()
return nil
}
func (s *KernelUpdatesSource) GetPackageChanges() PackageChanges {
args := glib.NewVariantTuple([]*glib.Variant{
glib.NewVariantString(""),
glib.NewVariantArray(glib.NewVariantType("s"), []*glib.Variant{}),
glib.NewVariantBoolean(false),
glib.NewVariantBoolean(true),
glib.NewVariantString("Ximper System Updater"),
})
reply, err := s.Proxy.CallSync(
context.Background(),
"UpdateKernel",
args,
gio.DBusCallFlagsNone,
-1,
)
if err != nil {
panic("DBus CheckUpgrade error: " + err.Error())
}
fmt.Println(reply.ChildValue(0).String())
var parsed UpdateKernelRootResponse
if err := json.Unmarshal([]byte(reply.ChildValue(0).String()), &parsed); err != nil {
panic("Failed to parse CheckUpgrade: " + err.Error())
}
return *parsed.Data.Preview.Changes
}
...@@ -39,14 +39,17 @@ func GetSystemUpdater() *SystemUpdater { ...@@ -39,14 +39,17 @@ func GetSystemUpdater() *SystemUpdater {
return mainApp return mainApp
} }
var updates []apm.PackageChanges var updates map[string]apm.PackageChanges
func (su *SystemUpdater) backgroundStart() { func (su *SystemUpdater) backgroundStart() {
updatesSources := apm.NewUpdatesSources() updatesSources := apm.NewUpdatesSources()
us := make(map[string]apm.PackageChanges)
for _, u := range updatesSources { for name, source := range updatesSources {
updates = append(updates, u.GetPackageChanges()) us[name] = source.GetPackageChanges()
} }
updates = us
} }
func (su *SystemUpdater) onActivate() { func (su *SystemUpdater) onActivate() {
...@@ -107,9 +110,9 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow { ...@@ -107,9 +110,9 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow {
return mainWin return mainWin
} }
func (sw *SystemUpdaterWindow) FillWithChanges(su *SystemUpdater, u []apm.PackageChanges) { func (sw *SystemUpdaterWindow) FillWithChanges(su *SystemUpdater, u map[string]apm.PackageChanges) {
for _, updatesList := range u { for name, updatesList := range u {
sw.listbox.Append(NewUpdateRow("System packages", updatesList, sw.StartUpdateProcess)) sw.listbox.Append(NewUpdateRow(name, updatesList, sw.StartUpdateProcess))
} }
} }
......
...@@ -94,7 +94,14 @@ func NewUpdateRow(name string, info apm.PackageChanges, runUpgradeCallback func( ...@@ -94,7 +94,14 @@ func NewUpdateRow(name string, info apm.PackageChanges, runUpgradeCallback func(
sem <- struct{}{} sem <- struct{}{}
defer func() { <-sem }() defer func() { <-sem }()
info := apm.GetPackageInfo(pkg) trimmedPkg := pkg
if strings.HasPrefix(pkg, "kernel-modules-") || strings.HasPrefix(pkg, "kernel-image-") {
if idx := strings.Index(pkg, "#"); idx != -1 {
trimmedPkg = pkg[:idx]
}
}
info := apm.GetPackageInfo(trimmedPkg)
mu.Lock() mu.Lock()
pkgsWithInfo[pkg] = info pkgsWithInfo[pkg] = info
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment