gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/daemon/api_debug_seeding.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package daemon 21 22 import ( 23 "time" 24 25 "github.com/snapcore/snapd/overlord/state" 26 ) 27 28 type seedingInfo struct { 29 // Seeded is true when the device was seeded (same as "seeded" in the 30 // state). 31 Seeded bool `json:"seeded,omitempty"` 32 33 // Preseeded is true if snap-preseed was applied. 34 Preseeded bool `json:"preseeded,omitempty"` 35 36 // PreseedStartTime is when snap-preseed was started. 37 PreseedStartTime *time.Time `json:"preseed-start-time,omitempty"` 38 39 // PreseedTime is when snap-preseed work finished (i.e. before firstboot). 40 PreseedTime *time.Time `json:"preseed-time,omitempty"` 41 42 // SeedStartTime is when traditional seeding started (when not preseeding). 43 SeedStartTime *time.Time `json:"seed-start-time,omitempty"` 44 45 // SeedRestartTime is when seeding was started after first boot of preseeded 46 // image. 47 SeedRestartTime *time.Time `json:"seed-restart-time,omitempty"` 48 49 // SeedTime is when seeding finished. 50 SeedTime *time.Time `json:"seed-time,omitempty"` 51 52 // PreseedSystemKey is the system-key that was created during preseeding 53 // (when snap-preseed was ran). 54 PreseedSystemKey interface{} `json:"preseed-system-key,omitempty"` 55 56 // SeedRestartSystemKey is the system-key that was created on first boot of the 57 // preseeded image. 58 SeedRestartSystemKey interface{} `json:"seed-restart-system-key,omitempty"` 59 60 // SeedError is set if no seed change succeeded yet and at 61 // least one was in error. It is set to the error of the 62 // oldest known in error one. 63 SeedError string `json:"seed-error,omitempty"` 64 } 65 66 func getSeedingInfo(st *state.State) Response { 67 var seeded, preseeded bool 68 err := st.Get("seeded", &seeded) 69 if err != nil && err != state.ErrNoState { 70 return InternalError(err.Error()) 71 } 72 if err = st.Get("preseeded", &preseeded); err != nil && err != state.ErrNoState { 73 return InternalError(err.Error()) 74 } 75 76 var preseedSysKey, seedRestartSysKey interface{} 77 if err := st.Get("preseed-system-key", &preseedSysKey); err != nil && err != state.ErrNoState { 78 return InternalError(err.Error()) 79 } 80 if err := st.Get("seed-restart-system-key", &seedRestartSysKey); err != nil && err != state.ErrNoState { 81 return InternalError(err.Error()) 82 } 83 84 var seedError string 85 var seedErrorChangeTime time.Time 86 if !seeded { 87 for _, chg := range st.Changes() { 88 if chg.Kind() != "seed" && !chg.IsReady() { 89 continue 90 } 91 if err := chg.Err(); err != nil { 92 if seedErrorChangeTime.IsZero() || chg.SpawnTime().Before(seedErrorChangeTime) { 93 seedError = chg.Err().Error() 94 seedErrorChangeTime = chg.SpawnTime() 95 } 96 } 97 } 98 } 99 100 data := &seedingInfo{ 101 Seeded: seeded, 102 SeedError: seedError, 103 Preseeded: preseeded, 104 PreseedSystemKey: preseedSysKey, 105 SeedRestartSystemKey: seedRestartSysKey, 106 } 107 108 for _, t := range []struct { 109 name string 110 destTm **time.Time 111 }{ 112 {"preseed-start-time", &data.PreseedStartTime}, 113 {"preseed-time", &data.PreseedTime}, 114 {"seed-start-time", &data.SeedStartTime}, 115 {"seed-restart-time", &data.SeedRestartTime}, 116 {"seed-time", &data.SeedTime}, 117 } { 118 var tm time.Time 119 if err := st.Get(t.name, &tm); err != nil && err != state.ErrNoState { 120 return InternalError(err.Error()) 121 } 122 if !tm.IsZero() { 123 *t.destTm = &tm 124 } 125 } 126 127 // XXX: consistency & sanity checks, e.g. if preseeded, then need to have 128 // preseed-start-time, preseeded-time, preseed-system-key etc? 129 130 return SyncResponse(data) 131 }