16
"github.com/mvo5/goconfigparser"
18
"launchpad.net/snappy/helpers"
21
var systemImageServer = "https://system-image.ubuntu.com/"
23
type updateStatus struct {
25
targetVersionDetails string
30
type channelImage struct {
31
Descripton string `json:"description,omitempty"`
32
Type string `json:"type, omitempty"`
33
Version int `json:"version, omitempty"`
34
VersionDetails string `json:"version_detail, omitempty"`
35
Files []channelImageFiles `json:"files"`
38
type channelImageFiles struct {
39
Size int64 `json:"size"`
42
type channelImageGlobal struct {
43
GeneratedAt string `json:"generated_at"`
46
type channelJSON struct {
47
Global channelImageGlobal `json:"global"`
48
Images []channelImage `json:"images"`
51
func systemImageClientCheckForUpdates(configFile string) (us updateStatus, err error) {
52
cfg := goconfigparser.New()
53
if err := cfg.ReadFile(configFile); err != nil {
56
channel, _ := cfg.Get("service", "channel")
57
device, _ := cfg.Get("service", "device")
59
indexURL := systemImageServer + "/" + path.Join(channel, device, "index.json")
61
resp, err := http.Get(indexURL)
65
defer resp.Body.Close()
67
if resp.StatusCode != 200 {
68
return us, fmt.Errorf("systemImageDbusProxy: unexpected http statusCode %v for %s", resp.StatusCode, indexURL)
72
var channelData channelJSON
73
dec := json.NewDecoder(resp.Body)
74
if err := dec.Decode(&channelData); err != nil {
79
us.lastUpdate, _ = time.Parse("Mon Jan 2 15:04:05 MST 2006", channelData.Global.GeneratedAt)
81
// FIXME: find latest image of type "full" here
82
latestImage := channelData.Images[len(channelData.Images)-1]
83
us.targetVersion = fmt.Sprintf("%d", latestImage.Version)
84
us.targetVersionDetails = latestImage.VersionDetails
86
// FIXME: this is not accurate right now as it does not take
87
// the deltas into account
88
for _, f := range latestImage.Files {
89
us.updateSize += f.Size
95
type genericJSON struct {
96
Type string `json:"type, omitempty"`
97
Message string `json:"msg, omitempty"`
98
Now float64 `json:"now, omitempty"`
99
Total float64 `json:"total, omitempty"`
102
func systemImageDownloadUpdate(configFile string, pb ProgressMeter) (err error) {
103
cmd := exec.Command(systemImageCli, "--machine-readable", "-C", configFile)
105
// collect progress over stdout
108
stdout, err = cmd.StdoutPipe()
114
// collect error message (traceback etc)
115
stderr, err := cmd.StderrPipe()
119
stderrCh := make(chan []byte)
121
stderrContent, _ := ioutil.ReadAll(stderr)
122
stderrCh <- stderrContent
126
if err := cmd.Start(); err != nil {
130
// and parse progress
132
scanner := bufio.NewScanner(stdout)
133
// s-i is funny, total changes during the runs
138
if os.Getenv("SNAPPY_DEBUG") != "" {
139
fmt.Println(scanner.Text())
142
jsonStream := strings.NewReader(scanner.Text())
143
dec := json.NewDecoder(jsonStream)
144
var genericData genericJSON
145
if err := dec.Decode(&genericData); err != nil {
150
case genericData.Type == "spinner":
151
pb.Spin(genericData.Message)
152
case genericData.Type == "error":
153
return fmt.Errorf("error from %s: %s", systemImageCli, genericData.Message)
154
case genericData.Type == "progress":
155
if total != genericData.Total {
156
total = genericData.Total
159
pb.Set(genericData.Now)
163
if err := scanner.Err(); err != nil {
168
if err := cmd.Wait(); err != nil {
169
stderrContent := <-stderrCh
170
retCode, _ := helpers.ExitCode(err)
171
return fmt.Errorf("%s failed with return code %v: %s", systemImageCli, retCode, string(stderrContent))