Change to use server metadata instead of extra

Use server metadata to be user friendly.

Change-Id: Ib396fba305d6138c2436a40559c267de5bb4e7f9
Closes-Bug: #1696899
This commit is contained in:
Zhenguo Niu 2017-06-13 17:56:35 +08:00
parent 6cf1af411b
commit ed5993efce
20 changed files with 67 additions and 57 deletions

View File

@ -130,13 +130,6 @@ created_at:
in: body
required: true
type: string
extra:
description: |
Metadata key and value pairs. The maximum size of the metadata key and value is
255 bytes each.
in: body
required: false
type: object
fixed_address:
description: |
The fixed IP address with which you want to associate the floating IP address.
@ -303,6 +296,13 @@ lock_state:
in: body
required: true
type: boolean
metadata:
description: |
Metadata key and value pairs. The maximum size of the metadata key and value is
255 bytes each.
in: body
required: false
type: object
max_count_body:
description: |
The max number of servers to be created. Defaults to the value of ``min_count``.

View File

@ -13,7 +13,7 @@
"port_type": "10GE"
}
],
"extra" : {
"metadata" : {
"My Server Name" : "Apache1"
},
"personality": [

View File

@ -23,7 +23,7 @@
"project_id": "2f15c3524826465a9afbd150478b3b76",
"user_id": "a6205fcab03d4a289251f420456b1289",
"nics": [],
"extra": {
"metadata": {
"My Server Name" : "Apache1"
}
}

View File

@ -33,7 +33,7 @@
"updated_at": "2016-10-17T04:12:44+00:00",
"user_id": "cdbf77d47f1d4d04ad9b7ff62b672467",
"uuid": "f978ef48-d4af-4dad-beec-e6174309bc71",
"extra": {
"metadata": {
"My Server Name" : "Apache1"
}
}

View File

@ -41,7 +41,7 @@
"updated_at": "2016-10-17T04:12:44+00:00",
"user_id": "cdbf77d47f1d4d04ad9b7ff62b672467",
"uuid": "f978ef48-d4af-4dad-beec-e6174309bc71",
"extra": {
"metadata": {
"My Server Name" : "Apache1"
}
}

View File

@ -43,7 +43,7 @@
"launched_at": null,
"user_id": "cdbf77d47f1d4d04ad9b7ff62b672467",
"uuid": "f978ef48-d4af-4dad-beec-e6174309bc71",
"extra": {
"metadata": {
"My Server Name" : "Apache1"
}
}

View File

@ -1,12 +1,12 @@
[
{
"op": "replace",
"path": "/extra/k1",
"path": "/metadata/k1",
"value": "v1"
},
{
"op": "add",
"path": "/extra/k2",
"path": "/metadata/k2",
"value": "v2"
}
]

View File

@ -41,7 +41,7 @@
]
}
],
"extra": {
"metadata": {
"k1": "v1",
"k2": "v2"
}

View File

@ -66,7 +66,7 @@ Response
- user_id: user_id_body
- updated_at: updated_at
- created_at: created_at
- extra: extra
- metadata: metadata
**Example Create Server: JSON response**
@ -202,7 +202,7 @@ Response
- updated_at: updated_at
- created_at: created_at
- launched_at: launched_at
- extra: extra
- metadata: metadata
**Example Detailed list of Servers: JSON response**
@ -253,7 +253,7 @@ Response
- updated_at: updated_at
- created_at: created_at
- launched_at: launched_at
- extra: extra
- metadata: metadata
**Example Server Details: JSON response**
@ -312,7 +312,7 @@ Response
- user_id: user_id_body
- updated_at: updated_at
- created_at: created_at
- extra: extra
- metadata: metadata
**Example Update Server: JSON response**

View File

@ -42,7 +42,7 @@ create_server = {
'key_name': parameter_types.name,
'min_count': {'type': 'integer', 'minimum': 1},
'max_count': {'type': 'integer', 'minimum': 1},
'extra': parameter_types.extra,
'metadata': parameter_types.metadata,
},
'required': ['name', 'image_uuid', 'flavor_uuid', 'networks'],
'additionalProperties': False,

View File

@ -446,7 +446,7 @@ class Server(base.APIBase):
launched_at = datetime.datetime
"""The UTC date and time of the server launched"""
extra = {wtypes.text: types.jsontype}
metadata = {wtypes.text: types.jsontype}
"""The meta data of the server"""
fault_info = {wtypes.text: types.jsontype}
@ -669,7 +669,7 @@ class ServerController(ServerControllerBase):
name=server.get('name'),
description=server.get('description'),
availability_zone=server.get('availability_zone'),
extra=server.get('extra'),
metadata=server.get('metadata'),
requested_networks=requested_networks,
user_data=user_data,
injected_files=injected_files,

View File

@ -58,7 +58,7 @@ flavor_id = {
}
extra = {
metadata = {
'type': 'object',
'patternProperties': {
'^[a-zA-Z0-9-_:. ]{1,255}$': {

View File

@ -77,7 +77,7 @@ class API(object):
def _validate_and_build_base_options(self, context, flavor,
image_uuid, name, description,
availability_zone, extra,
availability_zone, metadata,
requested_networks, user_data,
key_name, max_count):
"""Verify all the input parameters"""
@ -117,7 +117,7 @@ class API(object):
'name': name,
'description': description,
'locked': False,
'extra': extra or {},
'metadata': metadata or {},
'availability_zone': availability_zone}
# return the validated options
@ -247,7 +247,7 @@ class API(object):
max_count)
def _create_server(self, context, flavor, image_uuid,
name, description, availability_zone, extra,
name, description, availability_zone, metadata,
requested_networks, user_data, injected_files,
key_name, min_count, max_count):
"""Verify all the input parameters"""
@ -262,7 +262,7 @@ class API(object):
base_options, max_net_count, key_pair = \
self._validate_and_build_base_options(
context, flavor, image_uuid, name, description,
availability_zone, extra, requested_networks, user_data,
availability_zone, metadata, requested_networks, user_data,
key_name, max_count)
# max_net_count is the maximum number of servers requested by the
@ -304,7 +304,7 @@ class API(object):
def create(self, context, flavor, image_uuid,
name=None, description=None, availability_zone=None,
extra=None, requested_networks=None, user_data=None,
metadata=None, requested_networks=None, user_data=None,
injected_files=None, key_name=None, min_count=None,
max_count=None):
"""Provision servers
@ -323,7 +323,7 @@ class API(object):
return self._create_server(context, flavor,
image_uuid, name, description,
availability_zone, extra,
availability_zone, metadata,
requested_networks, user_data,
injected_files, key_name,
min_count, max_count)

View File

@ -51,7 +51,7 @@ class Server(base.MoganObject, object_base.VersionedObjectDictCompat):
'fault': object_fields.ObjectField('ServerFault', nullable=True),
'node_uuid': object_fields.UUIDField(nullable=True),
'launched_at': object_fields.DateTimeField(nullable=True),
'extra': object_fields.FlexibleDictField(nullable=True),
'metadata': object_fields.FlexibleDictField(nullable=True),
'locked': object_fields.BooleanField(default=False),
'locked_by': object_fields.StringField(nullable=True),
}
@ -78,7 +78,10 @@ class Server(base.MoganObject, object_base.VersionedObjectDictCompat):
:return: The object of the class with the database entity added
"""
for field in set(server.fields) - set(OPTIONAL_ATTRS):
server[field] = db_server[field]
if field == 'metadata':
server[field] = db_server['extra']
else:
server[field] = db_server[field]
if expected_attrs is None:
expected_attrs = []
@ -139,6 +142,9 @@ class Server(base.MoganObject, object_base.VersionedObjectDictCompat):
def create(self, context=None):
"""Create a Server record in the DB."""
values = self.obj_get_changes()
metadata = values.pop('metadata', None)
if metadata is not None:
values['extra'] = metadata
server_nics = values.pop('nics', None)
if server_nics:
values['nics'] = server_nics.as_list_of_dict()
@ -170,6 +176,9 @@ class Server(base.MoganObject, object_base.VersionedObjectDictCompat):
raise
updates.pop(field)
metadata = updates.pop('metadata', None)
if metadata is not None:
updates['extra'] = metadata
self.dbapi.server_update(context, self.uuid, updates)
self.obj_reset_changes()

View File

@ -136,7 +136,7 @@ class TestServers(v1_test.APITestV1):
'networks': [
{'net_id': 'c1940655-8b8e-4370-b8f9-03ba1daeca31',
'port_type': 'Ethernet'}],
'extra': {'fake_key': 'fake_value'}
'metadata': {'fake_key': 'fake_value'}
}
responses.append(
self.post_json('/servers', test_body, headers=headers,
@ -154,7 +154,7 @@ class TestServers(v1_test.APITestV1):
resp['image_uuid'])
self.assertEqual('mogan', resp['availability_zone'])
self.assertEqual([], resp['nics'])
self.assertEqual({'fake_key': 'fake_value'}, resp['extra'])
self.assertEqual({'fake_key': 'fake_value'}, resp['metadata'])
self.assertIn('links', resp)
self.assertIn('created_at', resp)
self.assertIn('updated_at', resp)
@ -176,7 +176,7 @@ class TestServers(v1_test.APITestV1):
resp['image_uuid'])
self.assertEqual('mogan', resp['availability_zone'])
self.assertEqual([], resp['nics'])
self.assertEqual({'fake_key': 'fake_value'}, resp['extra'])
self.assertEqual({'fake_key': 'fake_value'}, resp['metadata'])
self.assertIn('links', resp)
self.assertIn('created_at', resp)
self.assertIn('updated_at', resp)

View File

@ -36,7 +36,7 @@ class BaremetalComputeAPIServersTest(base.BaseBaremetalComputeTest):
self.assertEqual(self.image_id, resp['image_uuid'])
self.assertIn('launched_at', resp)
self.assertIn('updated_at', resp)
self.assertIn('extra', resp)
self.assertIn('metadata', resp)
self.assertIn('links', resp)
self.assertIn('project_id', resp)
self.assertIn('user_id', resp)
@ -54,7 +54,7 @@ class BaremetalComputeAPIServersTest(base.BaseBaremetalComputeTest):
self.assertEqual('power on', resp['power_state'])
self.assertIn('launched_at', resp)
self.assertIn('updated_at', resp)
self.assertIn('extra', resp)
self.assertIn('metadata', resp)
self.assertIn('links', resp)
self.assertIn('project_id', resp)
self.assertIn('user_id', resp)

View File

@ -135,7 +135,7 @@ class TestPatch(v1_test.APITestV1):
def test_update_not_found(self):
uuid = uuidutils.generate_uuid()
response = self.patch_json('/servers/%s' % uuid,
[{'path': '/extra/a', 'value': 'b',
[{'path': '/metadata/a', 'value': 'b',
'op': 'add'}],
headers=self.headers,
expect_errors=True)
@ -169,7 +169,7 @@ class TestPatch(v1_test.APITestV1):
extra=extra)
new_value = 'new value'
response = self.patch_json('/servers/%s' % server.uuid,
[{'path': '/extra/foo2',
[{'path': '/metadata/foo2',
'value': new_value, 'op': 'replace'}],
headers=self.headers)
self.assertEqual('application/json', response.content_type)
@ -178,7 +178,7 @@ class TestPatch(v1_test.APITestV1):
headers=self.headers)
extra["foo2"] = new_value
self.assertEqual(extra, result['extra'])
self.assertEqual(extra, result['metadata'])
def test_remove_singular(self):
uuid = uuidutils.generate_uuid()
@ -195,7 +195,7 @@ class TestPatch(v1_test.APITestV1):
# Assert nothing else was changed
self.assertEqual(server.uuid, result['uuid'])
self.assertEqual(server.extra, result['extra'])
self.assertEqual(server.extra, result['metadata'])
def test_remove_multi(self):
extra = {"foo1": "bar1", "foo2": "bar2", "foo3": "bar3"}
@ -204,24 +204,25 @@ class TestPatch(v1_test.APITestV1):
uuid=uuid, description="foobar")
# Removing one item from the collection
response = self.patch_json('/servers/%s' % server.uuid,
[{'path': '/extra/foo2', 'op': 'remove'}],
headers=self.headers)
response = self.patch_json(
'/servers/%s' % server.uuid,
[{'path': '/metadata/foo2', 'op': 'remove'}],
headers=self.headers)
self.assertEqual('application/json', response.content_type)
self.assertEqual(http_client.OK, response.status_code)
result = self.get_json('/servers/%s' % server.uuid,
headers=self.headers)
extra.pop("foo2")
self.assertEqual(extra, result['extra'])
self.assertEqual(extra, result['metadata'])
# Removing the collection
response = self.patch_json('/servers/%s' % server.uuid,
[{'path': '/extra', 'op': 'remove'}],
[{'path': '/metadata', 'op': 'remove'}],
headers=self.headers)
self.assertEqual(http_client.OK, response.status_code)
result = self.get_json('/servers/%s' % server.uuid,
headers=self.headers)
self.assertEqual({}, result['extra'])
self.assertEqual({}, result['metadata'])
# Assert nothing else was changed
self.assertEqual(server.uuid, result['uuid'])
@ -230,7 +231,7 @@ class TestPatch(v1_test.APITestV1):
def test_remove_non_existent_property_fail(self):
response = self.patch_json(
'/servers/%s' % self.server.uuid,
[{'path': '/extra/non-existent', 'op': 'remove'}],
[{'path': '/metadata/non-existent', 'op': 'remove'}],
headers=self.headers,
expect_errors=True)
self.assertEqual(http_client.BAD_REQUEST, response.status_code)
@ -256,9 +257,9 @@ class TestPatch(v1_test.APITestV1):
def test_add_multi(self):
response = self.patch_json('/servers/%s' % self.server.uuid,
[{'path': '/extra/foo1', 'value': 'bar1',
[{'path': '/metadata/foo1', 'value': 'bar1',
'op': 'add'},
{'path': '/extra/foo2', 'value': 'bar2',
{'path': '/metadata/foo2', 'value': 'bar2',
'op': 'add'}],
headers=self.headers)
self.assertEqual('application/json', response.content_type)
@ -266,7 +267,7 @@ class TestPatch(v1_test.APITestV1):
result = self.get_json('/servers/%s' % self.server.uuid,
headers=self.headers)
expected = {"foo1": "bar1", "foo2": "bar2"}
self.assertEqual(expected, result['extra'])
self.assertEqual(expected, result['metadata'])
def test_remove_uuid(self):
response = self.patch_json('/servers/%s' % self.server.uuid,

View File

@ -58,7 +58,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
name='fake-name',
description='fake-descritpion',
availability_zone='test_az',
extra={'k1', 'v1'},
metadata={'k1', 'v1'},
requested_networks=None,
user_data=None,
key_name=None,
@ -68,7 +68,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
self.assertEqual('fake-project', base_opts['project_id'])
self.assertEqual(states.BUILDING, base_opts['status'])
self.assertEqual(flavor.uuid, base_opts['flavor_uuid'])
self.assertEqual({'k1', 'v1'}, base_opts['extra'])
self.assertEqual({'k1', 'v1'}, base_opts['metadata'])
self.assertEqual('test_az', base_opts['availability_zone'])
self.assertIsNone(key_pair)
@ -107,7 +107,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
'flavor_uuid': 'fake-type-uuid',
'name': 'fake-name',
'description': 'fake-description',
'extra': {'k1', 'v1'},
'metadata': {'k1', 'v1'},
'availability_zone': 'test_az'}
min_count = 1
max_count = 2
@ -131,7 +131,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
name='fake-name',
description='fake-descritpion',
availability_zone='test_az',
extra={'k1', 'v1'},
metadata={'k1', 'v1'},
requested_networks=requested_networks,
min_count=min_count,
max_count=max_count)
@ -180,7 +180,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
'flavor_uuid': 'fake-type-uuid',
'name': 'fake-name',
'description': 'fake-description',
'extra': {'k1', 'v1'},
'metadata': {'k1', 'v1'},
'availability_zone': 'test_az'}
min_count = 11
max_count = 20

View File

@ -382,7 +382,7 @@ class _TestObject(object):
# version bump. It is md5 hash of object fields and remotable methods.
# The fingerprint values should only be changed if there is a version bump.
expected_object_fingerprints = {
'Server': '1.0-f3ef6866ef8072b063014a2c49060c6d',
'Server': '1.0-dc54162c0cc91fac43fed5304cd2c968',
'ComputeNode': '1.0-586e7eaadd4ec88a0506c4238ebdd7a5',
'ComputeNodeList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
'ComputePort': '1.0-ca4c1817ad7324286813f2cfcdcf802e',

View File

@ -61,11 +61,11 @@ class TestServerObject(base.DbTestCase):
autospec=True) as mock_server_create:
mock_server_create.return_value = self.fake_server
server = objects.Server(self.context, **self.fake_server)
server.obj_get_changes()
server.create(self.context)
expected_called = copy.deepcopy(self.fake_server)
expected_called['nics'][0].update(
server_uuid=self.fake_server['uuid'])
expected_called.pop('extra', None)
mock_server_create.assert_called_once_with(self.context,
expected_called)
self.assertEqual(self.fake_server['uuid'], server['uuid'])