github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/configstate/configcore/refresh.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  // +build !nomanagers
     3  
     4  /*
     5   * Copyright (C) 2017-2018 Canonical Ltd
     6   *
     7   * This program is free software: you can redistribute it and/or modify
     8   * it under the terms of the GNU General Public License version 3 as
     9   * published by the Free Software Foundation.
    10   *
    11   * This program is distributed in the hope that it will be useful,
    12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14   * GNU General Public License for more details.
    15   *
    16   * You should have received a copy of the GNU General Public License
    17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18   *
    19   */
    20  
    21  package configcore
    22  
    23  import (
    24  	"fmt"
    25  	"strconv"
    26  	"time"
    27  
    28  	"github.com/snapcore/snapd/overlord/configstate/config"
    29  	"github.com/snapcore/snapd/overlord/devicestate"
    30  	"github.com/snapcore/snapd/strutil"
    31  	"github.com/snapcore/snapd/timeutil"
    32  )
    33  
    34  func init() {
    35  	supportedConfigurations["core.refresh.hold"] = true
    36  	supportedConfigurations["core.refresh.schedule"] = true
    37  	supportedConfigurations["core.refresh.timer"] = true
    38  	supportedConfigurations["core.refresh.metered"] = true
    39  	supportedConfigurations["core.refresh.retain"] = true
    40  	supportedConfigurations["core.refresh.rate-limit"] = true
    41  }
    42  
    43  func validateRefreshSchedule(tr config.Conf) error {
    44  	refreshRetainStr, err := coreCfg(tr, "refresh.retain")
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if refreshRetainStr != "" {
    49  		if n, err := strconv.ParseUint(refreshRetainStr, 10, 8); err != nil || (n < 2 || n > 20) {
    50  			return fmt.Errorf("retain must be a number between 2 and 20, not %q", refreshRetainStr)
    51  		}
    52  	}
    53  
    54  	refreshHoldStr, err := coreCfg(tr, "refresh.hold")
    55  	if err != nil {
    56  		return err
    57  	}
    58  	if refreshHoldStr != "" {
    59  		if _, err := time.Parse(time.RFC3339, refreshHoldStr); err != nil {
    60  			return fmt.Errorf("refresh.hold cannot be parsed: %v", err)
    61  		}
    62  	}
    63  
    64  	refreshOnMeteredStr, err := coreCfg(tr, "refresh.metered")
    65  	if err != nil {
    66  		return err
    67  	}
    68  	switch refreshOnMeteredStr {
    69  	case "", "hold":
    70  		// noop
    71  	default:
    72  		return fmt.Errorf("refresh.metered value %q is invalid", refreshOnMeteredStr)
    73  	}
    74  
    75  	// check (new) refresh.timer
    76  	refreshTimerStr, err := coreCfg(tr, "refresh.timer")
    77  	if err != nil {
    78  		return err
    79  	}
    80  	if refreshTimerStr == "managed" {
    81  		st := tr.State()
    82  		st.Lock()
    83  		defer st.Unlock()
    84  
    85  		if !devicestate.CanManageRefreshes(st) {
    86  			return fmt.Errorf("cannot set schedule to managed")
    87  		}
    88  		return nil
    89  	}
    90  	if refreshTimerStr != "" {
    91  		// try legacy refresh.schedule setting if new-style
    92  		// refresh.timer is not set
    93  		if _, err = timeutil.ParseSchedule(refreshTimerStr); err != nil {
    94  			return err
    95  		}
    96  	}
    97  
    98  	// check (legacy) refresh.schedule
    99  	refreshScheduleStr, err := coreCfg(tr, "refresh.schedule")
   100  	if err != nil {
   101  		return err
   102  	}
   103  	if refreshScheduleStr == "" {
   104  		return nil
   105  	}
   106  
   107  	if refreshScheduleStr == "managed" {
   108  		st := tr.State()
   109  		st.Lock()
   110  		defer st.Unlock()
   111  
   112  		if !devicestate.CanManageRefreshes(st) {
   113  			return fmt.Errorf("cannot set schedule to managed")
   114  		}
   115  		return nil
   116  	}
   117  
   118  	_, err = timeutil.ParseLegacySchedule(refreshScheduleStr)
   119  	return err
   120  }
   121  
   122  func validateRefreshRateLimit(tr config.Conf) error {
   123  	refreshRateLimit, err := coreCfg(tr, "refresh.rate-limit")
   124  	if err != nil {
   125  		return err
   126  	}
   127  	// reset is fine
   128  	if len(refreshRateLimit) == 0 {
   129  		return nil
   130  	}
   131  	if _, err := strutil.ParseByteSize(refreshRateLimit); err != nil {
   132  		return err
   133  	}
   134  	return nil
   135  }