Merge branch 'master' into still-better-i18n
This commit is contained in:
commit
7bcfcba99b
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -161,6 +161,7 @@ class FilesystemController(SubiquityController):
|
|||
"block probing failed restricted=%s", restricted)
|
||||
report = self.app.make_apport_report(
|
||||
kind, "block probing", interrupt=False)
|
||||
if report is not None:
|
||||
self._crash_reports[restricted] = report
|
||||
continue
|
||||
break
|
||||
|
|
|
@ -153,6 +153,7 @@ class InstallProgressController(SubiquityController):
|
|||
self.progress_view.set_status(('info_error',
|
||||
_("An error has occurred")))
|
||||
self.start_ui()
|
||||
if crash_report is not None:
|
||||
self.progress_view.show_error(crash_report)
|
||||
|
||||
def logged_command(self, cmd):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -274,6 +274,7 @@ class Subiquity(Application):
|
|||
report = self.make_apport_report(
|
||||
ErrorReportKind.UI, "Installer UI", interrupt=False,
|
||||
wait=True)
|
||||
if report is not None:
|
||||
print("report saved to {path}".format(report.path))
|
||||
except Exception:
|
||||
print("report generation failed")
|
||||
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue