github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/configstate/configcore/swap_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2021 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 configcore_test
    21  
    22  import (
    23  	"fmt"
    24  	"io/ioutil"
    25  	"os"
    26  	"path/filepath"
    27  
    28  	. "gopkg.in/check.v1"
    29  
    30  	"github.com/snapcore/snapd/dirs"
    31  	"github.com/snapcore/snapd/overlord/configstate/configcore"
    32  	"github.com/snapcore/snapd/release"
    33  	"github.com/snapcore/snapd/testutil"
    34  )
    35  
    36  type swapCfgSuite struct {
    37  	configcoreSuite
    38  
    39  	configSwapFile string
    40  }
    41  
    42  var _ = Suite(&swapCfgSuite{})
    43  
    44  func (s *swapCfgSuite) SetUpTest(c *C) {
    45  	s.configcoreSuite.SetUpTest(c)
    46  
    47  	s.systemctlArgs = nil
    48  	s.configSwapFile = filepath.Join(dirs.GlobalRootDir, "/etc/default/swapfile")
    49  
    50  	err := os.MkdirAll(filepath.Join(dirs.GlobalRootDir, "/etc/"), 0755)
    51  	c.Assert(err, IsNil)
    52  
    53  	err = ioutil.WriteFile(filepath.Join(dirs.GlobalRootDir, "/etc/environment"), nil, 0644)
    54  	c.Assert(err, IsNil)
    55  }
    56  
    57  func (s *swapCfgSuite) TestConfigureSwapSizeOnlyWhenChanged(c *C) {
    58  	restore := release.MockOnClassic(false)
    59  	defer restore()
    60  
    61  	// set it to 1M initially
    62  	err := configcore.Run(&mockConf{
    63  		state: s.state,
    64  		changes: map[string]interface{}{
    65  			"swap.size": "1048576",
    66  		},
    67  	})
    68  	c.Assert(err, IsNil)
    69  
    70  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/swapfile.swp
    71  SIZE=1
    72  `)
    73  
    74  	c.Check(s.systemctlArgs, DeepEquals, [][]string{
    75  		{"stop", "swapfile.service"},
    76  		{"show", "--property=ActiveState", "swapfile.service"},
    77  		{"start", "swapfile.service"},
    78  	})
    79  
    80  	s.systemctlArgs = nil
    81  
    82  	// running it with the same changes as conf results in no calls to systemd
    83  	err = configcore.Run(&mockConf{
    84  		state: s.state,
    85  		conf: map[string]interface{}{
    86  			"swap.size": "1048576",
    87  		},
    88  		changes: map[string]interface{}{
    89  			"swap.size": "1048576",
    90  		},
    91  	})
    92  	c.Assert(err, IsNil)
    93  
    94  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/swapfile.swp
    95  SIZE=1
    96  `)
    97  
    98  	c.Check(s.systemctlArgs, HasLen, 0)
    99  }
   100  
   101  func (s *swapCfgSuite) TestConfigureSwapSize(c *C) {
   102  	restore := release.MockOnClassic(false)
   103  	defer restore()
   104  
   105  	// set it to 1M initially
   106  	err := configcore.Run(&mockConf{
   107  		state: s.state,
   108  		changes: map[string]interface{}{
   109  			"swap.size": "1048576",
   110  		},
   111  	})
   112  	c.Assert(err, IsNil)
   113  
   114  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/swapfile.swp
   115  SIZE=1
   116  `)
   117  
   118  	c.Check(s.systemctlArgs, DeepEquals, [][]string{
   119  		{"stop", "swapfile.service"},
   120  		{"show", "--property=ActiveState", "swapfile.service"},
   121  		{"start", "swapfile.service"},
   122  	})
   123  
   124  	s.systemctlArgs = nil
   125  
   126  	// now change it to empty
   127  	err = configcore.Run(&mockConf{
   128  		state: s.state,
   129  		conf: map[string]interface{}{
   130  			"swap.size": "1048576",
   131  		},
   132  		changes: map[string]interface{}{
   133  			"swap.size": "",
   134  		},
   135  	})
   136  	c.Assert(err, IsNil)
   137  
   138  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/swapfile.swp
   139  SIZE=0
   140  `)
   141  
   142  	c.Check(s.systemctlArgs, DeepEquals, [][]string{
   143  		{"stop", "swapfile.service"},
   144  		{"show", "--property=ActiveState", "swapfile.service"},
   145  		{"start", "swapfile.service"},
   146  	})
   147  }
   148  
   149  func (s *swapCfgSuite) TestSwapSizeNumberFormats(c *C) {
   150  	tt := []struct {
   151  		sizeStr     string
   152  		sizeFileStr string
   153  		err         string
   154  	}{
   155  		{
   156  			sizeStr:     "1073741824",
   157  			sizeFileStr: "1024",
   158  		},
   159  		{
   160  			sizeStr:     "1024M",
   161  			sizeFileStr: "1024",
   162  		},
   163  		{
   164  			sizeStr:     "1G",
   165  			sizeFileStr: "1024",
   166  		},
   167  		{
   168  			sizeStr: "1048576K",
   169  			err:     "invalid suffix \"K\"",
   170  		},
   171  		{
   172  			sizeStr: "1073741824.4",
   173  			err:     "invalid suffix \".4\"",
   174  		},
   175  		{
   176  			sizeStr: "1",
   177  			err:     "swap size setting must be at least one megabyte",
   178  		},
   179  		{
   180  			sizeStr: "1073741825",
   181  			err:     "swap size setting must be an integer number of megabytes",
   182  		},
   183  	}
   184  
   185  	err := os.MkdirAll(filepath.Dir(s.configSwapFile), 0755)
   186  	c.Assert(err, IsNil)
   187  
   188  	for _, t := range tt {
   189  		conf := configcore.PlainCoreConfig(map[string]interface{}{
   190  			"swap.size": t.sizeStr,
   191  		})
   192  
   193  		err := configcore.FilesystemOnlyApply(dirs.GlobalRootDir, conf, nil)
   194  		if t.err != "" {
   195  			c.Assert(err, ErrorMatches, t.err)
   196  		} else {
   197  			c.Assert(err, IsNil)
   198  			c.Check(s.configSwapFile, testutil.FileEquals, fmt.Sprintf(`FILE=/var/tmp/swapfile.swp
   199  SIZE=%s
   200  `, t.sizeFileStr))
   201  		}
   202  	}
   203  }
   204  
   205  func (s *swapCfgSuite) TestSwapSizeFilesystemOnlyApply(c *C) {
   206  	conf := configcore.PlainCoreConfig(map[string]interface{}{
   207  		"swap.size": "1024M",
   208  	})
   209  
   210  	// with no swapfile config in place we use sensible defaults
   211  	err := os.MkdirAll(filepath.Dir(s.configSwapFile), 0755)
   212  	c.Assert(err, IsNil)
   213  
   214  	c.Assert(configcore.FilesystemOnlyApply(dirs.GlobalRootDir, conf, nil), IsNil)
   215  
   216  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/swapfile.swp
   217  SIZE=1024
   218  `)
   219  }
   220  
   221  func (s *swapCfgSuite) TestSwapSizeFilesystemOnlyApplyExistingConfig(c *C) {
   222  	conf := configcore.PlainCoreConfig(map[string]interface{}{
   223  		"swap.size": "1024M",
   224  	})
   225  
   226  	// we use the value from the config file if FILE is specified in the
   227  	// existing config file
   228  	err := os.MkdirAll(filepath.Dir(s.configSwapFile), 0755)
   229  	c.Assert(err, IsNil)
   230  
   231  	err = ioutil.WriteFile(s.configSwapFile, []byte(`FILE=/var/tmp/other-swapfile.swp
   232  SIZE=0`), 0644)
   233  	c.Assert(err, IsNil)
   234  
   235  	err = configcore.FilesystemOnlyApply(dirs.GlobalRootDir, conf, nil)
   236  	c.Assert(err, IsNil)
   237  
   238  	c.Check(s.configSwapFile, testutil.FileEquals, `FILE=/var/tmp/other-swapfile.swp
   239  SIZE=1024
   240  `)
   241  }