Merge "Create default flavors as part of undercloud install"
This commit is contained in:
@@ -41,13 +41,13 @@ class TestUndercloud(BaseTestCase):
|
||||
@mock.patch('instack_undercloud.undercloud._configure_logging')
|
||||
@mock.patch('instack_undercloud.undercloud._check_hostname')
|
||||
@mock.patch('instack_undercloud.undercloud._run_command')
|
||||
@mock.patch('instack_undercloud.undercloud._configure_ssh_keys')
|
||||
@mock.patch('instack_undercloud.undercloud._post_config')
|
||||
@mock.patch('instack_undercloud.undercloud._run_orc')
|
||||
@mock.patch('instack_undercloud.undercloud._run_instack')
|
||||
@mock.patch('instack_undercloud.undercloud._generate_environment')
|
||||
@mock.patch('instack_undercloud.undercloud._load_config')
|
||||
def test_install(self, mock_load_config, mock_generate_environment,
|
||||
mock_run_instack, mock_run_orc, mock_configure_ssh_keys,
|
||||
mock_run_instack, mock_run_orc, mock_post_config,
|
||||
mock_run_command, mock_check_hostname,
|
||||
mock_configure_logging):
|
||||
fake_env = mock.MagicMock()
|
||||
@@ -342,38 +342,100 @@ class TestConfigureSshKeys(base.BaseTestCase):
|
||||
undercloud._ensure_user_identity(id_path)
|
||||
self.assertFalse(mock_run.called)
|
||||
|
||||
def _test_configure_ssh_keys(self, mock_eui, mock_extract, mock_client,
|
||||
mock_run, exists=True):
|
||||
def _test_configure_ssh_keys(self, mock_eui, exists=True):
|
||||
id_path = self._create_test_id()
|
||||
mock_run.side_effect = [None, None, '3nigma']
|
||||
mock_extract.side_effect = ['aturing', 'http://bletchley:5000/v2.0',
|
||||
'hut8']
|
||||
|
||||
mock_client_instance = mock.Mock()
|
||||
mock_client.return_value = mock_client_instance
|
||||
if not exists:
|
||||
get = mock_client_instance.keypairs.get
|
||||
get.side_effect = exceptions.NotFound('test')
|
||||
undercloud._configure_ssh_keys()
|
||||
undercloud._configure_ssh_keys(mock_client_instance)
|
||||
mock_eui.assert_called_with(id_path)
|
||||
mock_client.assert_called_with(2, 'aturing', '3nigma', 'hut8',
|
||||
'http://bletchley:5000/v2.0')
|
||||
mock_client_instance.keypairs.get.assert_called_with('default')
|
||||
if not exists:
|
||||
mock_client_instance.keypairs.create.assert_called_with(
|
||||
'default', 'test public')
|
||||
|
||||
@mock.patch('novaclient.client.Client', autospec=True)
|
||||
@mock.patch('instack_undercloud.undercloud._extract_from_stackrc')
|
||||
@mock.patch('instack_undercloud.undercloud._ensure_user_identity')
|
||||
def test_configure_ssh_keys_exists(self, mock_eui, mock_extract,
|
||||
mock_client, mock_run):
|
||||
self._test_configure_ssh_keys(mock_eui, mock_extract, mock_client,
|
||||
mock_run)
|
||||
def test_configure_ssh_keys_exists(self, mock_eui, _):
|
||||
self._test_configure_ssh_keys(mock_eui)
|
||||
|
||||
@mock.patch('novaclient.client.Client', autospec=True)
|
||||
@mock.patch('instack_undercloud.undercloud._extract_from_stackrc')
|
||||
@mock.patch('instack_undercloud.undercloud._ensure_user_identity')
|
||||
def test_configure_ssh_keys_missing(self, mock_eui, mock_extract,
|
||||
mock_client, mock_run):
|
||||
self._test_configure_ssh_keys(mock_eui, mock_extract, mock_client,
|
||||
mock_run, False)
|
||||
def test_configure_ssh_keys_missing(self, mock_eui, _):
|
||||
self._test_configure_ssh_keys(mock_eui, False)
|
||||
|
||||
|
||||
class TestPostConfig(base.BaseTestCase):
|
||||
@mock.patch('novaclient.client.Client', autospec=True)
|
||||
@mock.patch('instack_undercloud.undercloud._copy_stackrc')
|
||||
@mock.patch('instack_undercloud.undercloud._get_auth_values')
|
||||
@mock.patch('instack_undercloud.undercloud._configure_ssh_keys')
|
||||
@mock.patch('instack_undercloud.undercloud._ensure_flavor')
|
||||
def test_post_config(self, mock_ensure_flavor, mock_configure_ssh_keys,
|
||||
mock_get_auth_values, mock_copy_stackrc, mock_client):
|
||||
mock_get_auth_values.return_value = ('aturing', '3nigma', 'hut8',
|
||||
'http://bletchley:5000/v2.0')
|
||||
mock_instance = mock.Mock()
|
||||
mock_client.return_value = mock_instance
|
||||
undercloud._post_config()
|
||||
mock_client.assert_called_with(2, 'aturing', '3nigma', 'hut8',
|
||||
'http://bletchley:5000/v2.0')
|
||||
self.assertTrue(mock_copy_stackrc.called)
|
||||
mock_configure_ssh_keys.assert_called_with(mock_instance)
|
||||
calls = [mock.call(mock_instance, 'baremetal'),
|
||||
mock.call(mock_instance, 'control', 'control'),
|
||||
mock.call(mock_instance, 'compute', 'compute'),
|
||||
mock.call(mock_instance, 'ceph-storage', 'ceph-storage'),
|
||||
mock.call(mock_instance, 'block-storage', 'block-storage'),
|
||||
mock.call(mock_instance, 'swift-storage', 'swift-storage'),
|
||||
]
|
||||
mock_ensure_flavor.assert_has_calls(calls)
|
||||
|
||||
@mock.patch('instack_undercloud.undercloud._run_command')
|
||||
def test_copy_stackrc(self, mock_run):
|
||||
undercloud._copy_stackrc()
|
||||
calls = [mock.call(['sudo', 'cp', '/root/stackrc', mock.ANY],
|
||||
name='Copy stackrc'),
|
||||
mock.call(['sudo', 'chown', mock.ANY, mock.ANY],
|
||||
name='Chown stackrc'),
|
||||
]
|
||||
mock_run.assert_has_calls(calls)
|
||||
|
||||
def _create_flavor_mocks(self):
|
||||
mock_nova = mock.Mock()
|
||||
mock_nova.flavors.create = mock.Mock()
|
||||
mock_flavor = mock.Mock()
|
||||
mock_nova.flavors.create.return_value = mock_flavor
|
||||
mock_flavor.set_keys = mock.Mock()
|
||||
return mock_nova, mock_flavor
|
||||
|
||||
def test_ensure_flavor_no_profile(self):
|
||||
mock_nova, mock_flavor = self._create_flavor_mocks()
|
||||
undercloud._ensure_flavor(mock_nova, 'test')
|
||||
mock_nova.flavors.create.assert_called_with('test', 4096, 1, 40)
|
||||
keys = {'capabilities:boot_option': 'local'}
|
||||
mock_flavor.set_keys.assert_called_with(keys)
|
||||
|
||||
def test_ensure_flavor_profile(self):
|
||||
mock_nova, mock_flavor = self._create_flavor_mocks()
|
||||
undercloud._ensure_flavor(mock_nova, 'test', 'test')
|
||||
mock_nova.flavors.create.assert_called_with('test', 4096, 1, 40)
|
||||
keys = {'capabilities:boot_option': 'local',
|
||||
'capabilities:profile': 'test'}
|
||||
mock_flavor.set_keys.assert_called_with(keys)
|
||||
|
||||
def test_ensure_flavor_exists(self):
|
||||
mock_nova, mock_flavor = self._create_flavor_mocks()
|
||||
mock_nova.flavors.create.side_effect = exceptions.Conflict(None)
|
||||
undercloud._ensure_flavor(mock_nova, 'test')
|
||||
mock_flavor.set_keys.assert_not_called()
|
||||
|
||||
@mock.patch('instack_undercloud.undercloud._extract_from_stackrc')
|
||||
@mock.patch('instack_undercloud.undercloud._run_command')
|
||||
def test_get_auth_values(self, mock_run, mock_extract):
|
||||
mock_run.return_value = '3nigma'
|
||||
mock_extract.side_effect = ['aturing', 'hut8',
|
||||
'http://bletchley:5000/v2.0']
|
||||
values = undercloud._get_auth_values()
|
||||
expected = ('aturing', '3nigma', 'hut8', 'http://bletchley:5000/v2.0')
|
||||
self.assertEqual(expected, values)
|
||||
|
||||
@@ -519,7 +519,20 @@ def _ensure_user_identity(id_path):
|
||||
LOG.info('Generated new ssh key in ~/.ssh/id_rsa')
|
||||
|
||||
|
||||
def _configure_ssh_keys():
|
||||
def _get_auth_values():
|
||||
"""Get auth values from stackrc
|
||||
|
||||
Returns the user, password, tenant and auth_url as read from stackrc,
|
||||
in that order as a tuple.
|
||||
"""
|
||||
user = _extract_from_stackrc('OS_USERNAME')
|
||||
password = _run_command(['sudo', 'hiera', 'admin_password']).rstrip()
|
||||
tenant = _extract_from_stackrc('OS_TENANT')
|
||||
auth_url = _extract_from_stackrc('OS_AUTH_URL')
|
||||
return user, password, tenant, auth_url
|
||||
|
||||
|
||||
def _configure_ssh_keys(nova):
|
||||
"""Configure default ssh keypair in Nova
|
||||
|
||||
Generates a new ssh key for the current user if one does not already
|
||||
@@ -528,16 +541,6 @@ def _configure_ssh_keys():
|
||||
id_path = os.path.expanduser('~/.ssh/id_rsa')
|
||||
_ensure_user_identity(id_path)
|
||||
|
||||
args = ['sudo', 'cp', '/root/stackrc', os.path.expanduser('~')]
|
||||
_run_command(args, name='Copy stackrc')
|
||||
args = ['sudo', 'chown', getpass.getuser() + ':',
|
||||
os.path.expanduser('~/stackrc')]
|
||||
_run_command(args, name='Chown stackrc')
|
||||
password = _run_command(['sudo', 'hiera', 'admin_password']).rstrip()
|
||||
user = _extract_from_stackrc('OS_USERNAME')
|
||||
auth_url = _extract_from_stackrc('OS_AUTH_URL')
|
||||
tenant = _extract_from_stackrc('OS_TENANT')
|
||||
nova = novaclient.Client(2, user, password, tenant, auth_url)
|
||||
try:
|
||||
nova.keypairs.get('default')
|
||||
except exceptions.NotFound:
|
||||
@@ -545,6 +548,43 @@ def _configure_ssh_keys():
|
||||
nova.keypairs.create('default', pubkey.read().rstrip())
|
||||
|
||||
|
||||
def _ensure_flavor(nova, name, profile=None):
|
||||
try:
|
||||
flavor = nova.flavors.create(name, 4096, 1, 40)
|
||||
except exceptions.Conflict:
|
||||
LOG.info('Not creating flavor "%s" because it already exists.', name)
|
||||
return
|
||||
keys = {'capabilities:boot_option': 'local'}
|
||||
if profile is not None:
|
||||
keys['capabilities:profile'] = profile
|
||||
flavor.set_keys(keys)
|
||||
message = 'Created flavor "%s" with profile "%s"'
|
||||
LOG.info(message, name, profile)
|
||||
|
||||
|
||||
def _copy_stackrc():
|
||||
args = ['sudo', 'cp', '/root/stackrc', os.path.expanduser('~')]
|
||||
_run_command(args, name='Copy stackrc')
|
||||
args = ['sudo', 'chown', getpass.getuser() + ':',
|
||||
os.path.expanduser('~/stackrc')]
|
||||
_run_command(args, name='Chown stackrc')
|
||||
|
||||
|
||||
def _post_config():
|
||||
_copy_stackrc()
|
||||
user, password, tenant, auth_url = _get_auth_values()
|
||||
nova = novaclient.Client(2, user, password, tenant, auth_url)
|
||||
|
||||
_configure_ssh_keys(nova)
|
||||
|
||||
_ensure_flavor(nova, 'baremetal')
|
||||
_ensure_flavor(nova, 'control', 'control')
|
||||
_ensure_flavor(nova, 'compute', 'compute')
|
||||
_ensure_flavor(nova, 'ceph-storage', 'ceph-storage')
|
||||
_ensure_flavor(nova, 'block-storage', 'block-storage')
|
||||
_ensure_flavor(nova, 'swift-storage', 'swift-storage')
|
||||
|
||||
|
||||
def install(instack_root):
|
||||
"""Install the undercloud
|
||||
|
||||
@@ -564,7 +604,7 @@ def install(instack_root):
|
||||
# TODO(bnemec): Do we still need INSTACK_ROOT?
|
||||
instack_env['INSTACK_ROOT'] = os.environ.get('INSTACK_ROOT') or ''
|
||||
_run_orc(instack_env)
|
||||
_configure_ssh_keys()
|
||||
_post_config()
|
||||
_run_command(['sudo', 'rm', '-f', '/tmp/svc-map-services'], None, 'rm')
|
||||
LOG.info(COMPLETION_MESSAGE, {'password_path': PATHS.PASSWORD_PATH,
|
||||
'stackrc_path': os.path.expanduser('~/stackrc')})
|
||||
|
||||
Reference in New Issue
Block a user