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