Merge "Add virtual_mcp11_k8s_calico template"
diff --git a/.gitreview b/.gitreview
index 7dfb0a5..22fa62c 100644
--- a/.gitreview
+++ b/.gitreview
@@ -1,4 +1,4 @@
[gerrit]
-host=review.openstack.org
+host=review.gerrithub.io
port=29418
project=Mirantis/tcp-qa.git
diff --git a/tcp_tests/fixtures/underlay_fixtures.py b/tcp_tests/fixtures/underlay_fixtures.py
index d7351bf..1e17518 100644
--- a/tcp_tests/fixtures/underlay_fixtures.py
+++ b/tcp_tests/fixtures/underlay_fixtures.py
@@ -73,7 +73,6 @@
# for empty manager: do nothing
# for maas manager: provision nodes and wait for SSH
if not env.has_snapshot(ext.SNAPSHOT.hardware):
- env.start()
env.create_snapshot(ext.SNAPSHOT.hardware)
def fin():
@@ -173,6 +172,13 @@
if not config.underlay.ssh:
# If config.underlay.ssh wasn't provided from external config, then
# try to get necessary data from hardware manager (fuel-devops)
+
+ # for devops manager: power on nodes and wait for SSH
+ # for empty manager: do nothing
+ # for maas manager: provision nodes and wait for SSH
+ hardware.start(underlay_node_roles=config.underlay.roles,
+ timeout=config.underlay.bootstrap_timeout)
+
config.underlay.ssh = hardware.get_ssh_data(
roles=config.underlay.roles)
diff --git a/tcp_tests/helpers/oslo_cfg_types.py b/tcp_tests/helpers/oslo_cfg_types.py
index 962f2d3..135798f 100644
--- a/tcp_tests/helpers/oslo_cfg_types.py
+++ b/tcp_tests/helpers/oslo_cfg_types.py
@@ -104,7 +104,10 @@
env_var_name = args[0].upper()
if 'default' in kwargs:
- kwargs['default'] = os.environ.get(env_var_name, kwargs.get('default', None))
+ # Load a default environment variable with expected type
+ kwargs['default'] = args[1](
+ os.environ.get(env_var_name, kwargs.get('default', None))
+ )
super(Cfg, self).__init__(*args, **kwargs)
# Print info about default environment variables to console
diff --git a/tcp_tests/managers/envmanager_devops.py b/tcp_tests/managers/envmanager_devops.py
index 2116e29..c4a0642 100644
--- a/tcp_tests/managers/envmanager_devops.py
+++ b/tcp_tests/managers/envmanager_devops.py
@@ -275,7 +275,7 @@
'Environment "{0}" created'.format(env_name)
)
- def start(self):
+ def start(self, underlay_node_roles, timeout=480):
"""Method for start environment
"""
@@ -283,9 +283,8 @@
raise exceptions.EnvironmentIsNotSet()
self.__env.start()
LOG.info('Environment "{0}" started'.format(self.__env.name))
- for node in self.__env.get_nodes(role__in=ext.UNDERLAY_NODE_ROLES):
+ for node in self.__env.get_nodes(role__in=underlay_node_roles):
LOG.info("Waiting for SSH on node '{}...'".format(node.name))
- timeout = 480
helpers.wait(
lambda: helpers.tcp_ping(self.node_ip(node), 22),
timeout=timeout,
diff --git a/tcp_tests/settings_oslo.py b/tcp_tests/settings_oslo.py
index 609fd69..f51f8ce 100644
--- a/tcp_tests/settings_oslo.py
+++ b/tcp_tests/settings_oslo.py
@@ -69,6 +69,9 @@
help="Node roles managed by underlay in the environment",
default=[ext.UNDERLAY_NODE_ROLES.salt_master,
ext.UNDERLAY_NODE_ROLES.salt_minion, ]),
+ ct.Cfg('bootstrap_timeout', ct.Integer(),
+ help="Timeout of waiting SSH for nodes with specified roles",
+ default=480),
ct.Cfg('nameservers', ct.JSONList(),
help="IP addresses of DNS servers",
default=[]),
diff --git a/tcp_tests/templates/ironic_standalone/underlay--meta-data.yaml b/tcp_tests/templates/ironic_standalone/underlay--meta-data.yaml
new file mode 100644
index 0000000..3699401
--- /dev/null
+++ b/tcp_tests/templates/ironic_standalone/underlay--meta-data.yaml
@@ -0,0 +1,4 @@
+| # All the data below will be stored as a string object
+ instance-id: iid-local1
+ hostname: {hostname}
+ local-hostname: {hostname}
diff --git a/tcp_tests/templates/ironic_standalone/underlay--user-data-ironic.yaml b/tcp_tests/templates/ironic_standalone/underlay--user-data-ironic.yaml
new file mode 100644
index 0000000..54a7f79
--- /dev/null
+++ b/tcp_tests/templates/ironic_standalone/underlay--user-data-ironic.yaml
@@ -0,0 +1,130 @@
+| # All the data below will be stored as a string object
+ #cloud-config, see http://cloudinit.readthedocs.io/en/latest/topics/examples.html
+
+ ssh_pwauth: True
+ users:
+ - name: root
+ sudo: ALL=(ALL) NOPASSWD:ALL
+ shell: /bin/bash
+ ssh_authorized_keys:
+ - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCp0evjOaK8c8SKYK4r2+0BN7g+8YSvQ2n8nFgOURCyvkJqOHi1qPGZmuN0CclYVdVuZiXbWw3VxRbSW3EH736VzgY1U0JmoTiSamzLHaWsXvEIW8VCi7boli539QJP0ikJiBaNAgZILyCrVPN+A6mfqtacs1KXdZ0zlMq1BPtFciR1JTCRcVs5vP2Wwz5QtY2jMIh3aiwkePjMTQPcfmh1TkOlxYu5IbQyZ3G1ahA0mNKI9a0dtF282av/F6pwB/N1R1nEZ/9VtcN2I1mf1NW/tTHEEcTzXYo1R/8K9vlqAN8QvvGLZtZduGviNVNoNWvoxaXxDt8CPv2B2NCdQFZp
+
+ disable_root: false
+ chpasswd:
+ list: |
+ root:r00tme
+ expire: False
+
+ bootcmd:
+ # Block access to SSH while node is preparing
+ - cloud-init-per once sudo iptables -A INPUT -p tcp --dport 22 -j DROP
+ # Enable root access
+ - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
+ - service sshd restart
+ output:
+ all: '| tee -a /var/log/cloud-init-output.log /dev/tty0'
+
+ runcmd:
+ # Configure dhclient
+ - sudo echo "nameserver {gateway}" >> /etc/resolvconf/resolv.conf.d/base
+ - sudo resolvconf -u
+
+ # Prepare network connection
+ - sudo ifup ens3
+ #- sudo route add default gw {gateway} {interface_name}
+ - sudo ifup ens4
+
+ # Create swap
+ - fallocate -l 4G /swapfile
+ - chmod 600 /swapfile
+ - mkswap /swapfile
+ - swapon /swapfile
+ - echo "/swapfile none swap defaults 0 0" >> /etc/fstab
+
+ ############## TCP Cloud cfg01 node ##################
+ #- sleep 120
+ - echo "Preparing base OS"
+
+ - echo "172.18.248.114 jenkins.mcp.mirantis.net gerrit.mcp.mirantis.net" >> /etc/hosts;
+ - echo "185.135.196.10 apt-mk.mirantis.com" >> /etc/hosts;
+ - echo "nameserver 172.18.208.44 >> /etc/resolv.conf;
+ - echo "nameserver 8.8.8.8 >> /etc/resolv.conf;
+ - which wget >/dev/null || (apt-get update; apt-get install -y wget);
+
+ - export IRONIC_PXE_MANAGER=dnsmasq
+ - export IRONIC_PXE_INTERFACE_NAME=ens4
+ - export IRONIC_PXE_INTERFACE_ADDRESS=10.0.175.2
+ - export IRONIC_DHCP_POOL_NETMASK_PREFIX=24
+ - export IRONIC_DHCP_POOL_START=10.0.175.100
+ - export IRONIC_DHCP_POOL_END=10.0.175.200
+ - export DNSMASQ_USE_EXTERNAL_DNS=true
+ - ip a a $IRONIC_PXE_INTERFACE_ADDRESS/$IRONIC_DHCP_POOL_NETMASK_PREFIX dev $IRONIC_PXE_INTERFACE_NAME
+ - curl https://raw.githubusercontent.com/dis-xcom/underpillar/master/bootstrap.sh -o ./bootstrap.sh && bash ./bootstrap.sh
+
+ - echo "Building ironic agent image (stable/newton) ..."
+ - apt-get install -y docker.io gzip uuid-runtime cpio findutils grep gnupg make
+ - service docker start
+ - git clone https://git.openstack.org/openstack/ironic-python-agent /tmp/ironic-python-agent
+ - cd /tmp/ironic-python-agent/imagebuild/coreos; git checkout stable/newton; make
+ - cp /tmp/ironic-python-agent/imagebuild/coreos/UPLOAD/coreos_production_pxe_image-oem.cpio.gz /httpboot/
+ - cp /tmp/ironic-python-agent/imagebuild/coreos/UPLOAD/coreos_production_pxe.vmlinuz /httpboot/
+ - chmod a+r /httpboot/coreos_production_pxe*
+
+ - echo "Download ubuntu cloudinit image"
+ - wget https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -O /httpboot/xenial-server-cloudimg-amd64.qcow2
+
+ ########################################################
+ # Node is ready, allow SSH access
+ - echo "Allow SSH access ..."
+ - sudo iptables -D INPUT -p tcp --dport 22 -j DROP
+ ########################################################
+
+ write_files:
+ - path: /etc/network/interfaces
+ content: |
+ auto ens3
+ iface ens3 inet dhcp
+ auto ens4
+ iface ens4 inet manual
+
+ - path: /root/.ssh/id_rsa
+ owner: root:root
+ permissions: '0600'
+ content: |
+ -----BEGIN RSA PRIVATE KEY-----
+ MIIEogIBAAKCAQEAqdHr4zmivHPEimCuK9vtATe4PvGEr0Np/JxYDlEQsr5Cajh4
+ tajxmZrjdAnJWFXVbmYl21sN1cUW0ltxB+9+lc4GNVNCZqE4kmpsyx2lrF7xCFvF
+ Qou26JYud/UCT9IpCYgWjQIGSC8gq1TzfgOpn6rWnLNSl3WdM5TKtQT7RXIkdSUw
+ kXFbObz9lsM+ULWNozCId2osJHj4zE0D3H5odU5DpcWLuSG0MmdxtWoQNJjSiPWt
+ HbRdvNmr/xeqcAfzdUdZxGf/VbXDdiNZn9TVv7UxxBHE812KNUf/Cvb5agDfEL7x
+ i2bWXbhr4jVTaDVr6MWl8Q7fAj79gdjQnUBWaQIDAQABAoIBAFU3kU6yIna9BViH
+ UX+S2ijtRBjZ68JjavEnp4xvo5h+nydcdT57q9lv/0nAi3g3gmXm/oJH+/ZU87HV
+ zy+zP+t+umDSChUkPBZFL5jxpKyN7BhMrP1KzRuEGYd6vJE/nfY5g095P5vDgnpX
+ o+SNg/YqrY1u8zgr/hnfRaV2/XyIDEEcQXTHseWTnnMQnULFU88xL8yq8ACT5GhK
+ 7A9m5ukfcU6d/fs/psz5Yqw5IQsWbv1yJ3/FKufPHlo2Nzh3/3eDAZUXvaBgf1so
+ FWFpHtkry3OXOGaZ98HgF9hL0twS0pzMvuypdGUQAt6nyB1N5re4LK/MAOddqwEc
+ 1+NQzfECgYEA2ryEf0GLJdtiYs3F4HbwTwJVIXdyWv7kjYGeMkutzzAjXl6wx8aq
+ kfqLJ7x7UkR5unZ1ajEbKBciAlSuFA+Gikn6a4Lv8h87aSnHpPd/2VSitRlI/gW7
+ w4U4CL3Br1JyonU5WA7VYfTow7KnHBhdwm27RMA9uosyIpveQRpqSG0CgYEAxsAS
+ wCQKrhuPq2YtGtFR7K4BL+N+0E1Vq6h49u1ukcgUe0GHVD3VzBypNCv7rWEVHzAg
+ biCVi7PCjzZYW4fYZmzVD4JbFLVGOUu7aJwLaE4wDe72DNr6YZhcS+Ta98BP+x0q
+ Wt34JNPDabRPfhXfhiCqnWjjod+4Zqx4VJVNgG0CgYB5EXL8xJhyAbW5Hk/x56Mm
+ +BGKjoR7HS3/rMiU6hJv5SMObrbGPI3YcqZm/gn8BO6jaEGg30E6tWMbiyc270j2
+ be/vZe/NQcAuevOHuX3IGvJb7nzaLO46UBgtrmnv0mCkzuFIfh1ZNKdI+i9Ie6wZ
+ m4bVjNod0EGVqlQgELDXGQKBgB+NNmzSS++/6FrpaZesSzkrlnynvOYMoOETacCp
+ iLgT70xx5q308w/oLORfZyDrHJNK7JsPCS6YZvadRgGh2zTHajuAEj2DWZaW8zV0
+ MEtqvi44FU+NI9qCeYSC3FAgc5IF20d5nX8bLxaEzWnSxx1f6jX7BMgZ4AhMsP2c
+ hiUxAoGAFaxn+t9blIjqUiuh0smSYFhLBVPZveYHQDmQYERjktptBd3X95fGnSKh
+ iDe2iPGyud2+Yu4X/VjHLh/MRru+ZXvPXw1XwEqX93q8a1n283ul0Rl9+KKKOVHR
+ eecTjI/BfXBf33mPRKny3xuHw6uwta2T3OXky9IhqYS1kkHiZWA=
+ -----END RSA PRIVATE KEY-----
+
+ - path: /root/.ssh/config
+ owner: root:root
+ permissions: '0600'
+ content: |
+ Host *
+ ServerAliveInterval 300
+ ServerAliveCountMax 10
+ StrictHostKeyChecking no
+ UserKnownHostsFile /dev/null
diff --git a/tcp_tests/templates/ironic_standalone/underlay.yaml b/tcp_tests/templates/ironic_standalone/underlay.yaml
new file mode 100644
index 0000000..6a25ced
--- /dev/null
+++ b/tcp_tests/templates/ironic_standalone/underlay.yaml
@@ -0,0 +1,111 @@
+# Set the repository suite, one of the: 'nightly', 'testing', 'stable', or any other required
+{% set REPOSITORY_SUITE = os_env('REPOSITORY_SUITE', 'stable') %}
+
+{% import 'ironic_standalone/underlay--meta-data.yaml' as CLOUDINIT_META_DATA with context %}
+{% import 'ironic_standalone/underlay--user-data-ironic.yaml' as CLOUDINIT_USER_DATA_IRONIC with context %}
+
+---
+aliases:
+ - &interface_model {{ os_env('INTERFACE_MODEL', 'virtio') }}
+ - &cloudinit_meta_data {{ CLOUDINIT_META_DATA }}
+ - &cloudinit_user_data_ironic {{ CLOUDINIT_USER_DATA_IRONIC }}
+
+{% set DOMAIN_NAME = os_env('LAB_CONFIG_NAME', 'standalone') + '.local' %}
+{% set HOSTNAME_IRONIC = os_env('HOSTNAME_IRONIC', 'ironic_master') %}
+
+
+template:
+ devops_settings:
+ env_name: {{ os_env('IRONIC_ENV_NAME', 'ironic_' + DOMAIN_NAME + '_' + REPOSITORY_SUITE + '_' + os_env('BUILD_NUMBER', '')) }}
+
+ address_pools:
+
+ ironic-pool01:
+ net: {{ os_env('IRONIC_ADDRESS_POOL01', '10.50.0.0/16:24') }}
+ params:
+ ip_reserved:
+ gateway: +1
+ l2_network_device: +1
+ default_{{ HOSTNAME_IRONIC }}: +2
+ ip_ranges:
+ dhcp: [+90, -10]
+
+ admin-pool01:
+ net: {{ os_env('ADMIN_ADDRESS_POOL01', '10.70.0.0/16:24') }}
+ params:
+ ip_reserved:
+ gateway: +1
+ l2_network_device: +1
+ default_{{ HOSTNAME_IRONIC }}: +2
+
+ groups:
+ - name: default
+ driver:
+ name: devops.driver.libvirt
+ params:
+ connection_string: !os_env CONNECTION_STRING, qemu:///system
+ storage_pool_name: !os_env STORAGE_POOL_NAME, default
+ stp: False
+ hpet: False
+ enable_acpi: true
+ use_host_cpu: !os_env DRIVER_USE_HOST_CPU, true
+
+ network_pools:
+ admin: admin-pool01
+
+ l2_network_devices:
+ # Ironic management interface
+ ironic:
+ address_pool: ironic-pool01
+ dhcp: true
+ forward:
+ mode: nat
+
+ # PXE / Salt-master admin network
+ admin:
+ address_pool: admin-pool01
+ dhcp: false
+ parent_iface:
+ phys_dev: !os_env BAREMETAL_ADMIN_IFACE, enp8s0f1
+
+ group_volumes:
+ - name: cloudimage1604 # This name is used for 'backing_store' option for node volumes.
+ source_image: !os_env IMAGE_PATH1604 # https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img or
+ # http://apt.tcpcloud.eu/images/ubuntu-16-04-x64-201608231004.qcow2
+ format: qcow2
+
+ nodes:
+ - name: {{ HOSTNAME_IRONIC }}
+ role: ironic_master
+ params:
+ vcpu: !os_env SLAVE_NODE_CPU, 1
+ memory: !os_env SLAVE_NODE_MEMORY, 2048
+ boot:
+ - hd
+ cloud_init_volume_name: iso
+ cloud_init_iface_up: ens3
+ volumes:
+ - name: system
+ capacity: !os_env NODE_VOLUME_SIZE, 150
+ backing_store: cloudimage1604
+ format: qcow2
+ - name: iso # Volume with name 'iso' will be used
+ # for store image with cloud-init metadata.
+ capacity: 1
+ format: raw
+ device: cdrom
+ bus: ide
+ cloudinit_meta_data: *cloudinit_meta_data
+ cloudinit_user_data: *cloudinit_user_data_ironic
+
+ interfaces:
+ - label: ens3
+ l2_network_device: ironic
+ interface_model: *interface_model
+ - label: ens4
+ l2_network_device: admin
+ interface_model: *interface_model
+ network_config:
+ ens4:
+ networks:
+ - admin
diff --git a/tcp_tests/tests/environment/conftest.py b/tcp_tests/tests/environment/conftest.py
new file mode 100644
index 0000000..90f0fd4
--- /dev/null
+++ b/tcp_tests/tests/environment/conftest.py
@@ -0,0 +1,48 @@
+# Copyright 2016 Mirantis, 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.
+
+#from tcp_tests.fixtures import *
+from tcp_tests.fixtures.common_fixtures import *
+from tcp_tests.fixtures.config_fixtures import *
+from tcp_tests.fixtures.underlay_fixtures import *
+from tcp_tests.fixtures.rally_fixtures import *
+from tcp_tests.fixtures.salt_fixtures import *
+from tcp_tests.fixtures.common_services_fixtures import *
+from tcp_tests.fixtures.openstack_fixtures import *
+from tcp_tests.fixtures.opencontrail_fixtures import *
+
+__all__ = sorted([ # sort for documentation
+ # common_fixtures
+ 'show_step',
+ 'revert_snapshot',
+ 'snapshot',
+ # config_fixtures
+ 'config',
+ #underlay_fixtures
+ 'hardware',
+ 'underlay',
+ # rally_fixtures
+ 'rally',
+ # salt_fixtures
+ 'salt_actions',
+ 'salt_deployed',
+ # common_services_fixtures
+ 'common_services_actions',
+ 'common_services_deployed',
+ # openstack_fixtures
+ 'openstack_actions',
+ 'openstack_deployed',
+ # component fixtures
+ 'opencontrail',
+])
diff --git a/tcp_tests/tests/environment/test_ironic_standalone.py b/tcp_tests/tests/environment/test_ironic_standalone.py
new file mode 100644
index 0000000..8d60279
--- /dev/null
+++ b/tcp_tests/tests/environment/test_ironic_standalone.py
@@ -0,0 +1,60 @@
+# Copyright 2016 Mirantis, 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.
+import copy
+import os
+import time
+
+import pytest
+
+from tcp_tests import settings
+from tcp_tests.helpers import ext
+from tcp_tests import logger
+
+LOG = logger.logger
+
+
+class TestIronicStandalone(object):
+ """Test class for testing TCP deployment"""
+
+ @pytest.mark.fail_snapshot
+ def test_install_ironic_standalone(self, config, underlay):
+ """Install a VM with standalone ironic
+
+ Before using, please set the correct roles and timeout:
+
+ export ROLES='["ironic_master"]'
+ export BOOTSTRAP_TIMEOUT=900
+
+ , and unset these variables after the bootstrap is completed.
+
+ Scenario:
+ 1. Install Ironic service and helper services
+ 2. Build ironic agent image
+ 3. Download Ubuntu cloud image and calculate MD5
+ 4. export environment variables to further use
+
+ """
+ cmd = "md5sum /httpboot/xenial-server-cloudimg-amd64.qcow2 | awk '{print $1}'"
+ res = underlay.check_call(cmd, host=config.salt.salt_master_host, verbose=True)
+
+ ironic_url = 'http://{0}:6385/'.format(config.salt.salt_master_host)
+ os.environ['CLOUDINIT_IMAGE_MD5'] = res['stdout']
+ os.environ['OS_AUTH_TOKEN'] = 'fake-token'
+ os.environ['IRONIC_URL'] = ironic_url
+
+ LOG.info("Ironic standalone server installed, to use it:\n"
+ " export OS_AUTH_TOKEN=fake-token\n"
+ " export IRONIC_URL={0}\n"
+ " export CLOUDINIT_IMAGE_MD5={1}"
+ .format(ironic_url, res['stdout']))