move reboot controller (the last one!) to new world
This commit is contained in:
parent
4367f8f97c
commit
303c0d75d6
|
@ -40,9 +40,6 @@ subiquity/common/tests/__init__.py
|
|||
subiquity/common/tests/test_filesystem.py
|
||||
subiquity/common/tests/test_keyboard.py
|
||||
subiquity/common/types.py
|
||||
subiquity/controller.py
|
||||
subiquity/controllers/__init__.py
|
||||
subiquity/controllers/reboot.py
|
||||
subiquitycore/async_helpers.py
|
||||
subiquitycore/contextlib38.py
|
||||
subiquitycore/context.py
|
||||
|
@ -129,6 +126,7 @@ subiquity/server/controllers/mirror.py
|
|||
subiquity/server/controllers/network.py
|
||||
subiquity/server/controllers/package.py
|
||||
subiquity/server/controllers/proxy.py
|
||||
subiquity/server/controllers/reboot.py
|
||||
subiquity/server/controllers/refresh.py
|
||||
subiquity/server/controllers/reporting.py
|
||||
subiquity/server/controllers/snaplist.py
|
||||
|
|
|
@ -186,6 +186,9 @@ class API:
|
|||
class status:
|
||||
def GET(cur: Optional[InstallState] = None) -> InstallStatus: ...
|
||||
|
||||
class reboot:
|
||||
def POST(): ...
|
||||
|
||||
|
||||
class LinkAction(enum.Enum):
|
||||
NEW = enum.auto()
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
# 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 json
|
||||
import logging
|
||||
import os
|
||||
|
||||
import jsonschema
|
||||
|
||||
from subiquitycore.context import with_context
|
||||
from subiquitycore.controller import (
|
||||
BaseController,
|
||||
)
|
||||
from subiquitycore.tuicontroller import (
|
||||
RepeatedController,
|
||||
TuiController,
|
||||
)
|
||||
|
||||
log = logging.getLogger("subiquity.controller")
|
||||
|
||||
|
||||
class Confirm(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SubiquityController(BaseController):
|
||||
|
||||
autoinstall_key = None
|
||||
autoinstall_schema = None
|
||||
autoinstall_default = None
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self.autoinstall_applied = False
|
||||
self.context.set('controller', self)
|
||||
|
||||
def interactive(self):
|
||||
return False
|
||||
|
||||
def setup_autoinstall(self):
|
||||
if self.app.autoinstall_config:
|
||||
with self.context.child("load_autoinstall_data"):
|
||||
ai_data = self.app.autoinstall_config.get(
|
||||
self.autoinstall_key,
|
||||
self.autoinstall_default)
|
||||
if ai_data is not None and self.autoinstall_schema is not None:
|
||||
jsonschema.validate(ai_data, self.autoinstall_schema)
|
||||
self.load_autoinstall_data(ai_data)
|
||||
|
||||
def load_autoinstall_data(self, data):
|
||||
"""Load autoinstall data.
|
||||
|
||||
This is called if there is an autoinstall happening. This
|
||||
controller may not have any data, and this controller may still
|
||||
be interactive.
|
||||
"""
|
||||
pass
|
||||
|
||||
@with_context()
|
||||
async def apply_autoinstall_config(self, context):
|
||||
"""Apply autoinstall configuration.
|
||||
|
||||
This is only called for a non-interactive controller. It should
|
||||
block until the configuration has been applied. (self.configured()
|
||||
is called after this is done).
|
||||
"""
|
||||
pass
|
||||
|
||||
def configured(self):
|
||||
"""Let the world know that this controller's model is now configured.
|
||||
"""
|
||||
with open(self.app.state_path('states', self.name), 'w') as fp:
|
||||
json.dump(self.serialize(), fp)
|
||||
if self.model_name is not None:
|
||||
self.app.base_model.configured(self.model_name)
|
||||
|
||||
def load_state(self):
|
||||
state_path = self.app.state_path('states', self.name)
|
||||
if not os.path.exists(state_path):
|
||||
return
|
||||
with open(state_path) as fp:
|
||||
self.deserialize(json.load(fp))
|
||||
|
||||
def deserialize(self, state):
|
||||
pass
|
||||
|
||||
def make_autoinstall(self):
|
||||
return {}
|
||||
|
||||
|
||||
class SubiquityTuiController(SubiquityController, TuiController):
|
||||
|
||||
def interactive(self):
|
||||
if not self.app.autoinstall_config:
|
||||
return True
|
||||
i_sections = self.app.autoinstall_config.get(
|
||||
'interactive-sections', [])
|
||||
return '*' in i_sections or self.autoinstall_key in i_sections
|
||||
|
||||
|
||||
class RepeatedController(RepeatedController):
|
||||
|
||||
autoinstall_key = None
|
||||
autoinstall_schema = None
|
||||
|
||||
def __init__(self, orig, index):
|
||||
super().__init__(orig, index)
|
||||
self.autoinstall_applied = False
|
||||
|
||||
def setup_autoinstall(self):
|
||||
pass
|
||||
|
||||
async def apply_autoinstall_config(self):
|
||||
await self.orig.apply_autoinstall_config(index=self.index)
|
||||
|
||||
def configured(self):
|
||||
self.orig.configured()
|
||||
|
||||
def interactive(self):
|
||||
return self.orig.interactive()
|
||||
|
||||
def make_autoinstall(self):
|
||||
return {}
|
||||
|
||||
def load_state(self):
|
||||
pass
|
|
@ -1,20 +0,0 @@
|
|||
# Copyright 2020 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/>.
|
||||
|
||||
from .reboot import RebootController
|
||||
|
||||
__all__ = [
|
||||
'RebootController',
|
||||
]
|
|
@ -24,6 +24,7 @@ from .mirror import MirrorController
|
|||
from .network import NetworkController
|
||||
from .package import PackageController
|
||||
from .proxy import ProxyController
|
||||
from .reboot import RebootController
|
||||
from .refresh import RefreshController
|
||||
from .reporting import ReportingController
|
||||
from .snaplist import SnapListController
|
||||
|
@ -45,6 +46,7 @@ __all__ = [
|
|||
'NetworkController',
|
||||
'PackageController',
|
||||
'ProxyController',
|
||||
'RebootController',
|
||||
'RefreshController',
|
||||
'ReportingController',
|
||||
'SnapListController',
|
||||
|
|
|
@ -13,28 +13,49 @@
|
|||
# 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 os
|
||||
import platform
|
||||
import subprocess
|
||||
|
||||
from subiquitycore.async_helpers import schedule_task
|
||||
from subiquitycore.context import with_context
|
||||
from subiquitycore.utils import arun_command, run_command
|
||||
|
||||
from subiquity.controller import SubiquityTuiController
|
||||
from subiquity.common.apidef import API
|
||||
from subiquity.server.controller import SubiquityController
|
||||
from subiquity.server.controllers.install import InstallState
|
||||
|
||||
log = logging.getLogger("subiquity.controllers.restart")
|
||||
|
||||
|
||||
class RebootController(SubiquityTuiController):
|
||||
class RebootController(SubiquityController):
|
||||
|
||||
endpoint = API.reboot
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self.context.set('hidden', True)
|
||||
self.user_reboot_event = asyncio.Event()
|
||||
self.rebooting_event = asyncio.Event()
|
||||
|
||||
def interactive(self):
|
||||
return self.app.interactive()
|
||||
async def POST(self):
|
||||
self.app.controllers.Install.stop_uu()
|
||||
self.user_reboot_event.set()
|
||||
await self.rebooting_event.wait()
|
||||
|
||||
def start(self):
|
||||
self.app.aio_loop.create_task(self._run())
|
||||
|
||||
async def _run(self):
|
||||
Install = self.app.controllers.Install
|
||||
await Install.install_task
|
||||
await self.app.controllers.Late.run_event.wait()
|
||||
await self.copy_logs_to_target()
|
||||
if self.app.interactive():
|
||||
await self.user_reboot_event.wait()
|
||||
self.reboot()
|
||||
elif Install.install_state == InstallState.DONE:
|
||||
self.reboot()
|
||||
|
||||
@with_context()
|
||||
async def copy_logs_to_target(self, context):
|
||||
|
@ -56,27 +77,12 @@ class RebootController(SubiquityTuiController):
|
|||
except Exception:
|
||||
log.exception("saving journal failed")
|
||||
|
||||
def reboot(self):
|
||||
@with_context()
|
||||
def reboot(self, context):
|
||||
self.rebooting_event.set()
|
||||
if self.opts.dry_run:
|
||||
self.app.exit()
|
||||
else:
|
||||
if platform.machine() == 's390x':
|
||||
run_command(["chreipl", "/target/boot"])
|
||||
run_command(["/sbin/reboot"])
|
||||
|
||||
@with_context()
|
||||
async def apply_autoinstall_config(self, context):
|
||||
await self.copy_logs_to_target(context=context)
|
||||
self.reboot()
|
||||
|
||||
async def _run(self):
|
||||
await self.copy_logs_to_target()
|
||||
await self.app.controllers.InstallProgress.reboot_clicked.wait()
|
||||
self.reboot()
|
||||
|
||||
def make_ui(self):
|
||||
schedule_task(self._run())
|
||||
return self.ui.body
|
||||
|
||||
def cancel(self):
|
||||
pass
|
|
@ -131,6 +131,7 @@ class SubiquityServer(Application):
|
|||
"SnapList",
|
||||
"Install",
|
||||
"Late",
|
||||
"Reboot",
|
||||
]
|
||||
|
||||
def make_model(self):
|
||||
|
|
|
@ -36,8 +36,6 @@ class SubiquityUI(SubiquityCoreUI):
|
|||
return super().keypress(size, key)
|
||||
|
||||
def set_body(self, widget):
|
||||
if widget is self.body:
|
||||
return
|
||||
super().set_body(widget)
|
||||
if isinstance(widget, BaseView):
|
||||
for overlay in self.app.global_overlays:
|
||||
|
|
Loading…
Reference in New Issue