[robot] Add configs and environment setup

Enable different configurations and setup requirements for deployment
environments as well as pip requirements.

- Config : Serie of configuration files to be used on deployment
        as well as exposed to the framework in order to use the values
        on the test cases.
- Qemu : All artifacts needed to deploy the virtual
        machines that simulate the nodes on libvirt/qemu
- Baremetal : Series of configuration files used
        to setup a deployment on a baremetal environment
- requirements.txt, test-requirements.txt : series of packages needed by
            the suite to work on a python virtualenv.

Depends-On: I796dcaf71089424dd37a050691fd0ee003ad3176
Change-Id: I34dfe1c01b27e5e8ce046de3305dd78c7f9d1383
Signed-off-by: Jose Perez Carranza <jose.perez.carranza@intel.com>
This commit is contained in:
Jose Perez Carranza 2019-08-12 11:08:41 -05:00
parent 2d3d047a8c
commit 4ee20f9e40
27 changed files with 1741 additions and 0 deletions

View File

View File

@ -0,0 +1,54 @@
[general]
LOG_PATH = /tmp/logs
IP_UNIT_0_ADDRESS = 10.10.10.3
IP_UNIT_1_ADDRESS = 10.10.10.4
CIRROS_FILE = cirros-0.4.0-x86_64-disk.qcow2
CENTOS_FILE = CentOS-7-x86_64-GenericCloud.qcow2
UBUNTU_FILE = xenial-server-cloudimg-amd64-disk1.qcow2
WINDOWS_FILE = windows_server_2012_r2.qcow2
APP_TARBALL = stx-openstack.tgz
STX_ISO_FILE = bootimage.iso
ENV_YAML_FILE = Qemu/qemu_setup.yaml
CONFIGURATION_TYPE = simplex
ENVIRONMENT = virtual
CONFIGURATION_FILE = stx-simplex.yml
[credentials]
STX_DEPLOY_USER_NAME = sysadmin
STX_DEPLOY_USER_PSWD = St4rlingX*
[iso_installer]
KERNEL_OPTION = 0
VIRSH_CMD = virsh -c qemu:///system console controller-0
VMLINUZ = vmlinuz append rootwait
CONSOLES = console=tty0,115200 console=ttyS0,115200 inst.text
SERIAL = serial
OPTS_1 = inst.stage2=hd:LABEL=oe_iso_boot user_namespace.enable=1
SYS_TYPE_1 = inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg
SYS_TYPE_2 = inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg
SYS_TYPE_3 = inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg
OPTS_2 = boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt
SEC_PROF_1 = security_profile=standard
SEC_PROF_2 = security_profile=extended
INITRD = initrd=initrd.img
BOOT_TIMEOUT = 1200
CONFIG_CONTROLLER_TIMEOUT = 3600
CONTROLLER_TMP_IP = 10.10.10.3
CONTROLLER_TMP_GATEWAY = 10.10.10.1
[logical_interface]
OAM = enp2s1
MGMT = enp2s2
[baremetal]
HTTP_SERVER = 192.168.200.3
[dashboard]
HORIZON_USERNAME = admin
HORIZON_PASSWORD = St4rlingX*
BROWSER = firefox
PROFILE = nk0f1p65.automation
[qemu]
XML = /etc/libvirt/qemu/networks/autostart/default.xml
CONFIG_FILE = /etc/libvirt/qemu.conf

View File

@ -0,0 +1,144 @@
"""Config file parser and config file generator.
Configuration values will be read from a file called <CONFIG_FILE>.
A config file with default values can be generated by running this module as a
script and using the --generate option.
The config file is a standard INI file that contains [sections] and options.
Variables that are between %(option)s are interpolated automatically by the
ConfigParser (with the caveat that they have to be in the same section).
Variables that are between ${section:option} will be interpolated with the
value from the appropriate section (similar to the way ConfigParse from
Python3 works).
Example of a config file:
E.g.
[Section1]
key_1 = value 1
key_2 = value 2
country = mexico
[section2]
name = John
lastname = Doe
fullname = %(name)s %(lastname)s
country = ${Section1:country}
To access config values from other modules follow this approach:
import Config.config as CONF
full_name = CONF.get('section2', 'fullname')
"""
from __future__ import print_function
import argparse
import configparser
import os
import re
CONFIG_FILE = os.path.join(os.path.dirname(__file__), 'config.ini')
CONFIG = configparser.SafeConfigParser()
def get(section, option, raw=False, variables=None):
"""Wrapper function to mimic behavior of ConfigParse (Python3).
Python3 uses a ConfigParse that is different than the Python2 ConfigParser,
it has some additional functionality. One of the biggest differences is
that with ConfigParse you can interpolate variables from one section into
another section of the config file. This functionality is not included in
the ConfigParse. Since it is very useful, this function wraps the original
get function from ConfigParser so it includes the missing interpolation.
:param section: the section where the option to be gotten is
:param option: the option to look for in the config file
:param raw: all the '%' interpolations are expanded in the return values,
unless the raw argument is true.
:param variables: the option is looked up in variables (if provided)
:return: the specified value from the config file
"""
# ensure file readed is up to date always
CONFIG.read(CONFIG_FILE)
original_option = CONFIG.get(section, option, raw=raw, vars=variables)
# find all matches that have the following pattern: ${something}
matches = re.findall(r'\$\{(.*?)\}', original_option)
new_value = original_option
for match in matches:
# interpolate matches found with ${something} with the referenced
# option from the appropriate section
pattern = '${' + match + '}'
value = match.split(':')
foreign_value = CONFIG.get(value[0], value[1])
new_value = new_value.replace(pattern, foreign_value)
if original_option != new_value:
CONFIG.set(section, option, new_value)
# return the interpolated value
return CONFIG.get(section, option, raw=raw, vars=variables)
def getint(section, option):
"""Wrapper that returns the value as an integer.
:param section: the section where the option to be gotten is
:param option: the option to look for in the config file
:return: the specified value from the config file
"""
return int(CONFIG.get(section, option))
def getfloat(section, option):
"""Wrapper that returns the value as a float.
:param section: the section where the option to be gotten is
:param option: the option to look for in the config file
:return: the specified value from the config file
"""
return float(CONFIG.get(section, option))
def getboolean(section, option):
"""Wrapper that returns the value as a boolean.
:param section: the section where the option to be gotten is
:param option: the option to look for in the config file
:return: the specified value from the config file
"""
value = CONFIG.get(section, option)
return value.lower() == 'true'
def _unload_current_values():
"""Removes current sections from the existing config object"""
for section in CONFIG.sections():
CONFIG.remove_section(section)
def create_config():
"""Creates the config file in the current directory"""
if os.path.isfile(CONFIG_FILE):
os.remove(CONFIG_FILE)
with open(CONFIG_FILE, 'wb') as configfile:
_unload_current_values()
CONFIG.write(configfile)
def parse_arguments():
"""Parses arguments from the command line"""
parser = argparse.ArgumentParser(
description='Config file generator')
parser.add_argument(
'--generate', action='store_true',
help='Generates a config file with default values')
return parser.parse_args()
if __name__ == '__main__':
ARGUMENTS = parse_arguments()
if ARGUMENTS.generate:
create_config()
print('Config file created at: {name}'.format(name=CONFIG_FILE))

