parent
							
								
									64ec967711
								
							
						
					
					
						commit
						1e31ec7ab0
					
				
				 2 changed files with 135 additions and 101 deletions
			
			
		@ -0,0 +1,113 @@ | 
				
			|||||||
 | 
					error_handler() { | 
				
			||||||
 | 
					    echo failed at ${BASH_LINENO[0]} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					trap error_handler ERR | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create_rootfs_diff() { | 
				
			||||||
 | 
					    sudo rm -f "$CACHE_ROOTFS_TARBALL_PATH" # remove the old diff tarball from previous run, if exists | 
				
			||||||
 | 
					    cd /upper | 
				
			||||||
 | 
					    sudo tar -cf "$CACHE_ROOTFS_TARBALL_PATH" . | 
				
			||||||
 | 
					    cd | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					apply_rootfs_diff() { | 
				
			||||||
 | 
					    cd / | 
				
			||||||
 | 
					    sudo tar -xf "$CACHE_ROOTFS_TARBALL_PATH" 2>/dev/null || true | 
				
			||||||
 | 
					    cd | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					prepare_build() { | 
				
			||||||
 | 
					    # create and mount the required volumes where they're expected | 
				
			||||||
 | 
					    mkdir -p /tmp/openpilot /tmp/scons_cache /tmp/comma_download_cache /tmp/openpilot_cache | 
				
			||||||
 | 
					    sudo mount --bind "$REPO" /tmp/openpilot | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sudo mount --bind "$REPO/.ci_cache/scons_cache" /tmp/scons_cache || true | 
				
			||||||
 | 
					    sudo mount --bind "$REPO/.ci_cache/comma_download_cache" /tmp/comma_download_cache || true | 
				
			||||||
 | 
					    sudo mount --bind "$REPO/.ci_cache/openpilot_cache" /tmp/openpilot_cache || true | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # needed for the unit tests not to fail | 
				
			||||||
 | 
					    sudo chmod 755 /sys/fs/pstore | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					post_commit_root() { | 
				
			||||||
 | 
					    # we have the diff tarball, now let's remove the folder too | 
				
			||||||
 | 
					    sudo rm -rf /upper | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # now we apply it straight away | 
				
			||||||
 | 
					    apply_rootfs_diff | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # before the next tasks are run, finalize the environment for them | 
				
			||||||
 | 
					    prepare_build | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# warning: this function initiates a somewhat complicated program flow, follow carefully | 
				
			||||||
 | 
					# (even despite this part was made sure to not be too relevant for the rest of the job) | 
				
			||||||
 | 
					commit_root() { | 
				
			||||||
 | 
					    # if that's a first execution | 
				
			||||||
 | 
					    if ! [ -e /root_committed ] | 
				
			||||||
 | 
					    then | 
				
			||||||
 | 
					        # prepare directories | 
				
			||||||
 | 
					        sudo mkdir -p /base /newroot /upper /work | 
				
			||||||
 | 
					         | 
				
			||||||
 | 
					        # re-execute the main script (causing it to go straight to `build_inside_namespace`), but | 
				
			||||||
 | 
					        # inside the newly created namespace, in a way which would cause all mounts | 
				
			||||||
 | 
					        # created to automatically umount before it exits | 
				
			||||||
 | 
					        sudo unshare -f --kill-child -m "$SELF_PATH" build_inside_namespace | 
				
			||||||
 | 
					        ec=$? | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # after it exited, remove the created directories (except the one containing created diff) | 
				
			||||||
 | 
					        sudo rm -rf /base /newroot /work | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # finally, create the rootfs diff tarball (to be pushed into the CI native cache) | 
				
			||||||
 | 
					        create_rootfs_diff | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # after creating the rootfs diff, bring the system into a state as if it was restored from cache | 
				
			||||||
 | 
					        post_commit_root | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        exit $ec | 
				
			||||||
 | 
					    fi | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					reexecute() { | 
				
			||||||
 | 
					    touch /root_committed | 
				
			||||||
 | 
					    sudo -u runner "$SELF_PATH" | 
				
			||||||
 | 
					    ec=$? | 
				
			||||||
 | 
					    exit $ec | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# that's where the script goes after being re-executed for the first time | 
				
			||||||
 | 
					build_inside_namespace() { | 
				
			||||||
 | 
					    # initialize the mounts namespace on overlayfs to be able to prepare the rootfs diff | 
				
			||||||
 | 
					    mount --bind / /base | 
				
			||||||
 | 
					    mount -t overlay overlay -o lowerdir=/base,upperdir=/upper,workdir=/work /newroot | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # apply the current DNS config (beware: systemd often symlinks /etc/resolv.conf, that's why it's needed) | 
				
			||||||
 | 
					    rm -f /newroot/etc/resolv.conf | 
				
			||||||
 | 
					    touch /newroot/etc/resolv.conf | 
				
			||||||
 | 
					    cat /etc/resolv.conf > /newroot/etc/resolv.conf | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # switch the namespace's root mount to the newly created one | 
				
			||||||
 | 
					    mkdir -p /newroot/old | 
				
			||||||
 | 
					    cd /newroot | 
				
			||||||
 | 
					    pivot_root . old | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # initialize basic required POSIX-standard additional mounts | 
				
			||||||
 | 
					    mount -t proc proc /proc | 
				
			||||||
 | 
					    mount -t devtmpfs devtmpfs /dev | 
				
			||||||
 | 
					    mkdir -p /dev/pts | 
				
			||||||
 | 
					    mount -t devpts devpts /dev/pts | 
				
			||||||
 | 
					    mount -t proc proc /proc | 
				
			||||||
 | 
					    mount -t sysfs sysfs /sys | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # re-execute the main script for the 2nd time, causing it to go back to the main flow | 
				
			||||||
 | 
					    # (but this time already inside the newly created namespace) | 
				
			||||||
 | 
					    reexecute | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # after the main flow terminates and the namespace exist, post_commit_root is executed - be sure to look at it | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$1" = "build_inside_namespace" ] | 
				
			||||||
 | 
					then | 
				
			||||||
 | 
					    build_inside_namespace | 
				
			||||||
 | 
					    exit | 
				
			||||||
 | 
					fi | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue