Update nspawn hosts

Use the common roles throught this role to remove all of the boilerplate
code we had. The common modules do most of the heavy lifing.

Update to fix the resolve.conf issue with the image cache prep.

Add legacy image support and use smaller upstream images by default.

Now that suse supports systemd-networkd we can enable suse support in
nspawn.

Change-Id: I5f6ceb928f5c0902adf2e34f96a5998840400777
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
Kevin Carter 2018-03-03 00:40:28 -06:00
parent 8254e5e2b3
commit 50d7cc82c5
No known key found for this signature in database
GPG Key ID: 9443251A787B9FB3
26 changed files with 537 additions and 352 deletions

View File

@ -58,3 +58,9 @@ nspawn_container_base_name: "{{ nspawn_cache_map.distro }}-{{ nspawn_cache_map.r
nspawn_container_cache_files_from_host: []
container_networks: {}
# URL to image tarball
nspawn_hosts_container_image_url: "{{ _nspawn_hosts_container_image_url | default(null) }}"
# Enable or disable the legacy image download system.
nspawn_hosts_container_image_download_legacy: "{{ _nspawn_hosts_container_image_download_legacy | default(false) }}"

View File

@ -0,0 +1,120 @@
#!/usr/bin/env python
# Copyright 2017, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
try:
import httplib
except ImportError:
import http.client as httplib
import ssl
try:
import urlparse
except ImportError:
import urllib.parse as urlparse
import sys
__DOC__ = """
USAGE:
This script will take arguments passed into it to discover the url
of a given container image using the distro, release, architecture,
and variant as the parameters.
EXAMPLE:
# python lxc-image-fetch-url ubuntu xenial amd64 default
"""
LXC_CACHE_SERVER = 'https://us.images.linuxcontainers.org'
LXC_INDEX = '{0}/meta/1.0/index-system'.format(LXC_CACHE_SERVER)
def get_image_url(url, depth=0):
if depth > 10:
raise SystemExit('Too many redirects')
url_path = urlparse.urlparse(url, allow_fragments=True)
if url_path.scheme == 'https':
conn = httplib.HTTPSConnection(
host=url_path.netloc,
context=ssl._create_unverified_context()
)
else:
conn = httplib.HTTPConnection(host=url_path.netloc)
try:
conn.request('GET', url_path.path)
except httplib.BadStatusLine:
raise SystemExit('Connection Failure')
else:
resp = conn.getresponse()
headers = dict(resp.getheaders())
check_redirect = headers.get('location', None)
if not check_redirect:
check_redirect = headers.get('Location', None)
if check_redirect:
depth += 1
return get_image_url(
url=check_redirect,
depth=depth
)
else:
return (
str(url),
resp.read().decode('UTF-8').splitlines()
)
finally:
conn.close()
def main():
try:
distro = sys.argv[1]
release = sys.argv[2]
arch = sys.argv[3]
variant = sys.argv[4]
except IndexError:
print('Missing argument, Please see the documentation.')
raise SystemExit(__DOC__)
_, meta = get_image_url(url=LXC_INDEX, depth=0)
image_hint = '{0};{1};{2};{3}'.format(
distro,
release,
arch,
variant
)
images = sorted([i for i in meta if i.strip().startswith(image_hint)])
if not images:
print(__DOC__ + '\nAvailable options:')
for line in meta:
print(';'.join(line.split(';')[:-2]))
raise SystemExit(
'No Image found with image hint "{0}"'.format(image_hint)
)
container_url = urlparse.urljoin(
urlparse.urljoin(
LXC_CACHE_SERVER,
images[0].split(';')[-1]
),
'rootfs.tar.xz'
)
print(container_url)
if __name__ == '__main__':
main()

View File

@ -1,23 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Virtual Machine and Container Registration Service
Documentation=man:systemd-machined.service(8)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/machined
Wants=machine.slice
After=machine.slice
[Service]
ExecStart=/lib/systemd/systemd-machined
BusName=org.freedesktop.machine1
CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID
WatchdogSec=3min
# Note that machined cannot be placed in a mount namespace, since it
# needs access to the host's mount namespace in order to implement the
# "machinectl bind" operation.

View File

@ -1,16 +0,0 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Virtual Machine and Container Storage
ConditionPathExists=/var/lib/machines.raw
[Mount]
What=/var/lib/machines.raw
Where=/var/lib/machines
Type=btrfs
Options=loop

View File

@ -13,29 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
- name: Restart networkd
service:
name: systemd-networkd
state: restarted
enabled: true
- name: Reload systemd units
systemd:
name: it_does_not_matter
daemon_reload: true
- name: Restart machined
systemd:
name: "systemd-machined.service"
state: "restarted"
enabled: true
- name: Restart machines mount
systemd:
name: "var-lib-machines.mount"
state: "restarted"
enabled: true
- name: Disable host dnsmasq service
systemd:
name: "dnsmasq.service"
@ -46,16 +23,9 @@
- name: Remove rootfs archive
file:
path: "/tmp/rootfs.tar.xz"
path: "/tmp/{{ cache_basename }}"
state: "absent"
- name: Enable macvlan service
systemd:
name: "nspawn-macvlan.service"
state: "restarted"
enabled: true
daemon_reload: true
- name: Enable network dnsmasq service
systemd:
name: "dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.service"
@ -77,7 +47,12 @@
changed_when: false
- name: Restart systemd-journald
service:
name: systemd-journald
systemd:
name: "systemd-journald"
state: restarted
enabled: yes
daemon_reload: true
- name: Reload systemd-daemon
systemd:
daemon_reload: true

View File

@ -13,15 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# NOTE(cloudnull): At this time the nspawn implementation does not support suse.
# When we can use networkd on suse this should be revised.
- name: Check if os is suse
fail:
msg: >-
At this time the nspawn implementation does not support suse.
when:
- ansible_pkg_mgr == 'zypper'
- name: Pull systemd version
command: "systemctl --version"
changed_when: false
@ -66,7 +57,6 @@
delay: 2
notify:
- Disable host dnsmasq service
- Restart networkd
- name: Move nspawn-attach into place
copy:
@ -123,5 +113,3 @@
- include: nspawn_networking.yml
- include: nspawn_cache.yml
- include: nspawn_networking.yml

View File

@ -40,7 +40,7 @@
- name: Place container rootfs
unarchive:
src: "/tmp/rootfs.tar.xz"
src: "/tmp/{{ cache_basename }}"
dest: "/var/lib/machines/{{ nspawn_container_base_name }}"
remote_src: True
notify:
@ -53,16 +53,12 @@
src: "prep-scripts/nspawn_{{ nspawn_cache_map.distro }}_prep.sh.j2"
dest: "/var/lib/machines/{{ nspawn_container_base_name }}/usr/local/bin/cache-prep-commands.sh"
mode: "0755"
when:
- nspawn_image_cache_refresh | bool
# This task runs several commands against the cached image to speed up the
# nspawn_container_create playbook.
- name: Prepare cached image setup commands
shell: "chroot /var/lib/machines/{{ nspawn_container_base_name }} /usr/local/bin/cache-prep-commands.sh > /var/log/nspawn-cache-prep-commands.log 2>&1"
changed_when: false
when:
- nspawn_image_cache_refresh | bool
- name: Sync files from the host into the container cache
shell: |
@ -86,8 +82,7 @@
state: directory
- name: Create static MACs in the container
template:
src: "templates/systemd-nspawn-default.link.j2"
copy:
src: "/etc/systemd/network/99-default.link"
dest: "/var/lib/machines/{{ nspawn_container_base_name }}/etc/systemd/network/99-default.link"
notify:
- Restart networkd
remote_src: true

View File

