Merge pull request #186 from CanonicalLtd/mwhudson/cleanups
assorted cleanups
This commit is contained in:
commit
5d667b16fe
|
@ -19,9 +19,9 @@ import os
|
||||||
from subiquitycore.controller import BaseController, view
|
from subiquitycore.controller import BaseController, view
|
||||||
from subiquitycore.ui.dummy import DummyView
|
from subiquitycore.ui.dummy import DummyView
|
||||||
from subiquitycore.ui.error import ErrorView
|
from subiquitycore.ui.error import ErrorView
|
||||||
from subiquitycore.curtin import (curtin_write_storage_actions,
|
|
||||||
curtin_write_preserved_actions)
|
|
||||||
|
|
||||||
|
from subiquity.curtin import (curtin_write_storage_actions,
|
||||||
|
curtin_write_preserved_actions)
|
||||||
from subiquity.models.actions import preserve_action
|
from subiquity.models.actions import preserve_action
|
||||||
from subiquity.models import (FilesystemModel, RaidModel)
|
from subiquity.models import (FilesystemModel, RaidModel)
|
||||||
from subiquity.models.filesystem import (_humanize_size)
|
from subiquity.models.filesystem import (_humanize_size)
|
||||||
|
|
|
@ -20,12 +20,12 @@ from tornado.gen import coroutine
|
||||||
|
|
||||||
from subiquitycore import utils
|
from subiquitycore import utils
|
||||||
from subiquitycore.controller import BaseController
|
from subiquitycore.controller import BaseController
|
||||||
from subiquitycore.curtin import (CURTIN_CONFIGS,
|
|
||||||
CURTIN_INSTALL_LOG,
|
|
||||||
CURTIN_POSTINSTALL_LOG,
|
|
||||||
curtin_reboot,
|
|
||||||
curtin_install_cmd)
|
|
||||||
|
|
||||||
|
from subiquity.curtin import (CURTIN_CONFIGS,
|
||||||
|
CURTIN_INSTALL_LOG,
|
||||||
|
CURTIN_POSTINSTALL_LOG,
|
||||||
|
curtin_reboot,
|
||||||
|
curtin_install_cmd)
|
||||||
from subiquity.models import InstallProgressModel
|
from subiquity.models import InstallProgressModel
|
||||||
from subiquity.ui.views import ProgressView
|
from subiquity.ui.views import ProgressView
|
||||||
|
|
||||||
|
@ -112,21 +112,18 @@ class InstallProgressController(BaseController):
|
||||||
raise Exception('AIEEE!')
|
raise Exception('AIEEE!')
|
||||||
|
|
||||||
self.install_spawned = True
|
self.install_spawned = True
|
||||||
shell = False
|
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
log.debug("Installprogress: this is a dry-run")
|
log.debug("Installprogress: this is a dry-run")
|
||||||
curtin_cmd = ["top", "-d", "0.5", "-n", "20", "-b", "-p",
|
curtin_cmd = [
|
||||||
str(os.getpid()),
|
"bash", "-c",
|
||||||
'>', self.install_log,
|
"i=0;while [ $i -le 10 ];do i=$((i+1)); echo line $i; sleep 1; done > %s 2>&1"%self.install_log]
|
||||||
'2>', self.install_log]
|
|
||||||
shell = True
|
|
||||||
else:
|
else:
|
||||||
log.debug("Installprogress: this is the *REAL* thing")
|
log.debug("Installprogress: this is the *REAL* thing")
|
||||||
configs = [CURTIN_CONFIGS['storage']]
|
configs = [CURTIN_CONFIGS['storage']]
|
||||||
curtin_cmd = curtin_install_cmd(configs)
|
curtin_cmd = curtin_install_cmd(configs)
|
||||||
|
|
||||||
log.debug('Curtin install cmd: {}'.format(curtin_cmd))
|
log.debug('Curtin install cmd: {}'.format(curtin_cmd))
|
||||||
result = yield utils.run_command_async(curtin_cmd, shell=shell)
|
result = yield utils.run_command_async(self.pool, curtin_cmd)
|
||||||
log.debug('curtin_install: result: {}'.format(result))
|
log.debug('curtin_install: result: {}'.format(result))
|
||||||
if result['status'] > 0:
|
if result['status'] > 0:
|
||||||
msg = ("Problem with curtin "
|
msg = ("Problem with curtin "
|
||||||
|
@ -155,16 +152,13 @@ class InstallProgressController(BaseController):
|
||||||
log.error('Attempting to spawn curtin install without a config')
|
log.error('Attempting to spawn curtin install without a config')
|
||||||
raise Exception('AIEEE!')
|
raise Exception('AIEEE!')
|
||||||
|
|
||||||
shell = False
|
|
||||||
self.postinstall_spawned = True
|
self.postinstall_spawned = True
|
||||||
self.install_log = CURTIN_POSTINSTALL_LOG
|
self.install_log = CURTIN_POSTINSTALL_LOG
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
log.debug("Installprogress: this is a dry-run")
|
log.debug("Installprogress: this is a dry-run")
|
||||||
curtin_cmd = ["top", "-d", "0.5", "-n", "20", "-b", "-p",
|
curtin_cmd = [
|
||||||
str(os.getpid()),
|
"bash", "-c",
|
||||||
'>', self.install_log,
|
"i=0;while [ $i -le 10 ];do i=$((i+1)); echo line $i; sleep 1; done > %s 2>&1"%self.install_log]
|
||||||
'2>', self.install_log]
|
|
||||||
shell = True
|
|
||||||
else:
|
else:
|
||||||
log.debug("Installprogress: this is the *REAL* thing")
|
log.debug("Installprogress: this is the *REAL* thing")
|
||||||
configs = [
|
configs = [
|
||||||
|
@ -174,7 +168,7 @@ class InstallProgressController(BaseController):
|
||||||
curtin_cmd = curtin_install_cmd(configs)
|
curtin_cmd = curtin_install_cmd(configs)
|
||||||
|
|
||||||
log.debug('Curtin postinstall cmd: {}'.format(curtin_cmd))
|
log.debug('Curtin postinstall cmd: {}'.format(curtin_cmd))
|
||||||
result = yield utils.run_command_async(curtin_cmd, shell=shell)
|
result = yield utils.run_command_async(self.pool, curtin_cmd)
|
||||||
if result['status'] > 0:
|
if result['status'] > 0:
|
||||||
msg = ("Problem with curtin "
|
msg = ("Problem with curtin "
|
||||||
"post-install: {}".format(result))
|
"post-install: {}".format(result))
|
||||||
|
|
|
@ -22,7 +22,7 @@ import yaml
|
||||||
from subiquitycore import utils
|
from subiquitycore import utils
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger("subiquitycore.curtin")
|
log = logging.getLogger("subiquity.curtin")
|
||||||
|
|
||||||
TMPDIR = '/tmp'
|
TMPDIR = '/tmp'
|
||||||
CURTIN_SEARCH_PATH = ['/usr/local/curtin/bin', '/usr/bin']
|
CURTIN_SEARCH_PATH = ['/usr/local/curtin/bin', '/usr/bin']
|
|
@ -15,20 +15,13 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.models.ceph_disk')
|
log = logging.getLogger('subiquity.models.ceph_disk')
|
||||||
|
|
||||||
|
|
||||||
class CephDiskModel(BaseModel):
|
class CephDiskModel(object):
|
||||||
""" Model representing iscsi Ceph storage
|
""" Model representing iscsi Ceph storage
|
||||||
"""
|
"""
|
||||||
prev_signal = (
|
|
||||||
'Back to filesystem view',
|
|
||||||
'filesystem:show',
|
|
||||||
'filesystem'
|
|
||||||
)
|
|
||||||
|
|
||||||
signals = [
|
signals = [
|
||||||
('Ceph view',
|
('Ceph view',
|
||||||
|
|
|
@ -19,8 +19,6 @@ import math
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
from .blockdev import (Bcachedev,
|
from .blockdev import (Bcachedev,
|
||||||
Blockdev,
|
Blockdev,
|
||||||
LVMDev,
|
LVMDev,
|
||||||
|
@ -37,7 +35,7 @@ class AttrDict(dict):
|
||||||
__setattr__ = dict.__setitem__
|
__setattr__ = dict.__setitem__
|
||||||
|
|
||||||
|
|
||||||
class FilesystemModel(BaseModel):
|
class FilesystemModel(object):
|
||||||
""" Model representing storage options
|
""" Model representing storage options
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.models.installpath")
|
log = logging.getLogger("subiquity.models.installpath")
|
||||||
|
|
||||||
|
|
||||||
class InstallpathModel(BaseModel):
|
class InstallpathModel(object):
|
||||||
""" Model representing install options
|
""" Model representing install options
|
||||||
|
|
||||||
List of install paths in the form of:
|
List of install paths in the form of:
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.models.installprogress')
|
log = logging.getLogger('subiquity.models.installprogress')
|
||||||
|
|
||||||
|
|
||||||
class InstallProgressModel(BaseModel):
|
class InstallProgressModel(object):
|
||||||
""" Model representing install progress
|
""" Model representing install progress
|
||||||
"""
|
"""
|
||||||
# FIXME: Decide what to do here if ESC is pressed, it's probably in
|
# FIXME: Decide what to do here if ESC is pressed, it's probably in
|
||||||
|
|
|
@ -15,20 +15,13 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.models.iscsi_disk')
|
log = logging.getLogger('subiquity.models.iscsi_disk')
|
||||||
|
|
||||||
|
|
||||||
class IscsiDiskModel(BaseModel):
|
class IscsiDiskModel(object):
|
||||||
""" Model representing iscsi network disk
|
""" Model representing iscsi network disk
|
||||||
"""
|
"""
|
||||||
prev_signal = (
|
|
||||||
'Back to filesystem view',
|
|
||||||
'filesystem:show',
|
|
||||||
'filesystem'
|
|
||||||
)
|
|
||||||
|
|
||||||
menu = [
|
menu = [
|
||||||
('Discover volumes now', 'iscsi:discover-volumes'),
|
('Discover volumes now', 'iscsi:discover-volumes'),
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.models.raid')
|
log = logging.getLogger('subiquity.models.raid')
|
||||||
|
|
||||||
|
|
||||||
class RaidModel(BaseModel):
|
class RaidModel(object):
|
||||||
""" Model representing software raid
|
""" Model representing software raid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import logging
|
||||||
|
|
||||||
from urwid import Pile, Columns, Text, ListBox
|
from urwid import Pile, Columns, Text, ListBox
|
||||||
|
|
||||||
from subiquitycore.curtin import curtin_write_postinst_config
|
|
||||||
from subiquitycore.ui.buttons import done_btn, cancel_btn
|
from subiquitycore.ui.buttons import done_btn, cancel_btn
|
||||||
from subiquitycore.ui.interactive import (PasswordEditor,
|
from subiquitycore.ui.interactive import (PasswordEditor,
|
||||||
RealnameEditor,
|
RealnameEditor,
|
||||||
|
@ -27,6 +26,7 @@ from subiquitycore.ui.utils import Padding, Color
|
||||||
from subiquitycore.user import create_user
|
from subiquitycore.user import create_user
|
||||||
from subiquitycore.view import BaseView
|
from subiquitycore.view import BaseView
|
||||||
|
|
||||||
|
from subiquity.curtin import curtin_write_postinst_config
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.views.identity")
|
log = logging.getLogger("subiquity.views.identity")
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
# Copyright 2015 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/>.
|
|
||||||
|
|
||||||
""" Async Handler
|
|
||||||
Provides async operations for various api calls and other non-blocking
|
|
||||||
work.
|
|
||||||
|
|
||||||
The way this works is you create your non-blocking thread:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
def my_async_method(self):
|
|
||||||
pool.submit(func, *args)
|
|
||||||
|
|
||||||
# In your controller you would then call using coroutines
|
|
||||||
|
|
||||||
@coroutine
|
|
||||||
def do_async_action(self):
|
|
||||||
try:
|
|
||||||
yield my_async_method()
|
|
||||||
# Move to next coroutine or return if finish
|
|
||||||
self.do_second_async_action()
|
|
||||||
except Exeception as e:
|
|
||||||
log.exception("Failed in our non-blocking code.")
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
|
||||||
log = logging.getLogger("subiquitycore.async")
|
|
||||||
|
|
||||||
|
|
||||||
class Async:
|
|
||||||
log.debug('instantiating ThreadPoolExector')
|
|
||||||
pool = ThreadPoolExecutor(1)
|
|
||||||
log.debug('pool={}'.format(pool))
|
|
|
@ -40,6 +40,7 @@ class BaseController(ABC):
|
||||||
self.loop = common['loop']
|
self.loop = common['loop']
|
||||||
self.prober = common['prober']
|
self.prober = common['prober']
|
||||||
self.controllers = common['controllers']
|
self.controllers = common['controllers']
|
||||||
|
self.pool = common['pool']
|
||||||
self.view_stack = []
|
self.view_stack = []
|
||||||
|
|
||||||
def register_signals(self):
|
def register_signals(self):
|
||||||
|
|
|
@ -27,7 +27,6 @@ import yaml
|
||||||
|
|
||||||
from probert.network import UdevObserver
|
from probert.network import UdevObserver
|
||||||
|
|
||||||
from subiquitycore.async import Async
|
|
||||||
from subiquitycore.models import NetworkModel
|
from subiquitycore.models import NetworkModel
|
||||||
from subiquitycore.ui.views import (NetworkView,
|
from subiquitycore.ui.views import (NetworkView,
|
||||||
NetworkSetDefaultRouteView,
|
NetworkSetDefaultRouteView,
|
||||||
|
@ -134,8 +133,9 @@ class WaitForDefaultRouteTask(BackgroundTask):
|
||||||
|
|
||||||
|
|
||||||
class TaskSequence:
|
class TaskSequence:
|
||||||
def __init__(self, loop, tasks, watcher):
|
def __init__(self, loop, pool, tasks, watcher):
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
|
self.pool = pool
|
||||||
self.tasks = tasks
|
self.tasks = tasks
|
||||||
self.watcher = watcher
|
self.watcher = watcher
|
||||||
self.canceled = False
|
self.canceled = False
|
||||||
|
@ -163,7 +163,7 @@ class TaskSequence:
|
||||||
# Vomiting a traceback all over the console is nasty, but not as
|
# Vomiting a traceback all over the console is nasty, but not as
|
||||||
# nasty as silently doing nothing.
|
# nasty as silently doing nothing.
|
||||||
fut.result()
|
fut.result()
|
||||||
Async.pool.submit(self.curtask.run, self).add_done_callback(cb)
|
self.pool.submit(self.curtask.run, self).add_done_callback(cb)
|
||||||
|
|
||||||
def call_from_thread(self, func, *args):
|
def call_from_thread(self, func, *args):
|
||||||
log.debug('call_from_thread %s %s', func, args)
|
log.debug('call_from_thread %s %s', func, args)
|
||||||
|
@ -384,7 +384,7 @@ class NetworkController(BaseController):
|
||||||
self.acw = ApplyingConfigWidget(len(tasks), cancel)
|
self.acw = ApplyingConfigWidget(len(tasks), cancel)
|
||||||
self.ui.frame.body.show_overlay(self.acw)
|
self.ui.frame.body.show_overlay(self.acw)
|
||||||
|
|
||||||
self.cs = TaskSequence(self.loop, tasks, self)
|
self.cs = TaskSequence(self.loop, self.pool, tasks, self)
|
||||||
self.cs.run()
|
self.cs.run()
|
||||||
|
|
||||||
def task_complete(self, stage):
|
def task_complete(self, stage):
|
||||||
|
|
|
@ -13,10 +13,13 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from concurrent import futures
|
||||||
import logging
|
import logging
|
||||||
import urwid
|
import urwid
|
||||||
|
|
||||||
from tornado.ioloop import IOLoop
|
from tornado.ioloop import IOLoop
|
||||||
from tornado.util import import_object
|
from tornado.util import import_object
|
||||||
|
|
||||||
from subiquitycore.signals import Signal
|
from subiquitycore.signals import Signal
|
||||||
from subiquitycore.palette import STYLES, STYLES_MONO
|
from subiquitycore.palette import STYLES, STYLES_MONO
|
||||||
from subiquitycore.prober import Prober, ProberException
|
from subiquitycore.prober import Prober, ProberException
|
||||||
|
@ -60,7 +63,8 @@ class Application:
|
||||||
"opts": opts,
|
"opts": opts,
|
||||||
"signal": Signal(),
|
"signal": Signal(),
|
||||||
"prober": prober,
|
"prober": prober,
|
||||||
"loop": None
|
"loop": None,
|
||||||
|
"pool": futures.ThreadPoolExecutor(1),
|
||||||
}
|
}
|
||||||
self.common['controllers'] = dict.fromkeys(self.controllers)
|
self.common['controllers'] = dict.fromkeys(self.controllers)
|
||||||
self.controller_index = -1
|
self.controller_index = -1
|
||||||
|
@ -70,7 +74,6 @@ class Application:
|
||||||
"""
|
"""
|
||||||
signals = []
|
signals = []
|
||||||
|
|
||||||
# Add quit signal
|
|
||||||
signals.append(('quit', self.exit))
|
signals.append(('quit', self.exit))
|
||||||
if self.common['opts'].dry_run:
|
if self.common['opts'].dry_run:
|
||||||
signals.append(('control-x-quit', self.exit))
|
signals.append(('control-x-quit', self.exit))
|
||||||
|
@ -104,20 +107,12 @@ class Application:
|
||||||
|
|
||||||
# EventLoop -------------------------------------------------------------------
|
# EventLoop -------------------------------------------------------------------
|
||||||
def redraw_screen(self):
|
def redraw_screen(self):
|
||||||
if hasattr(self, 'loop'):
|
if self.common['loop'] is not None:
|
||||||
try:
|
try:
|
||||||
self.common['loop'].draw_screen()
|
self.common['loop'].draw_screen()
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
log.critical("Redraw screen error: {}".format(e))
|
log.critical("Redraw screen error: {}".format(e))
|
||||||
|
|
||||||
def set_alarm_in(self, interval, cb):
|
|
||||||
self.common['loop'].set_alarm_in(interval, cb)
|
|
||||||
return
|
|
||||||
|
|
||||||
def update(self, *args, **kwds):
|
|
||||||
""" Update loop """
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
raise urwid.ExitMainLoop()
|
raise urwid.ExitMainLoop()
|
||||||
|
|
||||||
|
@ -146,7 +141,7 @@ class Application:
|
||||||
self.common['loop'].event_loop))
|
self.common['loop'].event_loop))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.set_alarm_in(0.05, self.next_screen)
|
self.common['loop'].set_alarm_in(0.05, self.next_screen)
|
||||||
for k in self.common['controllers']:
|
for k in self.common['controllers']:
|
||||||
log.debug("Importing controller: {}".format(k))
|
log.debug("Importing controller: {}".format(k))
|
||||||
klass = import_object(
|
klass = import_object(
|
||||||
|
|
|
@ -18,11 +18,8 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from logging.handlers import TimedRotatingFileHandler
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
|
|
||||||
LOGDIR = "/writable/.subiquity"
|
|
||||||
LOGFILE = os.path.join(LOGDIR, "subiquity-debug.log")
|
|
||||||
|
|
||||||
|
def setup_logger(dir):
|
||||||
def setup_logger(name=__name__, dir=LOGDIR):
|
|
||||||
LOGFILE = os.path.join(dir, "subiquity-debug.log")
|
LOGFILE = os.path.join(dir, "subiquity-debug.log")
|
||||||
try:
|
try:
|
||||||
os.makedirs(dir, exist_ok=True)
|
os.makedirs(dir, exist_ok=True)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Copyright 2015 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/>.
|
|
|
@ -1,26 +0,0 @@
|
||||||
# Copyright 2015 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/>.
|
|
||||||
|
|
||||||
""" Model Policy
|
|
||||||
"""
|
|
||||||
|
|
||||||
from abc import ABC
|
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(ABC):
|
|
||||||
"""Expected contract for defining models. """
|
|
||||||
|
|
||||||
# Back navigation
|
|
||||||
prev_signal = None
|
|
|
@ -14,7 +14,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
from subiquitycore.utils import crypt_password
|
from subiquitycore.utils import crypt_password
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ class LocalUser(object):
|
||||||
return "%s <%s>" % (self._realname, self._username)
|
return "%s <%s>" % (self._realname, self._username)
|
||||||
|
|
||||||
|
|
||||||
class IdentityModel(BaseModel):
|
class IdentityModel(object):
|
||||||
""" Model representing user identity
|
""" Model representing user identity
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,14 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquitycore.login')
|
log = logging.getLogger('subiquitycore.login')
|
||||||
|
|
||||||
|
|
||||||
class LoginModel(BaseModel):
|
class LoginModel(object):
|
||||||
""" Model representing Final login screen
|
""" Model representing Final login screen
|
||||||
"""
|
"""
|
||||||
prev_signal = 'menu:identity:main'
|
|
||||||
|
|
||||||
signals = [
|
signals = [
|
||||||
("Login view",
|
("Login view",
|
||||||
|
|
|
@ -23,7 +23,6 @@ from socket import AF_INET, AF_INET6
|
||||||
|
|
||||||
import yaml, yaml.reader
|
import yaml, yaml.reader
|
||||||
|
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
NETDEV_IGNORED_IFACE_NAMES = ['lo']
|
NETDEV_IGNORED_IFACE_NAMES = ['lo']
|
||||||
NETDEV_IGNORED_IFACE_TYPES = ['bridge', 'tun', 'tap', 'dummy', 'sit']
|
NETDEV_IGNORED_IFACE_TYPES = ['bridge', 'tun', 'tap', 'dummy', 'sit']
|
||||||
|
@ -338,7 +337,7 @@ def valid_ipv4_address(addr):
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
|
|
||||||
class NetworkModel(BaseModel):
|
class NetworkModel(object):
|
||||||
""" Model representing network interfaces
|
""" Model representing network interfaces
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,14 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from subiquitycore.model import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquitycore.welcome')
|
log = logging.getLogger('subiquitycore.welcome')
|
||||||
|
|
||||||
|
|
||||||
class WelcomeModel(BaseModel):
|
class WelcomeModel(object):
|
||||||
""" Model representing language selection
|
""" Model representing language selection
|
||||||
"""
|
"""
|
||||||
prev_signal = None
|
|
||||||
|
|
||||||
supported_languages = ['English',
|
supported_languages = ['English',
|
||||||
'Belgian',
|
'Belgian',
|
||||||
|
|
|
@ -29,7 +29,6 @@ class SignalException(Exception):
|
||||||
class Signal:
|
class Signal:
|
||||||
known_signals = []
|
known_signals = []
|
||||||
signal_stack = []
|
signal_stack = []
|
||||||
default_signal = None
|
|
||||||
|
|
||||||
def register_signals(self, signals):
|
def register_signals(self, signals):
|
||||||
if type(signals) is list:
|
if type(signals) is list:
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from urwid import WidgetWrap, Pile, Text, ProgressBar
|
from urwid import WidgetWrap, Pile, Text, ProgressBar
|
||||||
from collections import deque
|
|
||||||
from subiquitycore.ui.utils import Padding, Color
|
from subiquitycore.ui.utils import Padding, Color
|
||||||
from subiquitycore.ui.lists import SimpleList
|
from subiquitycore.ui.lists import SimpleList
|
||||||
|
|
||||||
|
@ -54,12 +53,12 @@ class Footer(WidgetWrap):
|
||||||
ProgressBar(normal='progress_incomplete',
|
ProgressBar(normal='progress_incomplete',
|
||||||
complete='progress_complete',
|
complete='progress_complete',
|
||||||
current=completion, done=100))
|
current=completion, done=100))
|
||||||
status = deque([
|
status = [
|
||||||
Padding.line_break(""),
|
Padding.line_break(""),
|
||||||
message_widget
|
message_widget,
|
||||||
])
|
]
|
||||||
if completion > 0:
|
if completion > 0:
|
||||||
status.appendleft(progress_bar)
|
status.insert(0, progress_bar)
|
||||||
super().__init__(Pile(status))
|
super().__init__(Pile(status))
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,8 +67,4 @@ class Body(WidgetWrap):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
text = [
|
super().__init__(SimpleList([Text("")]))
|
||||||
Padding.line_break(""),
|
|
||||||
]
|
|
||||||
w = (SimpleList(text))
|
|
||||||
super().__init__(w)
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class SimpleList(WidgetWrap):
|
||||||
super().__init__(self._build_widget())
|
super().__init__(self._build_widget())
|
||||||
|
|
||||||
def _build_widget(self):
|
def _build_widget(self):
|
||||||
lw = SimpleListWalker([x for x in self.contents])
|
lw = SimpleListWalker(list(self.contents))
|
||||||
|
|
||||||
return ListBox(lw)
|
return ListBox(lw)
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
# Copyright 2015 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 urwid import (LineBox, ListBox)
|
|
||||||
|
|
||||||
|
|
||||||
def Box(items, title=""):
|
|
||||||
""" Draws a linebox around a set of items """
|
|
||||||
container = ListBox(items)
|
|
||||||
return LineBox(container, title=title)
|
|
|
@ -18,10 +18,8 @@ import errno
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
|
||||||
import yaml
|
import yaml
|
||||||
from subprocess import Popen, PIPE, call
|
from subprocess import Popen, PIPE
|
||||||
from subiquitycore.async import Async
|
|
||||||
|
|
||||||
log = logging.getLogger("subiquitycore.utils")
|
log = logging.getLogger("subiquitycore.utils")
|
||||||
SYS_CLASS_NET = "/sys/class/net/"
|
SYS_CLASS_NET = "/sys/class/net/"
|
||||||
|
@ -86,9 +84,9 @@ def environment_check(check):
|
||||||
return env_ok
|
return env_ok
|
||||||
|
|
||||||
|
|
||||||
def run_command_async(cmd, timeout=None, shell=False):
|
def run_command_async(pool, cmd, timeout=None, shell=False):
|
||||||
log.debug('calling Async command: {}'.format(cmd))
|
log.debug('calling Async command: {}'.format(cmd))
|
||||||
return Async.pool.submit(run_command, cmd, timeout, shell)
|
return pool.submit(run_command, cmd, timeout, shell)
|
||||||
|
|
||||||
|
|
||||||
def run_command_start(command, timeout=None, shell=False):
|
def run_command_start(command, timeout=None, shell=False):
|
||||||
|
@ -150,32 +148,6 @@ def run_command(command, timeout=None, shell=False):
|
||||||
return run_command_summarize(p, stdout, stderr)
|
return run_command_summarize(p, stdout, stderr)
|
||||||
|
|
||||||
|
|
||||||
def sys_dev_path(devname, path=""):
|
|
||||||
return SYS_CLASS_NET + devname + "/" + path
|
|
||||||
|
|
||||||
|
|
||||||
def read_sys_net(devname, path, translate=None, enoent=None, keyerror=None):
|
|
||||||
try:
|
|
||||||
contents = ""
|
|
||||||
with open(sys_dev_path(devname, path), "r") as fp:
|
|
||||||
contents = fp.read().strip()
|
|
||||||
if translate is None:
|
|
||||||
return contents
|
|
||||||
|
|
||||||
try:
|
|
||||||
return translate.get(contents)
|
|
||||||
except KeyError:
|
|
||||||
log.debug("found unexpected value '%s' in '%s/%s'", contents,
|
|
||||||
devname, path)
|
|
||||||
if keyerror is not None:
|
|
||||||
return keyerror
|
|
||||||
raise
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ENOENT and enoent is not None:
|
|
||||||
return enoent
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME: replace with passlib and update package deps
|
# FIXME: replace with passlib and update package deps
|
||||||
def crypt_password(passwd, algo='SHA-512'):
|
def crypt_password(passwd, algo='SHA-512'):
|
||||||
# encryption algo - id pairs for crypt()
|
# encryption algo - id pairs for crypt()
|
||||||
|
@ -192,24 +164,6 @@ def crypt_password(passwd, algo='SHA-512'):
|
||||||
return crypt.crypt(passwd, algos[algo] + salt)
|
return crypt.crypt(passwd, algos[algo] + salt)
|
||||||
|
|
||||||
|
|
||||||
def is_root():
|
|
||||||
""" Returns root or if sudo user exists
|
|
||||||
"""
|
|
||||||
euid = os.geteuid()
|
|
||||||
|
|
||||||
log.debug('is_root: euid={}'.format(euid))
|
|
||||||
if euid != 0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def sudo_user():
|
|
||||||
""" Returns the value of env['SUDO_USER']
|
|
||||||
"""
|
|
||||||
sudo_user = os.getenv('SUDO_USER', None)
|
|
||||||
return sudo_user
|
|
||||||
|
|
||||||
|
|
||||||
def disable_first_boot_service():
|
def disable_first_boot_service():
|
||||||
""" Stop firstboot service; which also restores getty service """
|
""" Stop firstboot service; which also restores getty service """
|
||||||
log.info('disabling first boot service')
|
log.info('disabling first boot service')
|
||||||
|
|
Loading…
Reference in New Issue