Add support for changing metadata of compute instances

Change-Id: I2301e0ab2024c51e7482ce0f05b706e8a395d676
This commit is contained in:
Mário Santos 2016-05-20 16:56:20 +01:00
parent a1ab68cd2b
commit e67b306c10
No known key found for this signature in database
GPG Key ID: 498B903D47DAAAF7
6 changed files with 222 additions and 0 deletions

View File

@ -0,0 +1,3 @@
---
features:
- Add new APIs, OpenStackCloud.set_server_metadata() and OpenStackCloud.delete_server_metadata() to manage metadata of existing nova compute instances

View File

@ -172,6 +172,16 @@ class ServerRebuild(task_manager.Task):
return client.nova_client.servers.rebuild(**self.args)
class ServerSetMetadata(task_manager.Task):
def main(self, client):
return client.nova_client.servers.set_meta(**self.args)
class ServerDeleteMetadata(task_manager.Task):
def main(self, client):
return client.nova_client.servers.delete_meta(**self.args)
class ServerGroupList(task_manager.Task):
def main(self, client):
return client.nova_client.server_groups.list(**self.args)

View File

@ -4302,6 +4302,47 @@ class OpenStackCloud(object):
extra_data=dict(server=server))
return server
def set_server_metadata(self, name_or_id, metadata):
"""Set metadata in a server instance.
:param str name_or_id: The name or id of the server instance
to update.
:param dict metadata: A dictionary with the key=value pairs
to set in the server instance. It only updates the key=value
pairs provided. Existing ones will remain untouched.
:raises: OpenStackCloudException on operation error.
"""
try:
self.manager.submitTask(
_tasks.ServerSetMetadata(server=self.get_server(name_or_id),
metadata=metadata))
except OpenStackCloudException:
raise
except Exception as e:
raise OpenStackCloudException(
"Error updating metadata: {0}".format(e))
def delete_server_metadata(self, name_or_id, metadata_keys):
"""Delete metadata from a server instance.
:param str name_or_id: The name or id of the server instance
to update.
:param list metadata_keys: A list with the keys to be deleted
from the server instance.
:raises: OpenStackCloudException on operation error.
"""
try:
self.manager.submitTask(
_tasks.ServerDeleteMetadata(server=self.get_server(name_or_id),
keys=metadata_keys))
except OpenStackCloudException:
raise
except Exception as e:
raise OpenStackCloudException(
"Error deleting metadata: {0}".format(e))
def delete_server(
self, name_or_id, wait=False, timeout=180, delete_ips=False,
delete_ip_retry=1):

View File

@ -19,6 +19,7 @@ test_compute
Functional tests for `shade` compute methods.
"""
from shade import exc
from shade.tests.functional import base
from shade.tests.functional.util import pick_flavor, pick_image
@ -215,3 +216,37 @@ class TestCompute(base.BaseFunctionalTestCase):
wait=True)
self.addCleanup(self.demo_cloud.delete_image, image['id'])
self.assertEqual('active', image['status'])
def test_set_and_delete_metadata(self):
self.addCleanup(self._cleanup_servers_and_volumes, self.server_name)
self.demo_cloud.create_server(
name=self.server_name,
image=self.image,
flavor=self.flavor,
wait=True)
self.demo_cloud.set_server_metadata(self.server_name,
{'key1': 'value1',
'key2': 'value2'})
updated_server = self.demo_cloud.get_server(self.server_name)
self.assertEqual(set(updated_server.metadata.items()),
set({'key1': 'value1', 'key2': 'value2'}.items()))
self.demo_cloud.set_server_metadata(self.server_name,
{'key2': 'value3'})
updated_server = self.demo_cloud.get_server(self.server_name)
self.assertEqual(set(updated_server.metadata.items()),
set({'key1': 'value1', 'key2': 'value3'}.items()))
self.demo_cloud.delete_server_metadata(self.server_name, ['key2'])
updated_server = self.demo_cloud.get_server(self.server_name)
self.assertEqual(set(updated_server.metadata.items()),
set({'key1': 'value1'}.items()))
self.demo_cloud.delete_server_metadata(self.server_name, ['key1'])
updated_server = self.demo_cloud.get_server(self.server_name)
self.assertEqual(set(updated_server.metadata.items()), set([]))
self.assertRaises(
exc.OpenStackCloudException,
self.demo_cloud.delete_server_metadata,
self.server_name, ['key1'])

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# 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.
"""
test_server_delete_metadata
----------------------------------
Tests for the `delete_server_metadata` command.
"""
from mock import patch, Mock
import os_client_config
from shade import OpenStackCloud
from shade.exc import OpenStackCloudException
from shade.tests import base
class TestServerDeleteMetadata(base.TestCase):
def setUp(self):
super(TestServerDeleteMetadata, self).setUp()
config = os_client_config.OpenStackConfig()
self.client = OpenStackCloud(
cloud_config=config.get_one_cloud(validate=False))
self.client._SERVER_AGE = 0
def test_server_delete_metadata_with_delete_meta_exception(self):
"""
Test that a generic exception in the novaclient delete_meta raises
an exception in delete_server_metadata.
"""
with patch("shade.OpenStackCloud"):
config = {
"servers.delete_meta.side_effect": Exception("exception"),
}
OpenStackCloud.nova_client = Mock(**config)
self.assertRaises(
OpenStackCloudException, self.client.delete_server_metadata,
{'id': 'server-id'}, ['key'])
def test_server_delete_metadata_with_exception_reraise(self):
"""
Test that an OpenStackCloudException exception gets re-raised
in delete_server_metadata.
"""
with patch("shade.OpenStackCloud"):
config = {
"servers.delete_meta.side_effect":
OpenStackCloudException("exception"),
}
OpenStackCloud.nova_client = Mock(**config)
self.assertRaises(
OpenStackCloudException, self.client.delete_server_metadata,
'server-id', ['key'])

View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# 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.
"""
test_server_set_metadata
----------------------------------
Tests for the `set_server_metadata` command.
"""
from mock import patch, Mock
import os_client_config
from shade import OpenStackCloud
from shade.exc import OpenStackCloudException
from shade.tests import base
class TestServerSetMetadata(base.TestCase):
def setUp(self):
super(TestServerSetMetadata, self).setUp()
config = os_client_config.OpenStackConfig()
self.client = OpenStackCloud(
cloud_config=config.get_one_cloud(validate=False))
self.client._SERVER_AGE = 0
def test_server_set_metadata_with_set_meta_exception(self):
"""
Test that a generic exception in the novaclient set_meta raises
an exception in set_server_metadata.
"""
with patch("shade.OpenStackCloud"):
config = {
"servers.set_meta.side_effect": Exception("exception"),
}
OpenStackCloud.nova_client = Mock(**config)
self.assertRaises(
OpenStackCloudException, self.client.set_server_metadata,
{'id': 'server-id'}, {'meta': 'data'})
def test_server_set_metadata_with_exception_reraise(self):
"""
Test that an OpenStackCloudException exception gets re-raised
in set_server_metadata.
"""
with patch("shade.OpenStackCloud"):
config = {
"servers.set_meta.side_effect":
OpenStackCloudException("exception"),
}
OpenStackCloud.nova_client = Mock(**config)
self.assertRaises(
OpenStackCloudException, self.client.set_server_metadata,
'server-id', {'meta': 'data'})