diff --git a/config/types.go b/config/types.go index 0d878803..287cc50e 100644 --- a/config/types.go +++ b/config/types.go @@ -21,7 +21,8 @@ const ( SystemDockerHost = "unix:///var/run/system-docker.sock" DockerHost = "unix:///var/run/docker.sock" ImagesPath = "/usr/share/ros" - ImagesPattern = "images*.tar" + InitImages = "images-init.tar" + SystemImages = "images-system.tar" ModulesArchive = "/modules.tar" Debug = false SystemDockerLog = "/var/log/system-docker.log" diff --git a/init/bootstrap.go b/init/bootstrap.go index f1c8788d..2dae2b5b 100644 --- a/init/bootstrap.go +++ b/init/bootstrap.go @@ -68,7 +68,7 @@ func bootstrap(cfg *config.CloudConfig) error { _, err = config.ChainCfgFuncs(cfg, []config.CfgFuncData{ - config.CfgFuncData{"bootstrap loadImages", loadImages}, + config.CfgFuncData{"bootstrap loadImages", loadBootstrapImages}, config.CfgFuncData{"bootstrap Services", bootstrapServices}, }) return err @@ -84,7 +84,7 @@ func runCloudInitServices(cfg *config.CloudConfig) error { _, err = config.ChainCfgFuncs(cfg, []config.CfgFuncData{ - config.CfgFuncData{"cloudinit loadImages", loadImages}, + config.CfgFuncData{"cloudinit loadImages", loadBootstrapImages}, config.CfgFuncData{"cloudinit Services", runCloudInitServiceSet}, }) return err diff --git a/init/recovery.go b/init/recovery.go index d0ed940c..f73cf96a 100644 --- a/init/recovery.go +++ b/init/recovery.go @@ -87,7 +87,7 @@ func recovery(initFailure error) { _, err = config.ChainCfgFuncs(&recoveryConfig, []config.CfgFuncData{ - config.CfgFuncData{"loadImages", loadImages}, + config.CfgFuncData{"loadSystemImages", loadSystemImages}, config.CfgFuncData{"recovery console", recoveryServices}, }) if err != nil { diff --git a/init/sysinit.go b/init/sysinit.go index c8446f77..a6a2a129 100644 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -4,6 +4,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "syscall" "golang.org/x/net/context" @@ -29,62 +30,47 @@ func hasImage(name string) bool { return true } -func findImages(cfg *config.CloudConfig) ([]string, error) { - log.Debugf("Looking for images at %s", config.ImagesPath) - - result := []string{} - - dir, err := os.Open(config.ImagesPath) - if os.IsNotExist(err) { - log.Debugf("Not loading images, %s does not exist", config.ImagesPath) - return result, nil - } - if err != nil { - return nil, err +func getImagesArchive(bootstrap bool) string { + var archive string + if bootstrap { + archive = path.Join(config.ImagesPath, config.InitImages) + } else { + archive = path.Join(config.ImagesPath, config.SystemImages) } - defer dir.Close() - - files, err := dir.Readdirnames(0) - if err != nil { - return nil, err - } - - for _, fileName := range files { - if ok, _ := path.Match(config.ImagesPattern, fileName); ok { - log.Debugf("Found %s", fileName) - result = append(result, fileName) - } - } - - return result, nil + return archive } -func loadImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { - images, err := findImages(cfg) - if err != nil || len(images) == 0 { - return cfg, err - } +func loadBootstrapImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { + return loadImages(cfg, true) +} + +func loadSystemImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { + return loadImages(cfg, false) +} + +func loadImages(cfg *config.CloudConfig, bootstrap bool) (*config.CloudConfig, error) { + archive := getImagesArchive(bootstrap) client, err := docker.NewSystemClient() if err != nil { return cfg, err } - for _, image := range images { - if hasImage(image) { - continue + if !hasImage(filepath.Base(archive)) { + if _, err := os.Stat(archive); os.IsNotExist(err) { + log.Fatalf("FATAL: Could not load images from %s (file not found)", archive) } // client.ImageLoad is an asynchronous operation // To ensure the order of execution, use cmd instead of it - inputFileName := path.Join(config.ImagesPath, image) - log.Infof("Loading images from %s", inputFileName) - if err = exec.Command("/usr/bin/system-docker", "load", "-q", "-i", inputFileName).Run(); err != nil { - log.Fatalf("FATAL: failed loading images from %s: %s", inputFileName, err) + log.Infof("Loading images from %s", archive) + cmd := exec.Command("/usr/bin/system-docker", "load", "-q", "-i", archive) + if out, err := cmd.CombinedOutput(); err != nil { + log.Fatalf("FATAL: Error loading images from %s (%v)\n%s ", archive, err, out) } - log.Infof("Done loading images from %s", inputFileName) + log.Infof("Done loading images from %s", archive) } dockerImages, _ := client.ImageList(context.Background(), types.ImageListOptions{}) @@ -104,7 +90,7 @@ func SysInit() error { _, err := config.ChainCfgFuncs(cfg, []config.CfgFuncData{ - config.CfgFuncData{"loadImages", loadImages}, + config.CfgFuncData{"loadSystemImages", loadSystemImages}, config.CfgFuncData{"start project", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { p, err := compose.GetProject(cfg, false, true) if err != nil { diff --git a/scripts/layout-initrd b/scripts/layout-initrd index c22dbb4b..b15aa69f 100755 --- a/scripts/layout-initrd +++ b/scripts/layout-initrd @@ -7,7 +7,7 @@ mkdir -p ${INITRD_DIR}/usr/{etc,lib,bin,share/ros} ./scripts/template cp -rf assets/selinux ${INITRD_DIR}/usr/etc -cp build/images.tar ${INITRD_DIR}/usr/share/ros/ +cp build/images*.tar ${INITRD_DIR}/usr/share/ros/ cp bin/ros ${INITRD_DIR}/usr/bin/ ln -s usr/bin/ros ${INITRD_DIR}/init ln -s bin ${INITRD_DIR}/usr/sbin diff --git a/scripts/package-rootfs b/scripts/package-rootfs index c5800bd2..a68d6e86 100755 --- a/scripts/package-rootfs +++ b/scripts/package-rootfs @@ -12,24 +12,28 @@ PREPOP_DIR=${IMAGE_CACHE}/var/lib/system-docker INITRD_DIR=${BUILD}/initrd ARTIFACTS=$(pwd)/dist/artifacts INITRD=${ARTIFACTS}/initrd +INIT_IMAGES="images-init.tar" +SYSTEM_IMAGES="images-system.tar" mkdir -p ${ARTIFACTS} ${PREPOP_DIR} if [ "$(docker info | grep 'Storage Driver: ' | sed 's/Storage Driver: //')" != "overlay" ]; then - echo Overlay storage driver is required to prepackage exploded images - echo packaging images.tar instead + echo Overlay storage driver is require to prepackage exploded images + echo packaging image tar archives instead tar czf ${ARTIFACTS}/rootfs${SUFFIX}.tar.gz --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} . exit 0 fi DFS=$(docker run -d --privileged -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) ${DFS_IMAGE}${SUFFIX} ${DFS_ARGS}) trap "docker rm -fv ${DFS_ARCH} ${DFS}" EXIT -docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/images.tar +docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/${INIT_IMAGES} +docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/${SYSTEM_IMAGES} docker stop ${DFS} docker run --rm --volumes-from=${DFS} --entrypoint /bin/bash rancher/os-base -c "tar -c -C /var/lib/docker ./image" | tar -x -C ${PREPOP_DIR} docker run --rm --volumes-from=${DFS} --entrypoint /bin/bash rancher/os-base -c "tar -c -C /var/lib/docker ./overlay" | tar -x -C ${PREPOP_DIR} -tar -cf ${ARTIFACTS}/rootfs${SUFFIX}.tar --exclude usr/share/ros/images.tar --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} . +tar -cf ${ARTIFACTS}/rootfs${SUFFIX}.tar --exclude usr/share/ros/${INIT_IMAGES} --exclude usr/share/ros/${SYSTEM_IMAGES} --exclude lib/modules --exclude +lib/firmware -C ${INITRD_DIR} . tar -rf ${ARTIFACTS}/rootfs${SUFFIX}.tar -C ${IMAGE_CACHE} . rm -f ${ARTIFACTS}/rootfs${SUFFIX}.tar.gz gzip ${ARTIFACTS}/rootfs${SUFFIX}.tar diff --git a/scripts/tar-images b/scripts/tar-images index 6882a171..de991432 100755 --- a/scripts/tar-images +++ b/scripts/tar-images @@ -1,29 +1,48 @@ #!/bin/bash set -ex +INIT_DEP="rancher/os-bootstrap" +SHARED_DEP="rancher/os-base" +INIT_IMAGES_DST="build/images-init.tar" +SYSTEM_IMAGES_DST="build/images-system.tar" + cd $(dirname $0)/.. IMAGES=$(bin/host_ros c images -i build/initrd/usr/share/ros/os-config.yml) -echo "tar-image: IMAGES=$IMAGES" -for i in $IMAGES; do +INIT_IMAGES="" +SYSTEM_IMAGES="" +for i in ${IMAGES}; do echo "tar-image: pull($i)" if [ "${FORCE_PULL}" = "1" ] || ! docker inspect $i >/dev/null 2>&1; then - docker pull $i + docker pull ${i} + fi + + if [ "${i%%:*}" != "$INIT_DEP" ] ; then + SYSTEM_IMAGES="$SYSTEM_IMAGES $i" + fi + + if [ "${i%%:*}" = "$INIT_DEP" ] || [ "${i%%:*}" = "$SHARED_DEP" ] ; then + INIT_IMAGES="$INIT_IMAGES $i" fi done if [ -e ".make-vmware" ]; then docker pull rancher/os-openvmtools:${OPEN_VMTOOLS_VERSION} - IMAGES="$IMAGES rancher/os-openvmtools:${OPEN_VMTOOLS_VERSION}" + SYSTEM_IMAGES="$SYSTEM_IMAGES rancher/os-openvmtools:${OPEN_VMTOOLS_VERSION}" fi -echo "tar-images: docker save ${IMAGES}" +echo "tar-image: SYSTEM_IMAGES=$SYSTEM_IMAGES" +echo "tar-image: INIT_IMAGES=$INIT_IMAGES" + if [ "$COMPRESS" == "" ]; then - docker save ${IMAGES} | gzip > build/images.tar + ARCHIVE_CMD="gzip" else # system-docker can not load images which compressed by xz with a compression level of 9 # decompression consumes more memory if using level 9 # the default compression level for xz is 6 - docker save ${IMAGES} | xz -6 -e > build/images.tar + ARCHIVE_CMD="xz -4 -e" fi + +docker save ${INIT_IMAGES} | ${ARCHIVE_CMD} > ${INIT_IMAGES_DST} +docker save ${SYSTEM_IMAGES} | ${ARCHIVE_CMD} > ${SYSTEM_IMAGES_DST} echo "tar-images: DONE"