View File

@ -0,0 +1,16 @@
system_mode: duplex
dns_servers:
- 8.8.8.8
docker_http_proxy: http://<url>:<port>
docker_https_proxy: http://<url>:<port>
external_oam_subnet: 10.10.10.0/24
external_oam_gateway_address: 10.10.10.1
external_oam_floating_address: 10.10.10.2
external_oam_node_0_address: 10.10.10.3
external_oam_node_1_address: 10.10.10.4
ansible_become_pass: ANSIBLE_PASS
admin_password: ADMIN_PASS

View File

@ -0,0 +1,16 @@
system_mode: duplex
dns_servers:
- 8.8.8.8
docker_http_proxy: http://<url>:<port>
docker_https_proxy: http://<url>:<port>
external_oam_subnet: 10.10.10.0/24
external_oam_gateway_address: 10.10.10.1
external_oam_floating_address: 10.10.10.2
external_oam_node_0_address: 10.10.10.3
external_oam_node_1_address: 10.10.10.4
ansible_become_pass: ANSIBLE_PASS
admin_password: ADMIN_PASS

View File

@ -0,0 +1,12 @@
dns_servers:
- 8.8.8.8
docker_http_proxy: http://<url>:<port>
docker_https_proxy: http://<url>:<port>
external_oam_subnet: 10.10.10.0/24
external_oam_gateway_address: 10.10.10.1
external_oam_floating_address: 10.10.10.3
ansible_become_pass: ANSIBLE_PASS
admin_password: ADMIN_PASS

View File

