Re-enable uefi support with glanceclient
Use glanceclient to examine image metadata instead of the nova image proxy, which seems to have been removed in recent versions of novaclient.
This commit is contained in:
parent
2fe2fd0569
commit
53320ee72b
@ -127,3 +127,32 @@ def _get_keystone_token():
|
||||
project_domain_name=project_domain)
|
||||
|
||||
|
||||
def _get_token_and_endpoint(name):
|
||||
"""Return a token id and endpoint url for the specified service
|
||||
|
||||
:param name: The name of the service. heat, glance, etc.
|
||||
:returns: A tuple of (token_id, service_endpoint)
|
||||
"""
|
||||
auth_data = _create_auth_parameters()
|
||||
auth_url = auth_data['os_auth_url']
|
||||
# Get token for service to use
|
||||
if '/v3' not in auth_url:
|
||||
token_data = _get_keystone_token()
|
||||
token_id = token_data['token']['id']
|
||||
catalog_key = 'serviceCatalog'
|
||||
else:
|
||||
token_data = _get_keystone_token()
|
||||
token_id = token_data['auth_token']
|
||||
catalog_key = 'catalog'
|
||||
|
||||
# Get service endpoint
|
||||
for endpoint in token_data[catalog_key]:
|
||||
if endpoint['name'] == name:
|
||||
try:
|
||||
# TODO: What if there's more than one endpoint?
|
||||
service_endpoint = endpoint['endpoints'][0]['publicURL']
|
||||
except KeyError:
|
||||
# Keystone v3 endpoint data looks different
|
||||
service_endpoint = [e for e in endpoint['endpoints']
|
||||
if e['interface'] == 'public'][0]['url']
|
||||
return token_id, service_endpoint
|
||||
|
@ -19,6 +19,7 @@ import os
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
import glanceclient
|
||||
from neutronclient.v2_0 import client as neutronclient
|
||||
import novaclient as nc
|
||||
from novaclient import client as novaclient
|
||||
@ -91,6 +92,7 @@ def _get_clients():
|
||||
import os_client_config
|
||||
nova = os_client_config.make_client('compute', cloud=cloud)
|
||||
neutron = os_client_config.make_client('network', cloud=cloud)
|
||||
glance = os_client_config.make_client('image', cloud=cloud)
|
||||
|
||||
else:
|
||||
auth_data = auth._create_auth_parameters()
|
||||
@ -124,7 +126,10 @@ def _get_clients():
|
||||
project_domain_name=project_domain)
|
||||
sess = auth._get_keystone_session(auth_data)
|
||||
neutron = neutronclient.Client(session=sess)
|
||||
return nova, neutron
|
||||
token, glance_endpoint = auth._get_token_and_endpoint('glance')
|
||||
glance = glanceclient.Client('2', token=token,
|
||||
endpoint=glance_endpoint)
|
||||
return nova, neutron, glance
|
||||
|
||||
|
||||
def _get_ports(neutron, bmc_base, baremetal_base):
|
||||
@ -140,8 +145,8 @@ def _get_ports(neutron, bmc_base, baremetal_base):
|
||||
return bmc_ports, bm_ports
|
||||
|
||||
|
||||
def _build_nodes(nova, bmc_ports, bm_ports, provision_net, baremetal_base,
|
||||
undercloud_name):
|
||||
def _build_nodes(nova, glance, bmc_ports, bm_ports, provision_net,
|
||||
baremetal_base, undercloud_name):
|
||||
node_template = {
|
||||
'pm_type': 'pxe_ipmitool',
|
||||
'mac': '',
|
||||
@ -177,12 +182,11 @@ def _build_nodes(nova, bmc_ports, bm_ports, provision_net, baremetal_base,
|
||||
|
||||
# If a node has uefi firmware ironic needs to be aware of this, in nova
|
||||
# this is set using a image property called "hw_firmware_type"
|
||||
# TODO(bnemec): Re-enable uefi support
|
||||
#if not cache.get(baremetal.image['id']):
|
||||
#cache[baremetal.image['id']] = nova.images.get(baremetal.image['id'])
|
||||
#image = cache.get(baremetal.image['id'])
|
||||
#if image.metadata.get('hw_firmware_type') == 'uefi':
|
||||
#node['capabilities'] += ",boot_mode:uefi"
|
||||
if not cache.get(baremetal.image['id']):
|
||||
cache[baremetal.image['id']] = glance.images.get(baremetal.image['id'])
|
||||
image = cache.get(baremetal.image['id'])
|
||||
if image.get('hw_firmware_type') == 'uefi':
|
||||
node['capabilities'] += ",boot_mode:uefi"
|
||||
|
||||
bm_name_end = baremetal.name[len(baremetal_base):]
|
||||
if '-' in bm_name_end:
|
||||
@ -240,9 +244,10 @@ def _write_pairs(bmc_bm_pairs):
|
||||
def main():
|
||||
args = _parse_args()
|
||||
bmc_base, baremetal_base, provision_net, undercloud_name = _get_names(args)
|
||||
nova, neutron = _get_clients()
|
||||
nova, neutron, glance = _get_clients()
|
||||
bmc_ports, bm_ports = _get_ports(neutron, bmc_base, baremetal_base)
|
||||
nodes, bmc_bm_pairs, extra_nodes = _build_nodes(nova, bmc_ports, bm_ports,
|
||||
nodes, bmc_bm_pairs, extra_nodes = _build_nodes(nova, glance, bmc_ports,
|
||||
bm_ports,
|
||||
provision_net,
|
||||
baremetal_base,
|
||||
undercloud_name)
|
||||
|
@ -140,35 +140,7 @@ def _get_heat_client():
|
||||
import os_client_config
|
||||
return os_client_config.make_client('orchestration', cloud=cloud)
|
||||
else:
|
||||
auth_data = auth._create_auth_parameters()
|
||||
username = auth_data['os_user']
|
||||
password = auth_data['os_password']
|
||||
tenant = auth_data['os_tenant']
|
||||
auth_url = auth_data['os_auth_url']
|
||||
project = auth_data['os_project']
|
||||
user_domain = auth_data['os_user_domain']
|
||||
project_domain = auth_data['os_project_domain']
|
||||
# Get token for Heat to use
|
||||
if '/v3' not in auth_url:
|
||||
token_data = auth._get_keystone_token()
|
||||
token_id = token_data['token']['id']
|
||||
catalog_key = 'serviceCatalog'
|
||||
else:
|
||||
token_data = auth._get_keystone_token()
|
||||
token_id = token_data['auth_token']
|
||||
catalog_key = 'catalog'
|
||||
|
||||
# Get Heat endpoint
|
||||
for endpoint in token_data[catalog_key]:
|
||||
if endpoint['name'] == 'heat':
|
||||
try:
|
||||
# TODO: What if there's more than one endpoint?
|
||||
heat_endpoint = endpoint['endpoints'][0]['publicURL']
|
||||
except KeyError:
|
||||
# Keystone v3 endpoint data looks different
|
||||
heat_endpoint = [e for e in endpoint['endpoints']
|
||||
if e['interface'] == 'public'][0]['url']
|
||||
|
||||
token_id, heat_endpoint = auth._get_token_and_endpoint('heat')
|
||||
return heat_client.Client('1', endpoint=heat_endpoint, token=token_id)
|
||||
|
||||
def _deploy(stack_name, stack_template, env_path, poll):
|
||||
|
@ -190,6 +190,26 @@ class TestCreateAuthParameters(testtools.TestCase):
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
|
||||
V2_TOKEN_DATA = {'token': {'id': 'fake_token'},
|
||||
'serviceCatalog': [{'name': 'nova'},
|
||||
{'name': 'heat',
|
||||
'endpoints': [
|
||||
{'publicURL': 'heat_endpoint'}
|
||||
]
|
||||
}
|
||||
]}
|
||||
V3_TOKEN_DATA = {'auth_token': 'fake_v3_token',
|
||||
'catalog': [{'name': 'nova'},
|
||||
{'name': 'heat',
|
||||
'endpoints': [
|
||||
{'interface': 'private'},
|
||||
{'interface': 'public',
|
||||
'url': 'heat_endpoint'}
|
||||
]
|
||||
}
|
||||
]}
|
||||
|
||||
|
||||
class TestKeystoneAuth(testtools.TestCase):
|
||||
@mock.patch('keystoneauth1.session.Session')
|
||||
@mock.patch('keystoneauth1.identity.v3.Password')
|
||||
@ -289,3 +309,37 @@ class TestKeystoneAuth(testtools.TestCase):
|
||||
user_domain_name='default',
|
||||
project_domain_name='default'
|
||||
)
|
||||
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_keystone_token')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
||||
def test_get_token_and_endpoint_v2(self, mock_cap, mock_gkt):
|
||||
fake_auth_data = {'os_user': 'admin',
|
||||
'os_password': 'password',
|
||||
'os_tenant': 'admin',
|
||||
'os_auth_url': 'auth',
|
||||
'os_project': '',
|
||||
'os_user_domain': '',
|
||||
'os_project_domain': '',
|
||||
}
|
||||
mock_cap.return_value = fake_auth_data
|
||||
mock_gkt.return_value = V2_TOKEN_DATA
|
||||
token, endpoint = auth._get_token_and_endpoint('heat')
|
||||
self.assertEqual('fake_token', token)
|
||||
self.assertEqual('heat_endpoint', endpoint)
|
||||
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_keystone_token')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
||||
def test_get_token_and_endpoint_v3(self, mock_cap, mock_gkt):
|
||||
fake_auth_data = {'os_user': 'admin',
|
||||
'os_password': 'password',
|
||||
'os_tenant': '',
|
||||
'os_auth_url': 'auth/v3',
|
||||
'os_project': 'admin',
|
||||
'os_user_domain': 'default',
|
||||
'os_project_domain': 'default',
|
||||
}
|
||||
mock_cap.return_value = fake_auth_data
|
||||
mock_gkt.return_value = V3_TOKEN_DATA
|
||||
token, endpoint = auth._get_token_and_endpoint('heat')
|
||||
self.assertEqual('fake_v3_token', token)
|
||||
self.assertEqual('heat_endpoint', endpoint)
|
||||
|
@ -161,10 +161,12 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_CLOUD', 'foo'))
|
||||
build_nodes_json._get_clients()
|
||||
calls = [mock.call('compute', cloud='foo'),
|
||||
mock.call('network', cloud='foo')]
|
||||
mock.call('network', cloud='foo'),
|
||||
mock.call('image', cloud='foo')]
|
||||
self.assertEqual(calls, mock_make_client.mock_calls)
|
||||
|
||||
def _test_get_clients_env(self, mock_nova, mock_neutron):
|
||||
def _test_get_clients_env(self, mock_nova, mock_neutron, mock_glance,
|
||||
mock_gtae):
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'admin'))
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD', 'pw'))
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_TENANT_NAME',
|
||||
@ -174,28 +176,45 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
mock_nova.return_value = mock_nova_client
|
||||
mock_neutron_client = mock.Mock()
|
||||
mock_neutron.return_value = mock_neutron_client
|
||||
nova, neutron = build_nodes_json._get_clients()
|
||||
mock_glance_client = mock.Mock()
|
||||
mock_glance.return_value = mock_glance_client
|
||||
mock_token = 'abc-123'
|
||||
mock_endpoint = 'glance://endpoint'
|
||||
mock_gtae.return_value = (mock_token, mock_endpoint)
|
||||
nova, neutron, glance = build_nodes_json._get_clients()
|
||||
self.assertEqual(mock_nova_client, nova)
|
||||
self.assertEqual(mock_neutron_client, neutron)
|
||||
self.assertEqual(mock_glance_client, glance)
|
||||
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_token_and_endpoint')
|
||||
@mock.patch('openstack_virtual_baremetal.build_nodes_json.nc.__version__',
|
||||
('6', '0', '0'))
|
||||
@mock.patch('glanceclient.Client')
|
||||
@mock.patch('neutronclient.v2_0.client.Client')
|
||||
@mock.patch('novaclient.client.Client')
|
||||
def test_get_clients_env_6(self, mock_nova, mock_neutron):
|
||||
self._test_get_clients_env(mock_nova, mock_neutron)
|
||||
def test_get_clients_env_6(self, mock_nova, mock_neutron, mock_glance,
|
||||
mock_gtae):
|
||||
self._test_get_clients_env(mock_nova, mock_neutron, mock_glance,
|
||||
mock_gtae)
|
||||
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_token_and_endpoint')
|
||||
@mock.patch('openstack_virtual_baremetal.build_nodes_json.nc.__version__',
|
||||
('7', '0', '0'))
|
||||
@mock.patch('glanceclient.Client')
|
||||
@mock.patch('neutronclient.v2_0.client.Client')
|
||||
@mock.patch('novaclient.client.Client')
|
||||
def test_get_clients_env_7(self, mock_nova, mock_neutron):
|
||||
self._test_get_clients_env(mock_nova, mock_neutron)
|
||||
def test_get_clients_env_7(self, mock_nova, mock_neutron, mock_glance,
|
||||
mock_gtae):
|
||||
self._test_get_clients_env(mock_nova, mock_neutron, mock_glance,
|
||||
mock_gtae)
|
||||
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_token_and_endpoint')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_keystone_session')
|
||||
@mock.patch('glanceclient.Client')
|
||||
@mock.patch('neutronclient.v2_0.client.Client')
|
||||
@mock.patch('novaclient.client.Client')
|
||||
def test_get_clients_env_v3(self, mock_nova, mock_neutron, mock_gks):
|
||||
def test_get_clients_env_v3(self, mock_nova, mock_neutron, mock_glance,
|
||||
mock_gks, mock_gtae):
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'admin'))
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD', 'pw'))
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_PROJECT_NAME',
|
||||
@ -209,12 +228,20 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
mock_nova.return_value = mock_nova_client
|
||||
mock_neutron_client = mock.Mock()
|
||||
mock_neutron.return_value = mock_neutron_client
|
||||
mock_glance_client = mock.Mock()
|
||||
mock_glance.return_value = mock_glance_client
|
||||
mock_session_inst = mock.Mock()
|
||||
mock_gks.return_value = mock_session_inst
|
||||
nova, neutron = build_nodes_json._get_clients()
|
||||
mock_token = 'abc-123'
|
||||
mock_endpoint = 'glance://endpoint'
|
||||
mock_gtae.return_value = (mock_token, mock_endpoint)
|
||||
nova, neutron, glance = build_nodes_json._get_clients()
|
||||
mock_neutron.assert_called_once_with(session=mock_session_inst)
|
||||
mock_glance.assert_called_once_with('2', token=mock_token,
|
||||
endpoint=mock_endpoint)
|
||||
self.assertEqual(mock_nova_client, nova)
|
||||
self.assertEqual(mock_neutron_client, neutron)
|
||||
self.assertEqual(mock_glance_client, glance)
|
||||
|
||||
def test_get_ports(self):
|
||||
neutron = mock.Mock()
|
||||
@ -296,8 +323,10 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
ips_return_val = 'ips call value'
|
||||
nova.servers.ips.return_value = ips_return_val
|
||||
|
||||
glance = mock.Mock()
|
||||
|
||||
nodes, bmc_bm_pairs, extra_nodes = build_nodes_json._build_nodes(
|
||||
nova, bmc_ports, bm_ports, 'provision', 'bm', 'undercloud')
|
||||
nova, glance, bmc_ports, bm_ports, 'provision', 'bm', 'undercloud')
|
||||
expected_nodes = TEST_NODES
|
||||
self.assertEqual(expected_nodes, nodes)
|
||||
self.assertEqual([('1.1.1.1', 'bm_0'), ('1.1.1.2', 'bm_1')],
|
||||
@ -317,12 +346,14 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
servers[1].name = 'bm-foo-control_1'
|
||||
ips_return_val = 'ips call value'
|
||||
nova.servers.ips.return_value = ips_return_val
|
||||
|
||||
glance = mock.Mock()
|
||||
mock_image_get = mock.Mock()
|
||||
nova.images.get.return_value = mock_image_get
|
||||
mock_image_get.metadata.get.return_value = 'uefi'
|
||||
mock_image_get.get.return_value = 'uefi'
|
||||
glance.images.get.return_value = mock_image_get
|
||||
|
||||
nodes, bmc_bm_pairs, extra_nodes = build_nodes_json._build_nodes(
|
||||
nova, bmc_ports, bm_ports, 'provision', 'bm-foo', None)
|
||||
nova, glance, bmc_ports, bm_ports, 'provision', 'bm-foo', None)
|
||||
expected_nodes = copy.deepcopy(TEST_NODES)
|
||||
expected_nodes[0]['name'] = 'bm-foo-control-0'
|
||||
expected_nodes[0]['capabilities'] = ('boot_option:local,'
|
||||
@ -396,7 +427,8 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
undercloud_name)
|
||||
nova = mock.Mock()
|
||||
neutron = mock.Mock()
|
||||
mock_get_clients.return_value = (nova, neutron)
|
||||
glance = mock.Mock()
|
||||
mock_get_clients.return_value = (nova, neutron, glance)
|
||||
bmc_ports = mock.Mock()
|
||||
bm_ports = mock.Mock()
|
||||
mock_get_ports.return_value = (bmc_ports, bm_ports)
|
||||
@ -412,8 +444,9 @@ class TestBuildNodesJson(testtools.TestCase):
|
||||
mock_get_clients.assert_called_once_with()
|
||||
mock_get_ports.assert_called_once_with(neutron, bmc_base,
|
||||
baremetal_base)
|
||||
mock_build_nodes.assert_called_once_with(nova, bmc_ports, bm_ports,
|
||||
provision_net, baremetal_base,
|
||||
mock_build_nodes.assert_called_once_with(nova, glance, bmc_ports,
|
||||
bm_ports, provision_net,
|
||||
baremetal_base,
|
||||
undercloud_name)
|
||||
mock_write_nodes.assert_called_once_with(nodes, extra_nodes, args)
|
||||
mock_write_pairs.assert_called_once_with(pairs)
|
||||
|
@ -371,26 +371,6 @@ class TestDeploy(testtools.TestCase):
|
||||
deploy._validate_env(args, 'foo.yaml')
|
||||
|
||||
|
||||
V2_TOKEN_DATA = {'token': {'id': 'fake_token'},
|
||||
'serviceCatalog': [{'name': 'nova'},
|
||||
{'name': 'heat',
|
||||
'endpoints': [
|
||||
{'publicURL': 'heat_endpoint'}
|
||||
]
|
||||
}
|
||||
]}
|
||||
V3_TOKEN_DATA = {'auth_token': 'fake_v3_token',
|
||||
'catalog': [{'name': 'nova'},
|
||||
{'name': 'heat',
|
||||
'endpoints': [
|
||||
{'interface': 'private'},
|
||||
{'interface': 'public',
|
||||
'url': 'heat_endpoint'}
|
||||
]
|
||||
}
|
||||
]}
|
||||
|
||||
|
||||
class TestGetHeatClient(testtools.TestCase):
|
||||
@mock.patch('os_client_config.make_client')
|
||||
def test_os_cloud(self, mock_make_client):
|
||||
@ -399,41 +379,13 @@ class TestGetHeatClient(testtools.TestCase):
|
||||
mock_make_client.assert_called_once_with('orchestration', cloud='foo')
|
||||
|
||||
@mock.patch('heatclient.client.Client')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_keystone_token')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
||||
def test_keystone_v2(self, mock_cap, mock_gkt, mock_hc):
|
||||
fake_auth_data = {'os_user': 'admin',
|
||||
'os_password': 'password',
|
||||
'os_tenant': 'admin',
|
||||
'os_auth_url': 'auth',
|
||||
'os_project': '',
|
||||
'os_user_domain': '',
|
||||
'os_project_domain': '',
|
||||
}
|
||||
mock_cap.return_value = fake_auth_data
|
||||
mock_gkt.return_value = V2_TOKEN_DATA
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_token_and_endpoint')
|
||||
def test_heatclient(self, mock_gtae, mock_hc):
|
||||
mock_gtae.return_value = ('fake_token', 'heat_endpoint')
|
||||
deploy._get_heat_client()
|
||||
mock_hc.assert_called_once_with('1', endpoint='heat_endpoint',
|
||||
token='fake_token')
|
||||
|
||||
@mock.patch('heatclient.client.Client')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._get_keystone_token')
|
||||
@mock.patch('openstack_virtual_baremetal.auth._create_auth_parameters')
|
||||
def test_keystone_v3(self, mock_cap, mock_gkt, mock_hc):
|
||||
fake_auth_data = {'os_user': 'admin',
|
||||
'os_password': 'password',
|
||||
'os_tenant': 'admin',
|
||||
'os_auth_url': 'auth/v3',
|
||||
'os_project': 'admin',
|
||||
'os_user_domain': 'default',
|
||||
'os_project_domain': 'default',
|
||||
}
|
||||
mock_cap.return_value = fake_auth_data
|
||||
mock_gkt.return_value = V3_TOKEN_DATA
|
||||
deploy._get_heat_client()
|
||||
mock_hc.assert_called_once_with('1', endpoint='heat_endpoint',
|
||||
token='fake_v3_token')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,6 +1,7 @@
|
||||
os-client-config
|
||||
pyghmi
|
||||
PyYAML
|
||||
python-glanceclient
|
||||
python-heatclient
|
||||
python-keystoneclient
|
||||
python-neutronclient
|
||||
|
Loading…
Reference in New Issue
Block a user