
Handling of provisioning images has changed on the Tuskar side; this fix brings Tukskar-UI in line with these changes. * There used to be separate images for all the deployment roles. This is no longer the case and all the roles now use the same image, 'overcloud-full'. As the result, the way the relationship between images and roles is displayed on the Provisioning Images page needs to be updated. * Related to the previous point, test data needed updating to reflect that. * Images associated with roles are now saved by name in the Tuskar plan. This fix ensures that the UI saves and retrieves images by name and not by UUID, like it used to do. Change-Id: I11b73fcaed45200dfbdb72dc3ab9a27afb67a31d
597 lines
24 KiB
Python
597 lines
24 KiB
Python
# -*- coding: utf8 -*-
|
|
#
|
|
# 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 contextlib
|
|
import json
|
|
|
|
from ceilometerclient.v2 import client as ceilometer_client
|
|
from django.core import urlresolvers
|
|
from horizon import exceptions as horizon_exceptions
|
|
from ironicclient import exceptions as ironic_exceptions
|
|
import mock
|
|
from novaclient import exceptions as nova_exceptions
|
|
from openstack_dashboard.test.test_data import utils
|
|
|
|
from tuskar_ui import api
|
|
from tuskar_ui.handle_errors import handle_errors # noqa
|
|
from tuskar_ui.infrastructure.nodes import forms
|
|
from tuskar_ui.test import helpers as test
|
|
from tuskar_ui.test.test_data import heat_data
|
|
from tuskar_ui.test.test_data import node_data
|
|
from tuskar_ui.test.test_data import tuskar_data
|
|
|
|
|
|
INDEX_URL = urlresolvers.reverse('horizon:infrastructure:nodes:index')
|
|
REGISTER_URL = urlresolvers.reverse('horizon:infrastructure:nodes:register')
|
|
DETAIL_VIEW = 'horizon:infrastructure:nodes:node_detail'
|
|
PERFORMANCE_VIEW = 'horizon:infrastructure:nodes:performance'
|
|
TEST_DATA = utils.TestDataContainer()
|
|
node_data.data(TEST_DATA)
|
|
heat_data.data(TEST_DATA)
|
|
tuskar_data.data(TEST_DATA)
|
|
|
|
|
|
def _raise_nova_client_exception(*args, **kwargs):
|
|
raise nova_exceptions.ClientException("Boom!")
|
|
|
|
|
|
class NodesTests(test.BaseAdminViewTests):
|
|
@handle_errors("Error!", [])
|
|
def _raise_tuskar_exception(self, request, *args, **kwargs):
|
|
raise self.exceptions.tuskar
|
|
|
|
@handle_errors("Error!", [])
|
|
def _raise_horizon_exception_not_found(self, request, *args, **kwargs):
|
|
raise horizon_exceptions.NotFound
|
|
|
|
def _raise_ironic_exception(self, request, *args, **kwargs):
|
|
raise ironic_exceptions.Conflict
|
|
|
|
def stub_ceilometerclient(self):
|
|
if not hasattr(self, "ceilometerclient"):
|
|
self.mox.StubOutWithMock(ceilometer_client, 'Client')
|
|
self.ceilometerclient = self.mox.CreateMock(
|
|
ceilometer_client.Client,
|
|
)
|
|
return self.ceilometerclient
|
|
|
|
def test_index_get(self):
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list'],
|
|
'list.return_value': [],
|
|
}) as mocked:
|
|
res = self.client.get(INDEX_URL)
|
|
self.assertEqual(mocked.list.call_count, 3)
|
|
|
|
self.assertTemplateUsed(
|
|
res, 'infrastructure/nodes/index.html')
|
|
self.assertTemplateUsed(res, 'infrastructure/nodes/_overview.html')
|
|
|
|
def _all_mocked_nodes(self):
|
|
request = mock.MagicMock()
|
|
return [api.node.Node(api.node.Node(node, request))
|
|
for node in self.ironicclient_nodes.list()]
|
|
|
|
def _test_index_tab(self, tab_name, nodes):
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list'],
|
|
'list.return_value': nodes,
|
|
}) as Node:
|
|
res = self.client.get(INDEX_URL + '?tab=nodes__' + tab_name)
|
|
self.assertEqual(Node.list.call_count, 3)
|
|
|
|
self.assertTemplateUsed(
|
|
res, 'infrastructure/nodes/index.html')
|
|
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
|
self.assertItemsEqual(
|
|
res.context[tab_name + '_nodes_table_table'].data,
|
|
nodes)
|
|
|
|
def test_all_nodes(self):
|
|
nodes = self._all_mocked_nodes()
|
|
self._test_index_tab('all', nodes)
|
|
|
|
def test_provisioned_nodes(self):
|
|
nodes = self._all_mocked_nodes()
|
|
self._test_index_tab('provisioned', nodes)
|
|
|
|
def test_free_nodes(self):
|
|
nodes = self._all_mocked_nodes()
|
|
self._test_index_tab('free', nodes)
|
|
|
|
def test_maintenance_nodes(self):
|
|
nodes = self._all_mocked_nodes()[6:]
|
|
self._test_index_tab('maintenance', nodes)
|
|
|
|
def _test_index_tab_list_exception(self, tab_name):
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list'],
|
|
'list.side_effect': self._raise_tuskar_exception,
|
|
}) as mocked:
|
|
res = self.client.get(INDEX_URL + '?tab=nodes__' + tab_name)
|
|
self.assertEqual(mocked.list.call_count, 2)
|
|
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
|
|
def test_all_nodes_list_exception(self):
|
|
self._test_index_tab_list_exception('all')
|
|
|
|
def test_provisioned_nodes_list_exception(self):
|
|
self._test_index_tab_list_exception('provisioned')
|
|
|
|
def test_free_nodes_list_exception(self):
|
|
self._test_index_tab_list_exception('free')
|
|
|
|
def test_maintenance_nodes_list_exception(self):
|
|
self._test_index_tab_list_exception('maintenance')
|
|
|
|
def test_register_get(self):
|
|
with mock.patch('openstack_dashboard.api.glance.image_list_detailed',
|
|
return_value=([], False)) as mocked:
|
|
res = self.client.get(REGISTER_URL)
|
|
self.assertEqual(mocked.call_count, 2)
|
|
self.assertTemplateUsed(
|
|
res, 'infrastructure/nodes/register.html')
|
|
|
|
def test_register_post(self):
|
|
node = TEST_DATA.ironicclient_nodes.first
|
|
nodes = self._all_mocked_nodes()
|
|
images = self.glanceclient_images.list()
|
|
data = {
|
|
'register_nodes-TOTAL_FORMS': 2,
|
|
'register_nodes-INITIAL_FORMS': 1,
|
|
'register_nodes-MAX_NUM_FORMS': 1000,
|
|
|
|
'register_nodes-0-driver': 'pxe_ipmitool',
|
|
'register_nodes-0-ipmi_address': '127.0.0.1',
|
|
'register_nodes-0-ipmi_username': 'username',
|
|
'register_nodes-0-ipmi_password': 'password',
|
|
'register_nodes-0-mac_addresses': 'de:ad:be:ef:ca:fe',
|
|
'register_nodes-0-cpu_arch': 'x86',
|
|
'register_nodes-0-cpus': '1',
|
|
'register_nodes-0-memory_mb': '2',
|
|
'register_nodes-0-local_gb': '3',
|
|
'register_nodes-0-deployment_kernel': images[3].id,
|
|
'register_nodes-0-deployment_ramdisk': images[4].id,
|
|
|
|
'register_nodes-1-driver': 'pxe_ipmitool',
|
|
'register_nodes-1-ipmi_address': '127.0.0.2',
|
|
'register_nodes-1-mac_addresses': 'de:ad:be:ef:ca:ff',
|
|
'register_nodes-1-cpu_arch': 'x86',
|
|
'register_nodes-1-cpus': '4',
|
|
'register_nodes-1-memory_mb': '5',
|
|
'register_nodes-1-local_gb': '6',
|
|
'register_nodes-1-deployment_kernel': images[3].id,
|
|
'register_nodes-1-deployment_ramdisk': images[4].id,
|
|
}
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['create', 'get_all_mac_addresses'],
|
|
'create.return_value': node,
|
|
'get_all_mac_addresses.return_value': set(nodes),
|
|
}) as Node, mock.patch(
|
|
'openstack_dashboard.api.glance.image_list_detailed',
|
|
return_value=[images, False, False]
|
|
):
|
|
res = self.client.post(REGISTER_URL, data)
|
|
self.assertNoFormErrors(res)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
self.assertListEqual(Node.create.call_args_list, [
|
|
mock.call(
|
|
mock.ANY,
|
|
ipmi_address=u'127.0.0.1',
|
|
cpu_arch='x86',
|
|
cpus=1,
|
|
memory_mb=2,
|
|
local_gb=3,
|
|
mac_addresses=['DE:AD:BE:EF:CA:FE'],
|
|
ipmi_username=u'username',
|
|
ipmi_password=u'password',
|
|
driver='pxe_ipmitool',
|
|
deployment_kernel=images[3].id,
|
|
deployment_ramdisk=images[4].id,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
ipmi_address=u'127.0.0.2',
|
|
cpu_arch='x86',
|
|
cpus=4,
|
|
memory_mb=5,
|
|
local_gb=6,
|
|
mac_addresses=['DE:AD:BE:EF:CA:FF'],
|
|
ipmi_username=None,
|
|
ipmi_password=None,
|
|
driver='pxe_ipmitool',
|
|
deployment_kernel=images[3].id,
|
|
deployment_ramdisk=images[4].id,
|
|
),
|
|
])
|
|
|
|
def test_register_post_exception(self):
|
|
nodes = self._all_mocked_nodes()
|
|
images = self.glanceclient_images.list()
|
|
data = {
|
|
'register_nodes-TOTAL_FORMS': 2,
|
|
'register_nodes-INITIAL_FORMS': 1,
|
|
'register_nodes-MAX_NUM_FORMS': 1000,
|
|
|
|
'register_nodes-0-driver': 'pxe_ipmitool',
|
|
'register_nodes-0-ipmi_address': '127.0.0.1',
|
|
'register_nodes-0-ipmi_username': 'username',
|
|
'register_nodes-0-ipmi_password': 'password',
|
|
'register_nodes-0-mac_addresses': 'de:ad:be:ef:ca:fe',
|
|
'register_nodes-0-cpu_arch': 'x86',
|
|
'register_nodes-0-cpus': '1',
|
|
'register_nodes-0-memory_mb': '2',
|
|
'register_nodes-0-local_gb': '3',
|
|
'register_nodes-0-deployment_kernel': images[3].id,
|
|
'register_nodes-0-deployment_ramdisk': images[4].id,
|
|
|
|
'register_nodes-1-driver': 'pxe_ipmitool',
|
|
'register_nodes-1-ipmi_address': '127.0.0.2',
|
|
'register_nodes-1-mac_addresses': 'de:ad:be:ef:ca:ff',
|
|
'register_nodes-1-cpu_arch': 'x86',
|
|
'register_nodes-1-cpus': '4',
|
|
'register_nodes-1-memory_mb': '5',
|
|
'register_nodes-1-local_gb': '6',
|
|
'register_nodes-1-deployment_kernel': images[3].id,
|
|
'register_nodes-1-deployment_ramdisk': images[4].id,
|
|
}
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['create', 'get_all_mac_addresses'],
|
|
'create.side_effect': self.exceptions.tuskar,
|
|
'get_all_mac_addresses.return_value': set(nodes),
|
|
}) as Node, mock.patch(
|
|
'openstack_dashboard.api.glance.image_list_detailed',
|
|
return_value=[images, False, False]
|
|
):
|
|
res = self.client.post(REGISTER_URL, data)
|
|
self.assertEqual(res.status_code, 200)
|
|
self.assertListEqual(Node.create.call_args_list, [
|
|
mock.call(
|
|
mock.ANY,
|
|
ipmi_address=u'127.0.0.1',
|
|
cpu_arch='x86',
|
|
cpus=1,
|
|
memory_mb=2,
|
|
local_gb=3,
|
|
mac_addresses=['DE:AD:BE:EF:CA:FE'],
|
|
ipmi_username=u'username',
|
|
ipmi_password=u'password',
|
|
driver='pxe_ipmitool',
|
|
deployment_kernel=images[3].id,
|
|
deployment_ramdisk=images[4].id,
|
|
),
|
|
mock.call(
|
|
mock.ANY,
|
|
ipmi_address=u'127.0.0.2',
|
|
cpu_arch='x86',
|
|
cpus=4,
|
|
memory_mb=5,
|
|
local_gb=6,
|
|
mac_addresses=['DE:AD:BE:EF:CA:FF'],
|
|
ipmi_username=None,
|
|
ipmi_password=None,
|
|
driver='pxe_ipmitool',
|
|
deployment_kernel=images[3].id,
|
|
deployment_ramdisk=images[4].id,
|
|
),
|
|
])
|
|
self.assertTemplateUsed(
|
|
res, 'infrastructure/nodes/register.html')
|
|
|
|
def test_node_detail(self):
|
|
node = api.node.Node(self.ironicclient_nodes.list()[0])
|
|
|
|
def get_node(request, uuid, **kwargs):
|
|
node._request = request
|
|
node.addresses = []
|
|
return node
|
|
|
|
image = self.glanceclient_images.first()
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['get'],
|
|
'get.side_effect': get_node,
|
|
}),
|
|
mock.patch('tuskar_ui.api.heat.Resource', **{
|
|
'spec_set': ['get_by_node'],
|
|
'get_by_node.side_effect': lambda *args, **kwargs: {}[None],
|
|
# Raises LookupError
|
|
}),
|
|
mock.patch(
|
|
'openstack_dashboard.api.glance.image_get',
|
|
return_value=image,
|
|
),
|
|
mock.patch(
|
|
'openstack_dashboard.api.nova.server_list',
|
|
return_value=([], False),
|
|
),
|
|
) as (mock_node, mock_heat, mock_glance, mock_nova):
|
|
res = self.client.get(
|
|
urlresolvers.reverse(DETAIL_VIEW, args=(node.uuid,))
|
|
)
|
|
self.assertEqual(mock_node.get.call_count, 1)
|
|
|
|
self.assertTemplateUsed(res, 'infrastructure/nodes/detail.html')
|
|
self.assertEqual(res.context['node'], node)
|
|
|
|
def test_node_detail_exception(self):
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['get'],
|
|
'get.side_effect': self._raise_tuskar_exception,
|
|
}) as mocked:
|
|
res = self.client.get(
|
|
urlresolvers.reverse(DETAIL_VIEW, args=('no-such-node',))
|
|
)
|
|
self.assertEqual(mocked.get.call_count, 1)
|
|
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
|
|
def test_node_set_power_on(self):
|
|
all_nodes = [api.node.Node(api.node.Node(node))
|
|
for node in self.ironicclient_nodes.list()]
|
|
node = all_nodes[6]
|
|
roles = [api.tuskar.Role(r)
|
|
for r in TEST_DATA.tuskarclient_roles.list()]
|
|
instance = TEST_DATA.novaclient_servers.first()
|
|
image = TEST_DATA.glanceclient_images.first()
|
|
data = {'action': "all_nodes_table__set_power_state_on__{0}".format(
|
|
node.uuid)}
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list', 'set_power_state'],
|
|
'list.return_value': all_nodes,
|
|
'set_power_state.return_value': node,
|
|
}),
|
|
mock.patch('tuskar_ui.api.tuskar.Role', **{
|
|
'spec_set': ['list', 'name'],
|
|
'list.return_value': roles,
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.nova', **{
|
|
'spec_set': ['server_get', 'server_list'],
|
|
'server_get.return_value': instance,
|
|
'server_list.return_value': ([instance], False),
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.glance', **{
|
|
'spec_set': ['image_get'],
|
|
'image_get.return_value': image,
|
|
}),
|
|
mock.patch('tuskar_ui.api.heat.Resource', **{
|
|
'spec_set': ['get_by_node', 'list_all_resources'],
|
|
'get_by_node.side_effect': (
|
|
self._raise_horizon_exception_not_found),
|
|
'list_all_resources.return_value': [],
|
|
}),
|
|
) as (mock_node, mock_role, mock_nova, mock_glance, mock_resource):
|
|
res = self.client.post(INDEX_URL + '?tab=nodes__all', data)
|
|
self.assertNoFormErrors(res)
|
|
self.assertEqual(mock_node.set_power_state.call_count, 1)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL + '?tab=nodes__all')
|
|
|
|
def test_node_set_power_on_empty(self):
|
|
all_nodes = [api.node.Node(api.node.Node(node))
|
|
for node in self.ironicclient_nodes.list()]
|
|
node = all_nodes[6]
|
|
roles = [api.tuskar.Role(r)
|
|
for r in TEST_DATA.tuskarclient_roles.list()]
|
|
instance = TEST_DATA.novaclient_servers.first()
|
|
image = TEST_DATA.glanceclient_images.first()
|
|
data = {
|
|
'action': 'all_nodes_table__set_power_state_on',
|
|
'object_ids': '',
|
|
}
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list', 'set_power_state'],
|
|
'list.return_value': all_nodes,
|
|
'set_power_state.return_value': node,
|
|
}),
|
|
mock.patch('tuskar_ui.api.tuskar.Role', **{
|
|
'spec_set': ['list', 'name'],
|
|
'list.return_value': roles,
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.nova', **{
|
|
'spec_set': ['server_get', 'server_list'],
|
|
'server_get.return_value': instance,
|
|
'server_list.return_value': ([instance], False),
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.glance', **{
|
|
'spec_set': ['image_get'],
|
|
'image_get.return_value': image,
|
|
}),
|
|
mock.patch('tuskar_ui.api.heat.Resource', **{
|
|
'spec_set': ['get_by_node', 'list_all_resources'],
|
|
'get_by_node.side_effect': (
|
|
self._raise_horizon_exception_not_found),
|
|
'list_all_resources.return_value': [],
|
|
}),
|
|
) as (mock_node, mock_role, mock_nova, mock_glance, mock_resource):
|
|
res = self.client.post(INDEX_URL + '?tab=nodes__all', data)
|
|
self.assertEqual(mock_node.set_power_state.call_count, 0)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
|
|
def test_node_set_power_off(self):
|
|
all_nodes = [api.node.Node(api.node.Node(node))
|
|
for node in self.ironicclient_nodes.list()]
|
|
node = all_nodes[8]
|
|
roles = [api.tuskar.Role(r)
|
|
for r in TEST_DATA.tuskarclient_roles.list()]
|
|
instance = TEST_DATA.novaclient_servers.first()
|
|
image = TEST_DATA.glanceclient_images.first()
|
|
data = {'action': "all_nodes_table__set_power_state_off__{0}".format(
|
|
node.uuid)}
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['list', 'set_power_state'],
|
|
'list.return_value': all_nodes,
|
|
'set_power_state.return_value': node,
|
|
}),
|
|
mock.patch('tuskar_ui.api.tuskar.Role', **{
|
|
'spec_set': ['list', 'name'],
|
|
'list.return_value': roles,
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.nova', **{
|
|
'spec_set': ['server_get', 'server_list'],
|
|
'server_get.return_value': instance,
|
|
'server_list.return_value': ([instance], False),
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.glance', **{
|
|
'spec_set': ['image_get'],
|
|
'image_get.return_value': image,
|
|
}),
|
|
mock.patch('tuskar_ui.api.heat.Resource', **{
|
|
'spec_set': ['get_by_node', 'list_all_resources'],
|
|
'get_by_node.side_effect': (
|
|
self._raise_horizon_exception_not_found),
|
|
'list_all_resources.return_value': [],
|
|
}),
|
|
) as (mock_node, mock_role, mock_nova, mock_glance, mock_resource):
|
|
res = self.client.post(INDEX_URL + '?tab=nodes__all', data)
|
|
self.assertNoFormErrors(res)
|
|
self.assertEqual(mock_node.set_power_state.call_count, 1)
|
|
self.assertRedirectsNoFollow(res,
|
|
INDEX_URL + '?tab=nodes__all')
|
|
|
|
def test_performance(self):
|
|
node = api.node.Node(self.ironicclient_nodes.list()[0])
|
|
instance = TEST_DATA.novaclient_servers.first()
|
|
|
|
ceilometerclient = self.stub_ceilometerclient()
|
|
ceilometerclient.resources = self.mox.CreateMockAnything()
|
|
ceilometerclient.meters = self.mox.CreateMockAnything()
|
|
|
|
self.mox.ReplayAll()
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['get'],
|
|
'get.return_value': node,
|
|
}),
|
|
mock.patch('tuskar_ui.api.node.nova', **{
|
|
'spec_set': ['servers', 'server_get', 'server_list'],
|
|
'servers.return_value': [instance],
|
|
'server_list.return_value': ([instance], None),
|
|
}),
|
|
mock.patch('tuskar_ui.utils.metering.query_data',
|
|
return_value=[]),
|
|
):
|
|
url = urlresolvers.reverse(PERFORMANCE_VIEW, args=(node.uuid,))
|
|
url += '?meter=cpu&date_options=7'
|
|
res = self.client.get(url)
|
|
|
|
json_content = json.loads(res.content)
|
|
self.assertEqual(res.status_code, 200)
|
|
self.assertIn('series', json_content)
|
|
self.assertIn('settings', json_content)
|
|
|
|
def test_get_driver_info_dict(self):
|
|
data = {
|
|
'driver': 'pxe_ipmitool',
|
|
'ipmi_address': '127.0.0.1',
|
|
'ipmi_username': 'root',
|
|
'ipmi_password': 'P@55W0rd',
|
|
'deployment_kernel': '7',
|
|
'deployment_ramdisk': '8',
|
|
}
|
|
ret = forms.get_driver_info_dict(data)
|
|
self.assertEqual(ret, {
|
|
'driver': 'pxe_ipmitool',
|
|
'ipmi_address': '127.0.0.1',
|
|
'ipmi_username': 'root',
|
|
'ipmi_password': 'P@55W0rd',
|
|
'deployment_kernel': '7',
|
|
'deployment_ramdisk': '8',
|
|
})
|
|
data = {
|
|
'driver': 'pxe_ssh',
|
|
'ssh_address': '127.0.0.1',
|
|
'ssh_username': 'root',
|
|
'ssh_key_contents': 'P@55W0rd',
|
|
'deployment_kernel': '7',
|
|
'deployment_ramdisk': '8',
|
|
}
|
|
ret = forms.get_driver_info_dict(data)
|
|
self.assertEqual(ret, {
|
|
'driver': 'pxe_ssh',
|
|
'ssh_address': '127.0.0.1',
|
|
'ssh_username': 'root',
|
|
'ssh_key_contents': 'P@55W0rd',
|
|
'deployment_kernel': '7',
|
|
'deployment_ramdisk': '8',
|
|
})
|
|
|
|
def test_create_node(self):
|
|
data = {
|
|
'ipmi_address': '127.0.0.1',
|
|
'cpu_arch': 'x86',
|
|
'cpus': 1,
|
|
'memory_mb': 2,
|
|
'local_gb': 3,
|
|
'mac_addresses': 'DE:AD:BE:EF:CA:FE',
|
|
'ipmi_username': 'username',
|
|
'ipmi_password': 'password',
|
|
'driver': 'pxe_ipmitool',
|
|
'deployment_kernel': '7',
|
|
'deployment_ramdisk': '8',
|
|
}
|
|
with mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': ['create', 'set_maintenance', 'discover'],
|
|
'create.return_value': None,
|
|
}) as Node:
|
|
forms.create_node(None, data)
|
|
self.assertListEqual(Node.create.call_args_list, [
|
|
mock.call(
|
|
mock.ANY,
|
|
ipmi_address=u'127.0.0.1',
|
|
cpu_arch='x86',
|
|
cpus=1,
|
|
memory_mb=2,
|
|
local_gb=3,
|
|
mac_addresses=['DE:AD:BE:EF:CA:FE'],
|
|
ipmi_username=u'username',
|
|
ipmi_password=u'password',
|
|
driver='pxe_ipmitool',
|
|
deployment_kernel='7',
|
|
deployment_ramdisk='8',
|
|
),
|
|
])
|
|
|
|
def test_delete_deployed_on_servers(self):
|
|
all_nodes = [api.node.Node(node)
|
|
for node in self.ironicclient_nodes.list()]
|
|
node = all_nodes[6]
|
|
data = {'action': 'all_nodes_table__delete',
|
|
'object_ids': [node.uuid]}
|
|
|
|
with contextlib.nested(
|
|
mock.patch('tuskar_ui.api.node.Node', **{
|
|
'spec_set': [
|
|
'list',
|
|
'delete',
|
|
],
|
|
'list.return_value': [node],
|
|
'delete.side_effect': self._raise_ironic_exception,
|
|
}),
|
|
mock.patch('openstack_dashboard.api.nova.server_list',
|
|
return_value=([], False)),
|
|
):
|
|
res = self.client.post(INDEX_URL, data)
|
|
self.assertMessageCount(error=1, warning=0)
|
|
self.assertNoFormErrors(res)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|