Merge pull request #205 from CanonicalLtd/mwhudson/do-something-with-network-config
actually use the network config the user enters
This commit is contained in:
commit
ea96a72e9b
|
@ -67,12 +67,12 @@ done
|
||||||
# Create menuentry for installer
|
# Create menuentry for installer
|
||||||
menuentry "Boot Installer - Graphical Console" {
|
menuentry "Boot Installer - Graphical Console" {
|
||||||
set root=(hd0,msdos2)
|
set root=(hd0,msdos2)
|
||||||
linux /vmlinuz ro root=LABEL=cloudimg-rootfs overlayroot=device:dev=LABEL=overlay-rootfs net.ifnames=0 console=ttyS0 console=tty0 quiet splash
|
linux /vmlinuz ro root=LABEL=cloudimg-rootfs overlayroot=device:dev=LABEL=overlay-rootfs console=ttyS0 console=tty0 quiet splash
|
||||||
initrd /initrd.img
|
initrd /initrd.img
|
||||||
}
|
}
|
||||||
menuentry "Boot Installer - Serial Console" {
|
menuentry "Boot Installer - Serial Console" {
|
||||||
set root=(hd0,msdos2)
|
set root=(hd0,msdos2)
|
||||||
linux /vmlinuz ro root=LABEL=cloudimg-rootfs overlayroot=device:dev=LABEL=overlay-rootfs net.ifnames=0 console=tty0 console=ttyS0
|
linux /vmlinuz ro root=LABEL=cloudimg-rootfs overlayroot=device:dev=LABEL=overlay-rootfs console=tty0 console=ttyS0
|
||||||
initrd /initrd.img
|
initrd /initrd.img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import fcntl
|
import fcntl
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
from subiquitycore import utils
|
from subiquitycore import utils
|
||||||
from subiquitycore.controller import BaseController
|
from subiquitycore.controller import BaseController
|
||||||
|
@ -23,7 +24,8 @@ from subiquitycore.controller import BaseController
|
||||||
from subiquity.curtin import (CURTIN_CONFIGS,
|
from subiquity.curtin import (CURTIN_CONFIGS,
|
||||||
CURTIN_INSTALL_LOG,
|
CURTIN_INSTALL_LOG,
|
||||||
CURTIN_POSTINSTALL_LOG,
|
CURTIN_POSTINSTALL_LOG,
|
||||||
curtin_install_cmd)
|
curtin_install_cmd,
|
||||||
|
curtin_write_network_config)
|
||||||
from subiquity.models import InstallProgressModel
|
from subiquity.models import InstallProgressModel
|
||||||
from subiquity.ui.views import ProgressView
|
from subiquity.ui.views import ProgressView
|
||||||
|
|
||||||
|
@ -39,12 +41,12 @@ class InstallState:
|
||||||
DONE_POSTINSTALL = 4
|
DONE_POSTINSTALL = 4
|
||||||
ERROR = -1
|
ERROR = -1
|
||||||
|
|
||||||
|
|
||||||
class InstallProgressController(BaseController):
|
class InstallProgressController(BaseController):
|
||||||
signals = [
|
signals = [
|
||||||
('installprogress:curtin-install', 'curtin_start_install'),
|
('installprogress:curtin-install', 'curtin_start_install'),
|
||||||
('installprogress:wrote-install', 'curtin_wrote_install'),
|
('installprogress:wrote-install', 'curtin_wrote_install'),
|
||||||
('installprogress:wrote-postinstall', 'curtin_wrote_postinstall'),
|
('installprogress:wrote-postinstall', 'curtin_wrote_postinstall'),
|
||||||
|
('network-config-written', 'curtin_wrote_network_config'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, common):
|
def __init__(self, common):
|
||||||
|
@ -55,6 +57,9 @@ class InstallProgressController(BaseController):
|
||||||
self.postinstall_written = False
|
self.postinstall_written = False
|
||||||
self.tail_proc = None
|
self.tail_proc = None
|
||||||
|
|
||||||
|
def curtin_wrote_network_config(self, path):
|
||||||
|
curtin_write_network_config(open(path).read())
|
||||||
|
|
||||||
def curtin_wrote_install(self):
|
def curtin_wrote_install(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -85,7 +90,8 @@ class InstallProgressController(BaseController):
|
||||||
"{ i=0;while [ $i -le 25 ];do i=$((i+1)); echo install line $i; sleep 1; done; } > %s 2>&1"%CURTIN_INSTALL_LOG]
|
"{ i=0;while [ $i -le 25 ];do i=$((i+1)); echo install line $i; sleep 1; done; } > %s 2>&1"%CURTIN_INSTALL_LOG]
|
||||||
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_CONFIGS['network']]
|
||||||
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))
|
||||||
|
|
|
@ -139,37 +139,35 @@ def setup_yaml():
|
||||||
yaml.add_representer(OrderedDict, represent_dict_order)
|
yaml.add_representer(OrderedDict, represent_dict_order)
|
||||||
setup_yaml()
|
setup_yaml()
|
||||||
|
|
||||||
def curtin_write_network_actions(actions):
|
def curtin_write_network_config(netplan_config):
|
||||||
curtin_config = yaml.dump(actions, default_flow_style=False)
|
# As soon as curtin and cloud-init support v2 network config
|
||||||
curtin_config = " " + "\n ".join(curtin_config.splitlines())
|
# (RSN!) we can just pass this sensibly to curtin. But for now,
|
||||||
datestr = '# Autogenerated by SUbiquity: {} UTC'.format(
|
# just use write_files to install the config and make sure curtin
|
||||||
|
# and cloud-init doesn't do any networking stuff of their own
|
||||||
|
# accord.
|
||||||
|
curtin_conf = {
|
||||||
|
'write_files': {
|
||||||
|
'netplan': {
|
||||||
|
'path': 'etc/netplan/00-installer.yaml',
|
||||||
|
'content': netplan_config,
|
||||||
|
'permissions': '0600',
|
||||||
|
},
|
||||||
|
'nonet': {
|
||||||
|
'path': 'etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg',
|
||||||
|
'content': 'network: {config: disabled}\n',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'network_commands': {'builtin': []},
|
||||||
|
}
|
||||||
|
curtin_config = yaml.dump(curtin_conf, default_flow_style=False)
|
||||||
|
datestr = '# Autogenerated by SUbiquity: {} UTC\n'.format(
|
||||||
str(datetime.datetime.utcnow()))
|
str(datetime.datetime.utcnow()))
|
||||||
with open(CURTIN_NETWORK_CONFIG_FILE, 'w') as conf:
|
with open(CURTIN_NETWORK_CONFIG_FILE, 'w') as conf:
|
||||||
conf.write(datestr)
|
conf.write(datestr)
|
||||||
conf.write(CURTIN_CONFIG_HEADER + CURTIN_NETWORK_CONFIG_HEADER)
|
|
||||||
conf.write(curtin_config)
|
conf.write(curtin_config)
|
||||||
conf.close()
|
conf.close()
|
||||||
|
|
||||||
|
|
||||||
def curtin_apply_networking(actions, dryrun=True):
|
|
||||||
log.info('Applying network actions:\n%s', actions)
|
|
||||||
network_commands = []
|
|
||||||
for entry in actions:
|
|
||||||
if entry['type'] == 'physical':
|
|
||||||
for subnet in entry.get('subnets', []):
|
|
||||||
if subnet['type'] == 'static':
|
|
||||||
cmd = "ifconfig %s %s" % (entry['name'], subnet['address'])
|
|
||||||
if 'netmask' in subnet:
|
|
||||||
cmd += " netmask %s" % subnet['netmask']
|
|
||||||
cmd += " up"
|
|
||||||
network_commands += [cmd]
|
|
||||||
|
|
||||||
for cmd in network_commands:
|
|
||||||
log.info('Running command: [%s]', cmd)
|
|
||||||
if not dryrun:
|
|
||||||
utils.run_command(cmd.split(), shell=False)
|
|
||||||
|
|
||||||
|
|
||||||
def curtin_write_preserved_actions(actions):
|
def curtin_write_preserved_actions(actions):
|
||||||
''' caller must use models.actions.preserve_action on
|
''' caller must use models.actions.preserve_action on
|
||||||
all elements of the actions'''
|
all elements of the actions'''
|
||||||
|
|
|
@ -17,7 +17,6 @@ import copy
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import queue
|
|
||||||
import random
|
import random
|
||||||
import select
|
import select
|
||||||
import socket
|
import socket
|
||||||
|
@ -213,8 +212,6 @@ class TaskSequence:
|
||||||
self.watcher.task_error(self.stage, info)
|
self.watcher.task_error(self.stage, info)
|
||||||
|
|
||||||
|
|
||||||
netplan_config_file_name = '00-snapd-config.yaml'
|
|
||||||
|
|
||||||
def sanitize_config(config):
|
def sanitize_config(config):
|
||||||
"""Return a copy of config with passwords redacted."""
|
"""Return a copy of config with passwords redacted."""
|
||||||
config = copy.deepcopy(config)
|
config = copy.deepcopy(config)
|
||||||
|
@ -321,12 +318,15 @@ class NetworkController(BaseController):
|
||||||
def __init__(self, common):
|
def __init__(self, common):
|
||||||
super().__init__(common)
|
super().__init__(common)
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
import atexit, shutil, tempfile
|
self.root = os.path.abspath(".subiquity")
|
||||||
self.root = tempfile.mkdtemp()
|
|
||||||
self.tried_once = False
|
self.tried_once = False
|
||||||
atexit.register(shutil.rmtree, self.root)
|
netplan_path = self.netplan_path
|
||||||
os.makedirs(os.path.join(self.root, 'etc/netplan'))
|
netplan_dir = os.path.dirname(netplan_path)
|
||||||
with open(os.path.join(self.root, 'etc/netplan', netplan_config_file_name), 'w') as fp:
|
if os.path.exists(netplan_dir):
|
||||||
|
import shutil
|
||||||
|
shutil.rmtree(netplan_dir)
|
||||||
|
os.makedirs(netplan_dir)
|
||||||
|
with open(netplan_path, 'w') as fp:
|
||||||
fp.write(default_netplan)
|
fp.write(default_netplan)
|
||||||
self.model = NetworkModel(self.root)
|
self.model = NetworkModel(self.root)
|
||||||
|
|
||||||
|
@ -357,10 +357,18 @@ class NetworkController(BaseController):
|
||||||
self.ui.set_footer(footer, 20)
|
self.ui.set_footer(footer, 20)
|
||||||
self.ui.set_body(NetworkView(self.model, self))
|
self.ui.set_body(NetworkView(self.model, self))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def netplan_path(self):
|
||||||
|
if self.opts.project == "subiquity":
|
||||||
|
netplan_config_file_name = '00-installer-config.yaml'
|
||||||
|
else:
|
||||||
|
netplan_config_file_name = '00-snapd-config.yaml'
|
||||||
|
return os.path.join(self.root, 'etc/netplan', netplan_config_file_name)
|
||||||
|
|
||||||
def network_finish(self, config):
|
def network_finish(self, config):
|
||||||
log.debug("network config: \n%s", yaml.dump(sanitize_config(config), default_flow_style=False))
|
log.debug("network config: \n%s", yaml.dump(sanitize_config(config), default_flow_style=False))
|
||||||
|
|
||||||
netplan_path = os.path.join(self.root, 'etc/netplan', netplan_config_file_name)
|
netplan_path = self.netplan_path
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
tmppath = '%s.%s' % (netplan_path, random.randrange(0, 1000))
|
tmppath = '%s.%s' % (netplan_path, random.randrange(0, 1000))
|
||||||
|
@ -371,7 +379,7 @@ class NetworkController(BaseController):
|
||||||
break
|
break
|
||||||
w = os.fdopen(fd, 'w')
|
w = os.fdopen(fd, 'w')
|
||||||
with w:
|
with w:
|
||||||
w.write("# This is the network config written by 'console-conf'\n")
|
w.write("# This is the network config written by '{}'\n".format(self.opts.project))
|
||||||
w.write(yaml.dump(config))
|
w.write(yaml.dump(config))
|
||||||
os.rename(tmppath, netplan_path)
|
os.rename(tmppath, netplan_path)
|
||||||
self.model.parse_netplan_configs()
|
self.model.parse_netplan_configs()
|
||||||
|
@ -413,9 +421,9 @@ class NetworkController(BaseController):
|
||||||
self.ui.frame.body.show_network_error(stage, info)
|
self.ui.frame.body.show_network_error(stage, info)
|
||||||
|
|
||||||
def tasks_finished(self):
|
def tasks_finished(self):
|
||||||
|
self.signal.emit_signal('network-config-written', self.netplan_path)
|
||||||
self.signal.emit_signal('next-screen')
|
self.signal.emit_signal('next-screen')
|
||||||
|
|
||||||
|
|
||||||
@view
|
@view
|
||||||
def set_default_v4_route(self):
|
def set_default_v4_route(self):
|
||||||
self.ui.set_header("Default route")
|
self.ui.set_header("Default route")
|
||||||
|
|
|
@ -56,6 +56,8 @@ class Application:
|
||||||
log.exception(err)
|
log.exception(err)
|
||||||
raise ApplicationError(err)
|
raise ApplicationError(err)
|
||||||
|
|
||||||
|
opts.project = self.project
|
||||||
|
|
||||||
self.common = {
|
self.common = {
|
||||||
"ui": ui,
|
"ui": ui,
|
||||||
"opts": opts,
|
"opts": opts,
|
||||||
|
|
Loading…
Reference in New Issue