Merge branch 'master' into still-better-i18n

This commit is contained in:
Michael Hudson-Doyle 2020-05-21 11:15:32 +12:00
commit 7bcfcba99b
16 changed files with 97 additions and 54 deletions

View File

@ -17,6 +17,9 @@ if [ -e /run/snapd-recovery-chooser-triggered ]; then
# when recovery chooser is invoked it takes over the terminal
exec /usr/lib/snapd/snap-recovery-chooser
fi
if [ -e /var/lib/console-conf/complete ]; then
exit 0
fi
fi
if grep -q 'snapd_recovery_mode=install' /proc/cmdline ; then

View File

@ -10,7 +10,8 @@ After=core18.start-snapd.service core.start-snapd.service
After=snapd.recovery-chooser-trigger.service
IgnoreOnIsolate=yes
ConditionPathExists=/dev/tty0
ConditionPathExists=!/var/lib/console-conf/complete
ConditionPathExists=|!/var/lib/console-conf/complete
ConditionPathExists=|/run/snapd-recovery-chooser-triggered
StartLimitInterval=0
[Service]

View File

@ -161,7 +161,8 @@ class FilesystemController(SubiquityController):
"block probing failed restricted=%s", restricted)
report = self.app.make_apport_report(
kind, "block probing", interrupt=False)
self._crash_reports[restricted] = report
if report is not None:
self._crash_reports[restricted] = report
continue
break

View File