@ -25,74 +25,47 @@
when:
- cache_check.rc != 0
- name: Set nspawn cache path fact
- name: Legacy image url fetch
block:
- name: Create legacy image URL fetch
copy:
src: "lxc-image-fetch-url.py"
dest: "/usr/local/bin/lxc-image-fetch-url"
owner: "root"
group: "root"
mode: "0755"
- name: Fetch legacy container image url
command: "/usr/local/bin/lxc-image-fetch-url {{ nspawn_cache_map.distro }} {{ nspawn_cache_map.release }} {{ nspawn_cache_map.arch }} {{ nspawn_cache_default_variant }}"
register: legacy_image_url
retries: 3
delay: 1
until: legacy_image_url | success
- name: Set nspawn cache fact(s) (legacy)
set_fact:
nspawn_hosts_container_image_url: "{{ legacy_image_url.stdout.strip() }}"
when:
- nspawn_hosts_container_image_download_legacy | bool
- name: Set nspawn cache basename
set_fact:
cache_index_item: "{{ nspawn_cache_map.distro }};{{ nspawn_cache_map.release }};{{ nspawn_cache_map.arch }};{{ nspawn_cache_default_variant }};"
cache_time: "{{ ansible_date_time.epoch }}"
when:
- nspawn_image_cache_refresh | bool
cache_basename: "{{ nspawn_hosts_container_image_url | basename }}"
- name: Fetch nspawn image-index
shell: >
aria2c
--max-connection-per-server=4
--allow-overwrite=true
--dir=/tmp
--out=index-system
--check-certificate={{ (nspawn_hosts_validate_certs | bool) | lower }}
{% for server in nspawn_image_cache_server_mirrors %}{{ server }}/meta/1.0/index-system {% endfor %}
args:
warn: no
when:
- nspawn_image_cache_refresh | bool
tags:
- skip_ansible_lint
- name: Retrieve the index
slurp:
src: "/tmp/index-system"
changed_when: false
register: image_index
when:
- nspawn_image_cache_refresh | bool
# Example index lines:
# ubuntu;xenial;amd64;default;20180123_08:05;/images/ubuntu/xenial/amd64/default/20180123_08:05/
# As there may be multiple images, and they use a timestamp, we can sort
# the resulting list in reverse order and use the first item in the list
# as it will be the latest available.
- name: Set image index fact
set_fact:
nspawn_images: >
{%- set images = [] %}
{%- for image in (image_index.content | b64decode).splitlines() %}
{%- if image | match("^" + cache_index_item) %}
{%- set _ = images.append(image) %}
{%- endif %}
{%- endfor %}
{{- images | sort(reverse=True) -}}
when:
- nspawn_image_cache_refresh | bool
# We only want to download a single image, rather than downloading
# each of them in turn and they overwrite each other as they all
# download to the same file name and path.
- name: Pre-stage the nspawn image on the system
shell: >
aria2c
--max-connection-per-server=4
--allow-overwrite=true
--dir=/tmp
--out=rootfs.tar.xz
--out={{ cache_basename }}
--check-certificate={{ (nspawn_hosts_validate_certs | bool) | lower }}
{% for server in nspawn_image_cache_server_mirrors %}{{ server }}{{ nspawn_images[0].split(';')[-1] }}rootfs.tar.xz {% endfor %}
{{ nspawn_hosts_container_image_url }}
> /var/log/aria2c-image-prestage.log 2>&1
args:
warn: no
register: prestage_image
async: 300
poll: 0
when:
- nspawn_image_cache_refresh | bool
tags:
- skip_ansible_lint

View File

@ -38,40 +38,107 @@
when:
- (deployment_environment_variables | default({})).keys() | length > 0
- name: Create static MACs on the host
- name: Load override systemd-nspawn@
template:
src: "templates/systemd-nspawn-default.link.j2"
dest: /etc/systemd/network/99-default.link
src: systemd-nspawn@.service.j2
dest: /etc/systemd/system/systemd-nspawn@.service
notify:
- Restart networkd
- Reload systemd-daemon
- name: Create MACVLAN net device(s)
template:
src: "templates/systemd-nspawn-mv.netdev.j2"
dest: "/etc/systemd/network/{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.netdev"
with_dict: "{{ container_networks | combine(nspawn_networks) }}"
notify:
- Restart networkd
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_user_name: "root"
systemd_group_name: "root"
systemd_tempd_prefix: machine
systemd_slice_name: machine
system_lock_path: /var/lock/machine
systemd_services:
- service_name: "nspawn-macvlan"
program_sandboxing:
PrivateTmp: True
PrivateDevices: True
config_overrides:
Unit:
Description: nspawn host macvlan integrations
After: network-online.target
Wants: network-online.target
Service:
RemainAfterExit: yes
service_type: oneshot
execstarts: |-
{%- set start_commands = [] %}
{%- set seen_start_interfaces = [] %}
{%- for key, value in (container_networks | combine(nspawn_networks)).items() %}
{%- set interface = value.bridge.split('br-')[-1] %}
{%- set mv_interface = 'mv-' + interface %}
{%- if value.bridge not in seen_start_interfaces %}
{%- if value.private_device | default(false) | bool %}
{%- set _ = start_commands.append('-/sbin/ip link add dev ' + value.bridge + ' type dummy') %}
{%- set _ = start_commands.append('-/sbin/ip link set dev ' + value.bridge + ' up') %}
{%- endif %}
{%- set interface_from_ansible = 'ansible_' + value.bridge | replace('-', '_') %}
{%- set interface_data = hostvars[inventory_hostname][interface_from_ansible] | default({'type': none}) %}
{%- if interface_data['type'] == 'bridge' %}
{%- set _ = start_commands.append('-/sbin/ip link add dev veth-' + interface + '1 type veth peer name veth-' + interface + '2') %}
{%- set _ = start_commands.append('-/sbin/ip link set dev veth-' + interface + '1 up') %}
{%- set _ = start_commands.append('-/sbin/ip link set dev veth-' + interface + '1 mtu ' + (interface_data['mtu'] | default(1500)) | string) %}
{%- set _ = start_commands.append('-/sbin/ip link set dev veth-' + interface + '2 up') %}
{%- set _ = start_commands.append('-/sbin/ip link set dev veth-' + interface + '2 mtu ' + (interface_data['mtu'] | default(1500)) | string) %}
{%- set _ = start_commands.append('-/sbin/ip link set dev veth-' + interface + '1 master ' + value.bridge) %}
{%- set _ = start_commands.append('-/sbin/ip link add ' + mv_interface + ' link veth-' + interface + '2 type macvlan mode ' + value.macvlan_mode | default(nspawn_macvlan_mode)) %}
{%- else %}
{%- set _ = start_commands.append('-/sbin/ip link add ' + mv_interface + ' link ' + value.bridge + ' type macvlan mode ' + value.macvlan_mode | default(nspawn_macvlan_mode)) %}
{%- endif %}
{%- set _ = seen_start_interfaces.append(value.bridge) %}
{%- endif %}
{%- endfor %}
{{ start_commands }}
enabled: yes
state: started
tags:
- network-config
- name: Create MACVLAN network(s)
template:
src: "templates/systemd-nspawn-mv.network.j2"
dest: "/etc/systemd/network/{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.network"
with_dict: "{{ container_networks | combine(nspawn_networks) }}"
notify:
- Restart networkd
- name: Create macvlan service
template:
src: "nspawn-macvlan-systemd-init.j2"
dest: "/etc/systemd/system/nspawn-macvlan.service"
notify:
- Enable macvlan service
- name: Create systemd-nspawn@ service
template:
src: "systemd-nspawn@.service.j2"
dest: "/lib/systemd/system/systemd-nspawn@.service"
- name: Run the systemd-networkd role
include_role:
name: systemd_networkd
private: true
vars:
systemd_run_networkd: true
systemd_interface_cleanup: false
systemd_netdevs: |-
{% set _netdevs = [] %}
{% for _, value in (container_networks | combine(nspawn_networks)).items() %}
{% set _netdev = {'NetDev': {'Name': value.interface | default('mv-' + value.bridge.split('br-')[-1]), 'Kind': 'macvlan'}, 'MACVLAN': {'Mode': 'bridge'}} %}
{% set _ = _netdevs.append(_netdev) %}
{% endfor %}
{{ _netdevs }}
systemd_networks: |-
{% set _networks = [] %}
{% for _, value in (container_networks | combine(nspawn_networks)).items() %}
{% set _network = {'interface': value.interface | default('mv-' + value.bridge.split('br-')[-1])} %}
{% if value.address is defined %}
{% set _ = _network.__setitem__('address', value.address) %}
{% if (value.netmask is defined) and (_network.address != 'dhcp') %}
{% set _ = _network.__setitem__('netmask', value.netmask) %}
{% set prefix = (value.address + '/' + value.netmask) | ipaddr('prefix') %}
{% set _ = _network.__setitem__('address', [value.address + '/' + prefix | string]) %}
{% endif %}
{% endif %}
{% set _ = _network.__setitem__('usedns', (value.usedns | default(true) | bool) | ternary('yes', 'no')) %}
{% set _ = _network.__setitem__('static_routes', value.static_routes | default([])) %}
{% if value.gateway is defined %}
{% set _ = _network.__setitem__('gateway', value.gateway) %}
{% endif %}
{% set _ = _network.__setitem__('mtu', value.mtu | default(1500 | string)) %}
{% set _ = _network.__setitem__('config_overrides', {'Network': {'IPForward': 'yes', 'IPMasquerade': 'yes'}, 'Link': {'ARP': 'yes'}}) %}
{% set _ = _networks.append(_network) %}
{% endfor %}
{{ _networks }}
tags:
- network-config
- name: Create dnsmasq config(s)
template:
@ -83,12 +150,49 @@
notify:
- Enable network dnsmasq service
- name: Create dnsmasq systemd config(s)
template:
src: "nspawn-dnsmasq-systemd-init.j2"
dest: "/etc/systemd/system/dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.service"
with_dict: "{{ container_networks | combine(nspawn_networks) }}"
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_user_name: "root"
systemd_group_name: "root"
systemd_tempd_prefix: machine
systemd_slice_name: machine
system_lock_path: /var/lock/machine
systemd_CPUAccounting: true
systemd_BlockIOAccounting: true
systemd_MemoryAccounting: true
systemd_TasksAccounting: true
systemd_services:
- service_name: "dnsmasq-{{ 'mv-' + dnsmasq_var.value.bridge.split('br-')[-1] }}"
program_sandboxing:
PrivateTmp: True
PrivateDevices: True
config_overrides:
Unit:
Description: networking-post-up
After:
? network-online.target
? nspawn-macvlan.service
Wants: network-online.target
Service:
RemainAfterExit: yes
ExecStartPre: "-/sbin/iptables -t nat -A POSTROUTING -s {{ dnsmasq_var.value.address }}/{{ (dnsmasq_var.value.address | string + '/' + dnsmasq_var.value.netmask | string) | ipaddr('prefix') }} ! -d {{ dnsmasq_var.value.address }}/{{ (dnsmasq_var.value.address | string + '/' + dnsmasq_var.value.netmask | string) | ipaddr('prefix') }} -j MASQUERADE"
ExecStopPost: "-/sbin/iptables -t nat -D POSTROUTING -s {{ dnsmasq_var.value.address }}/{{ (dnsmasq_var.value.address | string + '/' + dnsmasq_var.value.netmask | string) | ipaddr('prefix') }} ! -d {{ dnsmasq_var.value.address }}/{{ (dnsmasq_var.value.address | string + '/' + dnsmasq_var.value.netmask | string) | ipaddr('prefix') }} -j MASQUERADE"
PIDFile: /run/run/nspawn-{{ dnsmasq_var.value.bridge }}-dnsmasq.pid
execstarts:
- "/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq.d/dnsmasq-{{ 'mv-' + dnsmasq_var.value.bridge.split('br-')[-1] }}.conf"
execstops:
- "-/usr/bin/killall -u systemd-network --regexp ^dnsmasq"
enabled: yes
state: started
when:
- item.value.enable_dhcp | default(false) | bool
notify:
- Enable network dnsmasq service
- dnsmasq_var.value.enable_dhcp | default(false) | bool
- dnsmasq_var.value.address is defined
- dnsmasq_var.value.netmask is defined
with_dict: "{{ container_networks | combine(nspawn_networks) }}"
loop_control:
loop_var: dnsmasq_var
tags:
- network-config

View File

@ -52,23 +52,53 @@
state: "directory"
recurse: true
- name: Move machines mount into place
copy:
src: var-lib-machines.mount
dest: /etc/systemd/system/var-lib-machines.mount
register: mount_unit
notify:
- Reload systemd units
- Restart machines mount
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_user_name: "root"
systemd_group_name: "root"
systemd_tempd_prefix: machine
systemd_slice_name: machine
system_lock_path: /var/lock/machine
systemd_CPUAccounting: false
systemd_BlockIOAccounting: false
systemd_MemoryAccounting: false
systemd_TasksAccounting: false
systemd_services:
- service_name: "systemd-machined"
config_overrides:
Unit:
Description: "Virtual Machine and Container Registration Service"
Documentation:
? "man:systemd-machined.service(8)"
? "http://www.freedesktop.org/wiki/Software/systemd/machined"
Wants: "machine.slice"
After: "machine.slice"
Service:
BusName: "org.freedesktop.machine1"
CapabilityBoundingSet: "CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID"
WatchdogSec: "3min"
execstarts:
- "/lib/systemd/systemd-machined"
enabled: yes
state: started
- name: Move machined service into place
copy:
src: systemd-machined.service
dest: /etc/systemd/system/systemd-machined.service
register: machined_unit
notify:
- Reload systemd units
- Restart machined
- name: Run the systemd mount role
include_role:
name: systemd_mount
private: true
vars:
systemd_mounts:
- what: "/var/lib/machines.raw"
where: "/var/lib/machines"
options: "loop"
type: "btrfs"
state: 'started'
enabled: true
tags:
- machines-config
when:
- machinectl_mount.rc != 0

View File

@ -1,37 +0,0 @@
# {{ ansible_managed }}
[Unit]
Description=nspawn dnsmasq service
After=syslog.target
After=network.target
After=nspawn-macvlan.service
[Service]
Type=simple
User=root
{% set addr_cidr = (item.value.address | string + '/' + item.value.netmask | string) | ipaddr('prefix') %}
ExecStartPre=-/sbin/iptables -t nat -A POSTROUTING -s {{ item.value.address }}/{{ addr_cidr }} ! -d {{ item.value.address }}/{{ addr_cidr }} -j MASQUERADE
ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq.d/dnsmasq-{{ 'mv-' + item.value.bridge.split('br-')[-1] }}.conf
ExecStop=-/usr/bin/killall -u systemd-network --regexp ^dnsmasq
ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -s {{ item.value.address }}/{{ addr_cidr }} ! -d {{ item.value.address }}/{{ addr_cidr }} -j MASQUERADE
PIDFile=/run/run/nspawn-{{ item.value.bridge }}-dnsmasq.pid
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=120
Restart=on-failure
RestartSec=2
# This creates a specific slice which all services will operate from
# The accounting options give us the ability to see resource usage through
# the `systemd-cgtop` command.
Slice=nspawn-networking.slice
CPUAccounting=true
BlockIOAccounting=true
MemoryAccounting=false
TasksAccounting=true
[Install]
WantedBy=multi-user.target

View File

