Skip to content

Commit 1deb1c7

Browse files
committed
Fix validation and apply mounts
1 parent cc07222 commit 1deb1c7

File tree

1 file changed

+43
-33
lines changed

1 file changed

+43
-33
lines changed

atomic-update.py

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
Usage: atomic-update [options] command
3939
4040
atomic-update provides safer transactional operations
41-
for systems with read-write root filesystem.
41+
for openSUSE systems with read-write root filesystems.
4242
4343
Commands:
4444
dup - Perform distribution upgrade
@@ -146,12 +146,22 @@ def sigint_handler(signum, frame):
146146
for index, item in enumerate(sys.argv):
147147
if index == 0:
148148
continue
149-
if item in VALID_OPT:
150-
OPT.append(item)
151-
if item in VALID_CMD:
152-
COMMAND = item
153-
ARG = sys.argv[index+1:]
154-
break
149+
if item.startswith("--"):
150+
if item in VALID_OPT:
151+
OPT.append(item)
152+
else:
153+
print(f"Invalid option {item!r}. See usage below.\n")
154+
print(help_text.strip())
155+
sys.exit(1)
156+
else:
157+
if item in VALID_CMD:
158+
COMMAND = item
159+
ARG = sys.argv[index+1:]
160+
break
161+
else:
162+
print(f"Invalid command {item!r}. See usage below.\n")
163+
print(help_text.strip())
164+
sys.exit(1)
155165

156166
# Print help
157167
if "--help" in OPT:
@@ -163,23 +173,12 @@ def sigint_handler(signum, frame):
163173
print(f"atomic-update v{VERSION}")
164174
sys.exit()
165175

166-
# Validate command
167-
if not COMMAND:
168-
print("No valid command provided. See usage below.\n")
169-
print(help_text.strip())
170-
sys.exit(1)
176+
# Validate command args
171177
if COMMAND == "run" and not ARG:
172178
print(f"No argument provided for command {COMMAND!r}. See usage below.\n")
173179
print(help_text.strip())
174180
sys.exit(1)
175181

176-
# Validate options
177-
for opt in OPT:
178-
if opt not in VALID_OPT:
179-
print(f"Invalid option {opt!r}. See usage below.\n")
180-
print(help_text.strip())
181-
sys.exit(1)
182-
183182
DEBUG = True if "--debug" in OPT else False
184183
CONFIRM = True if "--interactive" in OPT else False
185184
REBOOT = True if "--reboot" in OPT else False
@@ -287,21 +286,22 @@ def sigint_handler(signum, frame):
287286
# get active and default snapshot number
288287
active_snap, default_snap = get_snaps(snapper_root_config)
289288
logging.debug(f"Active snapshot number: {active_snap}, Default snapshot number: {default_snap}")
289+
base_snap = active_snap
290290
if CONTINUE:
291-
active_snap = default_snap
291+
base_snap = default_snap
292292
if continue_num:
293-
active_snap = continue_num
293+
base_snap = continue_num
294294
# create new read-write snapshot to perform atomic update in
295295
out, ret = shell_exec(f"snapper -c {snapper_root_config} create -c number " \
296-
f"-d 'Atomic update of #{active_snap}' " \
297-
f"-u 'atomic=yes' --from {active_snap} --read-write")
296+
f"-d 'Atomic update of #{base_snap}' " \
297+
f"-u 'atomic=yes' --from {base_snap} --read-write")
298298
if ret != 0:
299299
logging.error(f"Could not create read-write snapshot to perform atomic update in")
300300
sys.exit(6)
301301
# get latest atomic snapshot number we just created
302302
atomic_snap = get_atomic_snap(snapper_root_config)
303303
logging.debug(f"Latest atomic snapshot number: {atomic_snap}")
304-
logging.info(f"Using snapshot {active_snap} as base for new snapshot {atomic_snap}")
304+
logging.info(f"Using snapshot {base_snap} as base for new snapshot {atomic_snap}")
305305
snap_subvol = f"@/.snapshots/{atomic_snap}/snapshot"
306306
snap_dir = snap_subvol.lstrip("@")
307307
# check the latest atomic snapshot exists as btrfs subvolume
@@ -352,10 +352,10 @@ def sigint_handler(signum, frame):
352352
logging.error(f"Command returned exit code {ret}. Discarding snapshot {atomic_snap}")
353353
shell_exec(f"snapper -c {snapper_root_config} delete {atomic_snap}")
354354
cleanup()
355-
sys.exit()
355+
sys.exit(9)
356356
logging.info("Command run successfully")
357357
if SHELL:
358-
logging.info(f"Opening chroot in snapshot {atomic_snap}")
358+
logging.info(f"Opening bash shell within snapshot {atomic_snap} chroot")
359359
logging.info("Continue with 'exit' or discard with 'exit 1'")
360360
ret = os.system(f"chroot {snap_dir} env PS1='atomic-update:${{PWD}} # ' bash --noprofile --norc")
361361
if ret != 0:
@@ -374,21 +374,31 @@ def sigint_handler(signum, frame):
374374
if APPLY:
375375
logging.info(f"Using default snapshot {atomic_snap} to replace running system...")
376376
logging.info("Applying /usr...")
377-
os.system(f"mount -o bind {snap_dir}/usr /usr")
377+
command = f"mount --bind --make-rslave {snap_dir}/usr /usr"
378+
logging.debug(command)
379+
os.system(command)
378380
# find subvols under /usr and mount them
379381
out, ret = shell_exec("LC_ALL=C btrfs subvolume list / | grep -v snapshots | grep '@/usr' | awk '{print $9}'")
380382
for subvol in out.split("\n"):
381-
subvol = subvol.lstrip("@")
382-
os.system(f"mount -o bind {snap_dir}{subvol} {subvol}")
383+
subdir = subvol.lstrip("@")
384+
command = f"mount -o subvol={subvol} {rootfs_device} {subdir}"
385+
logging.debug(command)
386+
os.system(command)
383387
logging.info("Applying /etc...")
384-
os.system(f"mount -o bind {snap_dir}/etc /etc")
388+
command = f"mount --bind --make-rslave {snap_dir}/etc /etc"
389+
logging.debug(command)
390+
os.system(command)
385391
logging.info("Applying /boot...")
386-
os.system(f"mount -o bind {snap_dir}/boot /boot")
392+
command = f"mount --bind --make-rslave {snap_dir}/boot /boot"
393+
logging.debug(command)
394+
os.system(command)
387395
# find subvols under /boot and mount them
388396
out, ret = shell_exec("LC_ALL=C btrfs subvolume list / | grep -v snapshots | grep '@/boot' | awk '{print $9}'")
389397
for subvol in out.split("\n"):
390-
subvol = subvol.lstrip("@")
391-
os.system(f"mount -o bind {snap_dir}{subvol} {subvol}")
398+
subdir = subvol.lstrip("@")
399+
command = f"mount -o subvol={subvol} {rootfs_device} {subdir}"
400+
logging.debug(command)
401+
os.system(command)
392402
logging.info("Executing systemctl daemon-reexec...")
393403
os.system("systemctl daemon-reexec")
394404
logging.info("Executing systemd-tmpfiles --create...")

0 commit comments

Comments
 (0)