Move vino-builder into vino
This patchset moves the vino-builder image build from the images repo into the vino repo. [0] removes it from the images repo. [0] https://review.opendev.org/c/airship/images/+/786714 Change-Id: I8299045cdfaaf285e0f088b330a84e00fcb8307c
This commit is contained in:
parent
334f2de4aa
commit
6ad6bb6d8c
10
Makefile
10
Makefile
@ -2,6 +2,7 @@
|
||||
# IMG ?= controller:latest
|
||||
CONTROLLER_IMG ?= quay.io/airshipit/vino
|
||||
NODE_LABELER_IMG ?= quay.io/airshipit/nodelabeler
|
||||
VINO_BUILDER_IMG ?= quay.io/airshipit/vino-builder
|
||||
|
||||
# Produce CRDs that work back to Kubernetes 1.16
|
||||
CRD_OPTIONS ?= crd:crdVersions=v1
|
||||
@ -78,6 +79,11 @@ docker-build-controller:
|
||||
docker-build-nodelabeler:
|
||||
docker build -f nodelabeler/Dockerfile . ${DOCKER_PROXY_FLAGS} -t ${NODE_LABELER_IMG}
|
||||
|
||||
# Build the vino-builder docker image
|
||||
# If DOCKER_PROXY_FLAGS values are empty, we are fine with that
|
||||
docker-build-vino-builder:
|
||||
docker build -f vino-builder/Dockerfile . ${DOCKER_PROXY_FLAGS} -t ${VINO_BUILDER_IMG}
|
||||
|
||||
# Push the controller docker image
|
||||
docker-push-controller:
|
||||
docker push ${CONTROLLER_IMG}
|
||||
@ -86,6 +92,10 @@ docker-push-controller:
|
||||
docker-push-nodelabeler:
|
||||
docker push ${NODE_LABELER_IMG}
|
||||
|
||||
# Push the vino-builder docker image
|
||||
docker-push-vino-builder:
|
||||
docker push ${VINO_BUILDER_IMG}
|
||||
|
||||
# Generate API reference documentation
|
||||
api-docs: gen-crd-api-reference-docs
|
||||
$(API_REF_GEN) -api-dir=./pkg/api/v1 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/vino.md
|
||||
|
@ -114,7 +114,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 8001
|
||||
hostPort: 8001
|
||||
image: quay.io/airshipit/vino-builder:latest-ubuntu_bionic
|
||||
image: quay.io/airshipit/vino-builder
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- name: flavors
|
||||
|
@ -22,6 +22,7 @@
|
||||
./tools/deployment/install-airship.sh
|
||||
./tools/deployment/configure-airship.sh
|
||||
make docker-build-controller
|
||||
make docker-build-vino-builder
|
||||
./tools/deployment/run-test-plan.sh
|
||||
args:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
||||
|
@ -41,3 +41,17 @@
|
||||
shell: docker image inspect quay.io/airshipit/nodelabeler
|
||||
args:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
||||
|
||||
- name: Buid vino-builder image
|
||||
make:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
||||
target: docker-build-vino-builder
|
||||
params:
|
||||
PROXY: "{{ proxy.http }}"
|
||||
NO_PROXY: "{{ proxy.noproxy }}"
|
||||
USE_PROXY: "{{ proxy.enabled | lower }}"
|
||||
|
||||
- name: Verify vino-builder image exists
|
||||
shell: docker image inspect quay.io/airshipit/vino-builder
|
||||
args:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
@ -45,3 +45,8 @@
|
||||
make:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
||||
target: docker-push-nodelabeler
|
||||
|
||||
- name: Push vino-builder image with latest tag
|
||||
make:
|
||||
chdir: "{{ zuul.project.src_dir }}"
|
||||
target: docker-push-vino-builder
|
@ -3,6 +3,7 @@
|
||||
set -xe
|
||||
sudo snap install kustomize && sudo snap install go --classic
|
||||
make docker-build-controller
|
||||
make docker-build-vino-builder
|
||||
make deploy
|
||||
kubectl get po -A
|
||||
#Wait for vino controller manager Pod.
|
||||
|
45
vino-builder/Dockerfile
Normal file
45
vino-builder/Dockerfile
Normal file
@ -0,0 +1,45 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
SHELL ["bash", "-exc"]
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
ARG k8s_version=v1.18.3
|
||||
ARG kubectl_url=https://storage.googleapis.com/kubernetes-release/release/"${k8s_version}"/bin/linux/amd64/kubectl
|
||||
|
||||
|
||||
# Update distro and install common reqs
|
||||
RUN apt-get update ;\
|
||||
apt-get dist-upgrade -y ;\
|
||||
apt-get install -y \
|
||||
python3-minimal \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-libvirt \
|
||||
libvirt-clients \
|
||||
python3-netaddr \
|
||||
python3-lxml \
|
||||
curl \
|
||||
make \
|
||||
sudo \
|
||||
iproute2 \
|
||||
bridge-utils \
|
||||
iputils-ping \
|
||||
net-tools \
|
||||
less \
|
||||
jq \
|
||||
vim \
|
||||
openssh-client ;\
|
||||
curl -sSLo /usr/local/bin/kubectl "${kubectl_url}" ;\
|
||||
chmod +x /usr/local/bin/kubectl ;\
|
||||
pip3 install --upgrade pip ;\
|
||||
pip3 install --upgrade wheel ;\
|
||||
pip3 install --upgrade ansible ;\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY vino-builder/assets /opt/assets/
|
||||
RUN cp -ravf /opt/assets/* / ;\
|
||||
rm -rf /opt/assets
|
||||
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT /entrypoint.sh
|
70
vino-builder/assets/entrypoint.sh
Normal file
70
vino-builder/assets/entrypoint.sh
Normal file
@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -ex
|
||||
|
||||
READINESS_CHECK_FILE="/tmp/healthy"
|
||||
|
||||
## Remove healthy status before starting
|
||||
[ -f "${READINESS_CHECK_FILE}" ] && rm ${READINESS_CHECK_FILE}
|
||||
|
||||
# wait for libvirt socket to be ready
|
||||
TIMEOUT=300
|
||||
while [[ ! -e /var/run/libvirt/libvirt-sock ]]; do
|
||||
if [[ ${TIMEOUT} -gt 0 ]]; then
|
||||
let TIMEOUT-=1
|
||||
echo "Waiting for libvirt socket at /var/run/libvirt/libvirt-sock"
|
||||
sleep 1
|
||||
else
|
||||
echo "ERROR: libvirt did not start in time (socket missing) /var/run/libvirt/libvirt-sock"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# wait for dynamic data to be ready
|
||||
# data is node-specific, so it will be passed as a node annotations
|
||||
# of the form
|
||||
# metadata:
|
||||
# annotations:
|
||||
# airshipit.org/vino.network-values: |
|
||||
# bunch-of-yaml
|
||||
DYNAMIC_DATA_FILE=/var/lib/vino-builder/dynamic.yaml
|
||||
TIMEOUT=300
|
||||
while [[ ${TIMEOUT} -gt 0 ]]; do
|
||||
let TIMEOUT-=10
|
||||
if [[ ${TIMEOUT} -le 0 ]]; then
|
||||
echo "ERROR: vino-builder dynamic data was not ready in time"
|
||||
exit 1
|
||||
fi
|
||||
kubectl get node $HOSTNAME -o=jsonpath="{.metadata.annotations.airshipit\.org/vino\.network-values}" > $DYNAMIC_DATA_FILE
|
||||
if [[ -s $DYNAMIC_DATA_FILE ]]; then
|
||||
break
|
||||
fi
|
||||
echo "vino-builder dynamic data not ready yet - sleeping for 10 seconds..."
|
||||
sleep 10
|
||||
done
|
||||
|
||||
ansible-playbook -v \
|
||||
-e @/var/lib/vino-builder/flavors/flavors.yaml \
|
||||
-e @/var/lib/vino-builder/flavor-templates/flavor-templates.yaml \
|
||||
-e @/var/lib/vino-builder/network-templates/network-templates.yaml \
|
||||
-e @/var/lib/vino-builder/storage-templates/storage-templates.yaml \
|
||||
-e @$DYNAMIC_DATA_FILE \
|
||||
/playbooks/vino-builder.yaml
|
||||
|
||||
touch ${READINESS_CHECK_FILE}
|
||||
|
||||
while true; do
|
||||
sleep infinity
|
||||
done
|
@ -0,0 +1 @@
|
||||
libvirt_uri: qemu:///system
|
@ -0,0 +1,160 @@
|
||||
#!/usr/bin/python
|
||||
# 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.
|
||||
|
||||
# generate_baremetal_macs method ripped from
|
||||
# openstack/tripleo-incubator/scripts/configure-vm
|
||||
|
||||
import math
|
||||
import random
|
||||
import sys
|
||||
import fnmatch
|
||||
import os
|
||||
from itertools import chain
|
||||
import json
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: core_allocation
|
||||
version_added: "1.0"
|
||||
short_description: Allocate numa aligned cores for libvirt domains and track allocations
|
||||
description:
|
||||
- Generate numa aligned cores for libvirt domains and track allocations
|
||||
'''
|
||||
|
||||
PATH_SYS_DEVICES_NODE = "/sys/devices/system/node"
|
||||
|
||||
def _parse_range(rng):
|
||||
parts = rng.split('-')
|
||||
if 1 > len(parts) > 2:
|
||||
raise ValueError("Bad range: '%s'" % (rng,))
|
||||
parts = [int(i) for i in parts]
|
||||
start = parts[0]
|
||||
end = start if len(parts) == 1 else parts[1]
|
||||
if start > end:
|
||||
end, start = start, end
|
||||
return range(start, end + 1)
|
||||
|
||||
def _parse_range_list(rngs):
|
||||
return sorted(set(chain(*[_parse_range(rng) for rng in rngs.split(',')])))
|
||||
|
||||
def get_numa_cores():
|
||||
"""Return cores as a dict of numas each with their expanded core lists"""
|
||||
numa_core_dict = {}
|
||||
for root, dir, files in os.walk(PATH_SYS_DEVICES_NODE):
|
||||
for numa in fnmatch.filter(dir, "node*"):
|
||||
numa_path = os.path.join(PATH_SYS_DEVICES_NODE, numa)
|
||||
cpulist = os.path.join(numa_path, "cpulist")
|
||||
with open(cpulist, 'r') as f:
|
||||
parsed_range_list = _parse_range_list(f.read())
|
||||
numa_core_dict[numa] = parsed_range_list
|
||||
return numa_core_dict
|
||||
|
||||
def allocate_cores(nodes, flavors, exclude_cpu):
|
||||
"""Return"""
|
||||
|
||||
core_state = {}
|
||||
|
||||
try:
|
||||
f = open('/etc/libvirt/vino-cores.json', 'r')
|
||||
core_state = json.loads(f.read())
|
||||
except:
|
||||
pass
|
||||
|
||||
# instantiate initial inventory - we don't support the inventory
|
||||
# changing (e.g. adding cores)
|
||||
if 'inventory' not in core_state:
|
||||
core_state['inventory'] = get_numa_cores()
|
||||
|
||||
# explode exclude cpu list - we don't support adjusting this after-the-fact
|
||||
# right now
|
||||
if 'exclude' not in core_state:
|
||||
exclude_core_list = _parse_range_list(exclude_cpu)
|
||||
core_state['exclude'] = exclude_core_list
|
||||
|
||||
# reduce inventory by exclude
|
||||
if 'available' not in core_state:
|
||||
core_state['available'] = {}
|
||||
for numa in core_state['inventory'].keys():
|
||||
numa_available = [x for x in core_state['inventory'][numa] if x not in core_state['exclude']]
|
||||
core_state['available'][numa] = numa_available
|
||||
|
||||
if 'assignments' not in core_state:
|
||||
core_state['assignments'] = {}
|
||||
|
||||
# walk the nodes, consuming inventory or discovering previous allocations
|
||||
# address the case where previous != desired - delete previous, re-run
|
||||
for node in nodes:
|
||||
|
||||
flavor = node['bmhLabels']['airshipit.org/k8s-role']
|
||||
vcpus = flavors[flavor]['vcpus']
|
||||
|
||||
for num_node in range(0, node['count']):
|
||||
|
||||
# generate a unique name such as master-0, master-1
|
||||
node_name = node['name'] + '-' + str(num_node)
|
||||
|
||||
# extract the core count
|
||||
core_count = int(vcpus)
|
||||
|
||||
# discover any previous allocation
|
||||
if 'assignments' in core_state:
|
||||
if node_name in core_state['assignments']:
|
||||
if len(core_state['assignments'][node_name]) == core_count:
|
||||
continue
|
||||
else:
|
||||
# TODO: support releasing the cores and adding them back
|
||||
# to available
|
||||
raise Exception("Existing assignment exists for node %s but does not match current core count needed" % node_name)
|
||||
|
||||
# allocate the cores
|
||||
allocated=False
|
||||
for numa in core_state['available']:
|
||||
if core_count <= len(core_state['available'][numa]):
|
||||
allocated=True
|
||||
cores_to_use = core_state['available'][numa][:core_count]
|
||||
core_state['assignments'][node_name] = cores_to_use
|
||||
core_state['available'][numa] = core_state['available'][numa][core_count:]
|
||||
break
|
||||
else:
|
||||
continue
|
||||
if not allocated:
|
||||
raise Exception("Unable to find sufficient cores (%s) for node %s (available was %r)" % (core_count, node_name, core_state['available']))
|
||||
|
||||
# return a dict of nodes: cores
|
||||
# or error if insufficient
|
||||
with open('/etc/libvirt/vino-cores.json', 'w') as f:
|
||||
f.write(json.dumps(core_state))
|
||||
|
||||
return core_state['assignments']
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
nodes=dict(required=True, type='list'),
|
||||
flavors=dict(required=True, type='dict'),
|
||||
exclude_cpu=dict(required=True, type='str')
|
||||
)
|
||||
)
|
||||
result = allocate_cores(module.params["nodes"],
|
||||
module.params["flavors"],
|
||||
module.params["exclude_cpu"])
|
||||
module.exit_json(**result)
|
||||
|
||||
# see http://docs.ansible.com/developing_modules.html#common-module-boilerplate
|
||||
from ansible.module_utils.basic import AnsibleModule # noqa
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -0,0 +1,52 @@
|
||||
- name: debug print loop
|
||||
debug:
|
||||
msg: "outer item={{ node }} inner item={{item}}"
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
|
||||
- name: debug print virsh xml domain
|
||||
debug:
|
||||
msg: "{{ flavorTemplates[node['bmhLabels']['airshipit.org/k8s-role']]['domainTemplate'] }}"
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
|
||||
- name: get state of existing volumes
|
||||
shell: |
|
||||
virsh vol-list vino-default
|
||||
register: vol_list
|
||||
|
||||
- name: write out domain volume request xml
|
||||
copy: content="{{ flavorTemplates[node['bmhLabels']['airshipit.org/k8s-role']]['volumeTemplate'] }}" dest=/tmp/vol-{{item}}.xml
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
|
||||
- name: create domain volume if it doesn't exist
|
||||
shell: |
|
||||
virsh vol-create vino-default /tmp/vol-{{item}}.xml
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
when: "node.name + '-' + item|string not in vol_list.stdout"
|
||||
|
||||
- name: ensure vino instance state directory exists
|
||||
file:
|
||||
path: /var/lib/libvirt/vino-instances
|
||||
state: directory
|
||||
recurse: yes
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
# the virt community plugin does not handle pushing out updates
|
||||
# to domains, so we must shell out here instead
|
||||
|
||||
- name: write out domain volume request xml
|
||||
copy: content="{{ flavorTemplates[node['bmhLabels']['airshipit.org/k8s-role']]['domainTemplate'] }}" dest=/tmp/domain-{{item}}.xml
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
|
||||
- name: virsh define domain
|
||||
shell: |
|
||||
virsh define /tmp/domain-{{item}}.xml
|
||||
loop: "{{ range(0,node.count)|list }}"
|
||||
|
||||
#- name: set vm to running
|
||||
# virt:
|
||||
# name: "{{ node.name + '-' + item|string}}"
|
||||
# state: running
|
||||
# autostart: yes
|
||||
# loop: "{{ range(0,node.count)|list }}"
|
||||
# ignore_errors: true
|
@ -0,0 +1,36 @@
|
||||
# Facts will be available as 'ansible_libvirt_networks'
|
||||
- name: initially gather facts on existing virsh networks
|
||||
virt_net:
|
||||
command: facts
|
||||
name: "" # this attribute is not needed but required
|
||||
uri: "{{ libvirt_uri }}"
|
||||
ignore_errors: true
|
||||
|
||||
- name: Print value of ansible networks
|
||||
debug:
|
||||
msg: "Value of ansible_libvirt_networks is {{ ansible_libvirt_networks }}"
|
||||
|
||||
# TODO(alanmeadows): deal with updates as once its defined we will
|
||||
# never re-define it
|
||||
- name: add networks defined if they do not already exist
|
||||
virt_net:
|
||||
state: present
|
||||
# looks like setting name here is a redundant, the name is anyways taken from the template xml file, but should set it to make virt_pool module happy.
|
||||
name: "{{ item.name }}"
|
||||
xml: "{{ item.libvirtTemplate }}"
|
||||
uri: "{{ libvirt_uri }}"
|
||||
vars:
|
||||
nodebridgegw: ipam.bridge_ip
|
||||
|
||||
- name: activate the network
|
||||
virt_net:
|
||||
state: active
|
||||
name: "{{ item.name }}"
|
||||
uri: "{{ libvirt_uri }}"
|
||||
|
||||
# these are idempotent so require no conditional checks
|
||||
- name: autostart the network
|
||||
virt_net:
|
||||
autostart: yes
|
||||
name: "{{ item.name }}"
|
||||
uri: "{{ libvirt_uri }}"
|
@ -0,0 +1,18 @@
|
||||
# Facts will be available as 'ansible_libvirt_pools'
|
||||
- name: initially gather facts on existing virsh pool
|
||||
virt_pool:
|
||||
command: facts
|
||||
uri: "{{ libvirt_uri }}"
|
||||
|
||||
- name: define storage the storage pool
|
||||
virt_pool:
|
||||
state: present
|
||||
name: "{{ item.name }}"
|
||||
uri: "{{ libvirt_uri }}"
|
||||
xml: "{{item.libvirtTemplate}}"
|
||||
|
||||
- name: activate the storage pool
|
||||
virt_pool:
|
||||
state: active
|
||||
name: "{{ item.name }}"
|
||||
uri: "{{ libvirt_uri }}"
|
39
vino-builder/assets/playbooks/roles/libvirt/tasks/main.yml
Normal file
39
vino-builder/assets/playbooks/roles/libvirt/tasks/main.yml
Normal file
@ -0,0 +1,39 @@
|
||||
##########################################
|
||||
# configure storage #
|
||||
##########################################
|
||||
|
||||
- name: create storage
|
||||
include_tasks: create-storage.yaml
|
||||
loop: "{{ libvirtStorage }}"
|
||||
|
||||
##########################################
|
||||
# configure networks #
|
||||
##########################################
|
||||
|
||||
# - name: create network
|
||||
# include_tasks: create-network.yaml
|
||||
# loop: "{{ libvirtNetworks }}"
|
||||
|
||||
##########################################
|
||||
# configure domains #
|
||||
##########################################
|
||||
|
||||
- name: allocate domain cores
|
||||
core_allocation:
|
||||
nodes: "{{ nodes }}"
|
||||
flavors: "{{ flavors }}"
|
||||
exclude_cpu: "{{ configuration.cpuExclude }}"
|
||||
register: node_core_map
|
||||
when: nodes
|
||||
|
||||
- name: debug print node_core_map
|
||||
debug:
|
||||
msg: "node_core_map = {{ node_core_map }}"
|
||||
|
||||
- name: define domain outer loop
|
||||
include_tasks: create-domain.yaml
|
||||
loop: "{{ nodes }}"
|
||||
loop_control:
|
||||
loop_var: node
|
||||
|
||||
|
198
vino-builder/assets/playbooks/sample-vino-ansible-input.yaml
Normal file
198
vino-builder/assets/playbooks/sample-vino-ansible-input.yaml
Normal file
@ -0,0 +1,198 @@
|
||||
configuration:
|
||||
cpuExclude: 0-1,54-60
|
||||
redfishCredentialSecret:
|
||||
name: redfishSecret
|
||||
namespace: airship-system
|
||||
networks:
|
||||
- name: management
|
||||
subnet: 192.168.2.0/20
|
||||
allocationStart: 192.168.2.10
|
||||
allocationStop: 192.168.2.14 # docs should specify that the range should = number of vms (to permit future expansion over multiple vino crs etc)
|
||||
routes:
|
||||
- to: 10.0.0.0/24
|
||||
via: "{{ ipam.bridge_ip | default(omit) }}" # vino will need to populate this from the nodelabel value `airshipit.org/vino.nodebridgegw`
|
||||
dns_servers: ["135.188.34.124"]
|
||||
- name: mobility-gn
|
||||
subnet: 169.0.0.0/24
|
||||
routes:
|
||||
- to: 0.0.0.0/0
|
||||
via: 169.0.0.1
|
||||
allocationStart: 169.0.0.10
|
||||
allocationStop: 169.0.0.254
|
||||
libvirtNetworks:
|
||||
- name: management
|
||||
libvirtTemplate: |
|
||||
<network>
|
||||
<name>management</name>
|
||||
<forward mode='route'/>
|
||||
<bridge name='management' stp='off' delay='0'/>
|
||||
<ip address='{{ ipam.bridge_ip | default(omit) }}' netmask='255.255.240.0'>
|
||||
<tftp root='/srv/tftp'/>
|
||||
<dhcp>
|
||||
<range start='192.168.1.1' end='192.168.1.254'/>
|
||||
<bootp file=''/>
|
||||
</dhcp>
|
||||
</ip>
|
||||
</network>
|
||||
# - name: mobility-gn
|
||||
# libvirtTemplate:
|
||||
libvirtStorage:
|
||||
- name: vino-default
|
||||
libvirtTemplate: |
|
||||
<pool type='dir'>
|
||||
<name>vino-default</name>
|
||||
<target>
|
||||
<path>/var/lib/libvirt/vino</path>
|
||||
<permissions>
|
||||
<mode>0711</mode>
|
||||
<owner>0</owner>
|
||||
<group>0</group>
|
||||
</permissions>
|
||||
</target>
|
||||
</pool>
|
||||
libvirtDomains:
|
||||
master:
|
||||
volumeTemplate: |
|
||||
{% set nodename = node.name + '-' + item|string %}
|
||||
<volume>
|
||||
<name>{{ nodename }}</name>
|
||||
<allocation>0</allocation>
|
||||
<capacity unit='G'>{{ node.instance.rootSize }}</capacity>
|
||||
</volume>
|
||||
domainTemplate: |
|
||||
{% set nodename = node.name + '-' + item|string %}
|
||||
<domain type="kvm">
|
||||
<name>{{ nodename }}</name>
|
||||
<uuid>{{ nodename | hash('md5') }}</uuid>
|
||||
<metadata>
|
||||
{% for flavor in node.labels %}
|
||||
{% for key in flavor.keys() %}
|
||||
{% if key == 'vm-flavor' %}
|
||||
<vino:flavor>{{ flavor[key] }}</vino:flavor>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<vino:creationTime>{{ ansible_date_time.date }}</vino:creationTime>
|
||||
</metadata>
|
||||
<memory unit="KiB">{{ node.instance.memory }}</memory>
|
||||
{% if node.instance.hugepages %}
|
||||
<memoryBacking>
|
||||
<hugepages>
|
||||
</hugepages>
|
||||
</memoryBacking>
|
||||
{% endif %}
|
||||
<vcpu placement="static">{{ node.instance.vcpu }}</vcpu>
|
||||
# function to produce list of cpus, in same numa (controled by bool), state will need to be tracked via file on hypervisor host. gotpl psudo:
|
||||
<cputune>
|
||||
<shares>8192</shares>
|
||||
{% for core in node_core_map[nodename] %}
|
||||
<vcpupin vcpu="{{ core }}" cpuset="{{ core }}"/>
|
||||
{% endfor %}
|
||||
<emulatorpin cpuset="{{ node_core_map[nodename]|join(',') }}"/>
|
||||
</cputune>
|
||||
<resource>
|
||||
<partition>/machine</partition>
|
||||
</resource>
|
||||
<os>
|
||||
<type arch="x86_64" machine="pc-i440fx-bionic">hvm</type>
|
||||
<boot dev="hd"/>
|
||||
</os>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
</features>
|
||||
<cpu mode="host-passthrough" />
|
||||
<clock offset="utc">
|
||||
<timer name="pit" tickpolicy="delay"/>
|
||||
<timer name="rtc" tickpolicy="catchup"/>
|
||||
<timer name="hpet" present="no"/>
|
||||
</clock>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
|
||||
# for each disk requested
|
||||
<disk type='volume' device='disk'>
|
||||
<driver name="qemu" type="qcow2" cache="none" discard="unmap"/>
|
||||
<source pool='vino-default' volume='{{ nodename }}'/>
|
||||
<target dev='vde' bus='virtio'/>
|
||||
</disk>
|
||||
|
||||
<controller type="usb" index="0" model="piix3-uhci">
|
||||
<alias name="usb"/>
|
||||
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x2"/>
|
||||
</controller>
|
||||
<controller type="pci" index="0" model="pci-root">
|
||||
<alias name="pci.0"/>
|
||||
</controller>
|
||||
<controller type="ide" index="0">
|
||||
<alias name="ide"/>
|
||||
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x1"/>
|
||||
</controller>
|
||||
|
||||
# for each interface defined in vino, e.g.
|
||||
<interface type='bridge'>
|
||||
<mac address='52:54:00:83:e9:f9'/>
|
||||
<source bridge='management'/>
|
||||
<model type='virtio'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
</interface>
|
||||
|
||||
<serial type="pty">
|
||||
<source path="/dev/pts/3"/>
|
||||
<log file="/var/lib/vino/instances/{{ nodename }}.console.log" append="off"/>
|
||||
<target type="isa-serial" port="0">
|
||||
<model name="isa-serial"/>
|
||||
</target>
|
||||
<alias name="serial0"/>
|
||||
</serial>
|
||||
<console type="pty" tty="/dev/pts/3">
|
||||
<source path="/dev/pts/3"/>
|
||||
<log file="/var/lib/vino/instances/{{ nodename }}.console.log" append="off"/>
|
||||
<target type="serial" port="0"/>
|
||||
<alias name="serial0"/>
|
||||
</console>
|
||||
<memballoon model="virtio">
|
||||
<stats period="10"/>
|
||||
<alias name="balloon0"/>
|
||||
<address type="pci" domain="0x0000" bus="0x00" slot="0x06" function="0x0"/>
|
||||
</memballoon>
|
||||
</devices>
|
||||
<seclabel type="dynamic" model="dac" relabel="yes">
|
||||
<label>+42424:+104</label>
|
||||
<imagelabel>+42424:+104</imagelabel>
|
||||
</seclabel>
|
||||
</domain>
|
||||
worker-standard:
|
||||
libvirtTemplate: ...
|
||||
nodes:
|
||||
- name: master
|
||||
labels:
|
||||
- vm-flavor: master
|
||||
instance:
|
||||
memory: 8
|
||||
vcpu: 2
|
||||
hugepages: true
|
||||
rootSize: 30
|
||||
count: 2
|
||||
BMHNetworkTemplate:
|
||||
name: configMapFooThatsGoTplForNetwork
|
||||
namespace: foo
|
||||
field: bmhnetwork
|
||||
- name: worker-standard
|
||||
labels:
|
||||
- vm-flavor: worker-standard
|
||||
instance:
|
||||
memory: 8
|
||||
vcpu: 2
|
||||
hugepages: true
|
||||
rootSize: 30
|
||||
count: 0
|
||||
libvirtTemplate: |
|
||||
foobar
|
||||
BMHNetworkTemplate:
|
||||
name: configMapFooThatsGoTplForNetwork
|
||||
namespace: foo
|
||||
field: bmhnetwork
|
46
vino-builder/assets/playbooks/vino-builder.yaml
Normal file
46
vino-builder/assets/playbooks/vino-builder.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
# 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.
|
||||
|
||||
# - host-annotator that populates the k8s node object with approprite annotations
|
||||
# - report back information such as:
|
||||
# - vminfra-bridge ip address as label to k8s node
|
||||
# - sushy-tools ip endpoint for BMC control
|
||||
# - vino-builder (ansible) that that consumes the `ConfigMap` that contains everything necessary for libvirt to define the virtual machines and networks on the host and does both green-field generation of VM resources and understands if the `ConfigMap` changed and will handle those lifecycle updates. There is no need to stage or coordinate changes to these `ConfigMap` resources as they will result in a no-op `virsh update` which only take effect with a VM stop/start.
|
||||
# - do the following (assumption is all of this is idempotent for day 2):
|
||||
# - interogate host
|
||||
# - prevalidate (is kvm loaded, etc)
|
||||
# - define host facts (eg cpu list, vf list, etc)
|
||||
# - interogate existing vms or state recording somewhere
|
||||
# - collect resources in use
|
||||
# - what cores are in use
|
||||
# - what vfs are in use
|
||||
# - memory in use
|
||||
# - define libvirt networks
|
||||
# - define libvirt storage pools
|
||||
# - ensure appropriate qcows exist
|
||||
# - define libvirt domains
|
||||
# - ensure mem/cpu aligned in one numa
|
||||
# - new domain validation (only on new domains):
|
||||
# - do a simple domain start/destroy test via redfish.
|
||||
# - wait for dhcp req on admin interface?
|
||||
|
||||
---
|
||||
- hosts: localhost
|
||||
|
||||
tasks:
|
||||
|
||||
# generate libvirt definitions for storage, networks, and domains
|
||||
- name: process libvirt definitions
|
||||
include_role:
|
||||
name: libvirt
|
Loading…
Reference in New Issue
Block a user