Change approach to detailed listings of baremetal resources

The current approach with separate ResourceDetail classes suffers
from serious flows and is barely usable. For example for nodes:
* get_node() returns complete Node objects
* nodes() returns incomplete Node objects
* nodes(details=True) returns NodeDetail objects, which are exactly
  like complete Node objects, except that you cannot do anything
  with them: updating, listing VIFs, etc.
This is confusing and essentially requires the caller to issue
a redundant get_node call after listing detailed nodes.

This change consolidates everything into Node (Port, etc) objects
and deprecates NodeDetail (PortDetail, etc). I would highly recommend
the same approach taken for other ResourceDetail objects.

Change-Id: Idedee2b394e2ed412a69880d4bc9315737e1c3ed
This commit is contained in:
Dmitry Tantsur
2018-11-22 15:00:45 +01:00
parent cdef4806ce
commit 5c5478d774
16 changed files with 145 additions and 247 deletions

View File

@@ -66,27 +66,3 @@ class TestChassis(base.TestCase):
self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['nodes'], sot.nodes)
self.assertEqual(FAKE['updated_at'], sot.updated_at)
class TestChassisDetail(base.TestCase):
def test_basic(self):
sot = chassis.ChassisDetail()
self.assertIsNone(sot.resource_key)
self.assertEqual('chassis', sot.resources_key)
self.assertEqual('/chassis/detail', sot.base_path)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_fetch)
self.assertFalse(sot.allow_commit)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_instantiate(self):
sot = chassis.ChassisDetail(**FAKE)
self.assertEqual(FAKE['uuid'], sot.id)
self.assertEqual(FAKE['created_at'], sot.created_at)
self.assertEqual(FAKE['description'], sot.description)
self.assertEqual(FAKE['extra'], sot.extra)
self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['nodes'], sot.nodes)
self.assertEqual(FAKE['updated_at'], sot.updated_at)

View File

@@ -153,58 +153,6 @@ class TestNode(base.TestCase):
self.assertEqual('available', sot.provision_state)
class TestNodeDetail(base.TestCase):
def test_basic(self):
sot = node.NodeDetail()
self.assertIsNone(sot.resource_key)
self.assertEqual('nodes', sot.resources_key)
self.assertEqual('/nodes/detail', sot.base_path)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_fetch)
self.assertFalse(sot.allow_commit)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_instantiate(self):
sot = node.NodeDetail(**FAKE)
self.assertEqual(FAKE['uuid'], sot.id)
self.assertEqual(FAKE['name'], sot.name)
self.assertEqual(FAKE['chassis_uuid'], sot.chassis_id)
self.assertEqual(FAKE['clean_step'], sot.clean_step)
self.assertEqual(FAKE['created_at'], sot.created_at)
self.assertEqual(FAKE['driver'], sot.driver)
self.assertEqual(FAKE['driver_info'], sot.driver_info)
self.assertEqual(FAKE['driver_internal_info'],
sot.driver_internal_info)
self.assertEqual(FAKE['extra'], sot.extra)
self.assertEqual(FAKE['instance_info'], sot.instance_info)
self.assertEqual(FAKE['instance_uuid'], sot.instance_id)
self.assertEqual(FAKE['console_enabled'], sot.is_console_enabled)
self.assertEqual(FAKE['maintenance'], sot.is_maintenance)
self.assertEqual(FAKE['last_error'], sot.last_error)
self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['maintenance_reason'], sot.maintenance_reason)
self.assertEqual(FAKE['name'], sot.name)
self.assertEqual(FAKE['network_interface'], sot.network_interface)
self.assertEqual(FAKE['ports'], sot.ports)
self.assertEqual(FAKE['portgroups'], sot.port_groups)
self.assertEqual(FAKE['power_state'], sot.power_state)
self.assertEqual(FAKE['properties'], sot.properties)
self.assertEqual(FAKE['provision_state'], sot.provision_state)
self.assertEqual(FAKE['raid_config'], sot.raid_config)
self.assertEqual(FAKE['reservation'], sot.reservation)
self.assertEqual(FAKE['resource_class'], sot.resource_class)
self.assertEqual(FAKE['states'], sot.states)
self.assertEqual(FAKE['target_provision_state'],
sot.target_provision_state)
self.assertEqual(FAKE['target_power_state'], sot.target_power_state)
self.assertEqual(FAKE['target_raid_config'], sot.target_raid_config)
self.assertEqual(FAKE['updated_at'], sot.updated_at)
@mock.patch('time.sleep', lambda _t: None)
@mock.patch.object(node.Node, 'fetch', autospec=True)
class TestNodeWaitForProvisionState(base.TestCase):

View File

@@ -70,32 +70,3 @@ class TestPort(base.TestCase):
self.assertEqual(FAKE['portgroup_uuid'], sot.port_group_id)
self.assertEqual(FAKE['pxe_enabled'], sot.is_pxe_enabled)
self.assertEqual(FAKE['updated_at'], sot.updated_at)
class TestPortDetail(base.TestCase):
def test_basic(self):
sot = port.PortDetail()
self.assertIsNone(sot.resource_key)
self.assertEqual('ports', sot.resources_key)
self.assertEqual('/ports/detail', sot.base_path)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_fetch)
self.assertFalse(sot.allow_commit)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_instantiate(self):
sot = port.PortDetail(**FAKE)
self.assertEqual(FAKE['uuid'], sot.id)
self.assertEqual(FAKE['address'], sot.address)
self.assertEqual(FAKE['created_at'], sot.created_at)
self.assertEqual(FAKE['extra'], sot.extra)
self.assertEqual(FAKE['internal_info'], sot.internal_info)
self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['local_link_connection'],
sot.local_link_connection)
self.assertEqual(FAKE['node_uuid'], sot.node_id)
self.assertEqual(FAKE['portgroup_uuid'], sot.port_group_id)
self.assertEqual(FAKE['pxe_enabled'], sot.is_pxe_enabled)
self.assertEqual(FAKE['updated_at'], sot.updated_at)

