func GenerateFullUpdate(version string, prod bool) error { var variant string if prod { variant = "production" } else { variant = "developer" } var ( dir = sdk.BuildImageDir(version) update_prefix = filepath.Join(dir, "coreos_"+variant+"_update") update_bin = update_prefix + ".bin" update_gz = update_prefix + ".gz" update_xml = update_prefix + ".xml" ) if err := checkUpdate(dir, update_xml); err == nil { plog.Infof("Using update manifest: %s", update_xml) return nil } plog.Noticef("Generating update payload: %s", update_gz) if err := run("delta_generator", "-new_image", update_bin, "-out_file", update_gz, "-private_key", privateKey); err != nil { return err } plog.Infof("Writing update manifest: %s", update_xml) update := omaha.Update{Id: sdk.GetDefaultAppId()} pkg, err := update.AddPackageFromPath(update_gz) // update engine needs the payload hash here in the action element postinstall := update.AddAction("postinstall") postinstall.Sha256 = pkg.Sha256 update.Version, err = sdk.GetVersionFromDir(dir) if err != nil { return err } return xmlMarshalFile(update_xml, &update) }
func runUpdatePayload(cmd *cobra.Command, args []string) { if len(args) != 0 { plog.Fatal("No args accepted") } plog.Info("Generating update payload") // check for update file, generate if it doesn't exist version := "latest" dir := sdk.BuildImageDir(version) payload := "coreos_production_update.gz" _, err := os.Stat(filepath.Join(dir, payload)) if err != nil { err = sdkomaha.GenerateFullUpdate("latest", true) if err != nil { plog.Fatalf("Building full update failed: %v", err) } } plog.Info("Bringing up test harness cluster") cluster, err := platform.NewQemuCluster(kola.QEMUOptions) qc := cluster.(*platform.QEMUCluster) if err != nil { plog.Fatalf("Cluster failed: %v", err) } defer cluster.Destroy() svc := &updateServer{ updatePath: dir, payload: payload, } qc.OmahaServer.Updater = svc // tell omaha server to handle file requests for the images dir qc.OmahaServer.Mux.Handle(dir+"/", http.StripPrefix(dir+"/", http.FileServer(http.Dir(dir)))) _, port, err := net.SplitHostPort(qc.OmahaServer.Addr().String()) if err != nil { plog.Errorf("SplitHostPort failed: %v", err) return } tmplVals := map[string]string{ "Server": fmt.Sprintf("10.0.0.1:%s", port), } tmpl := template.Must(template.New("userdata").Parse(userdata)) buf := new(bytes.Buffer) err = tmpl.Execute(buf, tmplVals) if err != nil { plog.Errorf("Template execution failed: %v", err) return } plog.Infof("Spawning test machine") m, err := cluster.NewMachine(buf.String()) if err != nil { plog.Errorf("Machine failed: %v", err) return } plog.Info("Checking for boot from USR-A partition") /* check that we are on USR-A. */ if err := checkUsrPartition(m, []string{"PARTUUID=" + sdk.USRAUUID.String(), "PARTLABEL=USR-A"}); err != nil { plog.Errorf("Did not find USR-A partition: %v", err) return } plog.Infof("Triggering update_engine") /* trigger update, monitor the progress. */ out, err := m.SSH("update_engine_client -check_for_update") if err != nil { plog.Errorf("Executing update_engine_client failed: %v: %v", out, err) return } checker := func() error { envs, err := m.SSH("update_engine_client -status 2>/dev/null") if err != nil { return err } em := splitNewlineEnv(string(envs)) if em["CURRENT_OP"] != "UPDATE_STATUS_UPDATED_NEED_REBOOT" { return fmt.Errorf("have not arrived in reboot state: currently at %s", em["CURRENT_OP"]) } return nil } if err := util.Retry(12, 10*time.Second, checker); err != nil { plog.Errorf("Applying update payload failed: %v", err) return } plog.Info("Rebooting test machine") /* reboot it */ if err := platform.Reboot(m); err != nil { plog.Errorf("Rebooting machine failed: %v", err) return } plog.Info("Checking for boot from USR-B partition") /* check that we are on USR-B now. */ if err := checkUsrPartition(m, []string{"PARTUUID=" + sdk.USRBUUID.String(), "PARTLABEL=USR-B"}); err != nil { plog.Errorf("Did not find USR-B partition: %v", err) return } plog.Info("Update complete!") }