@ -0,0 +1,155 @@
[qemu_logo]: ./images/qemu_logo.png
![alt text][qemu_logo]
Table of Contents
- [qemu_setup.yml](#qemu_setupyml)
- [Description](#description)
- [Examples](#examples)
- [1 controller + 2 compute](#1-controller--2-computes)
- [parameters](#parameters)
- [1 controller + 2 computes & 1 controller + 1 compute](#1-controller--2-computes--1-controller--1-compute)
- [Highlights](#highlights)
- [general_system_configurations section](#general_system_configurations-section)
# qemu_setup.yml
The purpose of this configurations file is to setup easily QEMU in the host.
# Description
YAML is a human-readable data serialization format that takes concepts from
programming languages such as C, Perl, and Python, and ideas from XML and the
data format of electronic mail.
It is available for several programming languages.
# Examples
## 1 controller + 2 computes
Please consider the following example to setup the following configuration:
`1 controller + 2 computes`
```yaml
configuration_0:
controller-0:
controller_0_partition_a: 20
controller_0_partition_b: 10
controller_0_memory_size: 5120
controller_0_system_cores: 2
controller-0-compute-0:
controller_0_compute_0_partition_a: 20
controller_0_compute_0_partition_b: 20
controller_0_compute_0_memory_size: 3072
controller_0_compute_0_system_cores: 1
controller-0-compute-1:
controller_0_compute_1_partition_a: 20
controller_0_compute_1_partition_b: 20
controller_0_compute_1_memory_size: 3072
controller_0_compute_1_system_cores: 1
````
### parameters
**`@param: configuration_0`**: which contains the controller and the computes.<br>
**`@param: controller-0`**: which contains the following:<br>
- `@param: controller_0_partition_a`: which is the controller 0 partition size
A in GB.
- `@param: controller_0_partition_b`: which is the controller 0 partition size
B size in GB.
- `@param: controller_0_memory_size`: which is the controller 0 memory size
in MB.
- `@param: controller_0_system_cores`: which is the controller 0 system cores
to be assigned.
**`@param: controller-0-compute-0`**: which contains the following:<br>
- `@param: controller_0_compute_0_partition_a`: which is the controller's
compute 0 partition size A in GB.
- `@param: controller_0_compute_0_partition_b`: which is the controller's
compute 0 partition size B in GB.
- `@param: controller_0_compute_0_memory_size`: which is the controller's
compute 0 memory size B in MB.
- `@param: controller_0_compute_0_system_cores`: which is the controller's
compute 0 system cores to be assigned.
**`@param: controller-0-compute-1`**: which contains the following:<br>
- `@param: controller_0_compute_1_partition_a`: which is the controller's
compute 1 partition size A in GB.
- `@param: controller_0_compute_1_partition_b`: which is the controller's
compute 1 partition size B in GB.
- `@param: controller_0_compute_1_memory_size`: which is the controller's
compute 1 memory size B in MB.
- `@param: controller_0_compute_1_system_cores`: which is the controller's
compute 1 system cores to be assigned.
## 1 controller + 2 computes & 1 controller + 1 compute
Please consider the following example to setup the following configuration:
`1 controller + 2 computes & 1 controller + 1 compute`
```yaml
configuration_0:
controller-0:
controller_0_partition_a: 20
controller_0_partition_b: 10
controller_0_memory_size: 5120
controller_0_system_cores: 2
controller-0-compute-0:
controller_0_compute_0_partition_a: 20
controller_0_compute_0_partition_b: 20
controller_0_compute_0_memory_size: 3072
controller_0_compute_0_system_cores: 1
controller-0-compute-1:
controller_0_compute_1_partition_a: 20
controller_0_compute_1_partition_b: 20
controller_0_compute_1_memory_size: 3072
controller_0_compute_1_system_cores: 1
configuration_1:
controller-1:
controller_1_partition_a: 15
controller_1_partition_b: 10
controller_1_memory_size: 5120
controller_1_system_cores: 2
controller-1-compute-0:
controller_1_compute_0_partition_a: 20
controller_1_compute_0_partition_b: 20
controller_1_compute_0_memory_size: 3072
controller_1_compute_0_system_cores: 1
```
:notebook: the parameters description are the same that the [section above](#parameters).
## Highlights
Please consider the following when creating the yaml configuration file:
- The total sum of the partitions must not exceed of the total free disk space
in the host.
- The total sum of the memory size must not exceed of the total free memory
size in the host.
- The total sum of the system cores must not exceed of the total system cores
subtracting the `os_system_cores` assigned in `general_system_configurations`
section.
## general_system_configurations section
The general_system_configurations will be explained below:
```yaml
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'
```
**`@param: general_system_configurations`**: which contains the following:
- `@param: os_system_memory`: which is the system memory reserved for the OS.
- `@param: disk_space_allocated_to_os`: which is the disk space reserved for
the OS.
- `@param: os_system_cores`: which is the system cores reserved for the OS.
- `@param: default_mount_point`: which is the mount point where the space in
disk will be analyzed by the script.
:notebook: The first 3 params are used for system reservation and they are for
the user's consideration in order to avoid that QEMU takes all the resources
making slow the current system.

View File

View File

@ -0,0 +1,92 @@
<domain type='kvm' id='187'>
<name>NAME</name>
<memory unit='UNIT'>MEMORY</memory>
<currentMemory unit='UNIT'>MEMORY</currentMemory>
<vcpu placement='static'>CORES</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu match='exact'>
<model fallback='forbid'>Nehalem</model>
<topology sockets='1' cores='CORES' threads='1'/>
<feature policy='require' name='vmx'/>
<feature policy='optional' name='svm'/>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK0'/>
<backingStore/>
<target dev='sda' bus='sata'/>
<boot order='1'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK1'/>
<backingStore/>
<target dev='sdb' bus='sata'/>
</disk>
<interface type='bridge'>
<source bridge='stxbr1'/>
<target dev='vnet8'/>
<model type='e1000'/>
<alias name='net0'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr2'/>
<target dev='vnet9'/>
<model type='e1000'/>
<boot order='2'/>
<alias name='net1'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr3'/>
<target dev='vnet10'/>
<model type='virtio'/>
<alias name='net2'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr4'/>
<target dev='vnet11'/>
<model type='virtio'/>
<alias name='net3'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/12'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/12'>
<source path='/dev/pts/12'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5903' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1,18 @@
Controllers:
controller-0:
partition_a: 600
partition_b: 100
partition_d: 100
memory_size: 25600
system_cores: 6
controller-1:
partition_a: 600
partition_b: 100
partition_d: 100
memory_size: 25600
system_cores: 6
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'

View File

@ -0,0 +1,29 @@
Controllers:
controller-0:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 16384
system_cores: 4
controller-1:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 16384
system_cores: 4
Computes:
compute-0:
partition_a: 250
partition_b: 250
memory_size: 10240
system_cores: 3
compute-1:
partition_a: 250
partition_b: 250
memory_size: 10240
system_cores: 3
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'

View File

@ -0,0 +1,42 @@
Controllers:
controller-0:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 16384
system_cores: 4
controller-1:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 16384
system_cores: 4
Computes:
compute-0:
partition_a: 250
partition_b: 250
memory_size: 10240
system_cores: 3
compute-1:
partition_a: 250
partition_b: 250
memory_size: 10240
system_cores: 3
Storages:
storage-0:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 6144
system_cores: 3
storage-1:
partition_a: 250
partition_b: 250
partition_d: 50
memory_size: 6144
system_cores: 3
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'

View File

@ -0,0 +1,12 @@
Controllers:
controller-0:
partition_a: 600
partition_b: 100
partition_d: 100
memory_size: 25600
system_cores: 6
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,106 @@
<domain type='kvm' id='164'>
<name>NAME</name>
<memory unit='UNIT'>MEMORY</memory>
<currentMemory unit='UNIT'>MEMORY</currentMemory>
<vcpu placement='static'>CORES</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu match='exact'>
<model fallback='forbid'>Nehalem</model>
<topology sockets='1' cores='CORES' threads='1'/>
<feature policy='optional' name='vmx'/>
<feature policy='optional' name='svm'/>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK0'/>
<backingStore/>
<target dev='sda' bus='sata'/>
<boot order='1'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK1'/>
<backingStore/>
<target dev='sdb' bus='sata'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK2'/>
<backingStore/>
<target dev='sdd' bus='sata'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='ISO'/>
<backingStore/>
<target dev='sdc' bus='sata'/>
<readonly/>
<boot order='2'/>
</disk>
<interface type='network'>
<source network='stx-nat'/>
<target dev='vnet0'/>
<model type='e1000'/>
<alias name='net0'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr2'/>
<target dev='vnet1'/>
<model type='e1000'/>
<alias name='net1'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr3'/>
<target dev='vnet2'/>
<model type='virtio'/>
<alias name='net2'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr4'/>
<target dev='vnet3'/>
<model type='virtio'/>
<alias name='net3'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/8'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/8'>
<source path='/dev/pts/8'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1,7 @@
<network>
<name>stx-nat</name>
<bridge name="stxbr1" stp="off"/>
<forward mode="nat"/>
<ip address="10.10.10.1" netmask="255.255.255.0">
</ip>
</network>

View File

@ -0,0 +1,638 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This module setup the controller(s)/computes(s) in the current host"""
from __future__ import print_function
import argparse
from argparse import RawDescriptionHelpFormatter
from imp import reload
import multiprocessing
import os
import re
from shutil import copy
from shutil import rmtree
import sys
# this needs to be exactly here after call network.delete_network_interfaces()
# otherwise the suite local modules they will not be recognized
# hence adding `noqa` to avoid linter issues.
SUITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(SUITE_DIR)
from Config import config # noqa: E402
from Utils import bash_utils as bash # noqa: E402
from Utils import logger # noqa: E402
from Utils import network # noqa: E402
from Utils import utils # noqa: E402
import kmodpy # noqa: E402
import yaml # noqa: E402
# reloading config.ini
reload(config)
# Global variables
THIS_PATH = os.path.dirname(os.path.abspath(__file__))
# setup the logger
LOG_FILENAME = 'qemu_setup.log'
LOG_PATH = config.get('general', 'LOG_PATH')
LOG = logger.setup_logging(
'qemu_setup', log_file='{path}/{filename}'.format(
path=LOG_PATH, filename=LOG_FILENAME), console_log=False)
def enable_nat_network():
"""Enable NAT network for VMs
This function creates a NAT network to allow VM external connection
needed for download docker images.
"""
nat_xml = os.path.join(THIS_PATH, 'nat-network.xml')
nat_net_name = 'stx-nat'
bash.run_command('sudo virsh net-define {}'.format(nat_xml))
bash.run_command('sudo virsh net-start {}'.format(nat_net_name))
def exit_dict_status(code):
"""Exit status
The aim of this function is to provide a exit status in dictionary format
as an string in order to grab it for robot for perform actions.
:param code: which is the exit status code
code 0: which represents an exit status god.
code 1: which represents an exit status bad.
"""
# defining the dictionary
if code == 1:
LOG.info('status: FAIL')
elif code == 0:
LOG.info('status: PASS')
else:
LOG.error('exit code not valid')
sys.exit(code)
def check_kernel_virtualization():
"""Check kernel virtualization
Checks if Virtualization Technology is enabled in the BIOS and it is
present in the kernel as a module.
QEMU requires KVM (Kernel Virtualization Module) to run the nodes.
"""
_km = kmodpy.Kmod()
module_list = [m for m in _km.list()]
virtualization = filter(lambda mod: mod[0] == 'kvm_intel', module_list)
if not virtualization:
message = ('KVM (vmx) is disabled by your BIOS\nEnter your BIOS setup '
'and enable Virtualization Technology (VT), and then hard '
'power off/power on your system')
raise OSError(message)
def check_preconditions():
"""Check host preconditions
The aim of this function is to check the requirements to run QEMU in the
host.
"""
# if this script is running through ssh connection the following
# environment variable needs to be setup in the host bashrc
if 'DISPLAY' not in os.environ:
LOG.info('configuring DISPLAY environment variable')
os.environ['DISPLAY'] = ':0'
def get_system_memory(configurations):
"""Get the system memory
The aim of this function is to get the system memory to be setup with QEMU.
:param: configurations
- which is an object with the values loaded from the yaml.
:return:
- system_free_memory: which is the total system free memory.
- recommended_system_free_memory: which is the recommended system free
memory.
"""
# calculating the system memory to be assigned (value in megabytes)
# os_system_memory will return 0 if either key1 or key2 does not exists
os_system_memory = configurations.get(
'general_system_configurations', 0).get("os_system_memory", 0)
system_free_memory = map(
int, os.popen('free -m | grep Mem').readlines()[-1][4:].split())[-1]
# subtracting OS system memory
recommended_system_free_memory = system_free_memory - os_system_memory
return system_free_memory, recommended_system_free_memory
def get_free_disk_space(configurations):
"""Get the system free disk space
The aim of this function if to get the system free disk in order to setup
with QEMU.
:param: configurations
- which is an object with the values loaded from the yaml.
:return
- system_free_disk_size: which is the total system free disk size in GB
- r_system_free_disk_size: which is the recommended system
free disk size in GB subtracting the disk_space_allocated_to_os
from yaml configuration file for the host OS in order to avoid
low performance.
"""
# disk_space_allocated_to_os will return 0 if either key1 or key2 does
# not exists
disk_space_allocated_to_os = configurations.get(
'general_system_configurations', 0).get(
"disk_space_allocated_to_os", 0)
# the mount point in which will be calculated the free space in disk
default_mount_point = configurations.get(
'general_system_configurations', 0).get(
"default_mount_point", '/')
statvfs = os.statvfs(default_mount_point)
# the following value will be get in megabytes
system_free_disk_size = statvfs.f_frsize * statvfs.f_bavail / 1000000000
# subtracting the 20% of the total disk free
r_system_free_disk_size = (
(100 - disk_space_allocated_to_os) * system_free_disk_size / 100)
return system_free_disk_size, r_system_free_disk_size
def get_system_resources(configurations):
"""Get resources from the current host
The aim of this function is to get resources for the virtual environment
with QEMU in order to setup properly it and avoid configuration issues.
:param: configurations
- which is an object with the values loaded from the yaml.
:return:
- recommended_system_free_memory: which is the recommended system free
memory to be setup with QEMU.
- system_free_disk_size: which is the total system free disk size.
- r_system_free_disk_size: which is the recommended system
- r_system_free_disk_size: which is the recommended system
free disk size.
- recommended_system_cores: which is the recommended system cores to be
setup with QEMU.
"""
# os_system_cores will return 0 if either key1 or key2 does not exists
os_system_cores = configurations.get(
'general_system_configurations', 0).get("os_system_cores", 0)
# Getting the system free memory and the recommended system memory
_, recommended_system_free_memory = get_system_memory(
configurations)
# Getting the system free disk size and the recommended system free (GB)
system_free_disk_size, r_system_free_disk_size = (
get_free_disk_space(configurations))
# Calculating the system cores to be assigned to the controller/computes
recommended_system_cores = multiprocessing.cpu_count() - os_system_cores
return (
recommended_system_free_memory,
system_free_disk_size, r_system_free_disk_size,
recommended_system_cores)
def check_system_resources(configurations):
"""Check basic configurations.
The aim of this function is to check the following aspects before to
proceed to configure the nodes.
- checks if the disk setup by the user in the yaml is less than the
recommended free space
- checks if the memory size setup by the user in the yaml is less than the
recommended memory size.
- checks if the system cores setup by the user in the yaml is less than the
recommended system cores.
:param configurations: which is the object that contains all the
configurations from the yaml file.
"""
# checking how many configurations the yaml file has
configurations_keys = configurations.keys()
regex = re.compile('configuration_.')
total_configurations = list(filter(regex.match, configurations_keys))
# getting the system recommendations
(recommended_system_free_memory, _,
r_system_free_disk_size,
recommended_system_cores) = get_system_resources(configurations)
# iterating over the total configurations setup in yaml file in order to
# get the disk/memory space assigned by the user
user_memory_defined, user_disk_space_defined, user_system_cores_defined = (
0, 0, 0)
for configuration in range(0, len(total_configurations)):
# iterating over the configurations
current_controller = 'controller-{}'.format(configuration)
# controller will return NoneType if either key1 or key2 does
# not exists
controller = configurations.get(
'configuration_{}'.format(configuration), {}).get(
'controller-{}'.format(configuration), {})
controller_partition_a = int(controller.get(
'controller_{}_partition_a'.format(configuration)))
controller_partition_b = int(controller.get(
'controller_{}_partition_b'.format(configuration)))
controller_partition_d = int(controller.get(
'controller_{}_partition_d'.format(configuration)))
controller_memory = int(controller.get(
'controller_{}_memory_size'.format(configuration)))
controller_system_cores = int(controller.get(
'controller_{}_system_cores'.format(configuration)))
# checking if the current controller at least has 1 cpu assigned in
# order to avoid the following error:
# error: XML error: Invalid CPU topology
if controller_system_cores < 1:
LOG.error('{}: must have assigned at least 1 core'.format(
current_controller))
exit_dict_status(1)
# checking how many computes the current controller has
compute_keys = configurations.get('configuration_{}'.format(
configuration), {}).keys()
regex = re.compile('controller-{0}-compute-.'.format(configuration))
total_computes = list(filter(regex.match, compute_keys))
for compute_number in range(0, len(total_computes)):
current_compute = '{0}-compute-{1}'.format(
current_controller, compute_number)
# compute will return NoneType if either key1 or key2 does
# not exists controller_1_compute_2:
compute = configurations.get('configuration_{}'.format(
configuration), {}).get(
'controller-{0}-compute-{1}'.format(
configuration, compute_number), {})
compute_partition_a = int(compute.get(
'controller_{0}_compute_{1}_partition_a'.format(
configuration, compute_number)))
compute_partition_b = int(compute.get(
'controller_{0}_compute_{1}_partition_b'.format(
configuration, compute_number)))
compute_memory = int(compute.get(
'controller_{0}_compute_{1}_memory_size'.format(
configuration, compute_number)))
compute_system_cores = int(compute.get(
'controller_{0}_compute_{1}_system_cores'.format(
configuration, compute_number)))
# checking if the current compute at least has 1 cpu assigned in
# order to avoid the following error:
# error: XML error: Invalid CPU topology
if compute_system_cores < 1:
LOG.error('{}: must have assigned at least 1 core'.format(
current_compute))
exit_dict_status(1)
# increasing the variables (computes loop)
user_disk_space_defined = (
user_disk_space_defined + compute_partition_a +
compute_partition_b)
user_memory_defined = user_memory_defined + compute_memory
user_system_cores_defined = (
user_system_cores_defined + compute_system_cores)
# increasing the variables (controller loop)
user_disk_space_defined = (
user_disk_space_defined + controller_partition_a +
controller_partition_b + controller_partition_d)
user_memory_defined = user_memory_defined + controller_memory
user_system_cores_defined = (
user_system_cores_defined + controller_system_cores)
# checking the conditions defined in the yaml
if user_memory_defined > recommended_system_free_memory:
LOG.error(
'the memory defined in the yaml is greater than the recommended '
'free memory')
LOG.error('user memory defined : {}'.format(
user_memory_defined))
LOG.error('recommended system free memory : {}'.format(
recommended_system_free_memory))
exit_dict_status(1)
elif user_disk_space_defined > r_system_free_disk_size:
LOG.error(
'the disk space defined in the yaml is greater than the '
'recommended free disk size')
LOG.error('user disk space defined : {}'.format(
user_disk_space_defined))
LOG.error('recommended system free disk size : {}'.format(
r_system_free_disk_size))
exit_dict_status(1)
elif user_system_cores_defined > recommended_system_cores:
LOG.error(
'the system cores defined in the yaml is greater than the '
'recommended system cores')
LOG.error('user system cores defined : {}'.format(
user_system_cores_defined))
LOG.error('recommended system cores : {}'.format(
recommended_system_cores))
exit_dict_status(1)
def setup_controller_computes(iso_file, configurations):
"""Setup the configurations in the host
This function setup the network and the configurations from yaml in the
current host.
:param iso_file: which is the absolute/relative path to the iso file which
will be setup in the controller(s) node(s).
:param configurations: which is the object that has all the configurations
to be setup in the system.
"""
# define the module's variables
libvirt_images_path = '/var/lib/libvirt/images'
# ----------------------------------
# customize Qemu configuration files
# ----------------------------------
utils.qemu_configuration_files()
# ----------------------------------
# configuring the network interfaces
# ----------------------------------
network.delete_network_interfaces()
enable_nat_network()
network.configure_network_interfaces()
# ------------------------------
# clean qemu/libvirt environment
# ------------------------------
utils.clean_qemu_environment()
if os.path.exists(os.path.join(THIS_PATH, 'vms')):
rmtree(os.path.join(THIS_PATH, 'vms'))
os.mkdir(os.path.join(THIS_PATH, 'vms'))
# ----------------------------------------------------------
# iterating over the total configurations setup in yaml file
# ----------------------------------------------------------
for controller, values in configurations.get('Controllers').items():
# iterating over the controllers
controller_partition_a = int(values.get('partition_a'))
controller_partition_b = int(values.get('partition_b'))
controller_partition_d = int(values.get('partition_d'))
controller_memory = int(values.get('memory_size'))
controller_system_cores = int(values.get('system_cores'))
# creating controller's partitions in the system
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-0.img {2}G'.format(
libvirt_images_path, controller, controller_partition_a),
raise_exception=True)
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-1.img {2}G'.format(
libvirt_images_path, controller, controller_partition_b),
raise_exception=True)
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-2.img {2}G'.format(
libvirt_images_path, controller, controller_partition_d),
raise_exception=True)
# Only controller-0 needs to have the ISO file in order to boot the
# subsequent controllers
# heck_controller = False if configuration == 'controller-0' else True
if controller == 'controller-0':
bash.run_command(
'sed -e "s,NAME,{0}," '
'-e "s,ISO,{1}," '
'-e "s,UNIT,MiB," '
'-e "s,MEMORY,{2}," '
'-e "s,CORES,{3}," '
'-e "s,DISK0,{4}/{0}-0.img," '
'-e "s,DISK1,{4}/{0}-1.img," '
'-e "s,DISK2,{4}/{0}-2.img," '
'-e "s,destroy,restart," {5}/master_controller.xml > '
'{5}/vms/{0}.xml'.format(
controller, iso_file, controller_memory,
controller_system_cores, libvirt_images_path, THIS_PATH),
raise_exception=True)
else:
# this mean that is the controller-N
# modifying xml parameters for the current controller
bash.run_command(
'sed -e "s,NAME,{0}," '
'-e "s,UNIT,MiB," '
'-e "s,MEMORY,{1}," '
'-e "s,CORES,{2}," '
'-e "s,DISK0,{3}/{0}-0.img," '
'-e "s,DISK1,{3}/{0}-1.img," '
'-e "s,DISK2,{3}/{0}-2.img," '
'-e "s,destroy,restart," {4}/slave_controller.xml > '
'{4}/vms/{0}.xml'.format(
controller, controller_memory,
controller_system_cores, libvirt_images_path, THIS_PATH),
raise_exception=True)
# the following command define a domain and it does not start it and
# makes it persistent even after shutdown
bash.run_command('sudo virsh define {0}/vms/{1}.xml'.format(
THIS_PATH, controller))
# starting only the controller-0 which is the one with ISO in the xml
if controller == 'controller-0':
# the following command start a domain
bash.run_command('sudo virsh start {}'.format(
controller), raise_exception=True)
if 'Computes' in configurations:
for compute, values in configurations.get('Computes').items():
# iterating over the computes
compute_partition_a = int(values.get('partition_a'))
compute_partition_b = int(values.get('partition_b'))
compute_memory = int(values.get('memory_size'))
compute_system_cores = int(values.get('system_cores'))
# copy the compute.xml to vms folder
origin = os.path.join(THIS_PATH, 'compute.xml')
destination = os.path.join(THIS_PATH,
'vms', '{}.xml'.format(compute))
copy(origin, destination)
# creating both compute's partitions in the system
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-0.img {2}G'.format(
libvirt_images_path, compute, compute_partition_a),
raise_exception=True)
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-1.img {2}G'.format(
libvirt_images_path, compute, compute_partition_b),
raise_exception=True)
# modifying xml compute parameters
bash.run_command(
'sed -i -e "s,NAME,{0}," '
'-e "s,UNIT,MiB," '
'-e "s,MEMORY,{1}," '
'-e "s,CORES,{2}," '
'-e "s,destroy,restart," '
'-e "s,DISK0,{3}/{0}-0.img," '
'-e "s,DISK1,{3}/{0}-1.img," '
'{4}/vms/{0}.xml'.format(compute, compute_memory,
compute_system_cores, libvirt_images_path, THIS_PATH),
raise_exception=True)
# creating the computes according to the XML, the following command
# create a domain but it does not start it and makes it persistent
# even after shutdown
bash.run_command('sudo virsh define {0}/vms/{1}.xml'.format(
THIS_PATH, compute))
if 'Storages' in configurations:
for storage, values in configurations.get('Storages').items():
# iterating over the storage
storage_partition_a = int(values.get('partition_a'))
storage_partition_b = int(values.get('partition_b'))
storage_memory = int(values.get('memory_size'))
storage_system_cores = int(values.get('system_cores'))
# copy the storage.xml to vms folder
origin = os.path.join(THIS_PATH, 'storage.xml')
destination = os.path.join(THIS_PATH,
'vms', '{}.xml'.format(storage))
copy(origin, destination)
# creating both storage's partitions in the system
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-0.img {2}G'.format(
libvirt_images_path, storage, storage_partition_a),
raise_exception=True)
bash.run_command(
'sudo qemu-img create -f qcow2 {0}/{1}-1.img {2}G'.format(
libvirt_images_path, storage, storage_partition_b),
raise_exception=True)
# modifying xml storage parameters
bash.run_command(
'sed -i -e "s,NAME,{0}," '
'-e "s,UNIT,MiB," '
'-e "s,MEMORY,{1}," '
'-e "s,CORES,{2}," '
'-e "s,destroy,restart," '
'-e "s,DISK0,{3}/{0}-0.img," '
'-e "s,DISK1,{3}/{0}-1.img," '
'{4}/vms/{0}.xml'.format(storage, storage_memory,
storage_system_cores, libvirt_images_path, THIS_PATH),
raise_exception=True)
# creating the storage according to the XML, the following command
# create a domain but it does not start it and makes it persistent
# even after shutdown
bash.run_command('sudo virsh define {0}/vms/{1}.xml'.format(
THIS_PATH, storage))
# opening the graphical interface
if bash.is_process_running('virt-manager'):
# in order that virt-manager takes the new configurations from the yaml
# file, is needed to kill it and start again.
LOG.info('Virtual Machine Manager is active, killing it ...')
bash.run_command('sudo kill -9 $(pgrep -x virt-manager)',
raise_exception=True)
# opening Virtual Machine Manager
bash.run_command('sudo virt-manager', raise_exception=True)
# opening the controller console
bash.run_command('virt-manager -c qemu:///system --show-domain-console '
'controller-0', raise_exception=True)
exit_dict_status(0)
def setup_qemu(iso_file, configuration_file):
"""Setup StarlingX
The aim of this function is to setup StarlingX in a smart way in order
to avoid configuration issues.
:param iso_file: the iso file to be configured in the controller(s).
:param configuration_file: the yaml configuration file.
"""
# before to run anything, KVM needs to be checked it this is present in the
# current host
check_kernel_virtualization()
# check the host requirements
check_preconditions()
# loading all the configurations from yaml file
configurations = yaml.safe_load(open(configuration_file))
# fixme(Humberto): check_system_resources is commented out due
# check is giving problems when configuring an instance on qemu virtual
# machine, for now this will be commented until more investigation is done
# this part will check the values given in the yaml
# check_system_resources(configurations)
# setting the controller/computes nodes
setup_controller_computes(iso_file, configurations)
def arguments():
"""Provides a set of arguments
Defined arguments must be specified in this function in order to interact
with the others functions in this module.
"""
parser = argparse.ArgumentParser(
formatter_class=RawDescriptionHelpFormatter, description='''
Program description:
This is a tool for setup virtual environments with libvirt/Qemu in the host.
maintainer : humberto.i.perez.rodriguez@intel.com''',
epilog='StarlingX |https://opendev.org/starlingx/test/',
usage='%(prog)s [options]')
group_mandatory = parser.add_argument_group('mandatory arguments')
group_mandatory.add_argument(
'-i', '--iso', dest='iso', required=True,
help='the iso file to be setup in the controller')
parser.add_argument(
'-c', '--configuration', dest='configuration',
help='the Qemu configuration file in yaml format. The default '
'configuration file is qemu_setup.yaml in this folder')
args = parser.parse_args()
# checks if the iso file given exists
if not os.path.isfile(args.iso):
print('{0}: does not exists, please verify it'.format(args.iso))
exit_dict_status(1)
# checks if the configuration exists
configuration_file = os.path.join(THIS_PATH, 'qemu_setup.yaml')
if args.configuration:
configuration_file = args.configuration
if not os.path.exists(configuration_file):
print('{0}: does not exists, please verify it'.format(
configuration_file))
exit_dict_status(1)
setup_qemu(args.iso, configuration_file)
if __name__ == '__main__':
arguments()

View File

@ -0,0 +1,32 @@
configuration_0:
controller-0:
controller_0_partition_a: 200
controller_0_partition_b: 200
controller_0_memory_size: 10240
controller_0_system_cores: 4
controller-0-compute-0:
controller_0_compute_0_partition_a: 200
controller_0_compute_0_partition_b: 200
controller_0_compute_0_memory_size: 16384
controller_0_compute_0_system_cores: 4
controller-0-compute-1:
controller_0_compute_1_partition_a: 200
controller_0_compute_1_partition_b: 200
controller_0_compute_1_memory_size: 16384
controller_0_compute_1_system_cores: 4
configuration_1:
controller-1:
controller_1_partition_a: 200
controller_1_partition_b: 200
controller_1_memory_size: 10240
controller_1_system_cores: 4
controller-1-compute-0:
controller_1_compute_0_partition_a: 200
controller_1_compute_0_partition_b: 200
controller_1_compute_0_memory_size: 3072
controller_1_compute_0_system_cores: 2
general_system_configurations:
os_system_memory: 1024
disk_space_allocated_to_os: 20
os_system_cores: 2
default_mount_point: '/'

View File

@ -0,0 +1,99 @@
<domain type='kvm' id='164'>
<name>NAME</name>
<memory unit='UNIT'>MEMORY</memory>
<currentMemory unit='UNIT'>MEMORY</currentMemory>
<vcpu placement='static'>CORES</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu match='exact'>
<model fallback='forbid'>Nehalem</model>
<topology sockets='1' cores='CORES' threads='1'/>
<feature policy='optional' name='vmx'/>
<feature policy='optional' name='svm'/>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK0'/>
<backingStore/>
<target dev='sda' bus='sata'/>
<boot order='1'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK1'/>
<backingStore/>
<target dev='sdb' bus='sata'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK2'/>
<backingStore/>
<target dev='sdd' bus='sata'/>
</disk>
<interface type='bridge'>
<source bridge='stxbr1'/>
<target dev='vnet0'/>
<model type='e1000'/>
<alias name='net0'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr2'/>
<target dev='vnet1'/>
<model type='e1000'/>
<boot order='2'/>
<alias name='net1'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr3'/>
<target dev='vnet2'/>
<model type='virtio'/>
<alias name='net2'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr4'/>
<target dev='vnet3'/>
<model type='virtio'/>
<alias name='net3'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/8'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/8'>
<source path='/dev/pts/8'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1,92 @@
<domain type='kvm' id='187'>
<name>NAME</name>
<memory unit='UNIT'>MEMORY</memory>
<currentMemory unit='UNIT'>MEMORY</currentMemory>
<vcpu placement='static'>CORES</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu match='exact'>
<model fallback='forbid'>Nehalem</model>
<topology sockets='1' cores='CORES' threads='1'/>
<feature policy='require' name='vmx'/>
<feature policy='optional' name='svm'/>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK0'/>
<backingStore/>
<target dev='sda' bus='sata'/>
<boot order='1'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='DISK1'/>
<backingStore/>
<target dev='sdb' bus='sata'/>
</disk>
<interface type='bridge'>
<source bridge='stxbr1'/>
<target dev='vnet8'/>
<model type='e1000'/>
<alias name='net0'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr2'/>
<target dev='vnet9'/>
<model type='e1000'/>
<boot order='2'/>
<alias name='net1'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr3'/>
<target dev='vnet10'/>
<model type='virtio'/>
<alias name='net2'/>
</interface>
<interface type='bridge'>
<source bridge='stxbr4'/>
<target dev='vnet11'/>
<model type='virtio'/>
<alias name='net3'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/12'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/12'>
<source path='/dev/pts/12'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5903' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1,47 @@
nodes:
controller-0:
name: controller-0
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
installation_ip:
controller-1:
name: controller-1
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
compute-0:
name: compute-0
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
compute-1:
name: compute-1
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
storage-0:
name: storage-0
personality: storage
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
storage-1:
name: storage-1
personality: storage
bmc_ip:
bmc_user: usr
bmc_pswd: psw
pxe_nic_mac:
extra_data_if_needed:
value1:
value2:

View File

@ -0,0 +1,18 @@
nodes:
controller-0:
name: controller-0
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
installation_ip:
oam_if:
mgmt_if:
controller-1:
name: controller-1
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:

View File

@ -0,0 +1,32 @@
nodes:
controller-0:
name: controller-0
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
installation_ip:
oam_if:
mgmt_if:
controller-1:
name: controller-1
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
compute-0:
name: compute-0
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
compute-1:
name: compute-1
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:

View File

@ -0,0 +1,46 @@
nodes:
controller-0:
name: controller-0
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
installation_ip:
oam_if:
mgmt_if:
controller-1:
name: controller-1
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
compute-0:
name: compute-0
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
compute-1:
name: compute-1
personality: worker
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
storage-0:
name: storage-0
personality: storage
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
storage-1:
name: storage-1
personality: storage
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:

View File

@ -0,0 +1,11 @@
nodes:
controller-0:
name: controller-0
personality: controller
bmc_ip:
bmc_user: usr
bmc_pswd: pswd
pxe_nic_mac:
installation_ip:
oam_if:
mgmt_if:

View File

@ -0,0 +1,14 @@
watchdog
robotframework==3.1.1
robotframework-debuglibrary
robotframework-seleniumlibrary
robotframework-sshlibrary
pexpect
PyYaml
netifaces
bash
elevate
ifparser
pynetlinux
kmodpy
psutil

View File

@ -0,0 +1,9 @@
flake8==2.6.2
hacking
flake8-import-order
mock
coverage
pylint
pep8-naming
ipdb
ipython