Major changes: * Plumbing necessary for strict confinement with the microstack-support interface https://github.com/snapcore/snapd/pull/8926 * Until the interface is merged, devmode will be used and kernel modules will be loaded via an auxiliary service. * upgraded OpenStack components to Focal (20.04) and OpenStack Ussuri; * reworked the old patches; * added the Placement service since it is now separate; * addressed various build issues due to changes in snapcraft and built dependencies: * e.g. libvirt requires the build directory to be separate from the source directory) and LP: #1882255; * LP: #1882535 and https://github.com/pypa/pip/issues/8414 * LP: #1882839 * LP: #1885294 * https://storyboard.openstack.org/#!/story/2007806 * LP: #1864589 * LP: #1777121 * LP: #1881590 * ML2/OVS replated with ML2/OVN; * dnsmasq is not used anymore; * neutron l3 and DHCP agents are not used anymore; * Linux network namespaces are only used for neutron-ovn-metadata-agent. * ML2 DNS support is done via native OVN mechanisms; * OVN-related database services (southbound and northbound dbs); * OVN-related control plane services (ovn-controller, ovn-northd); * core20 base support (bionic hosts are supported); * the removal procedure now relies on the "remove" hook since `snap remove` cannot be used from the confined environment anymore; * prerequisites to enabling AppArmor confinement for QEMU processes created by the confined libvirtd. * Added the Spice html5 console proxy service to enable clients to retrieve and use it via `microstack.openstack console url show --spice <servername>`. * Added missing Cinder templates and DB migrations for the Cinder DB. * Added experimental support for a loop device-based LVM backend for Cinder. Due to LP: #1892895 this is not recommended to be used in production except for tempest testing with an applied workaround; * includes iscsid and iscsi-tcp kernel module loading; * includes LIO and loading of relevant kernel modules; * An LVM PV is created on top of a loop device with a backing file present in $SNAP_COMMON/cinder-lvm.img; * A VG is created on top of the PV; * LVs are created by Cinder and exported via LIO over iscsi to iscsid which hot-plugs new SCSI devices. Those SCSI devices are then propagated by Nova to libvirt and QEMU during volume attachment; * Added post-deployment testing via rally and tempest (via the microstack-test snap). A set of tests included into Refstack 2018.02 is executed (except for object storage tests due to the lack of object storage support). Change-Id: Ic70770095860a57d5e0a55a8a9451f9db6be7448
136 lines
3.4 KiB
Python
136 lines
3.4 KiB
Python
import sys
|
|
import os
|
|
import unittest
|
|
|
|
import mock
|
|
|
|
# TODO: drop in test runner and get rid of this line.
|
|
sys.path.append(os.getcwd()) # noqa
|
|
|
|
from init.questions.question import (Question, InvalidQuestion, InvalidAnswer) # noqa
|
|
|
|
|
|
##############################################################################
|
|
#
|
|
# Test Fixtures
|
|
#
|
|
##############################################################################
|
|
|
|
|
|
class InvalidTypeQuestion(Question):
|
|
_type = 'foo'
|
|
config_key = 'invalid-type'
|
|
|
|
|
|
class GoodAutoQuestion(Question):
|
|
_type = 'auto'
|
|
config_key = 'good-auto-question'
|
|
|
|
def yes(self, answer):
|
|
return 'I am a good question!'
|
|
|
|
|
|
class GoodBooleanQuestion(Question):
|
|
_type = 'boolean'
|
|
config_key = 'good-bool-question'
|
|
|
|
def yes(self, answer):
|
|
return True
|
|
|
|
def no(self, answer):
|
|
return False
|
|
|
|
|
|
class GoodStringQuestion(Question):
|
|
"""Pass a string through to the output of Question.ask.
|
|
|
|
# TODO right now, we have separate handlers for Truthy and Falsey
|
|
answers, and this test class basically makes them do the same
|
|
thing. Is this a good pattern?
|
|
|
|
"""
|
|
_type = 'string'
|
|
config_key = 'good-string-question'
|
|
|
|
def yes(self, answer):
|
|
return answer
|
|
|
|
def no(self, answer):
|
|
return answer
|
|
|
|
|
|
##############################################################################
|
|
#
|
|
# Tests Proper
|
|
#
|
|
##############################################################################
|
|
|
|
|
|
class TestQuestionClass(unittest.TestCase):
|
|
"""
|
|
Test basic features of the Question class.
|
|
|
|
"""
|
|
def test_invalid_type(self):
|
|
|
|
with self.assertRaises(InvalidQuestion):
|
|
InvalidTypeQuestion().ask()
|
|
|
|
def test_valid_type(self):
|
|
|
|
self.assertTrue(GoodBooleanQuestion())
|
|
|
|
@mock.patch('init.questions.question.shell.check_output')
|
|
@mock.patch('init.questions.question.shell.check')
|
|
def test_auto_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = ''
|
|
|
|
self.assertEqual(GoodAutoQuestion().ask(), True)
|
|
|
|
|
|
class TestInput(unittest.TestCase):
|
|
"""
|
|
Test input handling.
|
|
|
|
Takes advantage of the fact that we can override the Question
|
|
class's input handler.
|
|
|
|
"""
|
|
@mock.patch('init.questions.question.shell.check_output')
|
|
@mock.patch('init.questions.question.shell.check')
|
|
def test_boolean_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = 'true'
|
|
|
|
q = GoodBooleanQuestion()
|
|
|
|
for answer in ['yes', 'Yes', 'y']:
|
|
q._input_func = lambda x: answer
|
|
self.assertTrue(q.ask())
|
|
|
|
for answer in ['No', 'n', 'no']:
|
|
q._input_func = lambda x: answer
|
|
self.assertFalse(q.ask())
|
|
|
|
with self.assertRaises(InvalidAnswer):
|
|
q._input_func = lambda x: 'foo'
|
|
q.ask()
|
|
|
|
@mock.patch('init.questions.question.shell.check_output')
|
|
@mock.patch('init.questions.question.shell.check')
|
|
def test_string_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = 'somedefault'
|
|
|
|
q = GoodStringQuestion()
|
|
|
|
for answer in ['foo', 'bar', 'baz', 'yadayadayada']:
|
|
q._input_func = lambda x: answer
|
|
self.assertEqual(answer, q.ask())
|
|
|
|
# Verify that a blank answer defaults properly
|
|
q._input_func = lambda x: ''
|
|
self.assertEqual('somedefault', q.ask())
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|