From 1a9508052249d00491cce2bcdf8e1a62fd5515e1 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Sat, 19 Dec 2015 22:26:09 -0700 Subject: [PATCH] Support OEM partition and oem-config.yml --- config/config.go | 2 +- config/disk.go | 8 ++--- config/types.go | 6 +++- init/init.go | 20 +++++++++-- init/root.go | 4 +++ os-config.yml | 4 ++- tests/integration/rostest/test_07_oem.py | 44 ++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 tests/integration/rostest/test_07_oem.py diff --git a/config/config.go b/config/config.go index 99fbd49d..4415e5fb 100644 --- a/config/config.go +++ b/config/config.go @@ -152,7 +152,7 @@ func (c *CloudConfig) Set(key string, value interface{}) (*CloudConfig, error) { } func (c *CloudConfig) Save() error { - files := append([]string{OsConfigFile}, CloudConfigDirFiles()...) + files := append([]string{OsConfigFile, OemConfigFile}, CloudConfigDirFiles()...) files = util.FilterStrings(files, func(x string) bool { return x != CloudConfigPrivateFile }) exCfg, err := ChainCfgFuncs(nil, func(_ *CloudConfig) (*CloudConfig, error) { diff --git a/config/disk.go b/config/disk.go index 9697c4ee..e74e6af2 100644 --- a/config/disk.go +++ b/config/disk.go @@ -18,7 +18,7 @@ var osConfig *CloudConfig func NewConfig() *CloudConfig { if osConfig == nil { - osConfig, _ = ReadConfig(nil, true, OsConfigFile) + osConfig, _ = ReadConfig(nil, true, OsConfigFile, OemConfigFile) } newCfg := *osConfig return &newCfg @@ -200,7 +200,7 @@ func amendContainerNames(c *CloudConfig) (*CloudConfig, error) { return c, nil } -func writeToFile(data interface{}, filename string) error { +func WriteToFile(data interface{}, filename string) error { content, err := yaml.Marshal(data) if err != nil { return err @@ -218,12 +218,12 @@ func saveToDisk(data map[interface{}]interface{}) error { "rancher.docker.server_cert", }) - err := writeToFile(config, CloudConfigFile) + err := WriteToFile(config, CloudConfigFile) if err != nil { return err } - return writeToFile(private, CloudConfigPrivateFile) + return WriteToFile(private, CloudConfigPrivateFile) } func readConfig(bytes []byte, substituteMetadataVars bool, files ...string) (map[interface{}]interface{}, error) { diff --git a/config/types.go b/config/types.go index c572816c..e4468adf 100644 --- a/config/types.go +++ b/config/types.go @@ -7,6 +7,7 @@ import ( ) const ( + OEM = "/usr/share/ros/oem" DOCKER_BIN = "/usr/bin/docker" DOCKER_DIST_BIN = "/usr/bin/docker.dist" ROS_BIN = "/usr/bin/ros" @@ -40,7 +41,8 @@ const ( ) var ( - VERSION string + OemConfigFile = OEM + "/oem-config.yml" + VERSION string ) func init() { @@ -111,6 +113,8 @@ type StateConfig struct { Required bool `yaml:"required,omitempty"` Autoformat []string `yaml:"autoformat,omitempty"` FormatZero bool `yaml:"formatzero,omitempty"` + OemFsType string `yaml:"oem_fstype,omitempty"` + OemDev string `yaml:"oem_dev,omitempty"` } type CloudInit struct { diff --git a/init/init.go b/init/init.go index 89d6292a..a9ca9353 100644 --- a/init/init.go +++ b/init/init.go @@ -111,6 +111,19 @@ func mountState(cfg *config.CloudConfig) error { return mountConfigured("state", cfg.Rancher.State.Dev, cfg.Rancher.State.FsType, STATE) } +func mountOem(cfg *config.CloudConfig) (*config.CloudConfig, error) { + if cfg == nil { + var err error + if cfg, err = config.LoadConfig(); err != nil { + return cfg, err + } + } + if err := mountConfigured("oem", cfg.Rancher.State.OemDev, cfg.Rancher.State.OemFsType, config.OEM); err != nil { + log.Infof("Not mounting OEM: %v", err) + } + return cfg, nil +} + func tryMountState(cfg *config.CloudConfig) error { if mountState(cfg) == nil { return nil @@ -132,8 +145,10 @@ func tryMountAndBootstrap(cfg *config.CloudConfig) (*config.CloudConfig, error) } log.Debugf("Switching to new root at %s %s", STATE, cfg.Rancher.State.Directory) - err := switchRoot(STATE, cfg.Rancher.State.Directory, cfg.Rancher.RmUsr) - return cfg, err + if err := switchRoot(STATE, cfg.Rancher.State.Directory, cfg.Rancher.RmUsr); err != nil { + return cfg, err + } + return mountOem(cfg) } func getLaunchConfig(cfg *config.CloudConfig, dockerCfg *config.DockerConfig) (*dockerlaunch.Config, []string) { @@ -162,6 +177,7 @@ func RunInit() error { func(c *config.CloudConfig) (*config.CloudConfig, error) { return c, dockerlaunch.PrepareFs(&mountConfig) }, + mountOem, func(_ *config.CloudConfig) (*config.CloudConfig, error) { cfg, err := config.LoadConfig() if err != nil { diff --git a/init/root.go b/init/root.go index d116c015..03c0e397 100644 --- a/init/root.go +++ b/init/root.go @@ -100,6 +100,10 @@ func copyMoveRoot(rootfs string, rmUsr bool) error { } func switchRoot(rootfs, subdir string, rmUsr bool) error { + if err := syscall.Unmount(config.OEM, 0); err != nil { + log.Debugf("Not umounting OEM: %v", err) + } + if subdir != "" { fullRootfs := path.Join(rootfs, subdir) if _, err := os.Stat(fullRootfs); os.IsNotExist(err) { diff --git a/os-config.yml b/os-config.yml index ff5ad755..066ff7d8 100644 --- a/os-config.yml +++ b/os-config.yml @@ -58,6 +58,8 @@ rancher: state: fstype: auto dev: LABEL=RANCHER_STATE + oem_fstype: auto + oem_dev: LABEL=RANCHER_OEM services: acpid: image: rancher/os-acpid:v0.4.3-dev @@ -251,7 +253,7 @@ rancher: - /lib/firmware:/lib/firmware - /lib/modules:/lib/modules - /run:/run - - /usr/share/ros/os-config.yml:/usr/share/ros/os-config.yml + - /usr/share/ros:/usr/share/ros - /var/lib/rancher/conf:/var/lib/rancher/conf - /var/lib/rancher:/var/lib/rancher - /var/log:/var/log diff --git a/tests/integration/rostest/test_07_oem.py b/tests/integration/rostest/test_07_oem.py new file mode 100644 index 00000000..33723333 --- /dev/null +++ b/tests/integration/rostest/test_07_oem.py @@ -0,0 +1,44 @@ +import time +import pytest +import rostest.util as u +from rostest.util import SSH + + +@pytest.fixture(scope="module") +def qemu(request): + q = u.run_qemu(request, run_args=['--append', 'rancher.state.dev=x']) + u.flush_out(q.stdout) + return q + + +def test_oem(qemu): + SSH(qemu).check_call('sudo', 'bash', '-c', ''' +set -x +set -e +sudo mkfs.ext4 -L RANCHER_OEM /dev/vda +sudo mount /dev/vda /mnt +cat > /tmp/oem-config.yml << "EOF" +#cloud-config +rancher: + upgrade: + url: 'foo' +EOF +sudo cp /tmp/oem-config.yml /mnt +sudo umount /mnt +sudo reboot >/dev/null 2>&1 &'''.strip()) + + time.sleep(1) + + SSH(qemu).check_call('bash', '-c', ''' +set -x +if [ ! -e /usr/share/ros/oem/oem-config.yml ]; then + echo Failed to find /usr/share/ros/oem/oem-config.yml + exit 1 +fi + +FOO="$(sudo ros config get rancher.upgrade.url)" +if [ "$FOO" != "foo" ]; then + echo rancher.upgrade.url is not foo + exit 1 +fi + '''.strip())