392 lines
16 KiB
Python
Executable File
392 lines
16 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2016 Red Hat 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 io
|
|
import unittest
|
|
import yaml
|
|
|
|
import fixtures
|
|
import mock
|
|
import testtools
|
|
|
|
from openstack_virtual_baremetal import auth
|
|
from openstack_virtual_baremetal import deploy
|
|
|
|
class TestProcessArgs(unittest.TestCase):
|
|
def test_basic(self):
|
|
mock_args = mock.Mock()
|
|
mock_args.name = None
|
|
mock_args.quintupleo = False
|
|
mock_args.id = None
|
|
mock_args.role = []
|
|
name, template = deploy._process_args(mock_args)
|
|
self.assertEqual('baremetal', name)
|
|
self.assertEqual('templates/virtual-baremetal.yaml', template)
|
|
|
|
def test_name(self):
|
|
mock_args = mock.Mock()
|
|
mock_args.name = 'foo'
|
|
mock_args.quintupleo = False
|
|
mock_args.id = None
|
|
mock_args.role = []
|
|
name, template = deploy._process_args(mock_args)
|
|
self.assertEqual('foo', name)
|
|
self.assertEqual('templates/virtual-baremetal.yaml', template)
|
|
|
|
def test_quintupleo(self):
|
|
mock_args = mock.Mock()
|
|
mock_args.name = None
|
|
mock_args.quintupleo = True
|
|
name, template = deploy._process_args(mock_args)
|
|
self.assertEqual('quintupleo', name)
|
|
self.assertEqual('templates/quintupleo.yaml', template)
|
|
|
|
def test_quintupleo_name(self):
|
|
mock_args = mock.Mock()
|
|
mock_args.name = 'foo'
|
|
mock_args.quintupleo = True
|
|
name, template = deploy._process_args(mock_args)
|
|
self.assertEqual('foo', name)
|
|
self.assertEqual('templates/quintupleo.yaml', template)
|
|
|
|
def test_id_quintupleo(self):
|
|
mock_args = mock.Mock()
|
|
mock_args.id = 'foo'
|
|
mock_args.quintupleo = False
|
|
self.assertRaises(RuntimeError, deploy._process_args, mock_args)
|
|
|
|
|
|
test_env = u"""parameters:
|
|
provision_net: provision
|
|
public_net: public
|
|
baremetal_prefix: baremetal
|
|
bmc_prefix: bmc
|
|
os_user: admin
|
|
"""
|
|
test_env_output = {
|
|
'parameter_defaults':
|
|
{'overcloud_internal_net': 'internal-foo',
|
|
'overcloud_storage_net': 'storage-foo',
|
|
'overcloud_storage_mgmt_net': 'storage_mgmt-foo',
|
|
'overcloud_tenant_net': 'tenant-foo'},
|
|
'parameters':
|
|
{'baremetal_prefix': 'baremetal-foo',
|
|
'undercloud_name': 'undercloud-foo',
|
|
'provision_net': 'provision-foo',
|
|
'public_net': 'public-foo',
|
|
'bmc_prefix': 'bmc-foo',
|
|
'os_user': 'admin'}
|
|
}
|
|
|
|
|
|
class TestIdEnv(unittest.TestCase):
|
|
def test_add_identifier(self):
|
|
env_data = {'parameters': {'foo': 'bar'}}
|
|
deploy._add_identifier(env_data, 'foo', 'baz')
|
|
self.assertEqual('bar-baz', env_data['parameters']['foo'])
|
|
|
|
def test_add_identifier_defaults(self):
|
|
env_data = {'parameter_defaults': {'foo': 'bar'}}
|
|
deploy._add_identifier(env_data, 'foo', 'baz', parameter=False)
|
|
self.assertEqual('bar-baz', env_data['parameter_defaults']['foo'])
|
|
|
|
@mock.patch('yaml.safe_dump')
|
|
def test_generate(self, mock_safe_dump):
|
|
mock_args = mock.Mock()
|
|
mock_args.id = 'foo'
|
|
with mock.patch('openstack_virtual_baremetal.deploy.open',
|
|
mock.mock_open(read_data=test_env),
|
|
create=True) as mock_open:
|
|
path = deploy._generate_id_env(mock_args)
|
|
self.assertEqual('env-foo.yaml', path)
|
|
mock_safe_dump.assert_called_once_with(test_env_output, mock.ANY,
|
|
default_flow_style=False)
|
|
|
|
@mock.patch('yaml.safe_dump')
|
|
def test_generate_undercloud_name(self, mock_safe_dump):
|
|
mock_args = mock.Mock()
|
|
mock_args.id = 'foo'
|
|
env = test_env + ' undercloud_name: undercloud\n'
|
|
env_output = dict(test_env_output)
|
|
env_output['parameters']['undercloud_name'] = 'undercloud-foo'
|
|
with mock.patch('openstack_virtual_baremetal.deploy.open',
|
|
mock.mock_open(read_data=env),
|
|
create=True) as mock_open:
|
|
path = deploy._generate_id_env(mock_args)
|
|
self.assertEqual('env-foo.yaml', path)
|
|
mock_safe_dump.assert_called_once_with(env_output, mock.ANY,
|
|
default_flow_style=False)
|
|
|
|
# _process_role test data
|
|
role_base_data = {
|
|
'parameter_defaults': {
|
|
'overcloud_storage_mgmt_net': 'storage_mgmt-foo',
|
|
'overcloud_internal_net': 'internal-foo',
|
|
'overcloud_storage_net': 'storage-foo',
|
|
'role': 'control',
|
|
'overcloud_tenant_net': 'tenant-foo'
|
|
},
|
|
'parameters': {
|
|
'os_user': 'admin',
|
|
'key_name': 'default',
|
|
'undercloud_name': 'undercloud-foo',
|
|
'bmc_image': 'bmc-base',
|
|
'baremetal_flavor': 'baremetal',
|
|
'os_auth_url': 'http://1.1.1.1:5000/v2.0',
|
|
'provision_net': 'provision-foo',
|
|
'os_password': 'password',
|
|
'os_tenant': 'admin',
|
|
'bmc_prefix': 'bmc-foo',
|
|
'public_net': 'public-foo',
|
|
'undercloud_image': 'centos7-base',
|
|
'baremetal_image': 'ipxe-boot',
|
|
'external_net': 'external',
|
|
'private_net': 'private',
|
|
'baremetal_prefix': 'baremetal-foo-control',
|
|
'undercloud_flavor': 'undercloud-16',
|
|
'node_count': 3,
|
|
'bmc_flavor': 'bmc'
|
|
},
|
|
'resource_registry': {
|
|
'OS::OVB::BaremetalNetworks': 'templates/baremetal-networks-all.yaml',
|
|
'OS::OVB::BaremetalPorts': 'templates/baremetal-ports-public-bond.yaml'
|
|
}
|
|
}
|
|
role_specific_data = {
|
|
'parameter_defaults': {
|
|
'role': 'compute',
|
|
},
|
|
'parameters': {
|
|
'key_name': 'default',
|
|
'baremetal_flavor': 'baremetal',
|
|
'bmc_image': 'bmc-base',
|
|
'bmc_prefix': 'bmc',
|
|
'node_count': 2,
|
|
'bmc_flavor': 'bmc'
|
|
},
|
|
'resource_registry': {
|
|
'OS::OVB::BaremetalNetworks': 'templates/baremetal-networks-all.yaml',
|
|
'OS::OVB::BaremetalPorts': 'templates/baremetal-ports-all.yaml'
|
|
}
|
|
}
|
|
role_original_data = {
|
|
'parameter_defaults': {
|
|
'role': 'control',
|
|
},
|
|
'parameters': {
|
|
'os_user': 'admin',
|
|
'key_name': 'default',
|
|
'undercloud_name': 'undercloud',
|
|
'baremetal_flavor': 'baremetal',
|
|
'os_auth_url': 'http://1.1.1.1:5000/v2.0',
|
|
'provision_net': 'provision',
|
|
'bmc_image': 'bmc-base',
|
|
'os_tenant': 'admin',
|
|
'bmc_prefix': 'bmc',
|
|
'public_net': 'public',
|
|
'undercloud_image': 'centos7-base',
|
|
'baremetal_image': 'ipxe-boot',
|
|
'external_net': 'external',
|
|
'os_password': 'password',
|
|
'private_net': 'private',
|
|
'baremetal_prefix': 'baremetal',
|
|
'undercloud_flavor': 'undercloud-16',
|
|
'node_count': 3,
|
|
'bmc_flavor': 'bmc'
|
|
},
|
|
'resource_registry': {
|
|
'OS::OVB::BaremetalNetworks': 'templates/baremetal-networks-all.yaml',
|
|
'OS::OVB::BaremetalPorts': 'templates/baremetal-ports-public-bond.yaml'
|
|
}
|
|
}
|
|
# end _process_role test data
|
|
|
|
class TestDeploy(testtools.TestCase):
|
|
def _test_deploy(self, mock_ghc, mock_tu, mock_poll, mock_cap, poll=False):
|
|
mock_client = mock.Mock()
|
|
mock_ghc.return_value = mock_client
|
|
template_files = {'template.yaml': {'foo': 'bar'}}
|
|
template = {'foo': 'bar'}
|
|
mock_tu.get_template_contents.return_value = (
|
|
template_files, template
|
|
)
|
|
env_files = {'templates/resource_registry.yaml': {'bar': 'baz'},
|
|
'env.yaml': {'parameters': {}}}
|
|
env = {'parameters': {}}
|
|
mock_tu.process_multiple_environments_and_files.return_value = (
|
|
env_files, env
|
|
)
|
|
all_files = {}
|
|
all_files.update(template_files)
|
|
all_files.update(env_files)
|
|
params = {'os_user': 'admin',
|
|
'os_password': 'password',
|
|
'os_tenant': 'admin',
|
|
'os_auth_url': 'http://1.1.1.1:5000/v2.0',
|
|
}
|
|
mock_cap.return_value = params
|
|
deploy._deploy('test', 'template.yaml', 'env.yaml', poll)
|
|
mock_tu.get_template_contents.assert_called_once_with('template.yaml')
|
|
process = mock_tu.process_multiple_environments_and_files
|
|
process.assert_called_once_with(['templates/resource-registry.yaml',
|
|
'env.yaml'])
|
|
mock_client.stacks.create.assert_called_once_with(stack_name='test',
|
|
template=template,
|
|
environment=env,
|
|
files=all_files,
|
|
parameters=params)
|
|
if not poll:
|
|
mock_poll.assert_not_called()
|
|
else:
|
|
mock_poll.assert_called_once_with('test', mock_client)
|
|
|
|
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._poll_stack')
|
|
@mock.patch('openstack_virtual_baremetal.deploy.template_utils')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._get_heat_client')
|
|
def test_deploy(self, mock_ghc, mock_tu, mock_poll, mock_cap):
|
|
self._test_deploy(mock_ghc, mock_tu, mock_poll, mock_cap)
|
|
|
|
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._poll_stack')
|
|
@mock.patch('openstack_virtual_baremetal.deploy.template_utils')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._get_heat_client')
|
|
def test_deploy_poll(self, mock_ghc, mock_tu, mock_poll, mock_cap):
|
|
self._test_deploy(mock_ghc, mock_tu, mock_poll, mock_cap, True)
|
|
|
|
@mock.patch('time.sleep')
|
|
def test_poll(self, mock_sleep):
|
|
hclient = mock.Mock()
|
|
stacks = [mock.Mock(), mock.Mock()]
|
|
stacks[0].status = 'IN_PROGRESS'
|
|
stacks[1].status = 'COMPLETE'
|
|
hclient.stacks.get.side_effect = stacks
|
|
deploy._poll_stack('foo', hclient)
|
|
self.assertEqual([mock.call('foo', resolve_outputs=False),
|
|
mock.call('foo', resolve_outputs=False)],
|
|
hclient.stacks.get.mock_calls)
|
|
|
|
@mock.patch('time.sleep')
|
|
def test_poll_fail(self, mock_sleep):
|
|
hclient = mock.Mock()
|
|
stacks = [mock.Mock(), mock.Mock()]
|
|
stacks[0].status = 'IN_PROGRESS'
|
|
stacks[1].status = 'FAILED'
|
|
hclient.stacks.get.side_effect = stacks
|
|
self.assertRaises(RuntimeError, deploy._poll_stack, 'foo', hclient)
|
|
self.assertEqual([mock.call('foo', resolve_outputs=False),
|
|
mock.call('foo', resolve_outputs=False)],
|
|
hclient.stacks.get.mock_calls)
|
|
|
|
@mock.patch('openstack_virtual_baremetal.deploy._write_role_file')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._load_role_data')
|
|
def test_process_role(self, mock_load, mock_write):
|
|
mock_load.return_value = (role_base_data, role_specific_data,
|
|
role_original_data)
|
|
args = mock.Mock()
|
|
args.id = 'foo'
|
|
role_file, role = deploy._process_role('foo-compute.yaml', 'foo.yaml',
|
|
'foo', args)
|
|
mock_load.assert_called_once_with('foo.yaml', 'foo-compute.yaml', args)
|
|
self.assertEqual('env-foo-compute.yaml', role_file)
|
|
self.assertEqual('compute', role)
|
|
output = mock_write.call_args[0][0]
|
|
# These values are computed in _process_role
|
|
self.assertEqual('baremetal-foo-compute',
|
|
output['parameters']['baremetal_prefix'])
|
|
self.assertEqual('bmc-foo-compute',
|
|
output['parameters']['bmc_prefix'])
|
|
# These should be inherited
|
|
self.assertEqual('ipxe-boot', output['parameters']['baremetal_image'])
|
|
self.assertEqual('tenant-foo',
|
|
output['parameter_defaults']['overcloud_tenant_net'])
|
|
# This should not be present in a role env, even if set in the file
|
|
self.assertNotIn('OS::OVB::BaremetalNetworks',
|
|
output['resource_registry'])
|
|
# This should be the value set in the role env, not the base one
|
|
self.assertEqual('templates/baremetal-ports-all.yaml',
|
|
output['resource_registry']['OS::OVB::BaremetalPorts'])
|
|
|
|
@mock.patch('openstack_virtual_baremetal.deploy._deploy')
|
|
@mock.patch('openstack_virtual_baremetal.deploy._process_role')
|
|
def test_deploy_roles(self, mock_process, mock_deploy):
|
|
args = mock.Mock()
|
|
args.role = ['foo-compute.yaml']
|
|
mock_process.return_value = ('env-foo-compute.yaml', 'compute')
|
|
deploy._deploy_roles('foo', args, 'foo.yaml')
|
|
mock_process.assert_called_once_with('foo-compute.yaml', 'foo.yaml',
|
|
'foo', args)
|
|
mock_deploy.assert_called_once_with('foo-compute',
|
|
'templates/virtual-baremetal.yaml',
|
|
'env-foo-compute.yaml',
|
|
poll=True)
|
|
|
|
@mock.patch('openstack_virtual_baremetal.deploy._process_role')
|
|
def test_deploy_roles_empty(self, mock_process):
|
|
args = mock.Mock()
|
|
args.role = []
|
|
deploy._deploy_roles('foo', args, 'foo.yaml')
|
|
mock_process.assert_not_called()
|
|
|
|
def _test_validate_env_ends_with_profile(self, mock_id):
|
|
test_env = dict(role_original_data)
|
|
test_env['parameters']['baremetal_prefix'] = 'baremetal-control'
|
|
test_env = yaml.safe_dump(test_env)
|
|
args = mock.Mock()
|
|
args.id = mock_id
|
|
with mock.patch('openstack_virtual_baremetal.deploy.open',
|
|
mock.mock_open(read_data=test_env),
|
|
create=True) as mock_open:
|
|
if not mock_id:
|
|
self.assertRaises(RuntimeError, deploy._validate_env,
|
|
args, 'foo.yaml')
|
|
else:
|
|
deploy._validate_env(args, 'foo.yaml')
|
|
|
|
def test_validate_env_fails(self):
|
|
self._test_validate_env_ends_with_profile(None)
|
|
|
|
def test_validate_env_with_id(self):
|
|
self._test_validate_env_ends_with_profile('foo')
|
|
|
|
def test_validate_env(self):
|
|
test_env = yaml.safe_dump(role_original_data)
|
|
args = mock.Mock()
|
|
args.id = None
|
|
with mock.patch('openstack_virtual_baremetal.deploy.open',
|
|
mock.mock_open(read_data=test_env),
|
|
create=True) as mock_open:
|
|
deploy._validate_env(args, 'foo.yaml')
|
|
|
|
|
|
class TestGetHeatClient(testtools.TestCase):
|
|
@mock.patch('os_client_config.make_client')
|
|
def test_os_cloud(self, mock_make_client):
|
|
self.useFixture(fixtures.EnvironmentVariable('OS_CLOUD', 'foo'))
|
|
deploy._get_heat_client()
|
|
mock_make_client.assert_called_once_with('orchestration', cloud='foo')
|
|
|
|
@mock.patch('heatclient.client.Client')
|
|
@mock.patch('openstack_virtual_baremetal.auth._get_token_and_endpoint')
|
|
def test_heatclient(self, mock_gtae, mock_hc):
|
|
mock_gtae.return_value = ('fake_token', 'heat_endpoint')
|
|
deploy._get_heat_client()
|
|
mock_hc.assert_called_once_with('1', endpoint='heat_endpoint',
|
|
token='fake_token')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|