move refresh controller to new world
This commit is contained in:
parent
7faa1634ff
commit
aac00dad6c
|
@ -3,6 +3,7 @@ subiquity/client/client.py
|
|||
subiquity/client/controller.py
|
||||
subiquity/client/controllers/__init__.py
|
||||
subiquity/client/controllers/progress.py
|
||||
subiquity/client/controllers/refresh.py
|
||||
subiquity/client/controllers/welcome.py
|
||||
subiquity/client/__init__.py
|
||||
subiquity/client/keycodes.py
|
||||
|
@ -35,7 +36,6 @@ subiquity/controllers/mirror.py
|
|||
subiquity/controllers/network.py
|
||||
subiquity/controllers/proxy.py
|
||||
subiquity/controllers/reboot.py
|
||||
subiquity/controllers/refresh.py
|
||||
subiquity/controllers/snaplist.py
|
||||
subiquity/controllers/ssh.py
|
||||
subiquity/controllers/tests/__init__.py
|
||||
|
@ -122,6 +122,7 @@ subiquity/server/controllers/__init__.py
|
|||
subiquity/server/controllers/install.py
|
||||
subiquity/server/controllers/locale.py
|
||||
subiquity/server/controllers/package.py
|
||||
subiquity/server/controllers/refresh.py
|
||||
subiquity/server/controllers/reporting.py
|
||||
subiquity/server/controllers/userdata.py
|
||||
subiquity/server/dryrun.py
|
||||
|
|
|
@ -91,6 +91,7 @@ class SubiquityClient(TuiApplication):
|
|||
|
||||
controllers = [
|
||||
"Welcome",
|
||||
"Refresh",
|
||||
"Progress",
|
||||
]
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .progress import ProgressController
|
||||
from .refresh import RefreshController
|
||||
from .welcome import WelcomeController
|
||||
|
||||
__all__ = [
|
||||
'ProgressController',
|
||||
'RefreshController',
|
||||
'WelcomeController',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright 2019 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
|
||||
from subiquitycore.tuicontroller import (
|
||||
Skip,
|
||||
)
|
||||
|
||||
from subiquity.common.types import (
|
||||
RefreshCheckState,
|
||||
)
|
||||
from subiquity.client.controller import (
|
||||
SubiquityTuiController,
|
||||
)
|
||||
from subiquity.ui.views.refresh import RefreshView
|
||||
|
||||
|
||||
log = logging.getLogger('subiquity.client.controllers.refresh')
|
||||
|
||||
|
||||
class RefreshController(SubiquityTuiController):
|
||||
|
||||
endpoint_name = 'refresh'
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self.offered_first_time = False
|
||||
|
||||
async def get_progress(self, change):
|
||||
while True:
|
||||
try:
|
||||
return await self.endpoint.progress.GET(change_id=change)
|
||||
except aiohttp.ClientError:
|
||||
# Probably the server is restarting.
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def make_ui(self, index=1):
|
||||
if self.app.updated:
|
||||
raise Skip()
|
||||
show = False
|
||||
self.status = await self.endpoint.GET()
|
||||
if index == 1:
|
||||
if self.status.availability == RefreshCheckState.AVAILABLE:
|
||||
show = True
|
||||
self.offered_first_time = True
|
||||
elif index == 2:
|
||||
if not self.offered_first_time:
|
||||
if self.status.availability in [RefreshCheckState.UNKNOWN,
|
||||
RefreshCheckState.AVAILABLE]:
|
||||
show = True
|
||||
else:
|
||||
raise AssertionError("unexpected index {}".format(index))
|
||||
if show:
|
||||
return RefreshView(self)
|
||||
else:
|
||||
raise Skip()
|
||||
|
||||
async def wait_for_check(self):
|
||||
self.status = await self.endpoint.GET(wait=True)
|
||||
return self.status
|
||||
|
||||
async def start_update(self):
|
||||
return await self.endpoint.POST()
|
||||
|
||||
def run_answers(self):
|
||||
# Handled in the view
|
||||
pass
|
||||
|
||||
def done(self, sender=None):
|
||||
log.debug("RefreshController.done next_screen")
|
||||
self.app.next_screen()
|
||||
|
||||
def cancel(self, sender=None):
|
||||
self.app.prev_screen()
|
|
@ -22,6 +22,7 @@ from subiquity.common.types import (
|
|||
ErrorReportRef,
|
||||
InstallState,
|
||||
InstallStatus,
|
||||
RefreshStatus,
|
||||
)
|
||||
|
||||
|
||||
|
@ -59,6 +60,18 @@ class API:
|
|||
def GET() -> None:
|
||||
"""Requests to this method will fail with a HTTP 500."""
|
||||
|
||||
class refresh:
|
||||
def GET(wait: bool = False) -> RefreshStatus:
|
||||
"""Get information about the snap refresh status.
|
||||
|
||||
If wait is true, block until the status is known."""
|
||||
|
||||
def POST() -> int:
|
||||
"""Start the update and return the change id."""
|
||||
|
||||
class progress:
|
||||
def GET(change_id: int) -> dict: ...
|
||||
|
||||
class install:
|
||||
class status:
|
||||
def GET(cur: Optional[InstallState] = None) -> InstallStatus: ...
|
||||
|
|
|
@ -21,7 +21,6 @@ from .mirror import MirrorController
|
|||
from .network import NetworkController
|
||||
from .proxy import ProxyController
|
||||
from .reboot import RebootController
|
||||
from .refresh import RefreshController
|
||||
from .snaplist import SnapListController
|
||||
from .ssh import SSHController
|
||||
from .zdev import ZdevController
|
||||
|
@ -34,7 +33,6 @@ __all__ = [
|
|||
'NetworkController',
|
||||
'ProxyController',
|
||||
'RebootController',
|
||||
'RefreshController',
|
||||
'RepeatedController',
|
||||
'SnapListController',
|
||||
'SSHController',
|
||||
|
|
|
@ -18,6 +18,7 @@ from .debconf import DebconfController
|
|||
from .install import InstallController
|
||||
from .locale import LocaleController
|
||||
from .package import PackageController
|
||||
from .refresh import RefreshController
|
||||
from .reporting import ReportingController
|
||||
from .userdata import UserdataController
|
||||
|
||||
|
@ -29,6 +30,7 @@ __all__ = [
|
|||
'LateController',
|
||||
'LocaleController',
|
||||
'PackageController',
|
||||
'RefreshController',
|
||||
'ReportingController',
|
||||
'UserdataController',
|
||||
]
|
||||
|
|
|
@ -24,24 +24,23 @@ from subiquitycore.async_helpers import (
|
|||
SingleInstanceTask,
|
||||
)
|
||||
from subiquitycore.context import with_context
|
||||
from subiquitycore.tuicontroller import (
|
||||
Skip,
|
||||
)
|
||||
|
||||
from subiquity.common.apidef import API
|
||||
from subiquity.common.types import (
|
||||
RefreshCheckState,
|
||||
RefreshStatus,
|
||||
)
|
||||
from subiquity.controller import (
|
||||
SubiquityTuiController,
|
||||
from subiquity.server.controller import (
|
||||
SubiquityController,
|
||||
)
|
||||
from subiquity.ui.views.refresh import RefreshView
|
||||
|
||||
|
||||
log = logging.getLogger('subiquity.controllers.refresh')
|
||||
log = logging.getLogger('subiquity.server.controllers.refresh')
|
||||
|
||||
|
||||
class RefreshController(SubiquityTuiController):
|
||||
class RefreshController(SubiquityController):
|
||||
|
||||
endpoint = API.refresh
|
||||
|
||||
autoinstall_key = "refresh-installer"
|
||||
autoinstall_schema = {
|
||||
|
@ -58,23 +57,24 @@ class RefreshController(SubiquityTuiController):
|
|||
]
|
||||
|
||||
def __init__(self, app):
|
||||
self.ai_data = {}
|
||||
super().__init__(app)
|
||||
self.ai_data = {}
|
||||
self.snap_name = os.environ.get("SNAP_NAME", "subiquity")
|
||||
self.configure_task = None
|
||||
self.check_task = None
|
||||
self.status = RefreshStatus(availability=RefreshCheckState.UNKNOWN)
|
||||
|
||||
self.offered_first_time = False
|
||||
if 'update' in self.ai_data:
|
||||
self.active = self.ai_data['update']
|
||||
else:
|
||||
self.active = self.interactive()
|
||||
|
||||
def load_autoinstall_data(self, data):
|
||||
if data is not None:
|
||||
self.ai_data = data
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
if 'update' in self.ai_data:
|
||||
return True
|
||||
else:
|
||||
return self.interactive()
|
||||
|
||||
def start(self):
|
||||
if not self.active:
|
||||
return
|
||||
|
@ -95,16 +95,9 @@ class RefreshController(SubiquityTuiController):
|
|||
return
|
||||
change_id = await self.start_update(context=context)
|
||||
while True:
|
||||
try:
|
||||
change = await self.get_progress(change_id)
|
||||
except requests.exceptions.RequestException as e:
|
||||
raise e
|
||||
if change['status'] == 'Done':
|
||||
# Clearly if we got here we didn't get restarted by
|
||||
# snapd/systemctl (dry-run mode or logged in via SSH)
|
||||
self.app.restart(remove_last_screen=False)
|
||||
if change['status'] not in ['Do', 'Doing']:
|
||||
raise Exception("update failed")
|
||||
change = await self.get_progress(change_id)
|
||||
if change['status'] not in ['Do', 'Doing', 'Done']:
|
||||
raise Exception("update failed: %s", change['status'])
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
@with_context()
|
||||
|
@ -137,8 +130,6 @@ class RefreshController(SubiquityTuiController):
|
|||
|
||||
def get_refresh_channel(self):
|
||||
"""Return the channel we should refresh subiquity to."""
|
||||
if 'channel' in self.answers:
|
||||
return self.answers['channel']
|
||||
prefix = "subiquity-channel="
|
||||
for arg in self.app.kernel_cmdline:
|
||||
if arg.startswith(prefix):
|
||||
|
@ -209,39 +200,20 @@ class RefreshController(SubiquityTuiController):
|
|||
|
||||
async def get_progress(self, change):
|
||||
result = await self.app.snapd.get('v2/changes/{}'.format(change))
|
||||
return result['result']
|
||||
change = result['result']
|
||||
if change['status'] == 'Done':
|
||||
# Clearly if we got here we didn't get restarted by
|
||||
# snapd/systemctl (dry-run mode)
|
||||
self.app.restart()
|
||||
return change
|
||||
|
||||
def make_ui(self, index=1):
|
||||
if self.app.updated:
|
||||
raise Skip()
|
||||
show = False
|
||||
if index == 1:
|
||||
if self.status.availability == RefreshCheckState.AVAILABLE:
|
||||
show = True
|
||||
self.offered_first_time = True
|
||||
elif index == 2:
|
||||
if not self.offered_first_time:
|
||||
if self.status.availability in [RefreshCheckState.UNKNOWN,
|
||||
RefreshCheckState.AVAILABLE]:
|
||||
show = True
|
||||
else:
|
||||
raise AssertionError("unexpected index {}".format(index))
|
||||
if show:
|
||||
return RefreshView(self)
|
||||
else:
|
||||
raise Skip()
|
||||
|
||||
async def wait_for_check(self):
|
||||
await self.check_task.task
|
||||
async def GET(self, wait: bool = False) -> RefreshStatus:
|
||||
if wait:
|
||||
await self.check_task.wait()
|
||||
return self.status
|
||||
|
||||
def run_answers(self):
|
||||
# Handled in the view
|
||||
pass
|
||||
async def POST(self, context) -> int:
|
||||
return await self.start_update(context=context)
|
||||
|
||||
def done(self, sender=None):
|
||||
log.debug("RefreshController.done next_screen")
|
||||
self.app.next_screen()
|
||||
|
||||
def cancel(self, sender=None):
|
||||
self.app.prev_screen()
|
||||
async def progress_GET(self, change_id: int) -> dict:
|
||||
return await self.get_progress(change_id)
|
|
@ -119,6 +119,7 @@ class SubiquityServer(Application):
|
|||
"Package",
|
||||
"Debconf",
|
||||
"Locale",
|
||||
"Refresh",
|
||||
"Install",
|
||||
"Late",
|
||||
]
|
||||
|
|
|
@ -17,7 +17,7 @@ import asyncio
|
|||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
import aiohttp
|
||||
|
||||
from urwid import (
|
||||
ProgressBar,
|
||||
|
@ -246,15 +246,11 @@ class RefreshView(BaseView):
|
|||
async def _update(self):
|
||||
try:
|
||||
change_id = await self.controller.start_update()
|
||||
except requests.exceptions.RequestException as e:
|
||||
except aiohttp.ClientError as e:
|
||||
self.update_failed(exc_message(e))
|
||||
return
|
||||
while True:
|
||||
try:
|
||||
change = await self.controller.get_progress(change_id)
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.update_failed(exc_message(e))
|
||||
return
|
||||
change = await self.controller.get_progress(change_id)
|
||||
if change['status'] == 'Done':
|
||||
# Clearly if we got here we didn't get restarted by
|
||||
# snapd/systemctl (dry-run mode or logged in via SSH)
|
||||
|
|
Loading…
Reference in New Issue