3613 lines
167 KiB
Python
3613 lines
167 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
# coding=utf-8
|
|
|
|
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
# Copyright 2013 International Business Machines Corporation
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
#
|
|
# Copyright (c) 2013-2019 Wind River Systems, Inc.
|
|
#
|
|
|
|
"""Test class for Sysinv ManagerService."""
|
|
|
|
import copy
|
|
import mock
|
|
import os.path
|
|
import tsconfig.tsconfig as tsc
|
|
import uuid
|
|
|
|
from cryptography import x509
|
|
from cryptography.hazmat.backends import default_backend
|
|
|
|
from fm_api import constants as fm_constants
|
|
from oslo_serialization import base64
|
|
from sysinv.agent import rpcapi as agent_rpcapi
|
|
from sysinv.common import constants
|
|
from sysinv.common import device as dconstants
|
|
from sysinv.common import exception
|
|
from sysinv.common import kubernetes
|
|
from sysinv.common import utils as cutils
|
|
from sysinv.conductor import manager
|
|
from sysinv.db import api as dbapi
|
|
from sysinv.openstack.common import context
|
|
|
|
from sysinv.tests.db import base
|
|
from sysinv.tests.db import utils
|
|
|
|
|
|
class FakeSecret(object):
|
|
|
|
def __init__(self, crt):
|
|
self.data = {'tls.crt': base64.encode_as_text(crt)}
|
|
|
|
|
|
class FakeCephOperator(object):
|
|
|
|
def __init__(self, db_api):
|
|
self.dbapi = dbapi
|
|
|
|
|
|
class FakePuppetOperator(object):
|
|
|
|
def __init__(self, db_api):
|
|
self.dbapi = dbapi
|
|
self.update_host_config = mock.MagicMock()
|
|
self.update_system_config = mock.MagicMock()
|
|
self.update_secure_system_config = mock.MagicMock()
|
|
|
|
|
|
class FakePopen(object):
|
|
|
|
def __init__(self, **kwargs):
|
|
# Pretend all is OK
|
|
self.returncode = 0
|
|
|
|
def communicate(self):
|
|
return "Fake stdout", "Fake stderr"
|
|
|
|
|
|
class ManagerTestCase(base.DbTestCase):
|
|
|
|
def extract_certs_from_pem(self, pem_contents):
|
|
"""
|
|
Extract certificates from a pem string
|
|
|
|
:param pem_contents: A string in pem format
|
|
:return certs: A list of x509 cert objects
|
|
"""
|
|
marker = b'-----BEGIN CERTIFICATE-----'
|
|
|
|
start = 0
|
|
certs = []
|
|
while True:
|
|
index = pem_contents.find(marker, start)
|
|
if index == -1:
|
|
break
|
|
try:
|
|
cert = x509.load_pem_x509_certificate(pem_contents[index::],
|
|
default_backend())
|
|
except Exception:
|
|
raise exception.SysinvException((
|
|
"Failed to load pem x509 certificate"))
|
|
|
|
certs.append(cert)
|
|
start = index + len(marker)
|
|
return certs
|
|
|
|
def setUp(self):
|
|
super(ManagerTestCase, self).setUp()
|
|
|
|
# Set up objects for testing
|
|
self.service = manager.ConductorManager('test-host', 'test-topic')
|
|
self.service.dbapi = dbapi.get_instance()
|
|
self.context = context.get_admin_context()
|
|
self.dbapi = dbapi.get_instance()
|
|
self.system = utils.create_test_isystem()
|
|
self.load = utils.create_test_load()
|
|
self.dnsmasq_hosts_file = '/tmp/dnsmasq.hosts'
|
|
|
|
# Mock the ceph operator
|
|
self.fake_ceph_operator = FakeCephOperator(self.dbapi)
|
|
p = mock.patch('sysinv.conductor.ceph.CephOperator')
|
|
self.mock_ceph_operator = p.start()
|
|
self.mock_ceph_operator.return_value = self.fake_ceph_operator
|
|
self.addCleanup(p.stop)
|
|
|
|
# Mock the puppet operator
|
|
self.fakepuppet_operator = FakePuppetOperator(self.dbapi)
|
|
p = mock.patch('sysinv.puppet.puppet.PuppetOperator')
|
|
self.mockpuppet_operator = p.start()
|
|
self.mockpuppet_operator.return_value = self.fakepuppet_operator
|
|
self.addCleanup(p.stop)
|
|
self.service._puppet = self.fakepuppet_operator
|
|
|
|
# Mock manager methods
|
|
self.upgrade_downgrade_kube_components_patcher = mock.patch.object(
|
|
manager.ConductorManager, '_upgrade_downgrade_kube_components')
|
|
self.mock_upgrade_downgrade_kube_components = \
|
|
self.upgrade_downgrade_kube_components_patcher.start()
|
|
self.addCleanup(self.mock_upgrade_downgrade_kube_components.stop)
|
|
|
|
self.service.fm_api = mock.Mock()
|
|
self.service.fm_api.set_fault.side_effect = self._raise_alarm
|
|
self.service.fm_api.clear_fault.side_effect = self._clear_alarm
|
|
self.service.fm_api.get_faults_by_id.side_effect = self._get_faults_by_id
|
|
|
|
# Mock sw_version check since tox tsc.SW_VERSION is "TEST.SW_VERSION"
|
|
self.host_load_matches_sw_version_patcher = mock.patch.object(
|
|
manager.ConductorManager, 'host_load_matches_sw_version')
|
|
self.mock_host_load_matches_sw_version = \
|
|
self.host_load_matches_sw_version_patcher.start()
|
|
self.mock_host_load_matches_sw_version.return_value = True
|
|
self.addCleanup(self.host_load_matches_sw_version_patcher.stop)
|
|
|
|
self.fail_config_apply_runtime_manifest = False
|
|
|
|
# Mock ready to apply runtime config
|
|
self._ready_to_apply_runtime_config = True
|
|
self.ready_to_apply_runtime_config_patcher = mock.patch.object(
|
|
manager.ConductorManager, '_ready_to_apply_runtime_config')
|
|
self.mock_ready_to_apply_runtime_config = \
|
|
self.ready_to_apply_runtime_config_patcher.start()
|
|
self.mock_ready_to_apply_runtime_config.return_value = \
|
|
self._ready_to_apply_runtime_config
|
|
self.addCleanup(self.ready_to_apply_runtime_config_patcher.stop)
|
|
|
|
# Mock check_cert_validity
|
|
def mock_cert_validity(obj):
|
|
return None
|
|
self.mocked_cert_validity = mock.patch.object(cutils, 'check_cert_validity', mock_cert_validity)
|
|
self.mocked_cert_validity.start()
|
|
self.addCleanup(self.mocked_cert_validity.stop)
|
|
|
|
# Mock agent config_apply_runtime_manifest
|
|
def mock_agent_config_apply_runtime_manifest(obj, context, config_uuid,
|
|
config_dict):
|
|
if not self.fail_config_apply_runtime_manifest:
|
|
# Pretend the config was applied
|
|
if 'host_uuids' in config_dict:
|
|
for host_uuid in config_dict['host_uuids']:
|
|
self.dbapi.ihost_update(host_uuid,
|
|
{'config_applied': config_uuid})
|
|
else:
|
|
for personality in config_dict['personalities']:
|
|
hosts = self.dbapi.ihost_get_by_personality(personality)
|
|
for host in hosts:
|
|
self.dbapi.ihost_update(
|
|
host.uuid, {'config_applied': config_uuid})
|
|
|
|
self.mocked_rpcapi_config_apply_runtime_manifest = mock.patch.object(
|
|
agent_rpcapi.AgentAPI, 'config_apply_runtime_manifest',
|
|
mock_agent_config_apply_runtime_manifest)
|
|
self.mocked_rpcapi_config_apply_runtime_manifest.start()
|
|
self.addCleanup(self.mocked_rpcapi_config_apply_runtime_manifest.stop)
|
|
|
|
self.mock_kube_create_secret = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_create_secret',
|
|
self.mock_kube_create_secret)
|
|
p.start()
|
|
self.addCleanup(p.stop)
|
|
|
|
self.mock_kube_create_issuer = mock.MagicMock()
|
|
q = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.apply_custom_resource',
|
|
self.mock_kube_create_issuer)
|
|
q.start()
|
|
self.addCleanup(q.stop)
|
|
|
|
self.mock_get_current_kube_rootca = mock.MagicMock()
|
|
z = mock.patch(
|
|
'sysinv.common.utils.get_certificate_from_file',
|
|
self.mock_get_current_kube_rootca
|
|
)
|
|
self.mock_current_kube_rootca = z.start()
|
|
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'ca-cert-one-cert.pem')
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
self.mock_get_current_kube_rootca.return_value = self.extract_certs_from_pem(f)[0]
|
|
|
|
self.addCleanup(z.stop)
|
|
|
|
self.fail_config_apply_runtime_manifest = False
|
|
|
|
# Mock agent iconfig_update_file
|
|
def mock_agent_iconfig_update_file(obj, context, iconfig_uuid, iconfig_dict):
|
|
if not self.fail_config_apply_runtime_manifest:
|
|
# Simulate the config was applied
|
|
if 'host_uuids' in iconfig_dict:
|
|
for host_uuid in iconfig_dict['host_uuids']:
|
|
self.dbapi.ihost_update(host_uuid,
|
|
{'config_applied': iconfig_uuid})
|
|
else:
|
|
for personality in iconfig_dict['personalities']:
|
|
hosts = self.dbapi.ihost_get_by_personality(personality)
|
|
for host in hosts:
|
|
self.dbapi.ihost_update(
|
|
host.uuid, {'config_applied': iconfig_uuid})
|
|
|
|
self.mocked_rpcapi_iconfig_update_file = mock.patch.object(
|
|
agent_rpcapi.AgentAPI, 'iconfig_update_file',
|
|
mock_agent_iconfig_update_file)
|
|
self.mocked_rpcapi_iconfig_update_file.start()
|
|
self.addCleanup(self.mocked_rpcapi_iconfig_update_file.stop)
|
|
|
|
self.mocked_is_initial_config_complete = mock.patch.object(
|
|
cutils, 'is_initial_config_complete')
|
|
self.mocked_is_initial_config_complete.start()
|
|
self.mocked_is_initial_config_complete.return_value = True
|
|
self.addCleanup(self.mocked_is_initial_config_complete.stop)
|
|
|
|
# Mock subprocess popen
|
|
self.fake_subprocess_popen = FakePopen()
|
|
p = mock.patch('eventlet.green.subprocess.Popen')
|
|
self.mock_subprocess_popen = p.start()
|
|
self.mock_subprocess_popen.return_value = self.fake_subprocess_popen
|
|
self.addCleanup(p.stop)
|
|
|
|
# Mock the KubeOperator
|
|
self.kube_get_control_plane_versions_result = {
|
|
'controller-0': 'v1.42.1',
|
|
'controller-1': 'v1.42.1',
|
|
'worker-0': 'v1.42.1'}
|
|
|
|
def mock_kube_get_control_plane_versions(obj):
|
|
return self.kube_get_control_plane_versions_result
|
|
self.mocked_kube_get_control_plane_versions = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_get_control_plane_versions',
|
|
mock_kube_get_control_plane_versions)
|
|
self.mocked_kube_get_control_plane_versions.start()
|
|
self.addCleanup(self.mocked_kube_get_control_plane_versions.stop)
|
|
|
|
self.kube_get_kubelet_versions_result = {
|
|
'controller-0': 'v1.42.1',
|
|
'controller-1': 'v1.42.1',
|
|
'worker-0': 'v1.42.1'}
|
|
|
|
def mock_kube_get_kubelet_versions(obj):
|
|
return self.kube_get_kubelet_versions_result
|
|
self.mocked_kube_get_kubelet_versions = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_get_kubelet_versions',
|
|
mock_kube_get_kubelet_versions)
|
|
self.mocked_kube_get_kubelet_versions.start()
|
|
self.addCleanup(self.mocked_kube_get_kubelet_versions.stop)
|
|
|
|
# Mock the KubeVersion
|
|
self.get_kube_versions_result = [
|
|
{'version': 'v1.42.1',
|
|
'upgrade_from': [],
|
|
'downgrade_to': [],
|
|
'applied_patches': [],
|
|
'available_patches': [],
|
|
},
|
|
{'version': 'v1.42.2',
|
|
'upgrade_from': ['v1.42.1'],
|
|
'downgrade_to': [],
|
|
'applied_patches': [],
|
|
'available_patches': [],
|
|
},
|
|
]
|
|
|
|
def mock_get_kube_versions():
|
|
return self.get_kube_versions_result
|
|
self.mocked_get_kube_versions = mock.patch(
|
|
'sysinv.common.kubernetes.get_kube_versions',
|
|
mock_get_kube_versions)
|
|
self.mocked_get_kube_versions.start()
|
|
self.addCleanup(self.mocked_get_kube_versions.stop)
|
|
|
|
self.service._puppet = mock.Mock()
|
|
self.service._allocate_addresses_for_host = mock.Mock()
|
|
self.service._update_pxe_config = mock.Mock()
|
|
self.service._ceph_mon_create = mock.Mock()
|
|
self.service._sx_to_dx_post_migration_actions = mock.Mock()
|
|
self.alarm_raised = False
|
|
|
|
def tearDown(self):
|
|
super(ManagerTestCase, self).tearDown()
|
|
self.upgrade_downgrade_kube_components_patcher.stop()
|
|
|
|
def _create_test_ihost(self, **kwargs):
|
|
# ensure the system ID for proper association
|
|
kwargs['forisystemid'] = self.system['id']
|
|
ihost_dict = utils.get_test_ihost(**kwargs)
|
|
# Let DB generate ID if it isn't specified explicitly
|
|
if 'id' not in kwargs:
|
|
del ihost_dict['id']
|
|
ihost = self.dbapi.ihost_create(ihost_dict)
|
|
return ihost
|
|
|
|
def test_create_ihost(self):
|
|
ihost_dict = {'mgmt_mac': '00:11:22:33:44:55',
|
|
'mgmt_ip': '1.2.3.4'}
|
|
|
|
self.service.start()
|
|
res = self.service.create_ihost(self.context, ihost_dict)
|
|
self.assertEqual(res['mgmt_mac'], '00:11:22:33:44:55')
|
|
self.assertEqual(res['mgmt_ip'], '1.2.3.4')
|
|
|
|
def test_create_duplicate_ihost(self):
|
|
ihost_dict = {'mgmt_mac': '00:11:22:33:44:55',
|
|
'mgmt_ip': '1.2.3.4'}
|
|
|
|
self.service.start()
|
|
# Create first ihost
|
|
res1 = self.service.create_ihost(self.context, ihost_dict)
|
|
# Update the serialid
|
|
res1['serialid'] = '1234567890abc'
|
|
res1 = self.service.update_ihost(self.context, res1)
|
|
|
|
# Attempt to create duplicate ihost
|
|
res2 = self.service.create_ihost(self.context, ihost_dict)
|
|
|
|
# Verify that original ihost was returned
|
|
self.assertEqual(res1['serialid'], res2['serialid'])
|
|
|
|
def test_create_ihost_without_mac(self):
|
|
ihost_dict = {'mgmt_ip': '1.2.3.4'}
|
|
|
|
self.assertRaises(exception.SysinvException,
|
|
self.service.create_ihost,
|
|
self.context,
|
|
ihost_dict)
|
|
|
|
# verify create did not happen
|
|
res = self.dbapi.ihost_get_list()
|
|
self.assertEqual(len(res), 0)
|
|
|
|
def test_create_ihost_with_invalid_mac(self):
|
|
ihost_dict = {'mgmt_mac': '52:54:00:59:02:9'}
|
|
|
|
self.assertRaises(exception.SysinvException,
|
|
self.service.create_ihost,
|
|
self.context,
|
|
ihost_dict)
|
|
|
|
# verify create did not happen
|
|
res = self.dbapi.ihost_get_list()
|
|
self.assertEqual(len(res), 0)
|
|
|
|
def test_create_ihost_without_ip(self):
|
|
ihost_dict = {'mgmt_mac': '00:11:22:33:44:55'}
|
|
|
|
self.service.start()
|
|
self.service.create_ihost(self.context, ihost_dict)
|
|
|
|
# verify create happened
|
|
res = self.dbapi.ihost_get_list()
|
|
self.assertEqual(len(res), 1)
|
|
|
|
def test_create_ihost_with_values(self):
|
|
ihost_dict = {'mgmt_mac': '00:11:22:33:44:55',
|
|
'mgmt_ip': '1.2.3.4',
|
|
'hostname': 'newhost',
|
|
'invprovision': 'unprovisioned',
|
|
'personality': 'worker',
|
|
'administrative': 'locked',
|
|
'operational': 'disabled',
|
|
'availability': 'not-installed',
|
|
'serialid': '1234567890abc',
|
|
'boot_device': 'sda',
|
|
'rootfs_device': 'sda',
|
|
'install_output': 'text',
|
|
'console': 'ttyS0,115200',
|
|
'tboot': ''
|
|
}
|
|
|
|
self.service.start()
|
|
res = self.service.create_ihost(self.context, ihost_dict)
|
|
|
|
for k, v in ihost_dict.items():
|
|
self.assertEqual(res[k], v)
|
|
|
|
def test_update_ihost(self):
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['mgmt_mac'] = '00:11:22:33:44:55'
|
|
ihost['mgmt_ip'] = '1.2.3.4'
|
|
ihost['hostname'] = 'newhost'
|
|
ihost['invprovision'] = 'unprovisioned'
|
|
ihost['personality'] = 'worker'
|
|
ihost['administrative'] = 'locked'
|
|
ihost['operational'] = 'disabled'
|
|
ihost['availability'] = 'not-installed'
|
|
ihost['serialid'] = '1234567890abc'
|
|
ihost['boot_device'] = 'sda'
|
|
ihost['rootfs_device'] = 'sda'
|
|
ihost['install_output'] = 'text'
|
|
ihost['console'] = 'ttyS0,115200'
|
|
|
|
res = self.service.update_ihost(self.context, ihost)
|
|
|
|
self.assertEqual(res['mgmt_mac'], '00:11:22:33:44:55')
|
|
self.assertEqual(res['mgmt_ip'], '1.2.3.4')
|
|
self.assertEqual(res['hostname'], 'newhost')
|
|
self.assertEqual(res['invprovision'], 'unprovisioned')
|
|
self.assertEqual(res['personality'], 'worker')
|
|
self.assertEqual(res['administrative'], 'locked')
|
|
self.assertEqual(res['operational'], 'disabled')
|
|
self.assertEqual(res['availability'], 'not-installed')
|
|
self.assertEqual(res['serialid'], '1234567890abc')
|
|
self.assertEqual(res['boot_device'], 'sda')
|
|
self.assertEqual(res['rootfs_device'], 'sda')
|
|
self.assertEqual(res['install_output'], 'text')
|
|
self.assertEqual(res['console'], 'ttyS0,115200')
|
|
|
|
def test_update_ihost_id(self):
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['id'] = '12345'
|
|
self.assertRaises(exception.SysinvException,
|
|
self.service.update_ihost,
|
|
self.context,
|
|
ihost)
|
|
|
|
def test_update_ihost_uuid(self):
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['uuid'] = 'asdf12345'
|
|
self.assertRaises(exception.SysinvException,
|
|
self.service.update_ihost,
|
|
self.context,
|
|
ihost)
|
|
|
|
def test_configure_ihost_new(self):
|
|
# Test skipped to prevent error message in Jenkins. Error thrown is:
|
|
# in test_configure_ihost_new
|
|
# with open(self.dnsmasq_hosts_file, 'w') as f:
|
|
# IOError: [Errno 13] Permission denied: '/tmp/dnsmasq.hosts'
|
|
self.skipTest("Skipping to prevent failure notification on Jenkins")
|
|
with open(self.dnsmasq_hosts_file, 'w') as f:
|
|
f.write("dhcp-host=08:00:27:0a:fa:fa,worker-1,192.168.204.25,2h\n")
|
|
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['mgmt_mac'] = '00:11:22:33:44:55'
|
|
ihost['mgmt_ip'] = '1.2.3.4'
|
|
ihost['hostname'] = 'newhost'
|
|
ihost['invprovision'] = 'unprovisioned'
|
|
ihost['personality'] = 'worker'
|
|
ihost['administrative'] = 'locked'
|
|
ihost['operational'] = 'disabled'
|
|
ihost['availability'] = 'not-installed'
|
|
ihost['serialid'] = '1234567890abc'
|
|
ihost['boot_device'] = 'sda'
|
|
ihost['rootfs_device'] = 'sda'
|
|
ihost['install_output'] = 'text'
|
|
ihost['console'] = 'ttyS0,115200'
|
|
|
|
self.service.configure_ihost(self.context, ihost)
|
|
|
|
with open(self.dnsmasq_hosts_file, 'r') as f:
|
|
self.assertEqual(
|
|
f.readline(),
|
|
"dhcp-host=08:00:27:0a:fa:fa,worker-1,192.168.204.25,2h\n")
|
|
self.assertEqual(
|
|
f.readline(),
|
|
"dhcp-host=00:11:22:33:44:55,newhost,1.2.3.4,2h\n")
|
|
|
|
def test_configure_ihost_replace(self):
|
|
# Test skipped to prevent error message in Jenkins. Error thrown is:
|
|
# in test_configure_ihost_replace
|
|
# with open(self.dnsmasq_hosts_file, 'w') as f:
|
|
# IOError: [Errno 13] Permission denied: '/tmp/dnsmasq.hosts'
|
|
self.skipTest("Skipping to prevent failure notification on Jenkins")
|
|
with open(self.dnsmasq_hosts_file, 'w') as f:
|
|
f.write("dhcp-host=00:11:22:33:44:55,oldhost,1.2.3.4,2h\n")
|
|
f.write("dhcp-host=08:00:27:0a:fa:fa,worker-1,192.168.204.25,2h\n")
|
|
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['mgmt_mac'] = '00:11:22:33:44:55'
|
|
ihost['mgmt_ip'] = '1.2.3.42'
|
|
ihost['hostname'] = 'newhost'
|
|
ihost['invprovision'] = 'unprovisioned'
|
|
ihost['personality'] = 'worker'
|
|
ihost['administrative'] = 'locked'
|
|
ihost['operational'] = 'disabled'
|
|
ihost['availability'] = 'not-installed'
|
|
ihost['serialid'] = '1234567890abc'
|
|
ihost['boot_device'] = 'sda'
|
|
ihost['rootfs_device'] = 'sda'
|
|
ihost['install_output'] = 'text'
|
|
ihost['console'] = 'ttyS0,115200'
|
|
|
|
self.service.configure_ihost(self.context, ihost)
|
|
|
|
with open(self.dnsmasq_hosts_file, 'r') as f:
|
|
self.assertEqual(
|
|
f.readline(),
|
|
"dhcp-host=00:11:22:33:44:55,newhost,1.2.3.42,2h\n")
|
|
self.assertEqual(
|
|
f.readline(),
|
|
"dhcp-host=08:00:27:0a:fa:fa,worker-1,192.168.204.25,2h\n")
|
|
|
|
def test_configure_ihost_no_hostname(self):
|
|
# Test skipped to prevent error message in Jenkins. Error thrown is:
|
|
# in update_dnsmasq_config
|
|
# os.rename(temp_dnsmasq_hosts_file, dnsmasq_hosts_file)
|
|
# OSError: [Errno 1] Operation not permitted
|
|
self.skipTest("Skipping to prevent failure notification on Jenkins")
|
|
ihost = self._create_test_ihost()
|
|
|
|
ihost['hostname'] = ''
|
|
self.assertRaises(exception.SysinvException,
|
|
self.service.configure_ihost,
|
|
self.context,
|
|
ihost)
|
|
|
|
def test_vim_host_add(self):
|
|
mock_vim_host_add = mock.MagicMock()
|
|
p = mock.patch('sysinv.api.controllers.v1.vim_api.vim_host_add',
|
|
mock_vim_host_add)
|
|
p.start().return_value = {}
|
|
self.addCleanup(p.stop)
|
|
|
|
ret = self.service.vim_host_add(self.context, None, str(uuid.uuid4()),
|
|
"newhostname", "worker", "locked", "disabled", "offline",
|
|
"disabled", "not-installed", 10)
|
|
|
|
mock_vim_host_add.assert_called_with(mock.ANY, mock.ANY,
|
|
"newhostname", "worker", "locked", "disabled", "offline",
|
|
"disabled", "not-installed", 10)
|
|
|
|
self.assertEqual(ret, {})
|
|
|
|
def test_mtc_host_add(self):
|
|
mock_notify_mtc_and_recv = mock.MagicMock()
|
|
p = mock.patch('sysinv.common.utils.notify_mtc_and_recv',
|
|
mock_notify_mtc_and_recv)
|
|
p.start().return_value = {'status': 'pass'}
|
|
self.addCleanup(p.stop)
|
|
|
|
ihost = {}
|
|
ihost['hostname'] = 'newhost'
|
|
ihost['personality'] = 'worker'
|
|
|
|
self.service.mtc_host_add(self.context, "localhost", 2112, ihost)
|
|
mock_notify_mtc_and_recv.assert_called_with("localhost", 2112, ihost)
|
|
|
|
def test_ilvg_get_nova_ilvg_by_ihost(self):
|
|
ihost = self._create_test_ihost()
|
|
lvg_dict = {
|
|
'lvm_vg_name': constants.LVG_NOVA_LOCAL,
|
|
}
|
|
ilvg = self.dbapi.ilvg_create(ihost['id'], lvg_dict)
|
|
ret = self.service.ilvg_get_nova_ilvg_by_ihost(self.context, ihost['uuid'])
|
|
self.assertEqual(ret[0]['uuid'], ilvg['uuid'])
|
|
|
|
def test_ilvg_get_nova_ilvg_by_ihost_no_nova_ilvg(self):
|
|
ihost = self._create_test_ihost()
|
|
ret = self.service.ilvg_get_nova_ilvg_by_ihost(self.context, ihost['uuid'])
|
|
self.assertEqual(ret, [])
|
|
|
|
def test_lldp_neighbour_tlv_update_exceed_length(self):
|
|
# Set up
|
|
ihost = self._create_test_ihost()
|
|
interface = utils.create_test_interface(
|
|
ifname='mgmt',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
port = utils.create_test_ethernet_port(
|
|
name='eth0',
|
|
host_id=ihost['id'],
|
|
interface_id=interface['id'],
|
|
pciaddr='0000:00:00.01',
|
|
dev_id=0)
|
|
|
|
# create fake neighbour
|
|
neighbour = self.dbapi.lldp_neighbour_create(
|
|
port.id, ihost.id, {
|
|
"msap": "08:00:27:82:35:fb,08:00:27:0d:ac:03"
|
|
})
|
|
|
|
# create tlv with excessive size
|
|
tlv_list = self.dbapi.lldp_tlv_get_list()
|
|
bad_size = (
|
|
'enp0s8.100, enp0s8.101, enp0s8.102, enp0s8.103,'
|
|
' enp0s8.104, enp0s8.105, enp0s8.106, enp0s8.107,'
|
|
' enp0s8.108, enp0s8.109, enp0s8.110, enp0s8.111,'
|
|
' enp0s8.112, enp0s8.113, enp0s8.114, enp0s8.115,'
|
|
' enp0s8.116, enp0s8.117, enp0s8.118, enp0s8.119,'
|
|
' enp0s8.120, enp0s8.121, enp0s8.122, enp0s8.12,'
|
|
' enp0s8.123'
|
|
)
|
|
vlan_list = bad_size
|
|
self.service.lldp_neighbour_tlv_update({
|
|
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: vlan_list
|
|
}, neighbour)
|
|
tlv_list = self.dbapi.lldp_tlv_get_list()
|
|
self.assertEqual(tlv_list[0]['value'][-3:], "...")
|
|
self.assertTrue(len(tlv_list[0]['value']) <= 255)
|
|
|
|
# update tlv to acceptable size
|
|
vlan_list = 'enp0s8.100'
|
|
self.service.lldp_neighbour_tlv_update({
|
|
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: vlan_list
|
|
}, neighbour)
|
|
tlv_list = self.dbapi.lldp_tlv_get_list()
|
|
self.assertEqual(tlv_list[0]['value'], vlan_list)
|
|
|
|
# update tlv to excessive size
|
|
vlan_list = bad_size
|
|
self.service.lldp_neighbour_tlv_update({
|
|
constants.LLDP_TLV_TYPE_DOT1_VLAN_NAMES: vlan_list
|
|
}, neighbour)
|
|
tlv_list = self.dbapi.lldp_tlv_get_list()
|
|
self.assertEqual(tlv_list[0]['value'][-3:], "...")
|
|
self.assertTrue(len(tlv_list[0]['value']) <= 255)
|
|
|
|
def test_platform_interfaces(self):
|
|
ihost = self._create_test_ihost()
|
|
interface = utils.create_test_interface(
|
|
ifname='mgmt',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
port = utils.create_test_ethernet_port(
|
|
name='eth0',
|
|
host_id=ihost['id'],
|
|
interface_id=interface['id'],
|
|
pciaddr='0000:00:00.01',
|
|
dev_id=0)
|
|
|
|
ret = self.service.platform_interfaces(self.context, ihost['id'])
|
|
self.assertEqual(ret[0]['name'], port['name'])
|
|
|
|
def test_platform_interfaces_multi(self):
|
|
ihost = self._create_test_ihost()
|
|
interface_mgmt = utils.create_test_interface(
|
|
ifname='mgmt',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
port_mgmt = utils.create_test_ethernet_port(
|
|
name='eth0',
|
|
host_id=ihost['id'],
|
|
interface_id=interface_mgmt['id'],
|
|
pciaddr='0000:00:00.01',
|
|
dev_id=0)
|
|
|
|
interface_oam = utils.create_test_interface(
|
|
ifname='oam',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
port_oam = utils.create_test_ethernet_port(
|
|
name='eth1',
|
|
host_id=ihost['id'],
|
|
interface_id=interface_oam['id'],
|
|
pciaddr='0000:00:00.02',
|
|
dev_id=1)
|
|
|
|
interface_data = utils.create_test_interface(
|
|
ifname='data',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
iftype=constants.INTERFACE_TYPE_VLAN)
|
|
utils.create_test_ethernet_port(
|
|
name='eth2',
|
|
host_id=ihost['id'],
|
|
interface_id=interface_data['id'],
|
|
pciaddr='0000:00:00.03',
|
|
dev_id=2)
|
|
|
|
ret = self.service.platform_interfaces(self.context, ihost['id'])
|
|
self.assertEqual(len(ret), 2)
|
|
self.assertEqual(ret[0]['name'], port_mgmt['name'])
|
|
self.assertEqual(ret[1]['name'], port_oam['name'])
|
|
|
|
def test_platform_interfaces_no_port(self):
|
|
ihost = self._create_test_ihost()
|
|
utils.create_test_interface(
|
|
ifname='mgmt',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
|
|
ret = self.service.platform_interfaces(self.context, ihost['id'])
|
|
self.assertEqual(ret, [])
|
|
|
|
def test_platform_interfaces_invalid_ihost(self):
|
|
ihost = self._create_test_ihost()
|
|
interface = utils.create_test_interface(
|
|
ifname='mgmt',
|
|
forihostid=ihost['id'],
|
|
ihost_uuid=ihost['uuid'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET)
|
|
utils.create_test_ethernet_port(
|
|
name='eth0',
|
|
host_id=ihost['id'],
|
|
interface_id=interface['id'],
|
|
pciaddr='0000:00:00.01',
|
|
dev_id=0)
|
|
|
|
ret = self.service.platform_interfaces(self.context, ihost['id'] + 1)
|
|
self.assertEqual(ret, [])
|
|
|
|
def test_kube_download_images(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES,
|
|
)
|
|
|
|
# Download images
|
|
self.service.kube_download_images(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADED_IMAGES)
|
|
|
|
def test_kube_download_images_ansible_fail(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_FIRST_MASTER,
|
|
)
|
|
# Fake an ansible failure
|
|
self.fake_subprocess_popen.returncode = 1
|
|
|
|
# Download images
|
|
self.service.kube_download_images(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES_FAILED)
|
|
|
|
def test_kube_upgrade_init_actions(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# Test the handling of transitory upgrade states
|
|
expected_fail_results = [
|
|
(kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES_FAILED),
|
|
(kubernetes.KUBE_UPGRADING_FIRST_MASTER,
|
|
kubernetes.KUBE_UPGRADING_FIRST_MASTER_FAILED),
|
|
(kubernetes.KUBE_UPGRADING_NETWORKING,
|
|
kubernetes.KUBE_UPGRADING_NETWORKING_FAILED),
|
|
(kubernetes.KUBE_UPGRADING_SECOND_MASTER,
|
|
kubernetes.KUBE_UPGRADING_SECOND_MASTER_FAILED),
|
|
]
|
|
|
|
for current_state, fail_state in expected_fail_results:
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=current_state,
|
|
)
|
|
self.service._kube_upgrade_init_actions()
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state, fail_state)
|
|
self.dbapi.kube_upgrade_destroy(updated_upgrade.id)
|
|
|
|
# Test the handling of transitory host upgrade states
|
|
expected_fail_results = [
|
|
(kubernetes.KUBE_HOST_UPGRADING_CONTROL_PLANE,
|
|
kubernetes.KUBE_HOST_UPGRADING_CONTROL_PLANE_FAILED),
|
|
(kubernetes.KUBE_HOST_UPGRADING_KUBELET,
|
|
kubernetes.KUBE_HOST_UPGRADING_KUBELET_FAILED),
|
|
]
|
|
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_KUBELETS,
|
|
)
|
|
|
|
for current_status, fail_status in expected_fail_results:
|
|
self.dbapi.kube_host_upgrade_update(1, {'status': current_status})
|
|
self.service._kube_upgrade_init_actions()
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status, fail_status)
|
|
|
|
def test_kube_download_images_one_controller(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.MANIFEST_APPLY_TIMEOUT = 1
|
|
|
|
# Download images
|
|
self.service.kube_download_images(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADED_IMAGES)
|
|
|
|
def test_kube_download_images_one_controller_manifest_timeout(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.MANIFEST_APPLY_TIMEOUT = 1
|
|
|
|
# Make the manifest apply fail
|
|
self.fail_config_apply_runtime_manifest = True
|
|
|
|
# Download images
|
|
self.service.kube_download_images(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES_FAILED)
|
|
|
|
def test_kube_download_images_two_controllers(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADE_DOWNLOADING_IMAGES,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Create controller-1
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-1',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:56',
|
|
mgmt_ip='1.2.3.5',
|
|
)
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.MANIFEST_APPLY_TIMEOUT = 1
|
|
|
|
# Download images
|
|
self.service.kube_download_images(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADE_DOWNLOADED_IMAGES)
|
|
|
|
def test_kube_upgrade_control_plane_first_master(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_FIRST_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Make the control plane upgrade pass
|
|
self.kube_get_control_plane_versions_result = {
|
|
'controller-0': 'v1.42.2',
|
|
'controller-1': 'v1.42.1',
|
|
'worker-0': 'v1.42.1'}
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
|
|
# Upgrade the control plane
|
|
self.service.kube_upgrade_control_plane(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADED_FIRST_MASTER)
|
|
|
|
# Verify that the host upgrade status was cleared
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status, None)
|
|
|
|
def test_kube_upgrade_control_plane_first_master_manifest_timeout(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_FIRST_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Make the manifest apply fail
|
|
self.fail_config_apply_runtime_manifest = True
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.MANIFEST_APPLY_TIMEOUT = 1
|
|
|
|
# Upgrade the control plane
|
|
self.service.kube_upgrade_control_plane(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADING_FIRST_MASTER_FAILED)
|
|
|
|
# Verify that the host upgrade status was set
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status,
|
|
kubernetes.KUBE_HOST_UPGRADING_CONTROL_PLANE_FAILED)
|
|
|
|
def test_kube_upgrade_control_plane_first_master_upgrade_fail(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_FIRST_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
kubernetes.POD_START_TIMEOUT = 1
|
|
|
|
# Upgrade the control plane
|
|
self.service.kube_upgrade_control_plane(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADING_FIRST_MASTER_FAILED)
|
|
|
|
# Verify that the host upgrade status was cleared
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertIsNotNone(updated_host_upgrade.status)
|
|
|
|
def test_kube_upgrade_control_plane_second_master(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_SECOND_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:55',
|
|
mgmt_ip='1.2.3.4',
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Create controller-1
|
|
config_uuid = str(uuid.uuid4())
|
|
c1 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-1',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:56',
|
|
mgmt_ip='1.2.3.5',
|
|
)
|
|
# Set the target version for controller-1
|
|
self.dbapi.kube_host_upgrade_update(2, {'target_version': 'v1.42.2'})
|
|
# Make the control plane upgrade pass
|
|
self.kube_get_control_plane_versions_result = {
|
|
'controller-0': 'v1.42.2',
|
|
'controller-1': 'v1.42.2',
|
|
'worker-0': 'v1.42.1'}
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
|
|
# Upgrade the control plane
|
|
self.service.kube_upgrade_control_plane(self.context, c1.uuid)
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADED_SECOND_MASTER)
|
|
|
|
# Verify that the host upgrade status was cleared
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status, None)
|
|
|
|
def test_kube_upgrade_kubelet_controller(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADED_SECOND_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Make the kubelet upgrade pass
|
|
self.kube_get_kubelet_versions_result = {
|
|
'controller-0': 'v1.42.2',
|
|
'controller-1': 'v1.42.1',
|
|
'worker-0': 'v1.42.1'}
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
|
|
# Upgrade the kubelet
|
|
self.service.kube_upgrade_kubelet(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was not updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADED_SECOND_MASTER)
|
|
|
|
# Verify that the host upgrade status is upgraded-kubelet
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status,
|
|
kubernetes.KUBE_HOST_UPGRADED_KUBELET)
|
|
|
|
def test_kube_upgrade_kubelet_second_master(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_SECOND_MASTER,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:55',
|
|
mgmt_ip='1.2.3.4',
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Create controller-1
|
|
config_uuid = str(uuid.uuid4())
|
|
c1 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-1',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:56',
|
|
mgmt_ip='1.2.3.5',
|
|
)
|
|
# Set the target version for controller-1
|
|
self.dbapi.kube_host_upgrade_update(2, {'target_version': 'v1.42.2'})
|
|
# Make the kubelet upgrade pass
|
|
self.kube_get_kubelet_versions_result = {
|
|
'controller-0': 'v1.42.2',
|
|
'controller-1': 'v1.42.2'}
|
|
# Make the upgrade pass
|
|
self.kube_get_control_plane_versions_result = {
|
|
'controller-0': 'v1.42.2',
|
|
'controller-1': 'v1.42.2'}
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
|
|
# Upgrade the kubelet
|
|
self.service.kube_upgrade_kubelet(self.context, c1.uuid)
|
|
|
|
# Verify that the host upgrade status was cleared
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status, None)
|
|
|
|
def test_kube_upgrade_kubelet_controller_manifest_timeout(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_KUBELETS,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
# Make the manifest apply fail
|
|
self.fail_config_apply_runtime_manifest = True
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.MANIFEST_APPLY_TIMEOUT = 1
|
|
|
|
# Upgrade the kubelet
|
|
self.service.kube_upgrade_kubelet(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was not updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADING_KUBELETS)
|
|
|
|
# Verify that the host upgrade status was set
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertEqual(updated_host_upgrade.status,
|
|
kubernetes.KUBE_HOST_UPGRADING_KUBELET_FAILED)
|
|
|
|
def test_kube_upgrade_kubelet_controller_upgrade_fail(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_KUBELETS,
|
|
)
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
c0 = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
# Set the target version for controller-0
|
|
self.dbapi.kube_host_upgrade_update(1, {'target_version': 'v1.42.2'})
|
|
|
|
# Speed up the test
|
|
kubernetes.MANIFEST_APPLY_INTERVAL = 1
|
|
kubernetes.POD_START_INTERVAL = 1
|
|
kubernetes.POD_START_TIMEOUT = 1
|
|
|
|
# Upgrade the kubelet
|
|
self.service.kube_upgrade_kubelet(self.context, c0.uuid)
|
|
|
|
# Verify that the upgrade state was not updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADING_KUBELETS)
|
|
|
|
# Verify that the host upgrade status was cleared
|
|
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
|
|
self.assertIsNotNone(updated_host_upgrade.status)
|
|
|
|
def test_kube_upgrade_networking(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_NETWORKING,
|
|
)
|
|
|
|
# Upgrade kubernetes networking
|
|
self.service.kube_upgrade_networking(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADED_NETWORKING)
|
|
|
|
def test_kube_upgrade_networking_ansible_fail(self):
|
|
# Create an upgrade
|
|
utils.create_test_kube_upgrade(
|
|
from_version='v1.42.1',
|
|
to_version='v1.42.2',
|
|
state=kubernetes.KUBE_UPGRADING_NETWORKING,
|
|
)
|
|
# Fake an ansible failure
|
|
self.fake_subprocess_popen.returncode = 1
|
|
|
|
# Upgrade kubernetes networking
|
|
self.service.kube_upgrade_networking(self.context, 'v1.42.2')
|
|
|
|
# Verify that the upgrade state was updated
|
|
updated_upgrade = self.dbapi.kube_upgrade_get_one()
|
|
self.assertEqual(updated_upgrade.state,
|
|
kubernetes.KUBE_UPGRADING_NETWORKING_FAILED)
|
|
|
|
def _create_test_controller_config_out_of_date(self, hostname):
|
|
config_applied = self.service._config_set_reboot_required(uuid.uuid4())
|
|
config_target = self.service._config_set_reboot_required(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
uuid=str(uuid.uuid4()),
|
|
config_applied=config_applied,
|
|
config_target=config_target)
|
|
ihost['mgmt_mac'] = '00:11:22:33:44:55'
|
|
ihost['mgmt_ip'] = '1.2.3.42'
|
|
ihost['hostname'] = hostname
|
|
ihost['invprovision'] = 'provisioned'
|
|
ihost['personality'] = 'controller'
|
|
ihost['administrative'] = 'unlocked'
|
|
ihost['operational'] = 'disabled'
|
|
ihost['availability'] = 'online'
|
|
ihost['serialid'] = '1234567890abc'
|
|
ihost['boot_device'] = 'sda'
|
|
ihost['rootfs_device'] = 'sda'
|
|
ihost['install_output'] = 'text'
|
|
ihost['console'] = 'ttyS0,115200'
|
|
|
|
return ihost
|
|
|
|
def test_configure_out_of_date(self):
|
|
os.path.isfile = mock.Mock(return_value=True)
|
|
cutils.is_aio_system = mock.Mock(return_value=True)
|
|
ihost = self._create_test_controller_config_out_of_date('controller-0')
|
|
self.service.configure_ihost(self.context, ihost)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
imsg_dict = {'config_applied': res['config_target']}
|
|
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
|
|
self.assertEqual(self.alarm_raised, False)
|
|
|
|
personalities = [constants.CONTROLLER]
|
|
self.service._config_update_hosts(self.context, personalities, reboot=True)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
|
|
personalities = [constants.CONTROLLER]
|
|
self.service._config_update_hosts(self.context, personalities, reboot=False)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
config_uuid = self.service._config_clear_reboot_required(res['config_target'])
|
|
imsg_dict = {'config_applied': config_uuid}
|
|
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
def test_configure_out_of_date_upgrade(self):
|
|
os.path.isfile = mock.Mock(return_value=True)
|
|
cutils.is_aio_system = mock.Mock(return_value=True)
|
|
|
|
# Check upgrade where the target sw_version does not match
|
|
self.mock_host_load_matches_sw_version.return_value = False
|
|
ihost = self._create_test_controller_config_out_of_date('controller-1')
|
|
self.service.configure_ihost(self.context, ihost)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
imsg_dict = {'config_applied': res['config_target']}
|
|
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
|
|
self.assertEqual(self.alarm_raised, False)
|
|
|
|
personalities = [constants.CONTROLLER]
|
|
self.service._config_update_hosts(self.context, personalities, reboot=True)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
|
|
personalities = [constants.CONTROLLER]
|
|
self.service._config_update_hosts(self.context, personalities, reboot=False)
|
|
res = self.dbapi.ihost_get(ihost['uuid'])
|
|
config_uuid = self.service._config_clear_reboot_required(res['config_target'])
|
|
imsg_dict = {'config_applied': config_uuid}
|
|
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
def fake_rename(self, old, new):
|
|
self.executes.append(('mv', old, new))
|
|
|
|
@staticmethod
|
|
def scope_open(*args, **kwargs):
|
|
fake_contents = "lorem ipsum"
|
|
fake_file = mock.Mock()
|
|
fake_file.read.return_value = fake_contents
|
|
fake_context_manager = mock.MagicMock()
|
|
fake_context_manager.__enter__.return_value = fake_file
|
|
fake_context_manager.__exit__.return_value = None
|
|
|
|
if not args[0].startswith( # filename
|
|
os.path.join(tsc.CONFIG_PATH, 'resolv.conf')):
|
|
return open(*args, **kwargs)
|
|
else:
|
|
return fake_context_manager
|
|
|
|
def test_deferred_runtime_config_file(self):
|
|
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
chost = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create test dns nameservers config
|
|
utils.create_test_dns(forisystemid=self.system.id,
|
|
nameservers='8.8.8.8,8.8.4.4')
|
|
cutils.gethostbyname = mock.Mock(return_value='192.168.204.2')
|
|
|
|
self.executes = []
|
|
self.stub_out('os.rename', self.fake_rename)
|
|
|
|
# These mock for builtin open are needed for py27 and py3 compatibility
|
|
mock_trace_caller = mock.MagicMock()
|
|
p = mock.patch(
|
|
'traceback.format_stack',
|
|
mock_trace_caller)
|
|
p.start()
|
|
p.return_value = ['one', 'two', 'three']
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_open.side_effect = self.scope_open
|
|
self.mock_ready_to_apply_runtime_config.return_value = False
|
|
self.service.update_dns_config(self.context)
|
|
chost_updated = self.dbapi.ihost_get(chost.uuid)
|
|
|
|
# Verify that the config is updated and alarm is raised
|
|
self.assertNotEqual(chost_updated.config_applied,
|
|
chost_updated.config_target)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
self.mock_ready_to_apply_runtime_config.return_value = True
|
|
self.service._audit_deferred_runtime_config(self.context)
|
|
|
|
# Simulate agent update
|
|
chost_updated = self.dbapi.ihost_get(chost.uuid)
|
|
self.service._update_host_config_applied(
|
|
self.context, chost_updated, chost_updated.config_applied)
|
|
|
|
# Verify the config is up to date.
|
|
self.assertEqual(chost_updated.config_target,
|
|
chost_updated.config_applied)
|
|
self.assertEqual(self.alarm_raised, False)
|
|
|
|
def test_deferred_runtime_config_manifest(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
chost = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
self.mock_ready_to_apply_runtime_config.return_value = False
|
|
self.service.update_user_config(self.context)
|
|
chost_updated = self.dbapi.ihost_get(chost.uuid)
|
|
|
|
# Verify that the config is updated and alarm is raised
|
|
self.assertNotEqual(chost_updated.config_applied,
|
|
chost_updated.config_target)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
self.mock_ready_to_apply_runtime_config.return_value = True
|
|
self.service._audit_deferred_runtime_config(self.context)
|
|
|
|
# Simulate agent update
|
|
chost_updated = self.dbapi.ihost_get(chost.uuid)
|
|
self.service._update_host_config_applied(
|
|
self.context, chost_updated, chost_updated.config_applied)
|
|
|
|
# Verify the config is up to date.
|
|
self.assertEqual(chost_updated.config_target,
|
|
chost_updated.config_applied)
|
|
self.assertEqual(self.alarm_raised, False)
|
|
|
|
def test_deferred_multiple_runtime_config(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
chost = self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create test dns nameservers config
|
|
utils.create_test_dns(forisystemid=self.system.id,
|
|
nameservers='8.8.8.8,8.8.4.4')
|
|
cutils.gethostbyname = mock.Mock(return_value='192.168.204.2')
|
|
|
|
self.executes = []
|
|
self.stub_out('os.rename', self.fake_rename)
|
|
|
|
# These mock for builtin open are needed for py27 and py3 compatibility
|
|
mock_trace_caller = mock.MagicMock()
|
|
p = mock.patch(
|
|
'traceback.format_stack',
|
|
mock_trace_caller)
|
|
p.start()
|
|
p.return_value = ['one', 'two', 'three']
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_open.side_effect = self.scope_open
|
|
# Attempt to apply a runtime config, which is deferred
|
|
self.mock_ready_to_apply_runtime_config.return_value = False
|
|
self.service.update_dns_config(self.context)
|
|
c1host_updated = self.dbapi.ihost_get(chost.uuid)
|
|
|
|
# Verify that the config is updated and alarm is raised
|
|
self.assertNotEqual(c1host_updated.config_applied,
|
|
c1host_updated.config_target)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
# Attempt another runtime config, which is also deferred
|
|
self.service.update_user_config(self.context)
|
|
c2host_updated = self.dbapi.ihost_get(chost.uuid)
|
|
|
|
# Verify that the target is updated and alarm is still raised
|
|
self.assertNotEqual(c1host_updated.config_target,
|
|
c2host_updated.config_target)
|
|
self.assertEqual(c1host_updated.config_applied,
|
|
c1host_updated.config_applied)
|
|
self.assertNotEqual(c2host_updated.config_applied,
|
|
c2host_updated.config_target)
|
|
self.assertEqual(self.alarm_raised, True)
|
|
|
|
# Run the audit for deferred runtime config
|
|
self.mock_ready_to_apply_runtime_config.return_value = True
|
|
self.service._audit_deferred_runtime_config(self.context)
|
|
|
|
# Simulate agent update
|
|
chost_updated = self.dbapi.ihost_get(chost.uuid)
|
|
self.service._update_host_config_applied(
|
|
self.context, chost_updated, chost_updated.config_applied)
|
|
|
|
# Verify the config is up to date.
|
|
self.assertEqual(chost_updated.config_target,
|
|
chost_updated.config_applied)
|
|
self.assertEqual(self.alarm_raised, False)
|
|
|
|
def _raise_alarm(self, fault):
|
|
self.alarm_raised = True
|
|
|
|
def _clear_alarm(self, fm_id, fm_instance):
|
|
self.alarm_raised = False
|
|
|
|
def _get_faults_by_id(self, alarm_id):
|
|
return None
|
|
|
|
def _create_test_ihosts(self):
|
|
# Create controller-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:55',
|
|
mgmt_ip='1.2.3.4')
|
|
# Create controller-1
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.CONTROLLER,
|
|
hostname='controller-1',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='22:44:33:55:11:66',
|
|
mgmt_ip='1.2.3.5')
|
|
# Create compute-0
|
|
config_uuid = str(uuid.uuid4())
|
|
self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='22:44:33:55:11:77',
|
|
mgmt_ip='1.2.3.6')
|
|
|
|
def _create_test_iports(self):
|
|
enp25s0f0 = {'dev_id': 0, 'numa_node': 0, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Ethernet Controller X710 for 10GbE SFP+ [1572]', 'link_mode': '0',
|
|
'driver': 'i40e', 'pclass': 'Ethernet controller [0200]', 'mtu': 1500,
|
|
'psdevice': 'Ethernet Converged Network Adapter X710-2 [0008]',
|
|
'mac': '3c:fd:fe:b5:72:e0', 'prevision': '-r01', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:19:00.0', 'dpdksupport': True,
|
|
'pname': 'enp25s0f0', 'speed': 10000, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp25s0f1 = {'dev_id': 0, 'numa_node': 0, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Ethernet Controller X710 for 10GbE SFP+ [1572]', 'link_mode': '0',
|
|
'driver': 'i40e', 'pclass': 'Ethernet controller [0200]', 'mtu': 1500,
|
|
'psdevice': 'Ethernet Converged Network Adapter X710 [0000]',
|
|
'mac': '3c:fd:fe:b5:72:e1', 'prevision': '-r01', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:19:00.1', 'dpdksupport': True,
|
|
'pname': 'enp25s0f1', 'speed': 10000, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp134s0f0 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': '82571EB/82571GB Gigabit Ethernet Controller D0/D1 [105e]',
|
|
'link_mode': '0', 'driver': 'e1000e', 'pclass': 'Ethernet controller [0200]',
|
|
'mtu': 1500, 'psdevice': 'PRO/1000 PT Dual Port Server Adapter [115e]',
|
|
'mac': '00:15:17:cd:c4:ac', 'prevision': '-r06', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:86:00.0', 'dpdksupport': False,
|
|
'pname': 'enp134s0f0', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp134s0f1 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': '82571EB/82571GB Gigabit Ethernet Controller D0/D1 [105e]', 'link_mode': '0',
|
|
'driver': 'e1000e', 'pclass': 'Ethernet controller [0200]',
|
|
'mtu': 1500, 'psdevice': 'PRO/1000 PT Dual Port Server Adapter [115e]',
|
|
'mac': '00:15:17:cd:c4:ad', 'prevision': '-r06', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:86:00.1', 'dpdksupport': False,
|
|
'pname': 'enp134s0f1', 'speed': 1000, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp135s0f0 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Ethernet Controller X710 for 10GbE SFP+ [1572]', 'link_mode': '0',
|
|
'driver': 'i40e', 'pclass': 'Ethernet controller [0200]', 'mtu': 9216,
|
|
'psdevice': 'Ethernet Converged Network Adapter X710-2 [0008]',
|
|
'mac': '3c:fd:fe:b5:73:28', 'prevision': '-r01', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:87:00.0', 'dpdksupport': True,
|
|
'pname': 'enp135s0f0', 'speed': 10000, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp135s0f1 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Ethernet Controller X710 for 10GbE SFP+ [1572]', 'link_mode': '0',
|
|
'driver': 'i40e', 'pclass': 'Ethernet controller [0200]', 'mtu': 1500,
|
|
'psdevice': 'Ethernet Converged Network Adapter X710 [0000]',
|
|
'mac': '3c:fd:fe:b5:73:29', 'prevision': '-r01', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:87:00.1', 'dpdksupport': True,
|
|
'pname': 'enp135s0f1', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp177s0f0 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Device [0d58]', 'link_mode': '0', 'driver': 'i40e',
|
|
'pclass': 'Ethernet controller [0200]', 'mtu': 1500, 'psdevice': 'Device [0000]',
|
|
'mac': '64:4c:36:12:9b:78', 'prevision': '-r02', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:b1:00.0', 'dpdksupport': False,
|
|
'pname': 'enp177s0f0', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp177s0f1 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Device [0d58]', 'link_mode': '0', 'driver': 'i40e',
|
|
'pclass': 'Ethernet controller [0200]', 'mtu': 1500, 'psdevice': 'Device [0000]',
|
|
'mac': '64:4c:36:12:9b:79', 'prevision': '-r02', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:b1:00.1', 'dpdksupport': False,
|
|
'pname': 'enp177s0f1', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp181s0f0 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Device [0d58]', 'link_mode': '0', 'driver': 'i40e',
|
|
'pclass': 'Ethernet controller [0200]', 'mtu': 1500, 'psdevice': 'Device [0000]',
|
|
'mac': '64:4c:36:12:9b:7c', 'prevision': '-r02', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:b3:00.0', 'dpdksupport': False,
|
|
'pname': 'enp181s0f0', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
enp181s0f1 = {'dev_id': 0, 'numa_node': 1, 'sriov_numvfs': 0, 'sriov_vfs_pci_address': '',
|
|
'pdevice': 'Device [0d58]', 'link_mode': '0', 'driver': 'i40e',
|
|
'pclass': 'Ethernet controller [0200]', 'mtu': 1500, 'psdevice': 'Device [0000]',
|
|
'mac': '64:4c:36:12:9b:7d', 'prevision': '-r02', 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': 64, 'pciaddr': '0000:b3:00.1', 'dpdksupport': False,
|
|
'pname': 'enp181s0f1', 'speed': None, 'psvendor': 'Intel Corporation [8086]',
|
|
'sriov_vf_driver': None, 'pvendor': 'Intel Corporation [8086]'}
|
|
|
|
inic_dict_array = [enp25s0f0, enp25s0f1, enp134s0f0, enp134s0f1,
|
|
enp135s0f0, enp135s0f1, enp177s0f0, enp177s0f1, enp181s0f0, enp181s0f1]
|
|
|
|
return inic_dict_array
|
|
|
|
def _create_test_networks(self, mgmt_vlan_id):
|
|
address_pool_mgmt = utils.create_test_address_pool(id=1, network='192.168.204.0',
|
|
name='management', ranges=[['192.168.204.2', '192.168.204.254']], prefix=24)
|
|
mgmt_net = utils.create_test_network(id=1, name='mgmt', type=constants.NETWORK_TYPE_MGMT,
|
|
link_capacity=1000, vlan_id=mgmt_vlan_id, address_pool_id=address_pool_mgmt.id)
|
|
|
|
address_pool_pxeboot = utils.create_test_address_pool(id=2, network='192.168.205.0',
|
|
name='pxeboot', ranges=[['192.168.205.2', '192.168.205.254']], prefix=24)
|
|
pxeboot_net = utils.create_test_network(id=2, name='pxeboot',
|
|
type=constants.NETWORK_TYPE_PXEBOOT,
|
|
link_capacity=1000, address_pool_id=address_pool_pxeboot.id)
|
|
|
|
return mgmt_net, pxeboot_net
|
|
|
|
def test_get_ihost_by_macs(self):
|
|
self._create_test_ihosts()
|
|
ihost_macs = ['22:44:33:55:11:66', '22:44:33:88:11:66']
|
|
ihost = self.service.get_ihost_by_macs(self.context, ihost_macs)
|
|
self.assertEqual(ihost.mgmt_mac, '22:44:33:55:11:66')
|
|
|
|
def test_get_ihost_by_macs_no_match(self):
|
|
self._create_test_ihosts()
|
|
ihost = None
|
|
ihost_macs = ['22:44:33:99:11:66', '22:44:33:88:11:66']
|
|
ihost = self.service.get_ihost_by_macs(self.context, ihost_macs)
|
|
self.assertEqual(ihost, None)
|
|
|
|
def test_get_ihost_by_hostname(self):
|
|
self._create_test_ihosts()
|
|
ihost_hostname = 'controller-1'
|
|
ihost = self.service.get_ihost_by_hostname(self.context, ihost_hostname)
|
|
self.assertEqual(ihost.mgmt_mac, '22:44:33:55:11:66')
|
|
self.assertEqual(ihost.mgmt_ip, '1.2.3.5')
|
|
self.assertEqual(ihost.hostname, 'controller-1')
|
|
|
|
def test_get_ihost_by_hostname_invalid_name(self):
|
|
self._create_test_ihosts()
|
|
ihost_hostname = 'compute'
|
|
ihost = None
|
|
ihost = self.service.get_ihost_by_hostname(self.context, ihost_hostname)
|
|
self.assertEqual(ihost, None)
|
|
|
|
def test_iport_update_by_ihost_basic_creation(self):
|
|
"""Test the sysinv-agent port inventory basic port and interface creation
|
|
|
|
This test creates the port and interfaces based on the incoming report without any entry
|
|
matching the MAC address. The objective of this test if the data is stored on the correct
|
|
database tables
|
|
"""
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='compute-0', mgmt_mac='22:44:33:55:11:77', uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = 0
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
|
|
inic_mac_dict = dict()
|
|
for inic in inic_dict_array:
|
|
inic_mac_dict[inic['mac']] = inic
|
|
|
|
inic_pciaddr_dict = dict()
|
|
for inic in inic_dict_array:
|
|
inic_pciaddr_dict[inic['pciaddr']] = inic
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
# check fields for each table
|
|
iface_db_list = self.dbapi.iinterface_get_by_ihost(ihost['uuid'])
|
|
self.assertEqual(len(iface_db_list), len(inic_dict_array))
|
|
for iface in iface_db_list:
|
|
self.assertIn(iface.imac, inic_mac_dict)
|
|
self.assertEqual(inic_mac_dict[iface.imac]['pname'], iface.ifname)
|
|
self.assertEqual(inic_mac_dict[iface.imac]['mac'], iface.imac)
|
|
|
|
eth_iface_db_list = self.dbapi.ethernet_interface_get_by_ihost(ihost['uuid'])
|
|
self.assertEqual(len(eth_iface_db_list), len(inic_dict_array))
|
|
|
|
port_db_list = self.dbapi.port_get_by_host(ihost['uuid'])
|
|
self.assertEqual(len(port_db_list), len(inic_dict_array))
|
|
for port in port_db_list:
|
|
self.assertIn(port.pciaddr, inic_pciaddr_dict)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['pciaddr'], port.pciaddr)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['pname'], port.name)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['numa_node'], port.numa_node)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['pdevice'], port.pdevice)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['driver'], port.driver)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['pclass'], port.pclass)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['psdevice'], port.psdevice)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['psvendor'], port.psvendor)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['pvendor'], port.pvendor)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['sriov_vf_driver'],
|
|
port.sriov_vf_driver)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['sriov_numvfs'], port.sriov_numvfs)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['sriov_totalvfs'], port.sriov_totalvfs)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['sriov_vfs_pci_address'],
|
|
port.sriov_vfs_pci_address)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['sriov_vf_pdevice_id'],
|
|
port.sriov_vf_pdevice_id)
|
|
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
self.assertEqual(len(eth_port_db_list), len(inic_dict_array))
|
|
for port in eth_port_db_list:
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['mtu'], port.mtu)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['speed'], port.speed)
|
|
self.assertEqual(inic_pciaddr_dict[port.pciaddr]['link_mode'], port.link_mode)
|
|
|
|
def test_iport_update_by_ihost_report_with_mgmt_untagged(self):
|
|
"""Test the sysinv-agent port inventory for managemet interface without VLAN
|
|
|
|
If the port MAC matches the host's MAC and it is not the active controller, test the entry
|
|
update to become a managemet interface and attached to the management network. The port
|
|
must receive the bootp flag.
|
|
"""
|
|
mgmt_vlan_id = 0
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='compute-0', mgmt_mac='22:44:33:55:11:77', uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = mgmt_vlan_id
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
inic_dict_array[2]['mac'] = ihost['mgmt_mac']
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
iface_db_list = self.dbapi.iinterface_get_by_ihost(ihost['uuid'])
|
|
self.assertEqual(len(iface_db_list), len(inic_dict_array))
|
|
has_mgmt = False
|
|
for iface in iface_db_list:
|
|
if (iface.imac == ihost['mgmt_mac']):
|
|
self.assertEqual('mgmt0', iface.ifname)
|
|
self.assertEqual('ethernet', iface.iftype)
|
|
self.assertEqual('platform', iface.ifclass)
|
|
ifnets = self.dbapi.interface_network_get_by_interface(iface.uuid)
|
|
self.assertEqual(len(ifnets), 1)
|
|
network = self.dbapi.network_get_by_id(ifnets[0].network_id)
|
|
self.assertEqual(network.type, constants.NETWORK_TYPE_MGMT)
|
|
has_mgmt = True
|
|
self.assertTrue(has_mgmt)
|
|
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
for eth_port in eth_port_db_list:
|
|
if (eth_port.mac == ihost['mgmt_mac']):
|
|
self.assertTrue(eth_port.bootp)
|
|
else:
|
|
self.assertFalse(eth_port.bootp)
|
|
|
|
def test_iport_update_by_ihost_report_with_mgmt_vlan(self):
|
|
"""Test the sysinv-agent port inventory for managemet interface with VLAN
|
|
|
|
If the port MAC matches the host's MAC and it is not the active controller, there should
|
|
be 2 interfaces with the same MAC, one without VLAN and marked for pxeboot usage and the
|
|
other for management on the selected VLAN. The port must receive the bootp flag.
|
|
"""
|
|
mgmt_vlan_id = 111
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='compute-0', mgmt_mac='22:44:33:55:11:77', uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = mgmt_vlan_id
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
inic_dict_array[2]['mac'] = ihost['mgmt_mac']
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
iface_db_list = self.dbapi.iinterface_get_by_ihost(ihost['uuid'])
|
|
self.assertEqual(len(iface_db_list), len(inic_dict_array) + 1)
|
|
has_mgmt = False
|
|
has_pxeboot = False
|
|
for iface in iface_db_list:
|
|
if (iface.imac == ihost['mgmt_mac']):
|
|
ifnets = self.dbapi.interface_network_get_by_interface(iface.uuid)
|
|
if ('mgmt0' == iface.ifname):
|
|
self.assertEqual('vlan', iface.iftype)
|
|
self.assertEqual('platform', iface.ifclass)
|
|
self.assertEqual(mgmt_vlan_id, iface.vlan_id)
|
|
self.assertIn('mgmt', iface.networktypelist)
|
|
self.assertIn('pxeboot0', iface.uses)
|
|
has_mgmt = True
|
|
self.assertEqual(len(ifnets), 1)
|
|
network = self.dbapi.network_get_by_id(ifnets[0].network_id)
|
|
self.assertEqual(network.type, constants.NETWORK_TYPE_MGMT)
|
|
if ('pxeboot0' == iface.ifname):
|
|
self.assertEqual('ethernet', iface.iftype)
|
|
self.assertEqual('platform', iface.ifclass)
|
|
self.assertIn('mgmt0', iface.used_by)
|
|
has_pxeboot = True
|
|
self.assertEqual(len(ifnets), 1)
|
|
network = self.dbapi.network_get_by_id(ifnets[0].network_id)
|
|
self.assertEqual(network.type, constants.NETWORK_TYPE_PXEBOOT)
|
|
self.assertTrue(has_pxeboot and has_mgmt)
|
|
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
for eth_port in eth_port_db_list:
|
|
if (eth_port.mac == ihost['mgmt_mac']):
|
|
self.assertTrue(eth_port.bootp)
|
|
else:
|
|
self.assertFalse(eth_port.bootp)
|
|
|
|
def test_iport_update_by_ihost_report_active_controller_with_mgmt_untagged(self):
|
|
"""Test the port inventory for managemet interface without VLAN on the active controller
|
|
|
|
If the port MAC matches the host's MAC and it is the active controller, no managemet
|
|
interface is created and the port receive the bootp flag
|
|
"""
|
|
mgmt_vlan_id = 0
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.CONTROLLER, hostname='controller-0', uuid=str(uuid.uuid4()),
|
|
config_status=None, config_applied=config_uuid, config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED, administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED, availability=constants.AVAILABILITY_ONLINE,
|
|
mgmt_mac='00:11:22:33:44:55', mgmt_ip='1.2.3.4')
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = mgmt_vlan_id
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
inic_dict_array[2]['mac'] = ihost['mgmt_mac']
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
iface_db_list = self.dbapi.iinterface_get_by_ihost(ihost['uuid'])
|
|
for iface in iface_db_list:
|
|
if (iface.imac == ihost['mgmt_mac']):
|
|
self.assertNotEqual('mgmt0', iface.ifname)
|
|
self.assertNotEqual('platform', iface.ifclass)
|
|
ifnets = self.dbapi.interface_network_get_by_interface(iface.uuid)
|
|
self.assertEqual(len(ifnets), 0)
|
|
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
for eth_port in eth_port_db_list:
|
|
if (eth_port.mac == ihost['mgmt_mac']):
|
|
self.assertTrue(eth_port.bootp)
|
|
|
|
def test_iport_update_by_ihost_report_install_from_clone(self):
|
|
"""Test the port inventory MAC update when DB is in install from clone
|
|
|
|
When installing from clone the database interfaces will have the MAC filed with a special
|
|
marker, the inventory report will be used to update with the actual port MAC.
|
|
"""
|
|
mgmt_vlan_id = 111
|
|
inic_dict_array = self._create_test_iports()
|
|
hostname = 'compute-0'
|
|
clone_mgmt_mac = (constants.CLONE_ISO_MAC + hostname + inic_dict_array[3]['pname'])
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname=hostname, mgmt_mac=clone_mgmt_mac, uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = mgmt_vlan_id
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
sriov0 = utils.create_test_interface(ifname='sriov0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=(constants.CLONE_ISO_MAC + ihost['hostname']
|
|
+ inic_dict_array[0]['pname']))
|
|
sriov0a = utils.create_test_interface(ifname='sriov0a',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VF, uses=['sriov0'],
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=(constants.CLONE_ISO_MAC + ihost['hostname']
|
|
+ inic_dict_array[0]['pname']))
|
|
data0 = utils.create_test_interface(ifname='data0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
imac=(constants.CLONE_ISO_MAC + ihost['hostname']
|
|
+ inic_dict_array[1]['pname']))
|
|
pcipt0 = utils.create_test_interface(ifname='pcipt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
imac=(constants.CLONE_ISO_MAC + ihost['hostname']
|
|
+ inic_dict_array[2]['pname']))
|
|
pxeboot0 = utils.create_test_interface(ifname='pxeboot0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
imac=clone_mgmt_mac)
|
|
mgmt0 = utils.create_test_interface(ifname='mgmt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VLAN, uses=['pxeboot0'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=mgmt_vlan_id, imac=clone_mgmt_mac)
|
|
extra0 = utils.create_test_interface(ifname='extra0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VLAN, uses=['mgmt0'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=1001, imac=clone_mgmt_mac)
|
|
extra1 = utils.create_test_interface(ifname='extra1',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VLAN, uses=['mgmt0'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=1001, imac=clone_mgmt_mac)
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
self.assertEqual(self.dbapi.iinterface_get(sriov0.id).imac, inic_dict_array[0]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(sriov0a.id).imac, inic_dict_array[0]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(data0.id).imac, inic_dict_array[1]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(pcipt0.id).imac, inic_dict_array[2]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(pxeboot0.id).imac, inic_dict_array[3]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(mgmt0.id).imac, inic_dict_array[3]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(extra0.id).imac, inic_dict_array[3]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(extra1.id).imac, inic_dict_array[3]['mac'])
|
|
|
|
self.assertEqual(self.dbapi.ihost_get_by_hostname(hostname).mgmt_mac,
|
|
inic_dict_array[3]['mac'])
|
|
|
|
def test_iport_update_by_ihost_report_update(self):
|
|
"""Test the port inventory update
|
|
|
|
Some port fields can be updated from the inventory report after database creation
|
|
"""
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='compute-0', mgmt_mac='22:44:33:55:11:77', uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = 0
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
inic_dict_array[-1]['pname'] = 'new_centos_name'
|
|
inic_dict_array[-1]['sriov_totalvfs'] = 32
|
|
inic_dict_array[-1]['sriov_numvfs'] = 4
|
|
inic_dict_array[-1]['sriov_vfs_pci_address'] = \
|
|
'0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3'
|
|
inic_dict_array[-1]['sriov_vf_driver'] = 'iavf'
|
|
inic_dict_array[-1]['sriov_vf_pdevice_id'] = '254c'
|
|
inic_dict_array[-1]['driver'] = 'igb'
|
|
inic_dict_array[-1]['dpdksupport'] = True
|
|
inic_dict_array[-1]['speed'] = 5000
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
db_size = len(inic_dict_array)
|
|
self.assertEqual(len(self.dbapi.iinterface_get_by_ihost(ihost['uuid'])), db_size)
|
|
self.assertEqual(len(self.dbapi.ethernet_interface_get_by_ihost(ihost['uuid'])), db_size)
|
|
self.assertEqual(len(self.dbapi.port_get_by_host(ihost['uuid'])), db_size)
|
|
self.assertEqual(len(self.dbapi.ethernet_port_get_by_host(ihost['uuid'])), db_size)
|
|
|
|
port = self.dbapi.ethernet_port_get_by_mac(inic_dict_array[-1]['mac'])
|
|
self.assertEqual(port.name, inic_dict_array[-1]['pname'])
|
|
self.assertEqual(port.sriov_totalvfs, inic_dict_array[-1]['sriov_totalvfs'])
|
|
self.assertEqual(port.sriov_numvfs, inic_dict_array[-1]['sriov_numvfs'])
|
|
self.assertEqual(port.sriov_vfs_pci_address, inic_dict_array[-1]['sriov_vfs_pci_address'])
|
|
self.assertEqual(port.sriov_vf_driver, inic_dict_array[-1]['sriov_vf_driver'])
|
|
self.assertEqual(port.sriov_vf_pdevice_id, inic_dict_array[-1]['sriov_vf_pdevice_id'])
|
|
self.assertEqual(port.sriov_totalvfs, inic_dict_array[-1]['sriov_totalvfs'])
|
|
self.assertEqual(port.driver, inic_dict_array[-1]['driver'])
|
|
self.assertEqual(port.speed, inic_dict_array[-1]['speed'])
|
|
self.assertEqual(port.dpdksupport, inic_dict_array[-1]['dpdksupport'])
|
|
|
|
def test_iport_update_by_ihost_report_update_same_device_same_slot_diff_mac(self):
|
|
"""Test the interface MAC update
|
|
|
|
In case of NIC exchange by the same vendor/device-id the new MAC needs to be updated
|
|
on the database if the system is AIO-SX
|
|
"""
|
|
inic_dict_array = self._create_test_iports()
|
|
test_mgmt_mac = inic_dict_array[3]['mac']
|
|
mgmt_vlan_id = 111
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac=test_mgmt_mac, uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = 0
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
ifaces = dict()
|
|
ports = dict()
|
|
ifaces['sriov0'] = utils.create_test_interface(ifname='sriov0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=inic_dict_array[0]['mac'])
|
|
ports['sriov0'] = utils.create_test_ethernet_port(name=inic_dict_array[0]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['sriov0'].id,
|
|
mac=inic_dict_array[0]['mac'],
|
|
pciaddr=inic_dict_array[0]['pciaddr'],
|
|
pdevice=inic_dict_array[0]['pdevice'],
|
|
pvendor=inic_dict_array[0]['pvendor'])
|
|
ifaces['sriov0a'] = utils.create_test_interface(ifname='sriov0a',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VF, uses=['sriov0'],
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=inic_dict_array[0]['mac'])
|
|
|
|
ifaces['data0'] = utils.create_test_interface(ifname='data0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
imac=inic_dict_array[1]['mac'])
|
|
ports['data0'] = utils.create_test_ethernet_port(name=inic_dict_array[1]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['data0'].id,
|
|
mac=inic_dict_array[1]['mac'],
|
|
pciaddr=inic_dict_array[1]['pciaddr'],
|
|
pdevice=inic_dict_array[1]['pdevice'],
|
|
pvendor=inic_dict_array[1]['pvendor'])
|
|
|
|
ifaces['pcipt0'] = utils.create_test_interface(ifname='pcipt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
imac=inic_dict_array[2]['mac'])
|
|
ports['pcipt0'] = utils.create_test_ethernet_port(name=inic_dict_array[1]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['pcipt0'].id,
|
|
mac=inic_dict_array[2]['mac'],
|
|
pciaddr=inic_dict_array[2]['pciaddr'],
|
|
pdevice=inic_dict_array[2]['pdevice'],
|
|
pvendor=inic_dict_array[2]['pvendor'])
|
|
|
|
ifaces['pxeboot0'] = utils.create_test_interface(ifname='pxeboot0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
imac=test_mgmt_mac)
|
|
ports['pxeboot0'] = utils.create_test_ethernet_port(name=inic_dict_array[3]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['pxeboot0'].id,
|
|
mac=inic_dict_array[3]['mac'],
|
|
pciaddr=inic_dict_array[3]['pciaddr'],
|
|
pdevice=inic_dict_array[3]['pdevice'],
|
|
pvendor=inic_dict_array[3]['pvendor'])
|
|
ifaces['mgmt0'] = utils.create_test_interface(ifname='mgmt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VLAN, uses=['pxeboot0'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=mgmt_vlan_id, imac=test_mgmt_mac)
|
|
|
|
inic_dict_array[0]['mac'] = '1a:2a:3a:4a:5a:6a'
|
|
inic_dict_array[1]['mac'] = 'c0:ca:de:ad:be:ff'
|
|
inic_dict_array[3]['mac'] = '20:2a:2e:2d:2e:2f'
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array[0:4])
|
|
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['sriov0'].id).imac,
|
|
inic_dict_array[0]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['sriov0a'].id).imac,
|
|
inic_dict_array[0]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['data0'].id).imac,
|
|
inic_dict_array[1]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['pcipt0'].id).imac,
|
|
inic_dict_array[2]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['pxeboot0'].id).imac,
|
|
inic_dict_array[3]['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['mgmt0'].id).imac,
|
|
inic_dict_array[3]['mac'])
|
|
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['sriov0'].id).mac,
|
|
inic_dict_array[0]['mac'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['data0'].id).mac,
|
|
inic_dict_array[1]['mac'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['pcipt0'].id).mac,
|
|
inic_dict_array[2]['mac'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['pxeboot0'].id).mac,
|
|
inic_dict_array[3]['mac'])
|
|
|
|
def test_iport_update_by_ihost_report_update_different_device_same_slot(self):
|
|
"""Test different device exchange on the same PCI address
|
|
|
|
In case of NIC exchange with a new vendor/device-id on the same PCI slot, the old entry
|
|
is erased and a new one created if the port associated interface is of class none.
|
|
Otherwise we do not process the new port until the operator removes the existing database.
|
|
We also update the port.node_id if the inode entry related to the numa node is already
|
|
created.
|
|
"""
|
|
inic_dict_array = self._create_test_iports()
|
|
test_mgmt_mac = inic_dict_array[3]['mac']
|
|
mgmt_vlan_id = 111
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac=test_mgmt_mac, uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
self._create_test_networks(mgmt_vlan_id)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = 0
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
port_alarms = dict()
|
|
|
|
def port_set_fault(fault):
|
|
port_alarms[fault.entity_instance_id] = fault
|
|
|
|
def port_clear_fault(alarm_id, entity_id):
|
|
port_alarms[entity_id].alarm_state = fm_constants.FM_ALARM_STATE_CLEAR
|
|
|
|
def port_get_faults_by_id(alarm_id):
|
|
return [fault for fault in port_alarms.values()]
|
|
|
|
self.service.fm_api.set_fault.side_effect = port_set_fault
|
|
self.service.fm_api.clear_fault.side_effect = port_clear_fault
|
|
self.service.fm_api.get_faults_by_id.side_effect = port_get_faults_by_id
|
|
|
|
ifaces = dict()
|
|
ports = dict()
|
|
ifaces['sriov0'] = utils.create_test_interface(ifname='sriov0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=inic_dict_array[0]['mac'])
|
|
ports['sriov0'] = utils.create_test_ethernet_port(name=inic_dict_array[0]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['sriov0'].id,
|
|
mac=inic_dict_array[0]['mac'],
|
|
pciaddr=inic_dict_array[0]['pciaddr'],
|
|
pdevice=inic_dict_array[0]['pdevice'],
|
|
pvendor=inic_dict_array[0]['pvendor'])
|
|
ifaces['sriov0a'] = utils.create_test_interface(ifname='sriov0a',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VF, uses=['sriov0'],
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
imac=inic_dict_array[0]['mac'])
|
|
|
|
ifaces['data0'] = utils.create_test_interface(ifname='data0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
imac=inic_dict_array[1]['mac'])
|
|
ports['data0'] = utils.create_test_ethernet_port(name=inic_dict_array[1]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['data0'].id,
|
|
mac=inic_dict_array[1]['mac'],
|
|
pciaddr=inic_dict_array[1]['pciaddr'],
|
|
pdevice=inic_dict_array[1]['pdevice'],
|
|
pvendor=inic_dict_array[1]['pvendor'])
|
|
|
|
ifaces['pcipt0'] = utils.create_test_interface(ifname='pcipt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
imac=inic_dict_array[2]['mac'])
|
|
ports['pcipt0'] = utils.create_test_ethernet_port(name=inic_dict_array[1]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['pcipt0'].id,
|
|
mac=inic_dict_array[2]['mac'],
|
|
pciaddr=inic_dict_array[2]['pciaddr'],
|
|
pdevice=inic_dict_array[2]['pdevice'],
|
|
pvendor=inic_dict_array[2]['pvendor'])
|
|
|
|
ifaces['pxeboot0'] = utils.create_test_interface(ifname='pxeboot0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
imac=test_mgmt_mac)
|
|
ports['pxeboot0'] = utils.create_test_ethernet_port(name=inic_dict_array[3]['pname'],
|
|
host_id=ihost.id, interface_id=ifaces['pxeboot0'].id,
|
|
mac=inic_dict_array[3]['mac'],
|
|
pciaddr=inic_dict_array[3]['pciaddr'],
|
|
pdevice=inic_dict_array[3]['pdevice'],
|
|
pvendor=inic_dict_array[3]['pvendor'])
|
|
ifaces['mgmt0'] = utils.create_test_interface(ifname='mgmt0',
|
|
forihostid=ihost.id, ihost_uuid=ihost.uuid,
|
|
iftype=constants.INTERFACE_TYPE_VLAN, uses=['pxeboot0'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=mgmt_vlan_id, imac=test_mgmt_mac)
|
|
|
|
# create inodes to update port.node_id
|
|
inuma_dict_array = [{'numa_node': 0, 'capabilities': {}},
|
|
{'numa_node': 1, 'capabilities': {}}]
|
|
self.service.inumas_update_by_ihost(self.context, ihost['uuid'], inuma_dict_array)
|
|
|
|
old_pci_dev = copy.deepcopy(inic_dict_array[0])
|
|
inic_dict_array[0] = inic_dict_array[-1]
|
|
inic_dict_array[0]['pciaddr'] = old_pci_dev['pciaddr']
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array[0:4])
|
|
|
|
# since the port's interface is configured we do not change the DB (the operator needs to
|
|
# do it)
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['sriov0'].id).imac,
|
|
old_pci_dev['mac'])
|
|
self.assertEqual(self.dbapi.iinterface_get(ifaces['sriov0a'].id).imac,
|
|
old_pci_dev['mac'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['sriov0'].id).mac,
|
|
old_pci_dev['mac'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['sriov0'].id).pvendor,
|
|
old_pci_dev['pvendor'])
|
|
self.assertEqual(self.dbapi.ethernet_port_get(ports['sriov0'].id).pdevice,
|
|
old_pci_dev['pdevice'])
|
|
for fault in port_alarms.values():
|
|
self.assertEqual(fault.alarm_state, fm_constants.FM_ALARM_STATE_SET)
|
|
|
|
# remove dependant interface
|
|
self.dbapi.iinterface_destroy(ifaces['sriov0a'].id)
|
|
# update interface to class none
|
|
updates = {'ifclass': None}
|
|
self.dbapi.iinterface_update(ifaces['sriov0'].uuid, updates)
|
|
|
|
port_db_len = len(self.dbapi.ethernet_port_get_by_host(ihost['uuid']))
|
|
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array[0:4])
|
|
|
|
port_found = False
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
for eth_port in eth_port_db_list:
|
|
if (eth_port.pciaddr == inic_dict_array[0]['pciaddr']):
|
|
self.assertEqual(eth_port.mac, inic_dict_array[0]['mac'])
|
|
self.assertEqual(eth_port.pvendor, inic_dict_array[0]['pvendor'])
|
|
self.assertEqual(eth_port.pdevice, inic_dict_array[0]['pdevice'])
|
|
|
|
# check if node_id points to the correct inode entry (in our case is 2)
|
|
self.assertEqual(eth_port.node_id, 2)
|
|
|
|
iface = self.dbapi.iinterface_get(eth_port.interface_id)
|
|
self.assertEqual(iface.imac, inic_dict_array[0]['mac'])
|
|
self.assertEqual(iface.ifclass, None)
|
|
port_found = True
|
|
self.assertTrue(port_found)
|
|
self.assertEqual(len(self.dbapi.ethernet_port_get_by_host(ihost['uuid'])), port_db_len)
|
|
for fault in port_alarms.values():
|
|
self.assertEqual(fault.alarm_state, fm_constants.FM_ALARM_STATE_CLEAR)
|
|
|
|
def test_iport_update_by_ihost_report_update_same_device_different_slot(self):
|
|
"""Test same device exchange on a different PCI address
|
|
|
|
In case of NIC exchange with a new vendor/device-id on a different PCI slot, the old entry
|
|
is erased and a new one created if the port associated interface is of class none.
|
|
Otherwise we do not process the new port until the operator removes the existing database.
|
|
We also update the port.node_id if the inode entry related to the numa node is already
|
|
created.
|
|
"""
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='compute-0', mgmt_mac='22:44:33:55:11:77', uuid=str(uuid.uuid4()),
|
|
personality=constants.WORKER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
mock_find_local_mgmt_interface_vlan_id = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager._find_local_mgmt_interface_vlan_id',
|
|
mock_find_local_mgmt_interface_vlan_id)
|
|
p.start().return_value = 0
|
|
self.addCleanup(p.stop)
|
|
|
|
mock_socket_gethostname = mock.MagicMock()
|
|
p2 = mock.patch('socket.gethostname', mock_socket_gethostname)
|
|
p2.start().return_value = 'controller-0'
|
|
self.addCleanup(p2.stop)
|
|
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
inic_dict_array = self._create_test_iports()
|
|
|
|
# execute initial report
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array)
|
|
|
|
# create inodes
|
|
inuma_dict_array = [{'numa_node': 0, 'capabilities': {}},
|
|
{'numa_node': 1, 'capabilities': {}}]
|
|
self.service.inumas_update_by_ihost(self.context, ihost['uuid'], inuma_dict_array)
|
|
|
|
port_db_len = len(self.dbapi.ethernet_port_get_by_host(ihost['uuid']))
|
|
|
|
# now send a report moving the interface to another PCI address
|
|
inic_dict_array2 = self._create_test_iports()
|
|
inic_dict_array2[3]['pciaddr'] = '0000:d3:00.1'
|
|
self.service.iport_update_by_ihost(self.context, ihost['uuid'], inic_dict_array2)
|
|
|
|
port_found = False
|
|
eth_port_db_list = self.dbapi.ethernet_port_get_by_host(ihost['uuid'])
|
|
for eth_port in eth_port_db_list:
|
|
if (eth_port.pciaddr == inic_dict_array2[3]['pciaddr']):
|
|
self.assertEqual(eth_port.mac, inic_dict_array2[3]['mac'])
|
|
self.assertEqual(eth_port.pvendor, inic_dict_array2[3]['pvendor'])
|
|
self.assertEqual(eth_port.pdevice, inic_dict_array2[3]['pdevice'])
|
|
|
|
# check if node_id points to the correct inode entry (in our case is 2)
|
|
self.assertEqual(eth_port.node_id, 2)
|
|
|
|
iface = self.dbapi.iinterface_get(eth_port.interface_id)
|
|
self.assertEqual(iface.imac, inic_dict_array2[3]['mac'])
|
|
self.assertEqual(iface.ifclass, None)
|
|
port_found = True
|
|
self.assertTrue(port_found)
|
|
self.assertEqual(len(self.dbapi.ethernet_port_get_by_host(ihost['uuid'])), port_db_len)
|
|
|
|
def _create_test_pci_device_report(self, use_acc100=False):
|
|
dev1 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_11_0',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': 'ff0000',
|
|
'pclass': 'Unassigned class [ff00]', 'pdevice_id': 'a1ec',
|
|
'psdevice': 'Device 0000', 'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:00:11.0',
|
|
'pdevice': 'C620 Series Chipset Family MROM 0', 'pvendor_id': '8086',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False, 'pvendor': 'Intel Corporation'}
|
|
dev2 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_11_5',
|
|
'sriov_numvfs': 0, 'driver': 'ahci', 'pclass_id': '010601',
|
|
'pclass': 'SATA controller', 'pdevice_id': 'a1d2',
|
|
'psdevice': 'Intel Corporation', 'fpga_n3000_reset': True,
|
|
'sriov_vf_pdevice_id': None, 'sriov_totalvfs': None, 'pciaddr': '0000:00:11.5',
|
|
'pdevice': 'C620 Series Chipset Family SSATA Controller [AHCI mode]',
|
|
'pvendor_id': '8086', 'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': '-p01', 'enabled': False,
|
|
'pvendor': 'Intel Corporation'}
|
|
dev3 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_14_0',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': '0c0330',
|
|
'pclass': 'USB controller', 'pdevice_id': 'a1af', 'psdevice': 'Intel Corporation',
|
|
'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': None, 'sriov_totalvfs': None,
|
|
'pciaddr': '0000:00:14.0', 'pdevice': 'C620 Series Family USB 3.0 xHCI Controller',
|
|
'pvendor_id': '8086', 'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': '-p30', 'enabled': False,
|
|
'pvendor': 'Intel Corporation'}
|
|
dev4 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_14_2',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': '118000',
|
|
'pclass': 'Signal processing controller', 'pdevice_id': 'a1b1',
|
|
'psdevice': 'Device 35cf', 'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:00:14.2',
|
|
'pdevice': 'C620 Series Chipset Family Thermal Subsystem', 'pvendor_id': '8086',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False, 'pvendor': 'Intel Corporation'}
|
|
dev5 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_16_4',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': '078000',
|
|
'pclass': 'Communication controller', 'pdevice_id': 'a1be',
|
|
'psdevice': 'Device 35cf', 'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:00:16.4',
|
|
'pdevice': 'C620 Series Chipset Family MEI Controller #3', 'pvendor_id': '8086',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False, 'pvendor': 'Intel Corporation'}
|
|
dev6 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_1f_4',
|
|
'sriov_numvfs': 0, 'driver': 'i801_smbus', 'pclass_id': '0c0500', 'pclass': 'SMBus',
|
|
'pdevice_id': 'a1a3', 'psdevice': 'Device 35cf', 'fpga_n3000_reset': True,
|
|
'sriov_vf_pdevice_id': None, 'sriov_totalvfs': None, 'pciaddr': '0000:00:1f.4',
|
|
'pdevice': 'C620 Series Chipset Family SMBus', 'pvendor_id': '8086',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False, 'pvendor': 'Intel Corporation'}
|
|
dev7 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_00_1f_5',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': '0c8000',
|
|
'pclass': 'Serial bus controller [0c80]', 'pdevice_id': 'a1a4',
|
|
'psdevice': 'Device 35cf', 'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': None,
|
|
'sriov_totalvfs': None, 'pciaddr': '0000:00:1f.5',
|
|
'pdevice': 'C620 Series Chipset Family SPI Controller', 'pvendor_id': '8086',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False, 'pvendor': 'Intel Corporation'}
|
|
dev8 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_02_00_0',
|
|
'sriov_numvfs': 0, 'driver': None, 'pclass_id': '030000',
|
|
'pclass': 'VGA compatible controller', 'pdevice_id': '2000',
|
|
'psdevice': 'ASPEED Graphics Family', 'fpga_n3000_reset': True,
|
|
'sriov_vf_pdevice_id': None, 'sriov_totalvfs': None, 'pciaddr': '0000:02:00.0',
|
|
'pdevice': 'ASPEED Graphics Family', 'pvendor_id': '1a03', 'sriov_vfs_pci_address': '',
|
|
'extra_info': None, 'psvendor': 'ASPEED Technology, Inc.',
|
|
'enabled': True, 'pvendor': 'ASPEED Technology, Inc.'}
|
|
dev9 = {'sriov_vf_driver': None, 'numa_node': 0, 'name': 'pci_0000_18_00_0',
|
|
'sriov_numvfs': 0, 'driver': 'megaraid_sas', 'pclass_id': '010400',
|
|
'pclass': 'RAID bus controller', 'pdevice_id': '0017',
|
|
'psdevice': 'RAID Controller RSP3WD080E', 'fpga_n3000_reset': True,
|
|
'sriov_vf_pdevice_id': None, 'sriov_totalvfs': None, 'pciaddr': '0000:18:00.0',
|
|
'pdevice': 'MegaRAID Tri-Mode SAS3408', 'pvendor_id': '1000',
|
|
'sriov_vfs_pci_address': '', 'extra_info': None,
|
|
'psvendor': 'Intel Corporation', 'enabled': False,
|
|
'pvendor': 'LSI Logic / Symbios Logic'}
|
|
dev10 = {'sriov_vf_driver': 'c6xxvf', 'numa_node': 0, 'name': 'pci_0000_3d_00_0',
|
|
'sriov_numvfs': 3, 'driver': 'c6xx', 'pclass_id': '0b4000',
|
|
'pclass': 'Co-processor', 'pdevice_id': '37c8', 'psdevice': 'Device 35cf',
|
|
'fpga_n3000_reset': True, 'sriov_vf_pdevice_id': '37c9', 'sriov_totalvfs': 16,
|
|
'pciaddr': '0000:3d:00.0', 'pdevice': 'C62x Chipset QuickAssist Technology',
|
|
'pvendor_id': '8086', 'sriov_vfs_pci_address': '0000:3d:01.0,0000:3d:01.1,0000:3d:01.2',
|
|
'extra_info': None, 'psvendor': 'Intel Corporation',
|
|
'enabled': True, 'pvendor': 'Intel Corporation'}
|
|
n3000_fpga = {'name': 'pci_0000_b2_00_0', 'pciaddr': '0000:b2:00.0', 'pclass_id': '120000',
|
|
'pvendor_id': '8086', 'pdevice_id': '0b30', 'pclass': 'Processing accelerators',
|
|
'pvendor': 'Intel Corporation', 'pdevice': 'Device 0b30',
|
|
'psvendor': 'Intel Corporation', 'psdevice': 'Device 0000', 'numa_node': 1,
|
|
'driver': 'intel-fpga-pci', 'sriov_totalvfs': 1, 'sriov_numvfs': 0,
|
|
'sriov_vfs_pci_address': '', 'enabled': True, 'extra_info': None,
|
|
'sriov_vf_driver': None, 'sriov_vf_pdevice_id': None, 'fpga_n3000_reset': True}
|
|
n3000_pf = {'name': 'pci_0000_b4_00_0', 'pciaddr': '0000:b4:00.0', 'pclass_id': '120000',
|
|
'pvendor_id': '8086', 'pdevice_id': '0d8f', 'pclass': 'Processing accelerators',
|
|
'pvendor': 'Intel Corporation', 'pdevice': 'Device 0d8f',
|
|
'psvendor': 'Intel Corporation', 'psdevice': 'Device 0001', 'numa_node': 1,
|
|
'driver': 'igb_uio', 'sriov_totalvfs': 8, 'sriov_numvfs': 4,
|
|
'sriov_vfs_pci_address': '0000:b4:00.1,0000:b4:00.2,0000:b4:00.3,0000:b4:00.4',
|
|
'enabled': True, 'extra_info': None, 'sriov_vf_driver': 'vfio-pci',
|
|
'sriov_vf_pdevice_id': '0d90', 'fpga_n3000_reset': True}
|
|
acc100 = {'name': 'pci_0000_b4_00_0', 'pciaddr': '0000:b4:00.0', 'pclass_id': '120001',
|
|
'pvendor_id': '8086', 'pdevice_id': '0d5c', 'pclass': 'Processing accelerators',
|
|
'pvendor': 'Intel Corporation', 'pdevice': 'Device 0d5c',
|
|
'psvendor': 'Intel Corporation', 'psdevice': 'Device 0000', 'numa_node': 0,
|
|
'driver': 'igb_uio', 'sriov_totalvfs': 16, 'sriov_numvfs': 4,
|
|
'sriov_vfs_pci_address': '0000:b4:00.1,0000:b4:00.2,0000:b4:00.3,0000:b4:00.4',
|
|
'enabled': True, 'extra_info': None, 'sriov_vf_driver': 'vfio',
|
|
'sriov_vf_pdevice_id': '0d5d', 'fpga_n3000_reset': False}
|
|
|
|
response = [dev1, dev2, dev3, dev4, dev5, dev6, dev7, dev8, dev9, dev10]
|
|
if not use_acc100:
|
|
response.append(n3000_fpga)
|
|
response.append(n3000_pf)
|
|
else:
|
|
response.append(acc100)
|
|
for dev in response:
|
|
dev['fpga_n3000_reset'] = False
|
|
|
|
return response
|
|
|
|
def test_pci_device_update_by_host(self):
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
host_uuid = ihost['uuid']
|
|
host_id = ihost['id']
|
|
PCI_DEV_1 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_1',
|
|
'pciaddr': '0000:0b:01.0',
|
|
'pclass_id': '060100',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0443',
|
|
'enabled': True}
|
|
PCI_DEV_2 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_2',
|
|
'pciaddr': '0000:0c:01.0',
|
|
'pclass_id': '060200',
|
|
'pvendor_id': '8088',
|
|
'pdevice_id': '0444',
|
|
'enabled': True}
|
|
pci_device_dict_array = [PCI_DEV_1, PCI_DEV_2]
|
|
|
|
# create new dev
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_device_dict_array)
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_1['pciaddr'], host_id)
|
|
for key in PCI_DEV_1:
|
|
self.assertEqual(dev[key], PCI_DEV_1[key])
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
for key in PCI_DEV_2:
|
|
self.assertEqual(dev[key], PCI_DEV_2[key])
|
|
|
|
# update existed dev
|
|
pci_dev_dict_update1 = [{'pciaddr': PCI_DEV_2['pciaddr'],
|
|
'pclass_id': '060500',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0449',
|
|
'pclass': '0600',
|
|
'pvendor': '',
|
|
'psvendor': '',
|
|
'psdevice': 'qat',
|
|
'sriov_totalvfs': 32,
|
|
'sriov_numvfs': 4,
|
|
'sriov_vf_driver': None,
|
|
'sriov_vf_pdevice_id': '0450',
|
|
'sriov_vfs_pci_address': '',
|
|
'driver': ''}]
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_dev_dict_update1)
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
|
|
for key in pci_dev_dict_update1[0]:
|
|
self.assertEqual(dev[key], pci_dev_dict_update1[0][key])
|
|
|
|
# update existed dev failure case, failed to change uuid.
|
|
pci_dev_dict_update2 = [{'pciaddr': PCI_DEV_2['pciaddr'],
|
|
'pclass_id': '060500',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0449',
|
|
'pclass': '0600',
|
|
'pvendor': '',
|
|
'psvendor': '',
|
|
'psdevice': 'qat',
|
|
'sriov_totalvfs': 32,
|
|
'sriov_numvfs': 4,
|
|
'sriov_vf_driver': None,
|
|
'sriov_vf_pdevice_id': '0450',
|
|
'sriov_vfs_pci_address': '',
|
|
'driver': '',
|
|
'uuid': 1122}]
|
|
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_dev_dict_update2)
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
self.assertEqual(dev['uuid'], PCI_DEV_2['uuid'])
|
|
|
|
def test_pci_device_update_n3000_by_host(self):
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
host_uuid = ihost['uuid']
|
|
host_id = ihost['id']
|
|
PCI_DEV_1 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_1',
|
|
'pciaddr': '0000:0b:01.0',
|
|
'pclass_id': '060100',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0443',
|
|
'enabled': True,
|
|
'fpga_n3000_reset': True} # is the FPGA reset
|
|
PCI_DEV_2 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_0000_b4_00_0',
|
|
'pciaddr': '0000:b4:00.0',
|
|
'pclass_id': '120000',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0d8f', # N3000 FEC
|
|
'enabled': True,
|
|
'fpga_n3000_reset': True} # is the FPGA reset
|
|
|
|
pci_device_dict_array = [PCI_DEV_1, PCI_DEV_2]
|
|
|
|
# create new dev
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_device_dict_array)
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_1['pciaddr'], host_id)
|
|
for key in PCI_DEV_1:
|
|
self.assertEqual(dev[key], PCI_DEV_1[key])
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
for key in PCI_DEV_2:
|
|
self.assertEqual(dev[key], PCI_DEV_2[key])
|
|
|
|
# test with fpga_n3000_reset as False
|
|
PCI_DEV_3 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_3',
|
|
'pciaddr': '0000:0c:01.0',
|
|
'pclass_id': '060100',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0443',
|
|
'enabled': True,
|
|
'fpga_n3000_reset': False} # is the FPGA reset
|
|
PCI_DEV_4 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_0000_b8_00_0',
|
|
'pciaddr': '0000:b8:00.0',
|
|
'pclass_id': '120000',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0d8f', # N3000_FEC_PF_DEVICE
|
|
'enabled': True,
|
|
'fpga_n3000_reset': False} # is the FPGA reset
|
|
PCI_DEV_5 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_0000_b9_00_0',
|
|
'pciaddr': '0000:b9:00.0',
|
|
'pclass_id': '120000',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0b30', # N3000_DEVICE
|
|
'enabled': True,
|
|
'fpga_n3000_reset': False} # is the FPGA reset
|
|
PCI_DEV_6 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_0000_b0_00_0',
|
|
'pciaddr': '0000:b0:00.0',
|
|
'pclass_id': '120000',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0b32', # N3000_DEFAULT_DEVICE
|
|
'enabled': True,
|
|
'fpga_n3000_reset': False} # is the FPGA reset
|
|
|
|
pci_device_dict_array2 = [PCI_DEV_3, PCI_DEV_4, PCI_DEV_5, PCI_DEV_6]
|
|
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_device_dict_array2)
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_3['pciaddr'], host_id)
|
|
for key in PCI_DEV_3:
|
|
self.assertEqual(dev[key], PCI_DEV_3[key])
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, PCI_DEV_4['pciaddr'], host_id)
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, PCI_DEV_5['pciaddr'], host_id)
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, PCI_DEV_6['pciaddr'], host_id)
|
|
|
|
# update existing dev
|
|
pci_dev_dict_update = [{'pciaddr': PCI_DEV_2['pciaddr'],
|
|
'name': PCI_DEV_2['name'],
|
|
'pclass_id': '060500',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0d8f',
|
|
'pclass': '0600',
|
|
'pvendor': '',
|
|
'psvendor': '',
|
|
'psdevice': 'qat',
|
|
'sriov_totalvfs': 32,
|
|
'sriov_numvfs': 4,
|
|
'sriov_vf_driver': 'vfio-pci',
|
|
'sriov_vf_pdevice_id': '0d90',
|
|
'sriov_vfs_pci_address': '000:b4:00.1,0000:b4:00.2,0000:b4:00.3',
|
|
'driver': 'igb_uio',
|
|
'fpga_n3000_reset': True}]
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_dev_dict_update)
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
|
|
for key in pci_dev_dict_update[0]:
|
|
self.assertEqual(dev[key], pci_dev_dict_update[0][key])
|
|
|
|
pci_dev_dict_update[0]['sriov_vfs_pci_address'] = ''
|
|
pci_dev_dict_update[0]['fpga_n3000_reset'] = False
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_dev_dict_update)
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
self.assertNotEqual(dev['sriov_vfs_pci_address'],
|
|
pci_dev_dict_update[0]['sriov_vfs_pci_address'])
|
|
|
|
def test_pci_device_update_n3000_replacement_different_slot(self):
|
|
""" Test if an update contains a n3000 on a different PCI address
|
|
|
|
In AIO-SX it is possible to plug a N3000 card without a new server installation, this
|
|
test check that the pci_device database will take into account the card replacement on a new
|
|
PCI slot, by removing the old entry and creating the new one. On N3000 case the opertaion
|
|
is only executed if the reset operation was successful
|
|
"""
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac="1a:2a:3a:4a:5a:6a", uuid=str(uuid.uuid4()),
|
|
personality=constants.CONTROLLER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create new dev with N3000 already reset
|
|
pci_device_report1 = self._create_test_pci_device_report()
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report1)
|
|
|
|
for pci_dev in pci_device_report1:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
# N3000 moves to a different slot and the first report might be without reset
|
|
pci_device_report2 = self._create_test_pci_device_report()
|
|
old_n3000_fpga = copy.deepcopy(pci_device_report2[-2])
|
|
del old_n3000_fpga['fpga_n3000_reset'] # this field is removed in the conductor
|
|
old_n3000_pf = copy.deepcopy(pci_device_report2[-1])
|
|
del old_n3000_pf['fpga_n3000_reset'] # this field is removed in the conductor
|
|
pci_device_report2[-2]['name'] = 'pci_0000_c3_00_0'
|
|
pci_device_report2[-2]['pciaddr'] = '0000:c3:00.0'
|
|
pci_device_report2[-1]['name'] = 'pci_0000_c7_00_0'
|
|
pci_device_report2[-1]['pciaddr'] = '0000:c7:00.0'
|
|
for pci_dev in pci_device_report2:
|
|
pci_dev['fpga_n3000_reset'] = False
|
|
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'],
|
|
pci_device_report2)
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, pci_device_report2[-2]['pciaddr'], ihost['id'])
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, pci_device_report2[-1]['pciaddr'], ihost['id'])
|
|
db_dev = self.dbapi.pci_device_get(old_n3000_fpga['pciaddr'], ihost['id'])
|
|
for key in old_n3000_fpga:
|
|
self.assertEqual(old_n3000_fpga[key], db_dev[key])
|
|
db_dev = self.dbapi.pci_device_get(old_n3000_pf['pciaddr'], ihost['id'])
|
|
for key in old_n3000_pf:
|
|
self.assertEqual(old_n3000_pf[key], db_dev[key])
|
|
|
|
# N3000 report with reset executed
|
|
pci_device_report3 = self._create_test_pci_device_report()
|
|
pci_device_report3[-2]['name'] = 'pci_0000_c2_00_0'
|
|
pci_device_report3[-2]['pciaddr'] = '0000:c2:00.0'
|
|
pci_device_report3[-1]['name'] = 'pci_0000_c4_00_0'
|
|
pci_device_report3[-1]['pciaddr'] = '0000:c4:00.0'
|
|
for pci_dev in pci_device_report3:
|
|
pci_dev['fpga_n3000_reset'] = True
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'],
|
|
pci_device_report3)
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, old_n3000_fpga['pciaddr'], ihost['id'])
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, old_n3000_pf['pciaddr'], ihost['id'])
|
|
db_dev = self.dbapi.pci_device_get(pci_device_report3[-2]['pciaddr'], ihost['id'])
|
|
for key in pci_device_report3[-2]:
|
|
self.assertEqual(pci_device_report3[-2][key], db_dev[key])
|
|
db_dev = self.dbapi.pci_device_get(pci_device_report3[-1]['pciaddr'], ihost['id'])
|
|
for key in pci_device_report3[-1]:
|
|
self.assertEqual(pci_device_report3[-1][key], db_dev[key])
|
|
|
|
def test_pci_device_update_acc100_replacement_different_slot(self):
|
|
""" Test if an update contains an ACC100 on a different PCI address
|
|
|
|
In AIO-SX it is possible to plug a ACC100 card without a new server installation, this
|
|
test check that the pci_device database will take into account the card replacement on a new
|
|
PCI slot, by removing the old entry and creating the new one.
|
|
"""
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac="1a:2a:3a:4a:5a:6a", uuid=str(uuid.uuid4()),
|
|
personality=constants.CONTROLLER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create new devices with ACC100
|
|
pci_device_report1 = self._create_test_pci_device_report(True)
|
|
acc100_addr = pci_device_report1[-1]['pciaddr']
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report1)
|
|
|
|
for pci_dev in pci_device_report1:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
# ACC100 reports on a different slot
|
|
pci_device_report2 = self._create_test_pci_device_report(True)
|
|
pci_device_report2[-1]['name'] = 'pci_0000_c4_00_0'
|
|
pci_device_report2[-1]['pciaddr'] = '0000:c4:00.0'
|
|
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report2)
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, acc100_addr, ihost['id'])
|
|
for pci_dev in pci_device_report2:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
def test_pci_device_update_acc100_replacement_to_n3000_same_slot(self):
|
|
""" Test if an update contains a FEC card replacement on the same slot
|
|
|
|
In AIO-SX it is possible to replace a N3000 to ACC100 (or vice-versa). This test checks if
|
|
the previous FEC card entry are erased if the PCI address of the new card matches the
|
|
old card
|
|
"""
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac="1a:2a:3a:4a:5a:6a", uuid=str(uuid.uuid4()),
|
|
personality=constants.CONTROLLER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create new dev with N3000 already reset
|
|
pci_device_report1 = self._create_test_pci_device_report()
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report1)
|
|
|
|
# ACC100 reports on the same N3000 slot
|
|
pci_device_report2 = self._create_test_pci_device_report(True)
|
|
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report2)
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b2:00.0', ihost['id'])
|
|
for pci_dev in pci_device_report2:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
# N3000 without reset replaces ACC100
|
|
pci_device_report3 = self._create_test_pci_device_report()
|
|
pci_device_report3[-2]['name'] = 'pci_0000_b3_00_0'
|
|
pci_device_report3[-2]['pciaddr'] = '0000:b3:00.0'
|
|
pci_device_report3[-1]['name'] = 'pci_0000_b7_00_0'
|
|
pci_device_report3[-1]['pciaddr'] = '0000:b7:00.0'
|
|
for pci_dev in pci_device_report3:
|
|
pci_dev['fpga_n3000_reset'] = False
|
|
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report3)
|
|
|
|
# without reset, N3000 devices aren't created
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b3:00.0', ihost['id'])
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b7:00.0', ihost['id'])
|
|
# removed ACC100 device
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b4:00.0', ihost['id'])
|
|
|
|
# N3000 with reset is reported
|
|
pci_device_report4 = self._create_test_pci_device_report()
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report4)
|
|
|
|
for pci_dev in pci_device_report4:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
def test_pci_device_update_acc100_replacement_to_n3000_different_slot(self):
|
|
""" Test if an update contains a FEC card replacement on a different PCI slot
|
|
|
|
In AIO-SX it is possible to replace a N3000 to ACC100 (or vice-versa). This test checks if
|
|
the previous FEC card entry are erased if the PCI address of the new card is installed on a
|
|
different address than the old card
|
|
"""
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = True
|
|
self.addCleanup(p3.stop)
|
|
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac="1a:2a:3a:4a:5a:6a", uuid=str(uuid.uuid4()),
|
|
personality=constants.CONTROLLER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create new dev with N3000 already reset
|
|
pci_device_report1 = self._create_test_pci_device_report()
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report1)
|
|
|
|
# ACC100 reports on a different slot as N3000 is removed
|
|
pci_device_report2 = self._create_test_pci_device_report(True)
|
|
pci_device_report2[-1]['name'] = 'pci_0000_c4_00_0'
|
|
pci_device_report2[-1]['pciaddr'] = '0000:c4:00.0'
|
|
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report2)
|
|
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b2:00.0', ihost['id'])
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b4:00.0', ihost['id'])
|
|
for pci_dev in pci_device_report2:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
def test_pci_device_update_N3000_cleanup_stale_non_AIOSX(self):
|
|
|
|
mock_is_aio_simplex_system = mock.MagicMock()
|
|
p3 = mock.patch('sysinv.common.utils.is_aio_simplex_system', mock_is_aio_simplex_system)
|
|
p3.start().return_value = False
|
|
self.addCleanup(p3.stop)
|
|
|
|
# Create controller-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
hostname='controller-0', mgmt_mac="1a:2a:3a:4a:5a:6a", uuid=str(uuid.uuid4()),
|
|
personality=constants.CONTROLLER, config_status=None, config_applied=config_uuid,
|
|
config_target=config_uuid, invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED, operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
|
|
# create new dev with N3000 already reset but add invalid addresses so they simulate
|
|
# a database with both valid and invalid addresses from a possible situation from an upgrade
|
|
pci_device_report1 = self._create_test_pci_device_report()
|
|
pci_device_report1 += [copy.deepcopy(pci_device_report1[-2]),
|
|
copy.deepcopy(pci_device_report1[-1])]
|
|
|
|
pci_device_report1[-2]['name'] = 'pci_0000_b3_00_0'
|
|
pci_device_report1[-2]['pciaddr'] = '0000:b3:00.0'
|
|
pci_device_report1[-1]['name'] = 'pci_0000_b7_00_0'
|
|
pci_device_report1[-1]['pciaddr'] = '0000:b7:00.0'
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'], pci_device_report1)
|
|
|
|
pci_device_report2 = self._create_test_pci_device_report()
|
|
self.service.pci_device_update_by_host(self.context, ihost['uuid'],
|
|
pci_device_report2, True)
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b3:00.0', ihost['id'])
|
|
self.assertRaises(exception.ServerNotFound,
|
|
self.dbapi.pci_device_get, '0000:b7:00.0', ihost['id'])
|
|
for pci_dev in pci_device_report2:
|
|
db_dev = self.dbapi.pci_device_get(pci_dev['pciaddr'], ihost['id'])
|
|
for key in pci_dev:
|
|
self.assertEqual(pci_dev[key], db_dev[key])
|
|
|
|
def test_inumas_update_by_ihost(self):
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
host_uuid = ihost['uuid']
|
|
host_id = ihost['id']
|
|
utils.create_test_node(id=1, numa_node=0, forihostid=host_id)
|
|
utils.create_test_node(id=2, numa_node=1, forihostid=host_id)
|
|
port1 = utils.create_test_ethernet_port(
|
|
id=1, name="port1", host_id=host_id,
|
|
interface_id="1122", mac='08:00:27:43:60:11', numa_node=3)
|
|
self.assertEqual(port1['node_id'], None)
|
|
inuma_dict_array = [{'numa_node': 1}, {'numa_node': 3}]
|
|
self.service.inumas_update_by_ihost(self.context, host_uuid, inuma_dict_array)
|
|
updated_port = self.dbapi.ethernet_port_get(port1['uuid'], host_id)
|
|
|
|
self.assertEqual(updated_port['node_id'], 3)
|
|
|
|
def test_fpga_device_update_by_host(self):
|
|
# Create compute-0 node
|
|
config_uuid = str(uuid.uuid4())
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
config_status=None,
|
|
config_applied=config_uuid,
|
|
config_target=config_uuid,
|
|
invprovision=constants.PROVISIONED,
|
|
administrative=constants.ADMIN_UNLOCKED,
|
|
operational=constants.OPERATIONAL_ENABLED,
|
|
availability=constants.AVAILABILITY_ONLINE,
|
|
)
|
|
host_uuid = ihost['uuid']
|
|
host_id = ihost['id']
|
|
PCI_DEV_1 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_1',
|
|
'pciaddr': '0000:0b:01.0',
|
|
'pclass_id': '060100',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0443',
|
|
'enabled': True,
|
|
'fpga_n3000_reset': True}
|
|
PCI_DEV_2 = {'uuid': str(uuid.uuid4()),
|
|
'name': 'pci_dev_2',
|
|
'pciaddr': '0000:0c:01.0',
|
|
'pclass_id': '012000',
|
|
'pvendor_id': '8086',
|
|
'pdevice_id': '0b30',
|
|
'enabled': True,
|
|
'fpga_n3000_reset': True}
|
|
pci_device_dict_array = [PCI_DEV_1, PCI_DEV_2]
|
|
|
|
# create new PCI dev
|
|
self.service.pci_device_update_by_host(self.context, host_uuid, pci_device_dict_array)
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_1['pciaddr'], host_id)
|
|
for key in PCI_DEV_1:
|
|
self.assertEqual(dev[key], PCI_DEV_1[key])
|
|
|
|
dev = self.dbapi.pci_device_get(PCI_DEV_2['pciaddr'], host_id)
|
|
for key in PCI_DEV_2:
|
|
self.assertEqual(dev[key], PCI_DEV_2[key])
|
|
|
|
FPGA_DEV_1 = {
|
|
'pciaddr': PCI_DEV_1['pciaddr'],
|
|
'bmc_build_version': 'D.2.0.6',
|
|
'bmc_fw_version': 'D.2.0.21',
|
|
'retimer_a_version': '101c.1064',
|
|
'retimer_b_version': '0000.0000',
|
|
'boot_page': 'user',
|
|
'bitstream_id': '0x2383A62A010504',
|
|
'root_key': '0x2973c55fc739e8181b16b9b51b786a39c0860159df8fb94652b0fbca87223bc7',
|
|
'revoked_key_ids': '2,10,50-51',
|
|
}
|
|
fpga_device_dict_array = [FPGA_DEV_1]
|
|
|
|
# Create new FPGA device.
|
|
self.service.fpga_device_update_by_host(self.context, host_uuid,
|
|
fpga_device_dict_array)
|
|
dev = self.dbapi.fpga_device_get(FPGA_DEV_1['pciaddr'], host_id)
|
|
for key in FPGA_DEV_1:
|
|
self.assertEqual(dev[key], FPGA_DEV_1[key])
|
|
|
|
# Update existing FPGA device.
|
|
fpga_dev_dict_update = {
|
|
'pciaddr': FPGA_DEV_1['pciaddr'],
|
|
'bmc_build_version': 'D.2.0.7',
|
|
'bmc_fw_version': 'D.2.0.22',
|
|
'retimer_a_version': '101c.105c',
|
|
'retimer_b_version': '0000.0000',
|
|
'boot_page': 'factory',
|
|
'bitstream_id': '0x2383A62A010504',
|
|
'root_key': '',
|
|
'revoked_key_ids': '',
|
|
}
|
|
fpga_dev_dict_update_array = [fpga_dev_dict_update]
|
|
self.service.fpga_device_update_by_host(self.context, host_uuid,
|
|
fpga_dev_dict_update_array)
|
|
dev = self.dbapi.fpga_device_get(FPGA_DEV_1['pciaddr'], host_id)
|
|
for key in fpga_dev_dict_update:
|
|
self.assertEqual(dev[key], fpga_dev_dict_update[key])
|
|
|
|
def test_upload_rootca(self):
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'rootca-with-key.pem')
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
|
|
self.mock_kube_delete_secret = mock.MagicMock()
|
|
q = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_delete_secret',
|
|
self.mock_kube_delete_secret)
|
|
q.start()
|
|
self.addCleanup(q.stop)
|
|
|
|
self.mock_kube_get_secret = mock.MagicMock()
|
|
q = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_get_secret',
|
|
self.mock_kube_get_secret)
|
|
self.mock_kube_get_secret.return_value = FakeSecret(f)
|
|
q.start()
|
|
self.addCleanup(q.stop)
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATE_STARTED)
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'rootca-with-key.pem')
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
resp = self.service.save_kubernetes_rootca_cert(self.context, f)
|
|
|
|
self.assertTrue(resp.get('success'))
|
|
self.assertFalse(resp.get('error'))
|
|
|
|
def test_upload_rootca_only_key(self):
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATE_STARTED)
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'only_key.pem')
|
|
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
resp = self.service.save_kubernetes_rootca_cert(self.context, f)
|
|
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("Failed to extract certificate from file", resp.get('error'))
|
|
|
|
def test_upload_rootca_not_ca_certificate(self):
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATE_STARTED)
|
|
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data", 'cert-with-key-SAN.pem')
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
resp = self.service.save_kubernetes_rootca_cert(self.context, f)
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("certificate in the file is not a CA certificate", resp.get('error'))
|
|
|
|
def test_upload_rootca_not_in_progress(self):
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'rootca-with-key.pem')
|
|
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
resp = self.service.save_kubernetes_rootca_cert(self.context, f)
|
|
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("Kubernetes root CA update not started", resp.get('error'))
|
|
|
|
def test_upload_rootca_advanced_state(self):
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATING_PODS_TRUSTBOTHCAS)
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'rootca-with-key.pem')
|
|
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
resp = self.service.save_kubernetes_rootca_cert(self.context, f)
|
|
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("new root CA certificate already exists", resp.get('error'))
|
|
|
|
def test_generate_rootca(self):
|
|
file = os.path.join(os.path.dirname(__file__), "../api", "data",
|
|
'rootca-with-key.pem')
|
|
with open(file, 'rb') as certfile:
|
|
certfile.seek(0, os.SEEK_SET)
|
|
f = certfile.read()
|
|
|
|
self.mock_kube_get_secret = mock.MagicMock()
|
|
q = mock.patch(
|
|
'sysinv.common.kubernetes.KubeOperator.kube_get_secret',
|
|
self.mock_kube_get_secret)
|
|
self.mock_kube_get_secret.return_value = FakeSecret(f)
|
|
q.start()
|
|
self.addCleanup(q.stop)
|
|
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATE_STARTED)
|
|
resp = self.service.generate_kubernetes_rootca_cert(self.context, {}, None)
|
|
self.assertTrue(resp.get('success'))
|
|
|
|
def test_generate_rootca_not_in_progress(self):
|
|
resp = self.service.generate_kubernetes_rootca_cert(self.context, {}, None)
|
|
self.assertFalse(resp.get('success'))
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("Kubernetes root CA update not started", resp.get('error'))
|
|
|
|
def test_generate_rootca_advanced_state(self):
|
|
utils.create_test_kube_rootca_update(state=kubernetes.KUBE_ROOTCA_UPDATED_PODS_TRUSTBOTHCAS)
|
|
resp = self.service.generate_kubernetes_rootca_cert(self.context, {}, None)
|
|
self.assertFalse(resp.get('success'))
|
|
self.assertTrue(resp.get('error'))
|
|
self.assertIn("A new root CA certificate already exists", resp.get('error'))
|
|
|
|
def test_device_update_image_status(self):
|
|
|
|
mock_host_device_image_update_next = mock.MagicMock()
|
|
p = mock.patch(
|
|
'sysinv.conductor.manager.ConductorManager.host_device_image_update_next',
|
|
mock_host_device_image_update_next)
|
|
p.start()
|
|
self.addCleanup(p.stop)
|
|
|
|
# Create compute-0 node
|
|
ihost = self._create_test_ihost(
|
|
personality=constants.WORKER,
|
|
hostname='compute-0',
|
|
uuid=str(uuid.uuid4()),
|
|
)
|
|
|
|
host_uuid = ihost.uuid
|
|
host_id = ihost.id
|
|
|
|
# Make sure we start with this set to false.
|
|
self.dbapi.ihost_update(host_uuid, {'reboot_needed': False})
|
|
|
|
DEV_IMG_STATE = {
|
|
'host_id': host_id,
|
|
'pcidevice_id': 5,
|
|
'image_id': 11,
|
|
'status': '',
|
|
}
|
|
device_image_state = self.dbapi.device_image_state_create(
|
|
DEV_IMG_STATE)
|
|
for key in DEV_IMG_STATE:
|
|
self.assertEqual(device_image_state[key], DEV_IMG_STATE[key])
|
|
|
|
# set status to "in-progress"
|
|
self.service.device_update_image_status(self.context,
|
|
host_uuid, device_image_state.uuid,
|
|
dconstants.DEVICE_IMAGE_UPDATE_IN_PROGRESS)
|
|
|
|
mock_host_device_image_update_next.assert_not_called()
|
|
|
|
device_image_state = self.dbapi.device_image_state_get(
|
|
device_image_state.id)
|
|
self.assertEqual(device_image_state.status,
|
|
dconstants.DEVICE_IMAGE_UPDATE_IN_PROGRESS)
|
|
ihost = self.dbapi.ihost_get(host_id)
|
|
self.assertEqual(ihost.reboot_needed, False)
|
|
|
|
# set status to "completed"
|
|
self.service.device_update_image_status(self.context,
|
|
host_uuid, device_image_state.uuid,
|
|
dconstants.DEVICE_IMAGE_UPDATE_COMPLETED)
|
|
|
|
mock_host_device_image_update_next.assert_called_with(
|
|
self.context, host_uuid)
|
|
|
|
device_image_state = self.dbapi.device_image_state_get(
|
|
device_image_state.id)
|
|
self.assertEqual(device_image_state.status,
|
|
dconstants.DEVICE_IMAGE_UPDATE_COMPLETED)
|
|
ihost = self.dbapi.ihost_get(host_id)
|
|
self.assertEqual(ihost.reboot_needed, True)
|
|
|
|
def test_update_dnsmasq_config(self):
|
|
mock_config_update_hosts = mock.MagicMock()
|
|
mock_config_apply_runtime_manifest = mock.MagicMock()
|
|
p = mock.patch('sysinv.conductor.manager.ConductorManager._config_update_hosts',
|
|
mock_config_update_hosts)
|
|
p.start().return_value = '1234'
|
|
self.addCleanup(p.stop)
|
|
p2 = mock.patch('sysinv.conductor.manager.ConductorManager._config_apply_runtime_manifest',
|
|
mock_config_apply_runtime_manifest)
|
|
p2.start()
|
|
self.addCleanup(p2.stop)
|
|
self.service.update_dnsmasq_config(self.context)
|
|
personalities = [constants.CONTROLLER]
|
|
config_dict = {
|
|
"personalities": personalities,
|
|
"classes": ['platform::dns::dnsmasq::runtime'],
|
|
}
|
|
mock_config_apply_runtime_manifest.assert_called_with(mock.ANY, '1234', config_dict)
|
|
|
|
def test_update_ldap_client_config(self):
|
|
mock_config_update_hosts = mock.MagicMock()
|
|
mock_config_apply_runtime_manifest = mock.MagicMock()
|
|
p = mock.patch('sysinv.conductor.manager.ConductorManager._config_update_hosts',
|
|
mock_config_update_hosts)
|
|
p.start().return_value = '1234'
|
|
self.addCleanup(p.stop)
|
|
p2 = mock.patch('sysinv.conductor.manager.ConductorManager._config_apply_runtime_manifest',
|
|
mock_config_apply_runtime_manifest)
|
|
p2.start()
|
|
self.addCleanup(p2.stop)
|
|
self.service.update_ldap_client_config(self.context)
|
|
personalities = [constants.CONTROLLER]
|
|
config_dict = {
|
|
"personalities": personalities,
|
|
"classes": ['platform::ldap::client::runtime'],
|
|
}
|
|
mock_config_apply_runtime_manifest.assert_called_with(mock.ANY, '1234', config_dict)
|
|
|
|
|
|
class ManagerTestCaseInternal(base.BaseHostTestCase):
|
|
|
|
def setUp(self):
|
|
super(ManagerTestCaseInternal, self).setUp()
|
|
|
|
# Set up objects for testing
|
|
self.service = manager.ConductorManager('test-host', 'test-topic')
|
|
self.service.dbapi = dbapi.get_instance()
|
|
|
|
def test_remove_lease_for_address(self):
|
|
# create test interface
|
|
ihost = self._create_test_host(
|
|
personality=constants.WORKER,
|
|
administrative=constants.ADMIN_UNLOCKED)
|
|
iface = utils.create_test_interface(
|
|
ifname="test0",
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
forihostid=ihost.id,
|
|
ihost_uuid=ihost.uuid)
|
|
network = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT)
|
|
utils.create_test_interface_network(
|
|
interface_id=iface.id,
|
|
network_id=network.id)
|
|
|
|
# create test address associated with interface
|
|
address_name = cutils.format_address_name(ihost.hostname,
|
|
network.type)
|
|
self.dbapi.address_create({
|
|
'name': address_name,
|
|
'family': self.oam_subnet.version,
|
|
'prefix': self.oam_subnet.prefixlen,
|
|
'address': str(self.oam_subnet[24]),
|
|
'interface_id': iface.id,
|
|
'enable_dad': self.oam_subnet.version == 6
|
|
})
|
|
|
|
# stub the system i/o calls
|
|
self.mock_objs = [
|
|
mock.patch.object(
|
|
manager.ConductorManager, '_find_local_interface_name',
|
|
lambda x, y: iface.ifname),
|
|
mock.patch('sysinv.common.utils.get_dhcp_cid',
|
|
lambda x, y, z: None),
|
|
mock.patch.object(
|
|
manager.ConductorManager, '_dhcp_release',
|
|
lambda a, b, c, d, e: None)
|
|
]
|
|
|
|
for mock_obj in self.mock_objs:
|
|
mock_obj.start()
|
|
self.addCleanup(mock_obj.stop)
|
|
|
|
self.service._remove_lease_for_address(ihost.hostname,
|
|
constants.NETWORK_TYPE_MGMT)
|