snap switch subiquity to stable/ubuntu-XX.YY.Z
also support passing subquity-channel= on the kernel command line
This commit is contained in:
parent
4794a68306
commit
f1177788e1
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"type": "sync",
|
||||||
|
"status-code": 200,
|
||||||
|
"status": "OK",
|
||||||
|
"result": {
|
||||||
|
"id": "176",
|
||||||
|
"kind": "switch-snap",
|
||||||
|
"summary": "Switch \"subiquity\" snap to stable",
|
||||||
|
"status": "Done",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"id": "4715",
|
||||||
|
"kind": "switch-snap",
|
||||||
|
"summary": "Switch snap \"subiquity\" to stable",
|
||||||
|
"status": "Done",
|
||||||
|
"progress": {
|
||||||
|
"label": "",
|
||||||
|
"done": 1,
|
||||||
|
"total": 1
|
||||||
|
},
|
||||||
|
"spawn-time": "2019-03-29T14:13:32.922119778+13:00",
|
||||||
|
"ready-time": "2019-03-29T14:13:32.941910157+13:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ready": true,
|
||||||
|
"spawn-time": "2019-03-29T14:13:32.922139818+13:00",
|
||||||
|
"ready-time": "2019-03-29T14:13:32.941911437+13:00"
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
import enum
|
import enum
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
import requests.exceptions
|
import requests.exceptions
|
||||||
|
|
||||||
|
@ -36,6 +37,11 @@ class CheckState(enum.IntEnum):
|
||||||
def is_definite(self):
|
def is_definite(self):
|
||||||
return self in [self.AVAILABLE, self.UNAVAILABLE]
|
return self in [self.AVAILABLE, self.UNAVAILABLE]
|
||||||
|
|
||||||
|
class SwitchState(enum.IntEnum):
|
||||||
|
NOT_STARTED = enum.auto()
|
||||||
|
SWITCHING = enum.auto()
|
||||||
|
SWITCHED = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
class RefreshController(BaseController):
|
class RefreshController(BaseController):
|
||||||
|
|
||||||
|
@ -47,11 +53,90 @@ class RefreshController(BaseController):
|
||||||
super().__init__(common)
|
super().__init__(common)
|
||||||
self.snap_name = os.environ.get("SNAP_NAME", "subiquity")
|
self.snap_name = os.environ.get("SNAP_NAME", "subiquity")
|
||||||
self.check_state = CheckState.NOT_STARTED
|
self.check_state = CheckState.NOT_STARTED
|
||||||
|
self.switch_state = SwitchState.NOT_STARTED
|
||||||
|
self.network_state = "down"
|
||||||
self.view = None
|
self.view = None
|
||||||
self.offered_first_time = False
|
self.offered_first_time = False
|
||||||
self.answers = self.all_answers.get("Refresh", {})
|
self.answers = self.all_answers.get("Refresh", {})
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.switch_state = SwitchState.SWITCHING
|
||||||
|
channel = self.get_refresh_channel()
|
||||||
|
self.run_in_bg(
|
||||||
|
lambda: self._bg_switch_snap(channel),
|
||||||
|
self._snap_switched)
|
||||||
|
|
||||||
|
def get_refresh_channel(self):
|
||||||
|
"""Return the channel we should refresh subiquity to."""
|
||||||
|
|
||||||
|
with open('/proc/cmdline') as fp:
|
||||||
|
cmdline = fp.read()
|
||||||
|
prefix="subquity-channel="
|
||||||
|
for arg in cmdline.split():
|
||||||
|
if arg.startswith(prefix):
|
||||||
|
log.debug("found cmdline arg %s", arg)
|
||||||
|
return arg[len(prefix):]
|
||||||
|
|
||||||
|
info_file = '/cdrom/.disk/info'
|
||||||
|
try:
|
||||||
|
fp = open(info_file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
if self.opts.dry_run:
|
||||||
|
info = (
|
||||||
|
'Ubuntu-Server 18.04.2 LTS "Bionic Beaver" - '
|
||||||
|
'Release amd64 (20190214.3)')
|
||||||
|
else:
|
||||||
|
log.debug("failed to find .disk/info file")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
with fp:
|
||||||
|
info = fp.read()
|
||||||
|
release = info.split()[1]
|
||||||
|
return 'stable/ubuntu-' + release
|
||||||
|
|
||||||
|
def _bg_switch_snap(self, channel):
|
||||||
|
log.debug("switching %s to %s", self.snap_name, channel)
|
||||||
|
try:
|
||||||
|
response = self.snapd_connection.post(
|
||||||
|
'v2/snaps/{}'.format(self.snap_name),
|
||||||
|
{'action': 'switch', 'channel': channel})
|
||||||
|
response.raise_for_status()
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
log.exception("switching")
|
||||||
|
return
|
||||||
|
change = response.json()["change"]
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = self.snapd_connection.get(
|
||||||
|
'v2/changes/{}'.format(change))
|
||||||
|
response.raise_for_status()
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
log.exception("checking switch")
|
||||||
|
return
|
||||||
|
if response.json()["result"]["status"] == "Done":
|
||||||
|
return
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def _snap_switched(self, fut):
|
||||||
|
log.debug("snap switching completed")
|
||||||
|
try:
|
||||||
|
fut.result()
|
||||||
|
except:
|
||||||
|
log.exception("_snap_switched")
|
||||||
|
self.switch_state = SwitchState.SWITCHED
|
||||||
|
self._maybe_check_for_update()
|
||||||
|
|
||||||
def snapd_network_changed(self):
|
def snapd_network_changed(self):
|
||||||
|
self.network_state = "up"
|
||||||
|
self._maybe_check_for_update()
|
||||||
|
|
||||||
|
def _maybe_check_for_update(self):
|
||||||
|
# If we have not yet switched to the right channel, wait.
|
||||||
|
if self.switch_state != SwitchState.SWITCHED:
|
||||||
|
return
|
||||||
|
# If the network is not yet up, wait.
|
||||||
|
if self.network_state == "down":
|
||||||
|
return
|
||||||
# If we restarted into this version, don't check for a new version.
|
# If we restarted into this version, don't check for a new version.
|
||||||
if self.updated:
|
if self.updated:
|
||||||
return
|
return
|
||||||
|
@ -98,7 +183,7 @@ class RefreshController(BaseController):
|
||||||
|
|
||||||
def _bg_start_update(self):
|
def _bg_start_update(self):
|
||||||
return self.snapd_connection.post(
|
return self.snapd_connection.post(
|
||||||
'v2/snaps/subiquity', {'action': 'refresh'})
|
'v2/snaps/{}'.format(self.snap_name), {'action': 'refresh'})
|
||||||
|
|
||||||
def update_started(self, fut, callback):
|
def update_started(self, fut, callback):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -132,6 +132,13 @@ class FakeSnapdConnection:
|
||||||
"status-code": 200,
|
"status-code": 200,
|
||||||
"status": "OK",
|
"status": "OK",
|
||||||
})
|
})
|
||||||
|
if path == "v2/snaps/subiquity" and body['action'] == 'switch':
|
||||||
|
return _FakeMemoryResponse({
|
||||||
|
"type": "async",
|
||||||
|
"change": 8,
|
||||||
|
"status-code": 200,
|
||||||
|
"status": "Accepted",
|
||||||
|
})
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Don't know how to fake POST response to {}".format((path, args)))
|
"Don't know how to fake POST response to {}".format((path, args)))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue