Merge branch 'mwhudson/demo'

This commit is contained in:
Mathieu Trudel-Lapierre 2016-07-28 20:25:17 -04:00
commit d3c0bb95d7
11 changed files with 190 additions and 25 deletions

View File

@ -18,7 +18,7 @@ import argparse
import sys
import logging
import signal
from subiquitycore.log import setup_logger, LOGFILE
from subiquitycore.log import setup_logger
from subiquitycore import __version__ as VERSION
from console_conf.core import ConsoleConf
from subiquitycore.core import ApplicationError
@ -70,10 +70,14 @@ def parse_options(argv):
def control_c_handler(signum, frame):
sys.exit(1)
LOGDIR = "/writable/.subiquity"
def main():
opts = parse_options(sys.argv[1:])
setup_logger()
global LOGDIR
if opts.dry_run:
LOGDIR = ".subiquity"
LOGFILE = setup_logger(dir=LOGDIR)
logger = logging.getLogger('console_conf')
logger.info("Starting console-conf v{}".format(VERSION))
logger.info("Arguments passed: {}".format(sys.argv))

View File

@ -16,8 +16,32 @@
from subiquitycore.controllers.identity import BaseIdentityController
from console_conf.ui.views import IdentityView
from console_conf.ui.views import IdentityView, LoginView
class IdentityController(BaseIdentityController):
identity_view = IdentityView
def identity(self):
title = "Profile setup"
excerpt = "Enter an email address from your account in the store."
footer = ""
self.ui.set_header(title, excerpt)
self.ui.set_footer(footer, 40)
self.ui.set_body(self.identity_view(self.model, self.signal, self.opts, self.loop))
def login(self):
title = "Configuration Complete"
footer = "View configured user and device access methods"
self.ui.set_header(title)
self.ui.set_footer(footer)
net_model = self.controllers['Network'].model
configured_ifaces = net_model.get_configured_interfaces()
login_view = LoginView(self.opts,
self.model,
self.signal,
self.model.user,
configured_ifaces)
self.ui.set_body(login_view)

View File

@ -16,4 +16,5 @@
""" ConsoleConf UI Views """
from .identity import IdentityView # NOQA
from .login import LoginView # NOQA
from .welcome import WelcomeView # NOQA

View File

@ -14,19 +14,130 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import pwd
from subiquitycore.ui.views.identity import BaseIdentityView
from subiquitycore.user import create_user
from urwid import (Pile, Columns, Text, ListBox)
from subiquitycore.ui.buttons import done_btn, cancel_btn
from subiquitycore.ui.interactive import EmailEditor
from subiquitycore.ui.utils import Padding, Color
from subiquitycore.utils import run_command
from subiquitycore.view import BaseView
log = logging.getLogger("console_conf.views.identity")
class IdentityView(BaseIdentityView):
def create_user(self, result):
try:
create_user(
result, dryrun=self.opts.dry_run, extra_args=['--extrausers'])
except PermissionError:
# XXX do something here
log.exception('Failed to create user.')
return None
'''
+---------------------------------------------------+
| |
| Enter the email address of the account in the |
| store |
| |
| +-------------------------+ |
| Email address: | | |
| +-------------------------+ |
| |
| |
| +--------+ |
| | Done | |
| +--------+ |
| | Cancel | |
| +--------+ |
| |
+---------------------------------------------------+
'''
class IdentityView(BaseView):
def __init__(self, model, signal, opts, loop):
self.model = model
self.signal = signal
self.opts = opts
self.loop = loop
self.items = []
self.email = EmailEditor(caption="")
self.error = Text("", align="center")
self.progress = Text("", align="center")
body = [
Padding.center_90(self._build_model_inputs()),
Padding.line_break(""),
Padding.center_90(Color.info_error(self.error)),
Padding.center_90(self.progress),
Padding.line_break(""),
Padding.fixed_10(self._build_buttons()),
]
super().__init__(ListBox(body))
def _build_model_inputs(self):
sl = [
Columns(
[
("weight", 0.2, Text("Email address:", align="right")),
("weight", 0.3,
Color.string_input(self.email,
focus_map="string_input focus"))
],
dividechars=4
),
]
return Pile(sl)
def _build_buttons(self):
cancel = cancel_btn(on_press=self.cancel)
done = done_btn(on_press=self.done)
buttons = [
Color.button(done, focus_map='button focus'),
Color.button(cancel, focus_map='button focus')
]
return Pile(buttons)
def cancel(self, button):
self.signal.prev_signal()
def done(self, button):
if len(self.email.value) < 1:
self.error.set_text("Please enter an email address.")
return
if not self.opts.dry_run:
self.progress.set_text("Contacting store...")
self.loop.draw_screen()
users_before = users()
result = run_command(["snap", "create-user", self.email.value])
self.progress.set_text("")
if result['status'] != 0:
self.error.set_text("Creating user failed:\n" + result['err'])
return
else:
users_after = users()
new_users = users_after - users_before
if len(new_users) != 1:
self.error.set_text("uhh")
return
new_user = pwd.getpwnam(new_users.pop())
# Use email for realname until
# https://bugs.launchpad.net/snappy/+bug/1607121 is resolved.
result = {
'realname': self.email.value, #new_user.pw_gecos.split(",")[0]
'username': new_user.pw_name,
'passwod': '',
'confirm_password': ''
}
# Work around https://bugs.launchpad.net/snappy/+bug/1606815
run_command(["chown", "{}:{}".format(new_user.pw_uid, new_user.pw_gid), "-R", new_user.pw_dir])
self.model.add_user(result)
else:
result = {
'realname': self.email.value,
'username': self.email.value,
'passwod': '',
'confirm_password': '',
}
self.model.add_user(result)
self.signal.emit_signal('menu:identity:login:main')
def users():
r = set()
for pw in pwd.getpwall():
r.add(pw.pw_name)
return r

10
debian/changelog vendored
View File

@ -1,7 +1,11 @@
subiquity (0.0.6~cy3) UNRELEASED; urgency=medium
subiquity (0.0.7~1) UNRELEASED; urgency=medium
* Release 0.0.6 snapshot: port for yakkety:
- Build separate subiquitycore, subiquity, and console-conf packages.
[ Michael Hudson-Doyle ]
* Demo-ware.
* Install systemd units for console-conf.
[ Mathieu Trudel-Lapierre ]
* Release 0.0.7 snapshot
* debian/control: move Depends on curtin from subiquitycore to subiquity.
-- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Fri, 08 Jul 2016 16:44:55 -0400

View File

@ -7,7 +7,7 @@ ExecStop=systemctl start getty@%I
Before=getty.target
IgnoreOnIsolate=yes
ConditionPathExists=/dev/tty0
ConditionPathExists=!/var/lib/firstboot/firstboot-complete
ConditionPathExists=!/writable/firstboot-complete
[Service]
Environment=PYTHONPATH=/usr/share/subiquity

6
debian/console-conf.postinst vendored Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
#DEBHELPER#
systemctl enable console-conf@tty1.service
systemctl enable serial-console-conf@ttyS1.service

View File

@ -4,7 +4,7 @@ BindsTo=dev-%i.device
#After=getty@tty.service
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
ConditionPathExists=!/var/lib/firstboot/firstboot-complete
ConditionPathExists=!/writable/firstboot-complete
[Service]
Environment=PYTHONPATH=/usr/share/subiquity

View File

@ -18,14 +18,15 @@ import os
import sys
from logging.handlers import TimedRotatingFileHandler
LOGDIR = ".subiquity"
LOGDIR = "/writable/.subiquity"
LOGFILE = os.path.join(LOGDIR, "subiquity-debug.log")
def setup_logger(name=__name__):
def setup_logger(name=__name__, dir=LOGDIR):
LOGFILE = os.path.join(dir, "subiquity-debug.log")
try:
if not os.path.isdir(LOGDIR):
os.makedirs(LOGDIR)
if not os.path.isdir(dir):
os.makedirs(dir)
log = TimedRotatingFileHandler(LOGFILE,
when='D',
interval=1,
@ -46,4 +47,4 @@ def setup_logger(name=__name__):
logger = logging.getLogger('')
logger.setLevel('DEBUG')
logger.addHandler(log)
return logger
return LOGFILE

View File

@ -74,6 +74,20 @@ class RealnameEditor(StringEditor):
return super().keypress(size, key)
class EmailEditor(StringEditor):
""" Email input prompt with input rules
"""
def keypress(self, size, key):
''' restrict what chars we allow for username '''
realname = r'[-a-zA-Z0-9_.@]'
if re.match(realname, key) is None:
return False
return super().keypress(size, key)
class UsernameEditor(StringEditor):
""" Username input prompt with input rules
"""

View File

@ -202,7 +202,7 @@ def sudo_user():
def mark_firstboot_complete():
""" Touch our firstboot-complete eyecatcher """
log.info('marking firstboot service complete')
firstboot = '/var/lib/firstboot/firstboot-complete'
firstboot = '/writable/firstboot-complete'
if not os.path.exists(os.path.dirname(firstboot)):
os.makedirs(os.path.dirname(firstboot))
with open(firstboot, 'w') as fp: