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