@ -1,40 +0,0 @@
# {{ ansible_managed }}
[Unit]
Description=nspawn macvlan service
After=syslog.target
After=network.target
[Service]
Type=oneshot
User=root
RemainAfterExit=yes
{% set seen_start_interfaces = [] %}
{% for key, value in (container_networks | combine(nspawn_networks)).items() %}
{% set interface = value.bridge.split('br-')[-1] %}
{% set mv_interface = 'mv-' + interface %}
{% if value.bridge not in seen_start_interfaces %}
{% if value.private_device | default(false) | bool %}
ExecStart=-/sbin/ip link add dev "{{ value.bridge }}" type dummy
ExecStart=-/sbin/ip link set dev "{{ value.bridge }}" up
{% endif %}
{% set interface_from_ansible = 'ansible_' + value.bridge | replace('-', '_') %}
{% set interface_data = hostvars[inventory_hostname][interface_from_ansible] | default({'type': none}) %}
{% if interface_data['type'] == 'bridge' %}
ExecStart=-/sbin/ip link add dev "veth-{{ interface }}1" type veth peer name "veth-{{ interface }}2"
ExecStart=-/sbin/ip link set dev "veth-{{ interface }}1" up
ExecStart=-/sbin/ip link set dev "veth-{{ interface }}1" mtu {{ interface_data['mtu'] | default(1500) }}
ExecStart=-/sbin/ip link set dev "veth-{{ interface }}2" up
ExecStart=-/sbin/ip link set dev "veth-{{ interface }}2" mtu {{ interface_data['mtu'] | default(1500) }}
ExecStart=-/sbin/ip link set "veth-{{ interface }}1" master "{{ value.bridge }}"
ExecStart=-/sbin/ip link add "{{ mv_interface }}" link "veth-{{ interface }}2" type macvlan mode {{ value.macvlan_mode | default(nspawn_macvlan_mode) }}
{% else %}
ExecStart=-/sbin/ip link add "{{ mv_interface }}" link "{{ value.bridge }}" type macvlan mode {{ value.macvlan_mode | default(nspawn_macvlan_mode) }}
{% endif %}
{% set _ = seen_start_interfaces.append(value.bridge) %}
{% endif %}
{% endfor %}
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,34 @@
# System containers will require mount points for the following
mkdir -p /dev
mkdir -p /proc
mkdir -p /sys/fs/cgroup
# In order for the package manager to function /dev/null, /dev/random and
# /dev/urandom must exist. This is is being run here because some images do not
# create /dev/null by default.
[ ! -e /dev/null ] && mknod -m 0666 /dev/null c 1 3
[ ! -e /dev/random ] && mknod -m 0666 /dev/random c 1 8
[ ! -e /dev/urandom ] && mknod -m 0666 /dev/urandom c 1 9
# Create the directory where local facts will be stored
mkdir -p /etc/ansible/facts.d
# Create the cache resolvers
rm /etc/resolv.conf || true
{% for resolver in nspawn_cache_prep_dns %}
echo "nameserver {{ resolver }}" >> /etc/resolv.conf
{% endfor %}
rm /etc/machine-id || true
rm /var/lib/dbus/machine-id || true
mkdir -p /root/.ssh
chmod 700 /root/.ssh
mkdir -p /var/lib/empty
chmod -R 755 /var/lib/empty
if [[ -e "/etc/securetty" ]]; then
chmod 600 /etc/securetty
fi

View File

