Merge "Add Node.driver_internal_info"
This commit is contained in:
commit
d7f15f2bec
@ -38,7 +38,7 @@ from ironic.common.i18n import _
|
||||
|
||||
|
||||
MIN_VER = 0
|
||||
MAX_VER = 1
|
||||
MAX_VER = 2
|
||||
|
||||
|
||||
class MediaType(base.APIBase):
|
||||
|
@ -60,6 +60,12 @@ def assert_juno_provision_state_name(obj):
|
||||
obj.provision_state = ir_states.NOSTATE
|
||||
|
||||
|
||||
def hide_driver_internal_info(obj):
|
||||
# if requested version is < 1.2, hide driver_internal_info
|
||||
if pecan.request.version.minor < 2:
|
||||
obj.driver_internal_info = wsme.Unset
|
||||
|
||||
|
||||
class NodePatchType(types.JsonPatchType):
|
||||
|
||||
@staticmethod
|
||||
@ -70,7 +76,8 @@ class NodePatchType(types.JsonPatchType):
|
||||
return defaults + ['/console_enabled', '/last_error',
|
||||
'/power_state', '/provision_state', '/reservation',
|
||||
'/target_power_state', '/target_provision_state',
|
||||
'/provision_updated_at', '/maintenance_reason']
|
||||
'/provision_updated_at', '/maintenance_reason',
|
||||
'/driver_internal_info']
|
||||
|
||||
@staticmethod
|
||||
def mandatory_attrs():
|
||||
@ -459,6 +466,10 @@ class Node(base.APIBase):
|
||||
driver_info = {wtypes.text: types.jsontype}
|
||||
"""This node's driver configuration"""
|
||||
|
||||
driver_internal_info = wsme.wsattr({wtypes.text: types.jsontype},
|
||||
readonly=True)
|
||||
"""This driver's internal configuration"""
|
||||
|
||||
extra = {wtypes.text: types.jsontype}
|
||||
"""This node's meta data"""
|
||||
|
||||
@ -529,6 +540,7 @@ class Node(base.APIBase):
|
||||
def convert_with_links(cls, rpc_node, expand=True):
|
||||
node = Node(**rpc_node.as_dict())
|
||||
assert_juno_provision_state_name(node)
|
||||
hide_driver_internal_info(node)
|
||||
return cls._convert_with_links(node, pecan.request.host_url,
|
||||
expand)
|
||||
|
||||
@ -542,7 +554,8 @@ class Node(base.APIBase):
|
||||
target_power_state=ir_states.NOSTATE,
|
||||
last_error=None, provision_state=ir_states.ACTIVE,
|
||||
target_provision_state=ir_states.NOSTATE,
|
||||
reservation=None, driver='fake', driver_info={}, extra={},
|
||||
reservation=None, driver='fake', driver_info={},
|
||||
driver_internal_info={}, extra={},
|
||||
properties={'memory_mb': '1024', 'local_gb': '10',
|
||||
'cpus': '1'}, updated_at=time, created_at=time,
|
||||
provision_updated_at=time, instance_info={},
|
||||
|
@ -167,7 +167,8 @@ class JsonPatchType(wtypes.Base):
|
||||
|
||||
@staticmethod
|
||||
def validate(patch):
|
||||
if patch.path in patch.internal_attrs():
|
||||
_path = '/' + patch.path.split('/')[1]
|
||||
if _path in patch.internal_attrs():
|
||||
msg = _("'%s' is an internal attribute and can not be updated")
|
||||
raise wsme.exc.ClientSideError(msg % patch.path)
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
# 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.
|
||||
|
||||
"""add_node_driver_internal_info
|
||||
|
||||
Revision ID: bb59b63f55a
|
||||
Revises: 5674c57409b9
|
||||
Create Date: 2015-01-28 14:28:22.212790
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'bb59b63f55a'
|
||||
down_revision = '5674c57409b9'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('nodes', sa.Column('driver_internal_info',
|
||||
sa.Text(),
|
||||
nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('nodes', 'driver_internal_info')
|
@ -164,6 +164,7 @@ class Node(Base):
|
||||
properties = Column(JSONEncodedDict)
|
||||
driver = Column(String(15))
|
||||
driver_info = Column(JSONEncodedDict)
|
||||
driver_internal_info = Column(JSONEncodedDict)
|
||||
|
||||
# NOTE(deva): this is the host name of the conductor which has
|
||||
# acquired a TaskManager lock on the node.
|
||||
|
@ -31,7 +31,8 @@ class Node(base.IronicObject):
|
||||
# Version 1.6: Add reserve() and release()
|
||||
# Version 1.7: Add conductor_affinity
|
||||
# Version 1.8: Add maintenance_reason
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Add driver_internal_info
|
||||
VERSION = '1.9'
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
@ -44,6 +45,7 @@ class Node(base.IronicObject):
|
||||
|
||||
'driver': obj_utils.str_or_none,
|
||||
'driver_info': obj_utils.dict_or_none,
|
||||
'driver_internal_info': obj_utils.dict_or_none,
|
||||
|
||||
'instance_info': obj_utils.dict_or_none,
|
||||
'properties': obj_utils.dict_or_none,
|
||||
|
@ -93,7 +93,8 @@ class TestListNodes(test_api_base.FunctionalTest):
|
||||
|
||||
def test_one(self):
|
||||
node = obj_utils.create_test_node(self.context)
|
||||
data = self.get_json('/nodes')
|
||||
data = self.get_json('/nodes',
|
||||
headers={api_base.Version.string: "1.2"})
|
||||
self.assertIn('instance_uuid', data['nodes'][0])
|
||||
self.assertIn('maintenance', data['nodes'][0])
|
||||
self.assertIn('power_state', data['nodes'][0])
|
||||
@ -102,6 +103,7 @@ class TestListNodes(test_api_base.FunctionalTest):
|
||||
self.assertEqual(node['uuid'], data['nodes'][0]["uuid"])
|
||||
self.assertNotIn('driver', data['nodes'][0])
|
||||
self.assertNotIn('driver_info', data['nodes'][0])
|
||||
self.assertNotIn('driver_internal_info', data['nodes'][0])
|
||||
self.assertNotIn('extra', data['nodes'][0])
|
||||
self.assertNotIn('properties', data['nodes'][0])
|
||||
self.assertNotIn('chassis_uuid', data['nodes'][0])
|
||||
@ -116,10 +118,12 @@ class TestListNodes(test_api_base.FunctionalTest):
|
||||
|
||||
def test_get_one(self):
|
||||
node = obj_utils.create_test_node(self.context)
|
||||
data = self.get_json('/nodes/%s' % node['uuid'])
|
||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||
headers={api_base.Version.string: "1.2"})
|
||||
self.assertEqual(node.uuid, data['uuid'])
|
||||
self.assertIn('driver', data)
|
||||
self.assertIn('driver_info', data)
|
||||
self.assertIn('driver_internal_info', data)
|
||||
self.assertIn('extra', data)
|
||||
self.assertIn('properties', data)
|
||||
self.assertIn('chassis_uuid', data)
|
||||
@ -164,6 +168,17 @@ class TestListNodes(test_api_base.FunctionalTest):
|
||||
headers={api_base.Version.string: "1.1"})
|
||||
self.assertEqual(states.AVAILABLE, data['provision_state'])
|
||||
|
||||
def test_hide_driver_internal_info(self):
|
||||
node = obj_utils.create_test_node(self.context,
|
||||
driver_internal_info={"foo": "bar"})
|
||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||
headers={api_base.Version.string: "1.0"})
|
||||
self.assertNotIn('driver_internal_info', data)
|
||||
|
||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||
headers={api_base.Version.string: "1.2"})
|
||||
self.assertEqual({"foo": "bar"}, data['driver_internal_info'])
|
||||
|
||||
def test_many(self):
|
||||
nodes = []
|
||||
for id in range(5):
|
||||
|
@ -107,6 +107,13 @@ class TestJsonPatchType(base.TestCase):
|
||||
self.assertEqual(400, ret.status_int)
|
||||
self.assertTrue(ret.json['faultstring'])
|
||||
|
||||
def test_cannot_update_internal_dict_attr(self):
|
||||
patch = [{'path': '/internal/test', 'op': 'replace',
|
||||
'value': 'foo'}]
|
||||
ret = self._patch_json(patch, True)
|
||||
self.assertEqual(400, ret.status_int)
|
||||
self.assertTrue(ret.json['faultstring'])
|
||||
|
||||
def test_mandatory_attr(self):
|
||||
patch = [{'op': 'replace', 'path': '/mandatory', 'value': 'foo'}]
|
||||
ret = self._patch_json(patch, False)
|
||||
|
@ -360,6 +360,13 @@ class MigrationCheckersMixin(object):
|
||||
else:
|
||||
self.assertEqual(old, new)
|
||||
|
||||
def _check_bb59b63f55a(self, engine, data):
|
||||
nodes = db_utils.get_table(engine, 'nodes')
|
||||
col_names = [column.name for column in nodes.c]
|
||||
self.assertIn('driver_internal_info', col_names)
|
||||
self.assertIsInstance(nodes.c.driver_internal_info.type,
|
||||
sqlalchemy.types.TEXT)
|
||||
|
||||
def test_upgrade_and_version(self):
|
||||
with patch_with_engine(self.engine):
|
||||
self.migration_api.upgrade('head')
|
||||
|
@ -179,6 +179,7 @@ def get_test_node(**kw):
|
||||
'instance_info': kw.get('instance_info', fake_info),
|
||||
'driver': kw.get('driver', 'fake'),
|
||||
'driver_info': kw.get('driver_info', fake_info),
|
||||
'driver_internal_info': kw.get('driver_internal_info', fake_info),
|
||||
'properties': kw.get('properties', properties),
|
||||
'reservation': kw.get('reservation'),
|
||||
'maintenance': kw.get('maintenance', False),
|
||||
|
Loading…
x
Reference in New Issue
Block a user