Revert "Revert "Introduce deployment test for Ironic""

fuel-devops 2.9.16 has been released, and updated on jenkins slave. Also python-ironicclient has been installed.

This reverts commit 87a7bca7ee.

Change-Id: I072370299a16a02f98a79402a1c9c3efa379275e
This commit is contained in:
Vasyl Saienko 2016-01-20 12:44:33 +00:00 committed by vsaienko
parent 87a7bca7ee
commit e918673387
5 changed files with 307 additions and 0 deletions

View File

@ -122,3 +122,8 @@ SSH Manager
-----------
.. automodule:: fuelweb_test.helpers.ssh_manager
:members:
Ironic Actions
--------------
.. automodule:: fuelweb_test.helpers.ironic_actions
:members:

View File

@ -27,6 +27,7 @@ from keystoneclient.exceptions import ClientException
from novaclient.v2 import Client as NovaClient
import neutronclient.v2_0.client as neutronclient
from proboscis.asserts import assert_equal
import ironicclient.client as ironicclient
class Common(object):
@ -75,6 +76,14 @@ class Common(object):
token=token,
cacert=path_to_cert)
ironic_endpoint = self.keystone.service_catalog.url_for(
service_type='baremetal',
endpoint_type='publicURL')
self.ironic = ironicclient.get_client(
api_version=1,
os_auth_token=token,
ironic_url=ironic_endpoint, insecure=True)
def goodbye_security(self):
secgroup_list = self.nova.security_groups.list()
LOGGER.debug("Security list is {0}".format(secgroup_list))

View File

@ -0,0 +1,107 @@
# 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 devops.helpers.helpers import tcp_ping
from devops.helpers.helpers import wait
from fuelweb_test.helpers import os_actions
import json
class IronicActions(os_actions.OpenStackActions):
"""IronicActions.""" # TODO documentation
def __init__(self, controller_ip, user='admin',
passwd='admin', tenant='admin'):
super(IronicActions, self).__init__(controller_ip,
user, passwd,
tenant)
def upload_user_image(self, nailgun_node, ssh_manager, img_url):
disk_info = [{"name": "vda", "extra": [], "free_space": 11000,
"type": "disk", "id": "vda", "size": 11000,
"volumes": [{"mount": "/", "type": "partition",
"file_system": "ext4", "size": 10000}]}]
cmd = ('. /root/openrc; cd /tmp/; '
'curl {img_url} | tar -xzp; '
'glance image-create --name virtual_trusty_ext4 '
'--disk-format raw --container-format bare '
'--file trusty-server-cloudimg-amd64.img --visibility public '
'--property cpu_arch="x86_64" '
'--property hypervisor_type="baremetal" '
'--property mos_disk_info=\'{disk_info}\'').format(
disk_info=json.dumps(disk_info),
img_url=img_url)
ssh_manager.execute_on_remote(nailgun_node['ip'], cmd=cmd)
def enroll_ironic_node(self, ironic_slave, hw_ip):
deploy_kernel = self.get_image_by_name('ironic-deploy-linux')
deploy_ramdisk = self.get_image_by_name('ironic-deploy-initramfs')
deploy_squashfs = self.get_image_by_name('ironic-deploy-squashfs')
libvirt_uri = 'qemu+tcp://{server_ip}/system'.format(
server_ip=hw_ip)
driver_info = {'libvirt_uri': libvirt_uri,
'deploy_kernel': deploy_kernel.id,
'deploy_ramdisk': deploy_ramdisk.id,
'deploy_squashfs': deploy_squashfs.id}
mac_address = ironic_slave.interface_by_network_name(
'ironic')[0].mac_address
properties = {'memory_mb': ironic_slave.memory,
'cpu_arch': ironic_slave.architecture,
'local_gb': '50',
'cpus': ironic_slave.vcpu}
ironic_node = self.create_ironic_node(driver='fuel_libvirt',
driver_info=driver_info,
properties=properties)
self.create_ironic_port(address=mac_address,
node_uuid=ironic_node.uuid)
def wait_for_ironic_hypervisors(self, ironic_conn, ironic_slaves):
def _wait_for_ironic_hypervisor():
hypervisors = ironic_conn.get_hypervisors()
ironic_hypervisors = [h for h in hypervisors if
h.hypervisor_type == 'ironic']
if len(ironic_slaves) == len(ironic_hypervisors):
for hypervisor in ironic_hypervisors:
if hypervisor.memory_mb == 0:
return False
return True
return False
wait(_wait_for_ironic_hypervisor,
timeout=60 * 3, timeout_msg='Failed to update hypervisor details')
def wait_for_vms(self, ironic_conn):
srv_list = ironic_conn.get_servers()
for srv in srv_list:
wait(lambda: self.get_instance_detail(srv).status == "ACTIVE",
timeout=60 * 15, timeout_msg='Server didn\'t became active')
def verify_vms_connection(self, ironic_conn):
srv_list = ironic_conn.get_servers()
for srv in srv_list:
wait(lambda: tcp_ping(srv.networks['baremetal'][0], 22),
timeout=60 * 5, timeout_msg='Failed to connect to port 22')
def create_ironic_node(self, **kwargs):
return self.ironic.node.create(**kwargs)
def create_ironic_port(self, **kwargs):
return self.ironic.port.create(**kwargs)

View File

@ -562,3 +562,8 @@ CENTOS_DUMMY_DEPLOY = get_var_as_bool("CENTOS_DUMMY_DEPLOY", False)
PERESTROIKA_REPO = os.environ.get(
"PERESTROIKA_REPO", "http://perestroika-repo-tst.infra.mirantis.net/"
"mos-repos/centos/mos8.0-centos7-fuel/os/x86_64/")
# Ironic variables
IRONIC_USER_IMAGE_URL = os.environ.get(
"IRONIC_USER_IMAGE_URL", "https://cloud-images.ubuntu.com/trusty/current/"
"trusty-server-cloudimg-amd64.tar.gz")

View File

@ -13,7 +13,9 @@
# under the License.
from fuelweb_test.helpers.decorators import log_snapshot_after_test
from fuelweb_test.helpers import ironic_actions
from fuelweb_test.settings import DEPLOYMENT_MODE
from fuelweb_test.settings import IRONIC_USER_IMAGE_URL
from fuelweb_test.settings import NEUTRON_SEGMENT
from fuelweb_test.tests.base_test_case import SetupEnvironment
from fuelweb_test.tests.base_test_case import TestBasic
@ -80,3 +82,182 @@ class TestIronicBase(TestBasic):
cluster_id=cluster_id)
self.env.make_snapshot("ironic_base")
@test(groups=["ironic_deploy", "ironic"])
class TestIronicDeploy(TestBasic):
"""Test ironic provisioning on VM"""
def _deploy_ironic_cluster(self, **kwargs):
default_settings = {
'net_provider': 'neutron',
'net_segment_type': NEUTRON_SEGMENT['vlan'],
'ironic': True}
default_nodes = {
'slave-01': ['controller'],
'slave-02': ['controller', 'ironic'],
'slave-03': ['controller', 'ironic'],
'slave-04': ['ironic'],
'slave-05': ['compute']}
settings = kwargs.get('settings') or default_settings
nodes = kwargs.get('nodes') or default_nodes
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=DEPLOYMENT_MODE,
settings=settings
)
self.fuel_web.update_nodes(
cluster_id,
nodes
)
self.fuel_web.deploy_cluster_wait(cluster_id)
return cluster_id
def _create_os_resources(self, ironic_conn):
devops_node = self.fuel_web.get_nailgun_primary_node(
self.env.d_env.nodes().slaves[0])
nailgun_node = self.fuel_web.get_nailgun_node_by_devops_node(
devops_node)
ironic_conn.upload_user_image(nailgun_node,
ssh_manager=self.ssh_manager,
img_url=IRONIC_USER_IMAGE_URL)
ironic_slaves = self.env.d_env.nodes().ironics
server_ip = self.env.d_env.router('public')
for ironic_slave in ironic_slaves:
ironic_conn.enroll_ironic_node(ironic_slave, server_ip)
ironic_conn.wait_for_ironic_hypervisors(ironic_conn, ironic_slaves)
def _boot_nova_instances(self, ironic_conn):
ironic_slaves = self.env.d_env.nodes().ironics
user_image = ironic_conn.get_image_by_name('virtual_trusty_ext4')
network = ironic_conn.nova.networks.find(label='baremetal')
flavor = ironic_conn.create_flavor('baremetal_flavor', 1024, 1, 50)
nics = [{'net-id': network.id}]
for ironic_slave in ironic_slaves:
ironic_conn.nova.servers.create(
name=ironic_slave.name,
image=user_image.id,
flavor=flavor.id,
nics=nics)
@test(depends_on=[SetupEnvironment.prepare_slaves_5],
groups=["ironic_deploy_swift"])
@log_snapshot_after_test
def ironic_deploy_swift(self):
"""Deploy ironic with 1 baremetal node
Scenario:
1. Create cluster
2. Add 3 node with controller+ironic role
3. Add 1 node with compute role
4. Add 1 nodes with ironic role
5. Deploy the cluster
6. Upload image to glance
7. Enroll Ironic nodes
8. Boot nova instance
9. Check Nova instance status
Duration 90m
Snapshot ironic_deploy_swift
"""
self.env.revert_snapshot("ready_with_5_slaves")
self.show_step(1, initialize=True)
self.show_step(2)
self.show_step(3)
self.show_step(4)
self.show_step(5)
cluster_id = self._deploy_ironic_cluster()
ironic_conn = ironic_actions.IronicActions(
self.fuel_web.get_public_vip(cluster_id))
self.show_step(6)
self.show_step(7)
self._create_os_resources(ironic_conn)
self.show_step(8)
self._boot_nova_instances(ironic_conn)
self.show_step(9)
ironic_conn.wait_for_vms(ironic_conn)
ironic_conn.verify_vms_connection(ironic_conn)
self.env.make_snapshot("ironic_deploy_swift")
@test(depends_on=[SetupEnvironment.prepare_slaves_5],
groups=["ironic_deploy_ceph"])
@log_snapshot_after_test
def ironic_deploy_ceph(self):
"""Deploy ironic with 1 baremetal node
Scenario:
1. Create cluster
2. Add 3 node with controller+ironic+ceph-osd role
3. Add 1 node with compute role
4. Add 1 nodes with ironic role
5. Deploy the cluster
6. Upload image to glance
7. Enroll Ironic nodes
8. Boot nova instance
9. Check Nova instance status
Duration 90m
Snapshot ironic_deploy_ceph
"""
self.env.revert_snapshot("ready_with_5_slaves")
data = {
'volumes_ceph': True,
'images_ceph': True,
'objects_ceph': True,
'volumes_lvm': False,
'tenant': 'ceph1',
'user': 'ceph1',
'password': 'ceph1',
'net_provider': 'neutron',
'net_segment_type': NEUTRON_SEGMENT['vlan'],
'ironic': True}
nodes = {
'slave-01': ['controller', 'ceph-osd'],
'slave-02': ['controller', 'ironic', 'ceph-osd'],
'slave-03': ['controller', 'ironic', 'ceph-osd'],
'slave-04': ['ironic'],
'slave-05': ['compute']}
self.show_step(1, initialize=True)
self.show_step(2)
self.show_step(3)
self.show_step(4)
self.show_step(5)
cluster_id = self._deploy_ironic_cluster(settings=data, nodes=nodes)
ironic_conn = ironic_actions.IronicActions(
self.fuel_web.get_public_vip(cluster_id),
user='ceph1',
passwd='ceph1',
tenant='ceph1')
self.show_step(6)
self.show_step(7)
self._create_os_resources(ironic_conn)
self.show_step(8)
self._boot_nova_instances(ironic_conn)
self.show_step(9)
ironic_conn.wait_for_vms(ironic_conn)
ironic_conn.verify_vms_connection(ironic_conn)
self.env.make_snapshot("ironic_deploy_ceph")