@ -153,7 +153,8 @@ class InstallProgressController(SubiquityController):
self.progress_view.set_status(('info_error',
_("An error has occurred")))
self.start_ui()
self.progress_view.show_error(crash_report)
if crash_report is not None:
self.progress_view.show_error(crash_report)
def logged_command(self, cmd):
return ['systemd-cat', '--level-prefix=false',

View File

@ -35,7 +35,7 @@ class KeyboardController(SubiquityController):
'properties': {
'layout': {'type': 'string'},
'variant': {'type': 'string'},
'toggle': {'type': 'string'},
'toggle': {'type': ['string', 'null']},
},
'required': ['layout'],
'additionalProperties': False,

View File

@ -274,7 +274,8 @@ class Subiquity(Application):
report = self.make_apport_report(
ErrorReportKind.UI, "Installer UI", interrupt=False,
wait=True)
print("report saved to {path}".format(report.path))
if report is not None:
print("report saved to {path}".format(report.path))
except Exception:
print("report generation failed")
traceback.print_exc()
@ -457,6 +458,9 @@ class Subiquity(Application):
self._apport_data.append((key, value))
def make_apport_report(self, kind, thing, *, interrupt, wait=False, **kw):
if not self.opts.dry_run and not os.path.exists('/cdrom/.disk/info'):
return None
log.debug("generating crash report")
try:
@ -507,7 +511,7 @@ class Subiquity(Application):
self.add_global_overlay(ErrorReportStretchy(self, report))
def make_autoinstall(self):
config = {}
config = {'version': 1}
for controller in self.controllers.instances:
controller_conf = controller.make_autoinstall()
if controller_conf:

View File

@ -24,6 +24,7 @@ import math
import os
import pathlib
import platform
import tempfile
from curtin import storage_config
from curtin.util import human2bytes
@ -158,7 +159,7 @@ raidlevels = [
def _raidlevels_by_value():
r = {l.value: l for l in raidlevels}
r = {level.value: level for level in raidlevels}
for n in 0, 1, 5, 6, 10:
r[str(n)] = r[n] = r["raid"+str(n)]
r["stripe"] = r["raid0"]
@ -391,7 +392,7 @@ def asdict(inst):
continue
m = getattr(inst, 'serialize_' + field.name, None)
if m:
r[field.name] = m()
r.update(m())
else:
v = getattr(inst, field.name)
if v is not None:
@ -968,7 +969,7 @@ class Partition(_Formattable):
return self._fs._available()
def serialize_number(self):
return self._number
return {'number': self._number}
@property
def _number(self):
@ -1021,7 +1022,7 @@ class Raid(_Device):
# Surprisingly, the order of devices passed to mdadm --create
# matters (see get_raid_size) so we sort devices here the same
# way get_raid_size does.
return [d.id for d in raid_device_sort(self.devices)]
return {'devices': [d.id for d in raid_device_sort(self.devices)]}
spare_devices = attributes.reflist(
backlink="_constructed_device", default=attr.Factory(set))
@ -1161,7 +1162,7 @@ class LVM_LogicalVolume(_Formattable):
preserve = attr.ib(default=False)
def serialize_size(self):
return "{}B".format(self.size)
return {'size': "{}B".format(self.size)}
def available(self):
if self._constructed_device is not None:
@ -1209,6 +1210,16 @@ class DM_Crypt:
volume = attributes.ref(backlink="_constructed_device") # _Formattable
key = attr.ib(metadata={'redact': True})
def serialize_key(self):
if self.key:
f = tempfile.NamedTemporaryFile(
prefix='luks-key-', mode='w', delete=False)
f.write(self.key)
f.close()
return {'keyfile': f.name}
else:
return {}
dm_name = attr.ib(default=None)
preserve = attr.ib(default=False)

View File

@ -135,7 +135,7 @@ class KeyboardSetting:
# Non-latin keyboard layouts that are handled in a uniform way
standard_non_latin_layouts = set(
('af', 'am', 'ara', 'ben', 'bd', 'bg', 'bt', 'by', 'et', 'ge',
'gh', 'gr', 'guj', 'guru', 'il', ''in'', 'iq', 'ir', 'iku', 'kan',
'gh', 'gr', 'guj', 'guru', 'il', 'in', 'iq', 'ir', 'iku', 'kan',
'kh', 'kz', 'la', 'lao', 'lk', 'kg', 'ma', 'mk', 'mm', 'mn', 'mv',
'mal', 'np', 'ori', 'pk', 'ru', 'scc', 'sy', 'syr', 'tel', 'th',
'tj', 'tam', 'tib', 'ua', 'ug', 'uz')

View File

@ -149,9 +149,10 @@ class SubiquityModel:
'mode': 'off',
},
'locale': self.locale.selected_language + '.UTF-8',
'preserve_hostname': True,
'resize_rootfs': False,
}
if self.identity.hostname is not None:
config['preserve_hostname'] = True
user = self.identity.user
if user:
users_and_groups_path = (

View File

@ -86,7 +86,7 @@ class GuidedChoiceForm(SubForm):
lvm_options = SubFormField(LVMOptionsForm, "", help=NO_HELP)
def __init__(self, parent):
super().__init__(parent)
super().__init__(parent, initial={'use_lvm': True})
options = []
tables = []
initial = -1

View File

@ -29,7 +29,6 @@ from subiquitycore.file_util import write_file
from subiquitycore.models.network import (
BondParameters,
NetDevAction,
sanitize_config,
)
from subiquitycore import netplan
from subiquitycore.ui.views.network import (
@ -342,7 +341,9 @@ class NetworkController(BaseController):
config = self.model.render_config()
log.debug("network config: \n%s",
yaml.dump(sanitize_config(config), default_flow_style=False))
yaml.dump(
netplan.sanitize_config(config),
default_flow_style=False))
for p in netplan.configs_in_root(self.root, masked=True):
if p == self.netplan_path:

View File

@ -13,7 +13,6 @@
# 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 copy
import enum
import ipaddress
import logging
@ -49,27 +48,6 @@ class NetDevAction(enum.Enum):
return pgettext(type(self).__name__, self.value)
def _sanitize_inteface_config(iface_config):
for ap, ap_config in iface_config.get('access-points', {}).items():
if 'password' in ap_config:
ap_config['password'] = '<REDACTED>'
def sanitize_interface_config(iface_config):
iface_config = copy.deepcopy(iface_config)
_sanitize_inteface_config(iface_config)
return iface_config
def sanitize_config(config):
"""Return a copy of config with passwords redacted."""
config = copy.deepcopy(config)
interfaces = config.get('network', {}).get('wifis', {}).items()
for iface, iface_config in interfaces:
_sanitize_inteface_config(iface_config)
return config
class BondParameters:
# Just a place to hang various data about how bonds can be
# configured.
@ -176,6 +154,21 @@ class NetworkDev(object):
def supports_action(self, action):
return getattr(self, "_supports_" + action.name)
@property
def configured_ssid(self):
for ssid, settings in self.config.get('access-points', {}).items():
psk = settings.get('password')
return ssid, psk
return None, None
def set_ssid_psk(self, ssid, psk):
aps = self.config.setdefault('access-points', {})
aps.clear()
if ssid is not None:
aps[ssid] = {}
if psk is not None:
aps[ssid]['password'] = psk
@property
def ifindex(self):
if self.info is not None:
@ -298,7 +291,7 @@ class NetworkModel(object):
dev.config = config
log.debug("new_link %s %s with config %s",
ifindex, link.name,
sanitize_interface_config(dev.config))
netplan.sanitize_interface_config(dev.config))
self.devices_by_name[link.name] = dev
return dev

View File

@ -8,6 +8,27 @@ import yaml
log = logging.getLogger("subiquitycore.netplan")
def _sanitize_inteface_config(iface_config):
for ap, ap_config in iface_config.get('access-points', {}).items():
if 'password' in ap_config:
ap_config['password'] = '<REDACTED>'
def sanitize_interface_config(iface_config):
iface_config = copy.deepcopy(iface_config)
_sanitize_inteface_config(iface_config)
return iface_config
def sanitize_config(config):
"""Return a copy of config with passwords redacted."""
config = copy.deepcopy(config)
interfaces = config.get('network', {}).get('wifis', {}).items()
for iface, iface_config in interfaces:
_sanitize_inteface_config(iface_config)
return config
class Config:
"""A NetplanConfig represents the network config for a system.
@ -85,7 +106,9 @@ class _PhysicalDevice:
self.match_mac = match.get('macaddress')
self.match_driver = match.get('driver')
self.config = config
log.debug("config for %s = %s" % (name, self.config))
log.debug(
"config for %s = %s" % (
name, sanitize_interface_config(self.config)))
def matches_link(self, link):
if self.match_name is not None:
@ -107,7 +130,9 @@ class _VirtualDevice:
def __init__(self, name, config):
self.name = name
self.config = config
log.debug("config for %s = %s" % (name, self.config))
log.debug(
"config for %s = %s" % (
name, sanitize_interface_config(self.config)))
def configs_in_root(root, masked=False):

View File

@ -84,10 +84,10 @@ def get_ips_standalone():
prober.probe_network()
links = prober.get_results()['network']['links']
ips = []
for l in sorted(links, key=lambda l: l['netlink_data']['name']):
if l['type'] in NETDEV_IGNORED_IFACE_TYPES:
for link in sorted(links, key=lambda link: link['netlink_data']['name']):
if link['type'] in NETDEV_IGNORED_IFACE_TYPES:
continue
for addr in l['addresses']:
for addr in link['addresses']:
if addr['scope'] == "global":
ips.append(addr['address'].split('/')[0])
return ips

View File

@ -555,6 +555,6 @@ class SubFormField(FormField):
class SubForm(Form):
def __init__(self, parent):
def __init__(self, parent, **kw):
self.parent = parent
super().__init__()
super().__init__(**kw)

View File

@ -74,10 +74,11 @@ class NetworkConfigureWLANStretchy(Stretchy):
connect_signal(self.form, 'submit', self.done)
connect_signal(self.form, 'cancel', self.cancel)
if self.device.configured_ssid is not None:
self.form.ssid.value = self.device.configured_ssid
if self.device.configured_wifi_psk is not None:
self.form.psk.value = self.device.configured_wifi_psk
ssid, psk = self.device.configured_ssid
if ssid:
self.form.ssid.value = ssid
if psk:
self.form.psk.value = psk
self.ssid_row = self.form.ssid._table
self.psk_row = self.form.psk._table
@ -95,7 +96,8 @@ class NetworkConfigureWLANStretchy(Stretchy):
def show_ssid_list(self, sender):
self.parent.show_overlay(
NetworkList(self, self.device.actual_ssids), width=60)
NetworkList(
self, self.device.info.wlan['visible_ssids']), width=60)
def start_scan(self, sender):
fp = self.inputs.focus_position - 1
@ -109,13 +111,13 @@ class NetworkConfigureWLANStretchy(Stretchy):
self.error.set_text("%s" % (r,))
def _build_iface_inputs(self):
if len(self.device.actual_ssids) > 0:
if len(self.device.info.wlan['visible_ssids']) > 0:
networks_btn = menu_btn("Choose a visible network",
on_press=self.show_ssid_list)
else:
networks_btn = disabled(menu_btn("No visible networks"))
if not self.device.scan_state:
if not self.device.info.wlan['scan_state']:
scan_btn = menu_btn("Scan for networks", on_press=self.start_scan)
else:
scan_btn = disabled(menu_btn("Scanning for networks"))
@ -146,7 +148,7 @@ class NetworkConfigureWLANStretchy(Stretchy):
for obj in self._build_iface_inputs()]
def done(self, sender):
if self.device.configured_ssid is None and self.form.ssid.value:
if self.device.configured_ssid[0] is None and self.form.ssid.value:
# Turn DHCP4 on by default when specifying an SSID for
# the first time...
self.device.dhcp4 = True