529 lines
20 KiB
Python
529 lines
20 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2013 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 nailgun import consts
|
|
from nailgun.db.sqlalchemy.models import Node
|
|
from nailgun import objects
|
|
|
|
from nailgun.orchestrator import provisioning_serializers as ps
|
|
from nailgun.settings import settings
|
|
from nailgun.test.base import BaseIntegrationTest
|
|
from nailgun import utils
|
|
|
|
|
|
class TestGetSerializerForCluster(BaseIntegrationTest):
|
|
|
|
def _get_cluster(self, version):
|
|
"""Returns cluster object of a given version."""
|
|
release = self.env.create_release(api=False, version=version)
|
|
cluster = self.env.create_cluster(api=False, release_id=release.id)
|
|
return cluster
|
|
|
|
def test_env_5_0(self):
|
|
cluster = self._get_cluster('2014.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_5_0_1(self):
|
|
cluster = self._get_cluster('2014.1.1-5.0.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_5_1(self):
|
|
cluster = self._get_cluster('2014.1.1-5.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_5_1_1(self):
|
|
cluster = self._get_cluster('2014.1.1-5.1.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_6_0(self):
|
|
cluster = self._get_cluster('2014.2-6.0')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_6_0_1(self):
|
|
cluster = self._get_cluster('2014.2-6.0.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer)
|
|
|
|
def test_env_6_1(self):
|
|
cluster = self._get_cluster('2014.2-6.1')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer61)
|
|
|
|
def test_env_7_0(self):
|
|
cluster = self._get_cluster('2015.1-7.0')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer70)
|
|
|
|
def test_env_8_0(self):
|
|
cluster = self._get_cluster('2015.1-8.0')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer80)
|
|
|
|
def test_env_9_0(self):
|
|
cluster = self._get_cluster('2016.1-9.0')
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
|
|
self.assertIs(serializer, ps.ProvisioningSerializer90)
|
|
|
|
|
|
class TestProvisioningSerializer(BaseIntegrationTest):
|
|
|
|
def setUp(self):
|
|
super(TestProvisioningSerializer, self).setUp()
|
|
self.cluster_db = self.env.create()
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, 1,
|
|
**{
|
|
'roles': ['controller'],
|
|
'pending_addition': True,
|
|
'cluster_id': self.cluster_db.id
|
|
}
|
|
)
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, 1,
|
|
**{
|
|
'roles': ['compute'],
|
|
'pending_addition': True,
|
|
'cluster_id': self.cluster_db.id
|
|
}
|
|
)
|
|
self.attributes = self.cluster_db.attributes.editable
|
|
self.serialized_cluster = ps.serialize(
|
|
self.cluster_db, self.cluster_db.nodes)
|
|
|
|
def test_cloud_init_templates_serialization(self):
|
|
release = self.env.create_release(api=False, version='2014.2-6.1.1')
|
|
cluster = self.env.create_cluster(api=False, release_id=release.id)
|
|
serializer = ps.get_serializer_for_cluster(cluster)
|
|
self.assertEqual(
|
|
serializer.serialize_cloud_init_templates(release), {
|
|
'boothook': 'boothook_fuel_6.1.1_centos.jinja2',
|
|
'cloud_config': 'cloud_config_fuel_6.1.1_centos.jinja2',
|
|
'meta_data': 'meta_data_fuel_6.1.1_centos.jinja2'
|
|
}
|
|
)
|
|
|
|
def test_cluster_info_serialization(self):
|
|
engine = self.serialized_cluster['engine']
|
|
self.assertDictEqual(engine, {
|
|
'url': settings.COBBLER_URL,
|
|
'username': settings.COBBLER_USER,
|
|
'password': settings.COBBLER_PASSWORD,
|
|
'master_ip': settings.MASTER_IP
|
|
})
|
|
|
|
def test_node_serialization(self):
|
|
for node in self.serialized_cluster['nodes']:
|
|
node_db = self.db.query(Node).filter_by(
|
|
hostname=node['name']
|
|
).first()
|
|
# Get interface (in our case we created only one for each node)
|
|
intr_db = node_db.nic_interfaces[0]
|
|
intr_name = intr_db.name
|
|
intr_mac = intr_db.mac
|
|
kernal_params = self.attributes.get('kernel_params', {}) \
|
|
.get('kernel', {}).get('value')
|
|
self.assertEqual(
|
|
node['ks_meta']['cloud_init_templates'], {
|
|
'boothook': 'boothook_fuel_6.1_centos.jinja2',
|
|
'cloud_config': 'cloud_config_fuel_6.1_centos.jinja2',
|
|
'meta_data': 'meta_data_fuel_6.1_centos.jinja2'
|
|
}
|
|
)
|
|
self.assertEqual(node['uid'], node_db.uid)
|
|
self.assertEqual(node['power_address'], node_db.ip)
|
|
self.assertEqual(node['name'], "node-{0}".format(node_db.id))
|
|
self.assertEqual(node['hostname'],
|
|
objects.Node.get_node_fqdn(node_db))
|
|
self.assertEqual(
|
|
node['power_pass'], settings.PATH_TO_BOOTSTRAP_SSH_KEY)
|
|
|
|
self.assertDictEqual(node['kernel_options'], {
|
|
'netcfg/choose_interface':
|
|
objects.Node.get_admin_physical_iface(node_db).mac,
|
|
'udevrules': '{0}_{1}'.format(intr_mac, intr_name)
|
|
})
|
|
|
|
self.assertEqual(
|
|
node['ks_meta']['pm_data']['kernel_params'], kernal_params)
|
|
# Check node interfaces section
|
|
self.assertEqual(
|
|
node['interfaces'][intr_name]['mac_address'], intr_mac)
|
|
self.assertEqual(
|
|
node['interfaces'][intr_name]['static'], '0')
|
|
self.assertEqual(
|
|
node['interfaces'][intr_name]['dns_name'],
|
|
objects.Node.get_node_fqdn(node_db))
|
|
# Check node interfaces extra section
|
|
self.assertEqual(node['interfaces_extra'][intr_name], {
|
|
'peerdns': 'no',
|
|
'onboot': 'yes'
|
|
})
|
|
# check identity key for mcollective
|
|
self.assertEqual(node['ks_meta']['mco_identity'], node_db.id)
|
|
|
|
def test_node_serialization_w_bonded_admin_iface(self):
|
|
# create additional node to test bonding
|
|
admin_mac = self.env.generate_random_mac()
|
|
meta = {
|
|
'interfaces': [
|
|
{'name': 'eth1', 'mac': admin_mac, 'pxe': True},
|
|
{'name': 'eth2', 'mac': self.env.generate_random_mac()},
|
|
{'name': 'eth3', 'mac': self.env.generate_random_mac()},
|
|
{'name': 'eth4', 'mac': self.env.generate_random_mac()}
|
|
]
|
|
}
|
|
node = self.env.create_node(
|
|
pending_addition=True,
|
|
cluster_id=self.cluster_db.id,
|
|
meta=meta,
|
|
mac=admin_mac
|
|
)
|
|
# get node from db
|
|
node_db = objects.Node.get_by_uid(node['id'])
|
|
# bond admin iface
|
|
self.env.make_bond_via_api('lnx_bond',
|
|
'',
|
|
['eth1', 'eth4'],
|
|
node['id'],
|
|
bond_properties={
|
|
'mode': consts.BOND_MODES.balance_rr,
|
|
'type__': consts.BOND_TYPES.linux
|
|
})
|
|
# check serialized data
|
|
serialized_node = ps.serialize(self.cluster_db, [node_db])['nodes'][0]
|
|
out_mac = serialized_node['kernel_options']['netcfg/choose_interface']
|
|
self.assertEqual(out_mac, admin_mac)
|
|
|
|
|
|
class TestProvisioningSerializer61(BaseIntegrationTest):
|
|
|
|
serializer = ps.ProvisioningSerializer61
|
|
|
|
def test_make_privisioning_package_list(self):
|
|
provisioning_data = {
|
|
'packages': """
|
|
linux-firmware
|
|
linux-firmware-nonfree
|
|
linux-headers-generic-lts-trusty
|
|
linux-image-generic-lts-trusty"""
|
|
}
|
|
packages = self.serializer._make_provisioning_package_list(
|
|
provisioning_data)
|
|
self.assertEqual(packages, [
|
|
'linux-firmware',
|
|
'linux-firmware-nonfree',
|
|
'linux-headers-generic-lts-trusty',
|
|
'linux-image-generic-lts-trusty',
|
|
])
|
|
|
|
def test_ubuntu_prov_task_for_images(self):
|
|
release = self.env.create_release(
|
|
api=False, operating_system=consts.RELEASE_OS.ubuntu)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
self.cluster.attributes.editable['provision']['method'] = \
|
|
consts.PROVISION_METHODS.image
|
|
self.cluster.attributes.editable['provision']['packages'] = """
|
|
linux-firmware
|
|
linux-firmware-nonfree
|
|
linux-headers-generic-lts-trusty
|
|
linux-image-generic-lts-trusty
|
|
"""
|
|
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertTrue(filter(
|
|
lambda task: all([
|
|
task['uids'] == ['master'],
|
|
task['type'] == 'shell',
|
|
task['parameters']['cmd'].startswith('fa_build_image')
|
|
]),
|
|
serialized_info['pre_provision']))
|
|
self.assertFalse(filter(
|
|
lambda task: all([
|
|
task['uids'] == ['master'],
|
|
task['type'] == 'shell',
|
|
task['parameters']['cmd'].startswith(
|
|
'LOCAL_KERNEL_FILE')
|
|
]),
|
|
serialized_info['pre_provision']))
|
|
|
|
def test_centos_prov_task_for_cobbler(self):
|
|
release = self.env.create_release(
|
|
api=False, operating_system=consts.RELEASE_OS.centos)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
self.cluster.attributes.editable['provision']['method'] = \
|
|
consts.PROVISION_METHODS.cobbler
|
|
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertFalse(filter(
|
|
lambda task: all([
|
|
task['priority'] == 100,
|
|
task['uids'] == ['master'],
|
|
task['type'] == 'shell',
|
|
task['parameters']['cmd'].startswith('fuel-image')
|
|
]),
|
|
serialized_info['pre_provision']))
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertEquals([], serialized_info['pre_provision'])
|
|
|
|
def test_centos_prov_task_for_images(self):
|
|
release = self.env.create_release(
|
|
api=False, operating_system=consts.RELEASE_OS.centos)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
self.cluster.attributes.editable['provision']['method'] = \
|
|
consts.PROVISION_METHODS.image
|
|
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertFalse(filter(
|
|
lambda task: all([
|
|
task['priority'] == 100,
|
|
task['uids'] == ['master'],
|
|
task['type'] == 'shell',
|
|
task['parameters']['cmd'].startswith('fuel-image')
|
|
]),
|
|
serialized_info['pre_provision']))
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertEquals([], serialized_info['pre_provision'])
|
|
|
|
def test_engine_does_not_contain_provisioning_method(self):
|
|
self.cluster = self.env.create_cluster(api=False)
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertNotIn('provision_method', serialized_info['engine'])
|
|
|
|
def test_centos_fedora_kernel_selection(self):
|
|
release = self.env.create_release(
|
|
api=False, operating_system=consts.RELEASE_OS.centos)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
self.env.create_node(
|
|
api=False, cluster_id=self.cluster['id'], pending_addition=True)
|
|
self.cluster.attributes.editable['use_fedora_lt']['kernel'] = \
|
|
'fedora_lt_kernel'
|
|
|
|
serialized_info = self.serializer.serialize(
|
|
self.cluster,
|
|
self.cluster.nodes)
|
|
|
|
node_info = serialized_info['nodes'][0]
|
|
self.assertIn('kernel_lt', node_info['ks_meta'])
|
|
self.assertEqual(1, node_info['ks_meta']['kernel_lt'])
|
|
|
|
|
|
class TestProvisioningSerializer80(BaseIntegrationTest):
|
|
|
|
serializer = ps.ProvisioningSerializer80
|
|
|
|
def test_generate_ironic_bootstrap_keys_task(self):
|
|
release = self.env.create_release(
|
|
api=False,
|
|
operating_system=consts.RELEASE_OS.ubuntu)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
editable = self.cluster.attributes.editable
|
|
editable['additional_components']['ironic']['value'] = True
|
|
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertTrue(filter(
|
|
lambda task: all([
|
|
task['uids'] == ['master'],
|
|
task['type'] == 'shell',
|
|
task['parameters']['cmd'].startswith(
|
|
'sh /etc/puppet/modules/osnailyfacter/modular/'
|
|
'astute/generate_keys.sh')
|
|
]),
|
|
serialized_info['pre_provision']))
|
|
|
|
self.assertTrue(filter(
|
|
lambda task: all([
|
|
'fuel-bootstrap' in task['parameters']['cmd'],
|
|
'ironic.pub' in task['parameters']['cmd']]),
|
|
serialized_info['pre_provision']))
|
|
|
|
def test_do_not_generate_ironic_bootstrap_keys_task(self):
|
|
release = self.env.create_release(
|
|
api=False,
|
|
operating_system=consts.RELEASE_OS.ubuntu)
|
|
self.cluster = self.env.create_cluster(
|
|
api=False, release_id=release.id)
|
|
editable = self.cluster.attributes.editable
|
|
editable['additional_components']['ironic']['value'] = False
|
|
|
|
serialized_info = self.serializer.serialize(self.cluster, [])
|
|
|
|
self.assertIn('pre_provision', serialized_info)
|
|
self.assertFalse(filter(
|
|
lambda task: task['parameters']['cmd'].startswith(
|
|
'sh /etc/puppet/modules/osnailyfacter/modular/'
|
|
'astute/generate_keys.sh'),
|
|
serialized_info['pre_provision']))
|
|
|
|
self.assertFalse(filter(
|
|
lambda task: all([
|
|
'fuel-bootstrap-image' in task['parameters']['cmd'],
|
|
'ironic.pub' in task['parameters']['cmd']]),
|
|
serialized_info['pre_provision']))
|
|
|
|
|
|
class TestProvisioningSerializer90(BaseIntegrationTest):
|
|
|
|
serializer = ps.ProvisioningSerializer90
|
|
|
|
def test_user_account_info(self):
|
|
self.cluster_db = self.env.create(
|
|
release_kwargs={'version': 'mitaka-9.0'},
|
|
)
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, 1,
|
|
roles=['controller'],
|
|
pending_addition=True,
|
|
cluster_id=self.cluster_db.id
|
|
)
|
|
self.env.create_nodes_w_interfaces_count(
|
|
1, 1,
|
|
roles=['compute'],
|
|
pending_addition=True,
|
|
cluster_id=self.cluster_db.id
|
|
)
|
|
|
|
attributes = objects.Cluster.get_attributes(self.cluster_db)
|
|
operator_user = attributes['editable']['operator_user']
|
|
service_user = attributes['editable']['service_user']
|
|
|
|
serialized_cluster = self.serializer.serialize(
|
|
self.cluster_db, self.cluster_db.nodes)
|
|
|
|
operator_user_keys = utils.get_lines(
|
|
operator_user['authkeys']['value']
|
|
)
|
|
common_keys = settings.AUTHORIZED_KEYS
|
|
|
|
operator_user_dict = {
|
|
'name': operator_user['name']['value'],
|
|
'password': operator_user['password']['value'],
|
|
'homedir': operator_user['homedir']['value'],
|
|
'sudo': utils.get_lines(operator_user['sudo']['value']),
|
|
'ssh_keys': operator_user_keys + common_keys
|
|
}
|
|
service_user_dict = {
|
|
'name': service_user['name']['value'],
|
|
'password': service_user['password']['value'],
|
|
'homedir': service_user['homedir']['value'],
|
|
'sudo': utils.get_lines(service_user['sudo']['value']),
|
|
'ssh_keys': common_keys
|
|
}
|
|
root_user_dict = {
|
|
'name': 'root',
|
|
'homedir': '/root',
|
|
'password': service_user['root_password']['value'],
|
|
'ssh_keys': common_keys
|
|
}
|
|
|
|
user_accounts = [operator_user_dict,
|
|
service_user_dict,
|
|
root_user_dict]
|
|
|
|
for node in serialized_cluster['nodes']:
|
|
self.assertEqual(
|
|
node['ks_meta']['user_accounts'],
|
|
user_accounts
|
|
)
|
|
|
|
def test_serialize_iommu_parameters_for_sriov(self):
|
|
cluster = self.env.create(
|
|
release_kwargs={
|
|
'version': 'mitaka-9.0',
|
|
'operating_system': consts.RELEASE_OS.ubuntu},
|
|
nodes_kwargs=[
|
|
{'roles': ['compute']}]
|
|
)
|
|
|
|
sriov_nic = self.env.nodes[0].nic_interfaces[0]
|
|
sriov_nic.interface_properties['sriov']['available'] = True
|
|
sriov_nic.interface_properties['sriov']['enabled'] = True
|
|
objects.NIC.update(sriov_nic, {})
|
|
|
|
serialized_node = self.serializer.serialize(
|
|
cluster, self.env.nodes)['nodes'][0]
|
|
kernel_opts = serialized_node['ks_meta']['pm_data']['kernel_params']
|
|
self.assertIn("intel_iommu=on", kernel_opts)
|
|
self.assertIn("amd_iommu=on", kernel_opts)
|
|
|
|
def test_serialize_node_hugepages(self):
|
|
self.env.create(
|
|
api=False,
|
|
release_kwargs={
|
|
'operating_system': consts.RELEASE_OS.ubuntu,
|
|
'version': 'mitaka-9.0',
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['compute']}])
|
|
|
|
node = self.env.nodes[0]
|
|
node.attributes['hugepages']['nova']['value'] = {'2048': 5}
|
|
|
|
serialized_info = self.serializer.serialize(node.cluster, [node])
|
|
|
|
serialized_node = serialized_info['nodes'][0]
|
|
kernel_opts = serialized_node['ks_meta']['pm_data']['kernel_params']
|
|
|
|
self.assertIn(" hugepagesz=2M hugepages=5", kernel_opts)
|
|
|
|
def test_serialize_node_cpu_pinning(self):
|
|
self.env.create(
|
|
api=False,
|
|
release_kwargs={
|
|
'operating_system': consts.RELEASE_OS.ubuntu,
|
|
'version': 'mitaka-9.0',
|
|
},
|
|
nodes_kwargs=[
|
|
{'roles': ['compute']}])
|
|
|
|
node = self.env.nodes[0]
|
|
node.attributes['cpu_pinning']['nova']['value'] = 2
|
|
|
|
serialized_info = self.serializer.serialize(node.cluster, [node])
|
|
|
|
serialized_node = serialized_info['nodes'][0]
|
|
kernel_opts = serialized_node['ks_meta']['pm_data']['kernel_params']
|
|
|
|
self.assertIn(" isolcpus=0,1", kernel_opts)
|