@ -20,12 +20,7 @@ set -e
{{ nspawn_cache_prep_pre_commands }}
mkdir -p /etc/ansible/facts.d
mkdir -p /var/backup
{% for resolver in nspawn_cache_prep_dns %}
echo "nameserver {{ resolver }}" >> /etc/resolv.conf
{% endfor %}
{% include 'templates/prep-scripts/_container_sys_setup.sh.j2' %}
rpm --import /etc/pki/rpm-gpg/*
# Prefer dnf over yum for CentOS.
@ -41,19 +36,12 @@ rm -f /tmp/package-transaction.txt
rm -f /usr/bin/python || true
ln -s /usr/bin/python2.7 /usr/bin/python
rm /etc/machine-id || true
rm /var/lib/dbus/machine-id || true
mkdir -p /root/.ssh
chmod 700 /root/.ssh
systemctl enable systemd-hostnamed.service
systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service
ln -sf /var/run/systemd/resolve/resolv.conf /etc/resolv.conf
userdel --force --remove centos || true
chage -I -1 -d -1 -m 0 -M 99999 -E -1 root
systemctl enable systemd-networkd.service
{{ nspawn_cache_prep_post_commands }}

View File

@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Copyright 2018, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# {{ ansible_managed }}
set -e
{{ nspawn_cache_prep_pre_commands }}
{% include 'templates/prep-scripts/_container_sys_setup.sh.j2' %}
# We have (tried to!) copied repo-oss and repo-update from the host so wipe everything else.
find /etc/zypp/repos.d/ -type f ! -name "repo-oss.repo" -a ! -name "repo-update.repo" -delete
zypper lr | grep -q 'repo-oss' || zypper --quiet ar {{ nspawn_hosts_opensuse_mirror_url }}/distribution/leap/{{ ansible_distribution_version }}/repo/oss repo-oss
zypper lr | grep -q 'repo-update' || zypper --quiet ar {{ nspawn_hosts_opensuse_mirror_url }}/update/leap/{{ ansible_distribution_version }}/oss repo-update
# Disable recommended packages. Only update what's really needed
if ! fgrep -qx "solver.onlyRequires = true" /etc/zypp/zypp.conf; then
echo -e "\n\n## Disable recommended packages\nsolver.onlyRequires = true" >> /etc/zypp/zypp.conf
fi
# Update base distribution
zypper --gpg-auto-import-keys -n dup --force-resolution -l
zypper --gpg-auto-import-keys -n in --force-resolution -l {{ nspawn_container_distro_packages | join(' ') }}
rm -f /usr/bin/python || true
ln -s /usr/bin/python2.7 /usr/bin/python
for action in disable mask; do
systemctl ${action} wicked.service || true
systemctl ${action} wickedd.service || true
systemctl ${action} wickedd-auto4.service || true
systemctl ${action} wickedd-dhcp4.service || true
systemctl ${action} wickedd-dhcp6.service || true
systemctl ${action} wickedd-nanny.service || true
done
systemctl enable systemd-hostnamed.service
systemctl enable systemd-networkd.service
userdel --force --remove opensuse || true
chage -I -1 -d -1 -m 0 -M 99999 -E -1 root
{{ nspawn_cache_prep_post_commands }}

View File

@ -20,12 +20,7 @@ set -e
{{ nspawn_cache_prep_pre_commands }}
mkdir -p /etc/ansible/facts.d
mkdir -p /var/backup
{% for resolver in nspawn_cache_prep_dns %}
echo "nameserver {{ resolver }}" >> /etc/resolv.conf
{% endfor %}
{% include 'templates/prep-scripts/_container_sys_setup.sh.j2' %}
# Update base distribution
export DEBIAN_FRONTEND=noninteractive
@ -38,12 +33,6 @@ rm /var/cache/apt/archives/lock || true
rm -f /usr/bin/python || true
ln -s /usr/bin/python2.7 /usr/bin/python
rm /etc/machine-id || true
rm /var/lib/dbus/machine-id || true
mkdir -p /root/.ssh
chmod 700 /root/.ssh
for action in disable mask; do
systemctl ${action} resolvconf.service || true
systemctl ${action} systemd-networkd-resolvconf-update.path || true
@ -51,12 +40,11 @@ for action in disable mask; do
done
systemctl enable systemd-hostnamed.service
systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service
ln -sf /var/run/systemd/resolve/resolv.conf /etc/resolv.conf
userdel --force --remove ubuntu || true
chage -I -1 -d -1 -m 0 -M 99999 -E -1 root
systemctl enable systemd-networkd.service
{{ nspawn_cache_prep_post_commands }}

View File

@ -1,4 +0,0 @@
# {{ ansible_managed }}
[Link]
MACAddressPolicy=persistent

View File

@ -1,8 +0,0 @@
# {{ ansible_managed }}
[NetDev]
Name={{ 'mv-' + item.value.bridge.split('br-')[-1] }}
Kind=macvlan
[MACVLAN]
Mode=bridge

View File

@ -1,23 +0,0 @@
# {{ ansible_managed }}
[Match]
Name={{ 'mv-' + item.value.bridge.split('br-')[-1] }}
[Network]
DHCP=no
IPForward=yes
IPMasquerade=yes
{% if item.value.gateway is defined %}
Gateway={{ item.value.gateway }}
{% endif %}
{% if item.value.enable_dhcp | default(false) | bool %}
{% if item.value.address is defined %}
[Address]
{% set addr_cidr = (item.value.address | string + '/' + item.value.netmask | string) | ipaddr('prefix') %}
Address={{ item.value.address }}/{{ addr_cidr }}
{% endif %}
{% endif %}
[Link]
ARP=yes

View File

@ -1,5 +1,3 @@
# {{ ansible_managed }}
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
@ -15,11 +13,7 @@ Before=machines.target
After=network.target
[Service]
{% if nspawn_systemd_version | int > 219 %}
ExecStart=/usr/bin/systemd-nspawn --keep-unit --boot --link-journal=try-host --settings=override --machine=%I
{% else %}
ExecStart=/usr/bin/systemd-nspawn --keep-unit --boot --link-journal=try-host --machine=%I
{% endif %}
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth {{ (nspawn_systemd_version | int > 219) | ternary('--settings=override --machine=%I', '--machine=%I') }}
KillMode=mixed
Type=notify
RestartForceExitStatus=133
@ -47,3 +41,6 @@ DeviceAllow=char-pts rw
DeviceAllow=/dev/loop-control rw
DeviceAllow=block-loop rw
DeviceAllow=block-blkext rw
[Install]
WantedBy=machines.target

View File

@ -6,3 +6,15 @@
src: https://git.openstack.org/openstack/openstack-ansible-pip_install
scm: git
version: master
- name: systemd_service
src: https://git.openstack.org/openstack/ansible-role-systemd_service
scm: git
version: master
- name: systemd_service
src: https://git.openstack.org/openstack/ansible-role-systemd_networkd
scm: git
version: master
- name: systemd_service
src: https://git.openstack.org/openstack/ansible-role-systemd_mount
scm: git
version: master

View File

@ -17,6 +17,17 @@
hosts: localhost
connection: local
become: true
vars:
nspawn_networks:
nspawn_address:
bridge: "nspawn0"
private_device: true
enable_dhcp: true
dhcp_range: 10.100.101.2,10.100.101.129
address: 10.100.101.1
netmask: 255.255.255.0
macvlan_mode: bridge
pre_tasks:
- name: Show host facts
debug:

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
_nspawn_hosts_container_image_url: "https://github.com/CentOS/sig-cloud-instance-images/raw/CentOS-7/docker/centos-7-docker.tar.xz"
nspawn_hosts_distro_packages:
- aria2
- bridge-utils
@ -31,6 +33,8 @@ nspawn_container_distro_packages:
- cronie
- dbus
- epel-release
- iproute
- iputils
- python2
- rsync
- sudo

View File

@ -1,6 +1,5 @@
---
# Copyright 2016, Rackspace US, Inc.
# Copyright 2017, SUSE LINUX GmbH.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -14,4 +13,57 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Unimplemented. We'll need to circle back on this once OpenSUSE supports networkd
_nspawn_hosts_container_image_url: null
_nspawn_hosts_container_image_download_legacy: true
nspawn_hosts_distro_packages:
- apparmor-parser
- apparmor-profiles
- apparmor-utils
- aria2
- bridge-utils
- btrfsprogs
- dbus-1
- dnsmasq
- git-core
- libseccomp2
- xz
nspawn_container_distro_packages:
- ca-certificates
- ca-certificates-cacert
- ca-certificates-mozilla
- cronie
- dbus-1
- gcc
- iproute2
- iputils
- libffi-devel
- libopenssl-devel
- openssl
- python
- python-devel
- python-xml
- rsync
- sudo
- tar
- wget
- which
nspawn_cache_map:
distro: opensuse
arch: "{{ nspawn_architecture_mapping.get(ansible_architecture) }}"
release: "{{ hostvars[physical_host]['ansible_distribution_version'] }}"
nspawn_copy_from_host:
- /etc/zypp/repos.d/repo-oss.repo
- /etc/zypp/repos.d/repo-update.repo
## Set default mirror for openSUSE repositories
# NOTE(hwoarang): Ensure that the full path to the 'opensuse' directory is used.
# Additionally, set 'nspawn_hosts_opensuse_mirror_obs_url' to a mirror which also mirrors
# the OBS repositories. If you want to use the same mirror in both cases, then leave the
# 'nspawn_hosts_opensuse_mirror_obs_url' to its default value.
nspawn_hosts_opensuse_mirror_url: 'http://download.opensuse.org'
nspawn_hosts_opensuse_mirror_obs_url: "{{ nspawn_hosts_opensuse_mirror_url }}"

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
_nspawn_hosts_container_image_url: "http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.4-base-{{ nspawn_cache_map.arch }}.tar.gz"
nspawn_hosts_distro_packages:
- aria2
- bridge-utils
@ -31,6 +33,8 @@ nspawn_container_distro_packages:
- ca-certificates
- cron
- dbus
- iproute2
- iputils-ping
- libnss-resolve
- python2.7
- python-apt

View File

@ -17,7 +17,7 @@
jobs:
- openstack-ansible-linters
- openstack-ansible-functional-centos-7
# - openstack-ansible-functional-opensuse-423
- openstack-ansible-functional-opensuse-423
- openstack-ansible-functional-ubuntu-xenial
# - openstack-ansible-nspawn-centos-7
# - openstack-ansible-nspawn-opensuse-423
@ -27,5 +27,5 @@
jobs:
- openstack-ansible-linters
- openstack-ansible-functional-centos-7
# - openstack-ansible-functional-opensuse-423
- openstack-ansible-functional-opensuse-423
- openstack-ansible-functional-ubuntu-xenial