View File

@@ -75,32 +75,3 @@ class TestPortGroup(base.TestCase):
self.assertEqual(FAKE['standalone_ports_supported'],
sot.is_standalone_ports_supported)
self.assertEqual(FAKE['updated_at'], sot.updated_at)
class TestPortGroupDetail(base.TestCase):
def test_basic(self):
sot = port_group.PortGroupDetail()
self.assertIsNone(sot.resource_key)
self.assertEqual('portgroups', sot.resources_key)
self.assertEqual('/portgroups/detail', sot.base_path)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_fetch)
self.assertFalse(sot.allow_commit)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_instantiate(self):
sot = port_group.PortGroupDetail(**FAKE)
self.assertEqual(FAKE['uuid'], sot.id)
self.assertEqual(FAKE['address'], sot.address)
self.assertEqual(FAKE['created_at'], sot.created_at)
self.assertEqual(FAKE['extra'], sot.extra)
self.assertEqual(FAKE['internal_info'], sot.internal_info)
self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['name'], sot.name)
self.assertEqual(FAKE['node_uuid'], sot.node_id)
self.assertEqual(FAKE['ports'], sot.ports)
self.assertEqual(FAKE['standalone_ports_supported'],
sot.is_standalone_ports_supported)
self.assertEqual(FAKE['updated_at'], sot.updated_at)

View File

@@ -17,6 +17,7 @@ from openstack.baremetal.v1 import chassis
from openstack.baremetal.v1 import driver
from openstack.baremetal.v1 import node
from openstack.baremetal.v1 import port
from openstack.baremetal.v1 import port_group
from openstack import exceptions
from openstack.tests.unit import base
from openstack.tests.unit import test_proxy_base
@@ -34,17 +35,17 @@ class TestBaremetalProxy(test_proxy_base.TestProxyBase):
def test_get_driver(self):
self.verify_get(self.proxy.get_driver, driver.Driver)
def test_chassis_detailed(self):
self.verify_list(self.proxy.chassis, chassis.ChassisDetail,
paginated=True,
method_kwargs={"details": True, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(chassis.Chassis, 'list')
def test_chassis_detailed(self, mock_list):
result = self.proxy.chassis(details=True, query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=True, query=1)
def test_chassis_not_detailed(self):
self.verify_list(self.proxy.chassis, chassis.Chassis,
paginated=True,
method_kwargs={"details": False, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(chassis.Chassis, 'list')
def test_chassis_not_detailed(self, mock_list):
result = self.proxy.chassis(query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=False, query=1)
def test_create_chassis(self):
self.verify_create(self.proxy.create_chassis, chassis.Chassis)
@@ -64,17 +65,17 @@ class TestBaremetalProxy(test_proxy_base.TestProxyBase):
def test_delete_chassis_ignore(self):
self.verify_delete(self.proxy.delete_chassis, chassis.Chassis, True)
def test_nodes_detailed(self):
self.verify_list(self.proxy.nodes, node.NodeDetail,
paginated=True,
method_kwargs={"details": True, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(node.Node, 'list')
def test_nodes_detailed(self, mock_list):
result = self.proxy.nodes(details=True, query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=True, query=1)
def test_nodes_not_detailed(self):
self.verify_list(self.proxy.nodes, node.Node,
paginated=True,
method_kwargs={"details": False, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(node.Node, 'list')
def test_nodes_not_detailed(self, mock_list):
result = self.proxy.nodes(query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=False, query=1)
def test_create_node(self):
self.verify_create(self.proxy.create_node, node.Node)
@@ -106,17 +107,17 @@ class TestBaremetalProxy(test_proxy_base.TestProxyBase):
def test_delete_node_ignore(self):
self.verify_delete(self.proxy.delete_node, node.Node, True)
def test_ports_detailed(self):
self.verify_list(self.proxy.ports, port.PortDetail,
paginated=True,
method_kwargs={"details": True, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(port.Port, 'list')
def test_ports_detailed(self, mock_list):
result = self.proxy.ports(details=True, query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=True, query=1)
def test_ports_not_detailed(self):
self.verify_list(self.proxy.ports, port.Port,
paginated=True,
method_kwargs={"details": False, "query": 1},
expected_kwargs={"query": 1})
@mock.patch.object(port.Port, 'list')
def test_ports_not_detailed(self, mock_list):
result = self.proxy.ports(query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=False, query=1)
def test_create_port(self):
self.verify_create(self.proxy.create_port, port.Port)
@@ -136,6 +137,18 @@ class TestBaremetalProxy(test_proxy_base.TestProxyBase):
def test_delete_port_ignore(self):
self.verify_delete(self.proxy.delete_port, port.Port, True)
@mock.patch.object(port_group.PortGroup, 'list')
def test_port_groups_detailed(self, mock_list):
result = self.proxy.port_groups(details=True, query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=True, query=1)
@mock.patch.object(port_group.PortGroup, 'list')
def test_port_groups_not_detailed(self, mock_list):
result = self.proxy.port_groups(query=1)
self.assertIs(result, mock_list.return_value)
mock_list.assert_called_once_with(self.proxy, details=False, query=1)
@mock.patch('time.sleep', lambda _sec: None)
@mock.patch.object(_proxy.Proxy, 'get_node', autospec=True)