github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/daemon/api_console_conf.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 "encoding/json" 24 "io" 25 "net/http" 26 "time" 27 28 "github.com/snapcore/snapd/logger" 29 "github.com/snapcore/snapd/overlord/auth" 30 ) 31 32 var ( 33 routineConsoleConfStartCmd = &Command{ 34 Path: "/v2/internal/console-conf-start", 35 POST: consoleConfStartRoutine, 36 WriteAccess: authenticatedAccess{}, 37 } 38 ) 39 40 var delayTime = 20 * time.Minute 41 42 // consoleConfStartRoutineResult is the result of running the console-conf start 43 // routine.. 44 type consoleConfStartRoutineResult struct { 45 ActiveAutoRefreshChanges []string `json:"active-auto-refreshes,omitempty"` 46 ActiveAutoRefreshSnaps []string `json:"active-auto-refresh-snaps,omitempty"` 47 } 48 49 func consoleConfStartRoutine(c *Command, r *http.Request, _ *auth.UserState) Response { 50 // no body expected, error if we were provided anything 51 defer r.Body.Close() 52 var routineBody struct{} 53 decoder := json.NewDecoder(r.Body) 54 if err := decoder.Decode(&routineBody); err != nil && err != io.EOF { 55 return BadRequest("cannot decode request body into console-conf operation: %v", err) 56 } 57 58 // now run the start routine first by trying to grab a lock on the refreshes 59 // for all snaps, which fails if there are any active changes refreshing 60 // snaps 61 st := c.d.overlord.State() 62 st.Lock() 63 defer st.Unlock() 64 65 snapAutoRefreshChanges, err := c.d.overlord.SnapManager().EnsureAutoRefreshesAreDelayed(delayTime) 66 if err != nil { 67 return InternalError(err.Error()) 68 } 69 70 logger.Debugf("Ensured that new auto refreshes are delayed by %s to allow console-conf to run", delayTime) 71 72 if len(snapAutoRefreshChanges) == 0 { 73 // no changes yet, and we delayed the refresh successfully so 74 // console-conf is okay to run normally 75 return SyncResponse(&consoleConfStartRoutineResult{}) 76 } 77 78 chgIds := make([]string, 0, len(snapAutoRefreshChanges)) 79 snapNames := make([]string, 0) 80 for _, chg := range snapAutoRefreshChanges { 81 chgIds = append(chgIds, chg.ID()) 82 var updatedSnaps []string 83 err := chg.Get("snap-names", &updatedSnaps) 84 if err != nil { 85 return InternalError(err.Error()) 86 } 87 snapNames = append(snapNames, updatedSnaps...) 88 } 89 90 // we have changes that the client should wait for before being ready 91 return SyncResponse(&consoleConfStartRoutineResult{ 92 ActiveAutoRefreshChanges: chgIds, 93 ActiveAutoRefreshSnaps: snapNames, 94 }) 95 96 }