Added Support of microverison 2.26
This microversion allows to create/delete/update server tags and to search servers by tags. Implements: blueprint tag-instances Change-Id: I66b6d4a763c507335f27a425bc3d4c2aae377c00
This commit is contained in:
parent
4187c69184
commit
ff9b97b2c6
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
|||||||
# when client supported the max version, and bumped sequentially, otherwise
|
# when client supported the max version, and bumped sequentially, otherwise
|
||||||
# the client may break due to server side new version may include some
|
# the client may break due to server side new version may include some
|
||||||
# backward incompatible change.
|
# backward incompatible change.
|
||||||
API_MAX_VERSION = api_versions.APIVersion("2.25")
|
API_MAX_VERSION = api_versions.APIVersion("2.26")
|
||||||
|
@ -316,6 +316,50 @@ class Base(base.Fixture):
|
|||||||
self.url(1234, 'os-server-password'),
|
self.url(1234, 'os-server-password'),
|
||||||
status_code=202,
|
status_code=202,
|
||||||
headers=self.json_headers)
|
headers=self.json_headers)
|
||||||
|
#
|
||||||
|
# Server tags
|
||||||
|
#
|
||||||
|
|
||||||
|
self.requests.register_uri('GET',
|
||||||
|
self.url(1234, 'tags'),
|
||||||
|
json={'tags': ['tag1', 'tag2']},
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
self.requests.register_uri('GET',
|
||||||
|
self.url(1234, 'tags', 'tag'),
|
||||||
|
status_code=204,
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
self.requests.register_uri('DELETE',
|
||||||
|
self.url(1234, 'tags', 'tag'),
|
||||||
|
status_code=204,
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
self.requests.register_uri('DELETE',
|
||||||
|
self.url(1234, 'tags'),
|
||||||
|
status_code=204,
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
def put_server_tag(request, context):
|
||||||
|
body = jsonutils.loads(request.body)
|
||||||
|
assert body is None
|
||||||
|
context.status_code = 201
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.requests.register_uri('PUT',
|
||||||
|
self.url(1234, 'tags', 'tag'),
|
||||||
|
json=put_server_tag,
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
def put_server_tags(request, context):
|
||||||
|
body = jsonutils.loads(request.body)
|
||||||
|
assert list(body) == ['tags']
|
||||||
|
return body
|
||||||
|
|
||||||
|
self.requests.register_uri('PUT',
|
||||||
|
self.url(1234, 'tags'),
|
||||||
|
json=put_server_tags,
|
||||||
|
headers=self.json_headers)
|
||||||
|
|
||||||
|
|
||||||
class V1(Base):
|
class V1(Base):
|
||||||
|
@ -2221,6 +2221,24 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
def delete_servers_1234_migrations_1(self):
|
def delete_servers_1234_migrations_1(self):
|
||||||
return (202, {}, None)
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def put_servers_1234_tags_tag(self, **kw):
|
||||||
|
return (201, {}, None)
|
||||||
|
|
||||||
|
def put_servers_1234_tags(self, **kw):
|
||||||
|
return (201, {}, None)
|
||||||
|
|
||||||
|
def get_servers_1234_tags(self, **kw):
|
||||||
|
return (200, {}, {'tags': ['tag1', 'tag2']})
|
||||||
|
|
||||||
|
def delete_servers_1234_tags_tag(self, **kw):
|
||||||
|
return (204, {}, None)
|
||||||
|
|
||||||
|
def delete_servers_1234_tags(self, **kw):
|
||||||
|
return (204, {}, None)
|
||||||
|
|
||||||
|
def get_servers_1234_tags_tag(self, **kw):
|
||||||
|
return (204, {}, None)
|
||||||
|
|
||||||
|
|
||||||
class FakeSessionClient(fakes.FakeClient, client.Client):
|
class FakeSessionClient(fakes.FakeClient, client.Client):
|
||||||
|
|
||||||
|
@ -1148,3 +1148,45 @@ class ServersV225Test(ServersV219Test):
|
|||||||
s = self.cs.servers.get(1234)
|
s = self.cs.servers.get(1234)
|
||||||
self.assertRaises(ValueError, s.live_migrate, 'hostname',
|
self.assertRaises(ValueError, s.live_migrate, 'hostname',
|
||||||
'auto', 'True')
|
'auto', 'True')
|
||||||
|
|
||||||
|
|
||||||
|
class ServersV226Test(ServersV225Test):
|
||||||
|
def setUp(self):
|
||||||
|
super(ServersV219Test, self).setUp()
|
||||||
|
self.cs.api_version = api_versions.APIVersion("2.26")
|
||||||
|
|
||||||
|
def test_tag_list(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.tag_list()
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('GET', '/servers/1234/tags')
|
||||||
|
|
||||||
|
def test_tag_delete(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.delete_tag('tag')
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('DELETE', '/servers/1234/tags/tag')
|
||||||
|
|
||||||
|
def test_tag_delete_all(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.delete_all_tags()
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('DELETE', '/servers/1234/tags')
|
||||||
|
|
||||||
|
def test_tag_add(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.add_tag('tag')
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('PUT', '/servers/1234/tags/tag')
|
||||||
|
|
||||||
|
def test_tags_set(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.set_tags(['tag1', 'tag2'])
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('PUT', '/servers/1234/tags')
|
||||||
|
|
||||||
|
def test_tag_exists(self):
|
||||||
|
s = self.cs.servers.get(1234)
|
||||||
|
ret = s.tag_exists('tag')
|
||||||
|
self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
|
||||||
|
self.assert_called('GET', '/servers/1234/tags/tag')
|
||||||
|
@ -2775,6 +2775,52 @@ class ShellTest(utils.TestCase):
|
|||||||
self.run_command('list', api_version='2.10')
|
self.run_command('list', api_version='2.10')
|
||||||
self.assert_called('GET', '/servers/detail')
|
self.assert_called('GET', '/servers/detail')
|
||||||
|
|
||||||
|
def test_server_tag_add(self):
|
||||||
|
self.run_command('server-tag-add sample-server tag',
|
||||||
|
api_version='2.26')
|
||||||
|
self.assert_called('PUT', '/servers/1234/tags/tag', None)
|
||||||
|
|
||||||
|
def test_server_tag_set(self):
|
||||||
|
self.run_command('server-tag-set sample-server tag1 tag2',
|
||||||
|
api_version='2.26')
|
||||||
|
self.assert_called('PUT', '/servers/1234/tags',
|
||||||
|
{'tags': ['tag1', 'tag2']})
|
||||||
|
|
||||||
|
def test_server_tag_list(self):
|
||||||
|
self.run_command('server-tag-list sample-server', api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/1234/tags')
|
||||||
|
|
||||||
|
def test_server_tag_delete(self):
|
||||||
|
self.run_command('server-tag-delete sample-server tag',
|
||||||
|
api_version='2.26')
|
||||||
|
self.assert_called('DELETE', '/servers/1234/tags/tag')
|
||||||
|
|
||||||
|
def test_server_tag_delete_all(self):
|
||||||
|
self.run_command('server-tag-delete-all sample-server',
|
||||||
|
api_version='2.26')
|
||||||
|
self.assert_called('DELETE', '/servers/1234/tags')
|
||||||
|
|
||||||
|
def test_server_tag_exists(self):
|
||||||
|
self.run_command('server-tag-exists sample-server tag',
|
||||||
|
api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/1234/tags/tag')
|
||||||
|
|
||||||
|
def test_list_v2_26_tags(self):
|
||||||
|
self.run_command('list --tags tag1,tag2', api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/detail?tags=tag1%2Ctag2')
|
||||||
|
|
||||||
|
def test_list_v2_26_tags_any(self):
|
||||||
|
self.run_command('list --tags-any tag1,tag2', api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/detail?tags-any=tag1%2Ctag2')
|
||||||
|
|
||||||
|
def test_list_v2_26_not_tags(self):
|
||||||
|
self.run_command('list --not-tags tag1,tag2', api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/detail?not-tags=tag1%2Ctag2')
|
||||||
|
|
||||||
|
def test_list_v2_26_not_tags_any(self):
|
||||||
|
self.run_command('list --not-tags-any tag1,tag2', api_version='2.26')
|
||||||
|
self.assert_called('GET', '/servers/detail?not-tags-any=tag1%2Ctag2')
|
||||||
|
|
||||||
|
|
||||||
class ShellWithSessionClientTest(ShellTest):
|
class ShellWithSessionClientTest(ShellTest):
|
||||||
|
|
||||||
|
@ -526,6 +526,42 @@ class Server(base.Resource):
|
|||||||
"""Trigger crash dump in an instance"""
|
"""Trigger crash dump in an instance"""
|
||||||
return self.manager.trigger_crash_dump(self)
|
return self.manager.trigger_crash_dump(self)
|
||||||
|
|
||||||
|
def tag_list(self):
|
||||||
|
"""
|
||||||
|
Get list of tags from an instance.
|
||||||
|
"""
|
||||||
|
return self.manager.tag_list(self)
|
||||||
|
|
||||||
|
def delete_tag(self, tag):
|
||||||
|
"""
|
||||||
|
Remove single tag from an instance.
|
||||||
|
"""
|
||||||
|
return self.manager.delete_tag(self, tag)
|
||||||
|
|
||||||
|
def delete_all_tags(self):
|
||||||
|
"""
|
||||||
|
Remove all tags from an instance.
|
||||||
|
"""
|
||||||
|
return self.manager.delete_all_tags(self)
|
||||||
|
|
||||||
|
def set_tags(self, tags):
|
||||||
|
"""
|
||||||
|
Set list of tags to an instance.
|
||||||
|
"""
|
||||||
|
return self.manager.set_tags(self, tags)
|
||||||
|
|
||||||
|
def add_tag(self, tag):
|
||||||
|
"""
|
||||||
|
Add single tag to an instance.
|
||||||
|
"""
|
||||||
|
return self.manager.add_tag(self, tag)
|
||||||
|
|
||||||
|
def tag_exists(self, tag):
|
||||||
|
"""
|
||||||
|
Check if an instance has specified tag.
|
||||||
|
"""
|
||||||
|
return self.manager.tag_exists(self, tag)
|
||||||
|
|
||||||
|
|
||||||
class NetworkInterface(base.Resource):
|
class NetworkInterface(base.Resource):
|
||||||
@property
|
@property
|
||||||
@ -1709,3 +1745,51 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
url = '/servers/%s/remote-consoles' % base.getid(server)
|
url = '/servers/%s/remote-consoles' % base.getid(server)
|
||||||
resp, body = self.api.client.post(url, body=body)
|
resp, body = self.api.client.post(url, body=body)
|
||||||
return self.convert_into_with_meta(body, resp)
|
return self.convert_into_with_meta(body, resp)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def tag_list(self, server):
|
||||||
|
"""
|
||||||
|
Get list of tags from an instance.
|
||||||
|
"""
|
||||||
|
resp, body = self.api.client.get(
|
||||||
|
"/servers/%s/tags" % base.getid(server))
|
||||||
|
return base.ListWithMeta(body['tags'], resp)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def delete_tag(self, server, tag):
|
||||||
|
"""
|
||||||
|
Remove single tag from an instance.
|
||||||
|
"""
|
||||||
|
return self._delete("/servers/%s/tags/%s" % (base.getid(server), tag))
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def delete_all_tags(self, server):
|
||||||
|
"""
|
||||||
|
Remove all tags from an instance.
|
||||||
|
"""
|
||||||
|
return self._delete("/servers/%s/tags" % base.getid(server))
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def set_tags(self, server, tags):
|
||||||
|
"""
|
||||||
|
Set list of tags to an instance.
|
||||||
|
"""
|
||||||
|
body = {"tags": tags}
|
||||||
|
return self._update("/servers/%s/tags" % base.getid(server), body)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def add_tag(self, server, tag):
|
||||||
|
"""
|
||||||
|
Add single tag to an instance.
|
||||||
|
"""
|
||||||
|
return self._update(
|
||||||
|
"/servers/%s/tags/%s" % (base.getid(server), tag), None)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.26')
|
||||||
|
def tag_exists(self, server, tag):
|
||||||
|
"""
|
||||||
|
Check if an instance has specified tag.
|
||||||
|
"""
|
||||||
|
resp, body = self.api.client.get(
|
||||||
|
"/servers/%s/tags/%s" % (base.getid(server), tag))
|
||||||
|
return self.convert_into_with_meta(body, resp)
|
||||||
|
@ -1461,6 +1461,45 @@ def do_image_delete(cs, args):
|
|||||||
help=_("List only servers changed after a certain point of time."
|
help=_("List only servers changed after a certain point of time."
|
||||||
"The provided time should be an ISO 8061 formatted time."
|
"The provided time should be an ISO 8061 formatted time."
|
||||||
"ex 2016-03-04T06:27:59Z ."))
|
"ex 2016-03-04T06:27:59Z ."))
|
||||||
|
@utils.arg(
|
||||||
|
'--tags',
|
||||||
|
dest='tags',
|
||||||
|
metavar='<tags>',
|
||||||
|
default=None,
|
||||||
|
help=_("The given tags must all be present for a server to be included in "
|
||||||
|
"the list result. Boolean expression in this case is 't1 AND t2'. "
|
||||||
|
"Tags must be separated by commas: --tags <tag1,tag2>"),
|
||||||
|
start_version="2.26")
|
||||||
|
@utils.arg(
|
||||||
|
'--tags-any',
|
||||||
|
dest='tags-any',
|
||||||
|
metavar='<tags-any>',
|
||||||
|
default=None,
|
||||||
|
help=_("If one of the given tags is present the server will be included "
|
||||||
|
"in the list result. Boolean expression in this case is "
|
||||||
|
"'t1 OR t2'. Tags must be separated by commas: "
|
||||||
|
"--tags-any <tag1,tag2>"),
|
||||||
|
start_version="2.26")
|
||||||
|
@utils.arg(
|
||||||
|
'--not-tags',
|
||||||
|
dest='not-tags',
|
||||||
|
metavar='<not-tags>',
|
||||||
|
default=None,
|
||||||
|
help=_("Only the servers that do not have any of the given tags will"
|
||||||
|
"be included in the list results. Boolean expression in this case "
|
||||||
|
"is 'NOT(t1 AND t2)'. Tags must be separated by commas: "
|
||||||
|
"--not-tags <tag1,tag2>"),
|
||||||
|
start_version="2.26")
|
||||||
|
@utils.arg(
|
||||||
|
'--not-tags-any',
|
||||||
|
dest='not-tags-any',
|
||||||
|
metavar='<not-tags-any>',
|
||||||
|
default=None,
|
||||||
|
help=_("Only the servers that do not have at least one of the given tags"
|
||||||
|
"will be included in the list result. Boolean expression in this "
|
||||||
|
"case is 'NOT(t1 OR t2)'. Tags must be separated by commas: "
|
||||||
|
"--not-tags-any <tag1,tag2>"),
|
||||||
|
start_version="2.26")
|
||||||
def do_list(cs, args):
|
def do_list(cs, args):
|
||||||
"""List active servers."""
|
"""List active servers."""
|
||||||
imageid = None
|
imageid = None
|
||||||
@ -1488,6 +1527,10 @@ def do_list(cs, args):
|
|||||||
'instance_name': args.instance_name,
|
'instance_name': args.instance_name,
|
||||||
'changes-since': args.changes_since}
|
'changes-since': args.changes_since}
|
||||||
|
|
||||||
|
for arg in ('tags', "tags-any", 'not-tags', 'not-tags-any'):
|
||||||
|
if arg in args:
|
||||||
|
search_opts[arg] = getattr(args, arg)
|
||||||
|
|
||||||
filters = {'flavor': lambda f: f['id'],
|
filters = {'flavor': lambda f: f['id'],
|
||||||
'security_groups': utils.format_security_groups}
|
'security_groups': utils.format_security_groups}
|
||||||
|
|
||||||
@ -4956,3 +4999,56 @@ def do_virtual_interface_list(cs, args):
|
|||||||
server = _find_server(cs, args.server)
|
server = _find_server(cs, args.server)
|
||||||
interface_list = cs.virtual_interfaces.list(base.getid(server))
|
interface_list = cs.virtual_interfaces.list(base.getid(server))
|
||||||
_print_virtual_interface_list(cs, interface_list)
|
_print_virtual_interface_list(cs, interface_list)
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
def do_server_tag_list(cs, args):
|
||||||
|
"""Get list of tags from a server."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
tags = server.tag_list()
|
||||||
|
utils.print_list(tags, 'name')
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
@utils.arg('tag', metavar='<tag>', help=_('Tag to add.'))
|
||||||
|
def do_server_tag_add(cs, args):
|
||||||
|
"""Add single tag to a server."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
server.add_tag(args.tag)
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
@utils.arg('tags', metavar='<tags>', nargs='+', help=_('Tag(s) to set.'))
|
||||||
|
def do_server_tag_set(cs, args):
|
||||||
|
"""Set list of tags to a server."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
server.set_tags(args.tags)
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
@utils.arg('tag', metavar='<tag>', help=_('Tag to delete.'))
|
||||||
|
def do_server_tag_delete(cs, args):
|
||||||
|
"""Delete single tag from a server."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
server.delete_tag(args.tag)
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
def do_server_tag_delete_all(cs, args):
|
||||||
|
"""Delete all tags from a server."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
server.delete_all_tags()
|
||||||
|
|
||||||
|
|
||||||
|
@api_versions.wraps("2.26")
|
||||||
|
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||||
|
@utils.arg('tag', metavar='<tag>', help=_('Tag to check if it exists or not.'))
|
||||||
|
def do_server_tag_exists(cs, args):
|
||||||
|
"""Check if a server has specified tag."""
|
||||||
|
server = _find_server(cs, args.server)
|
||||||
|
server.tag_exists(args.tag)
|
||||||
|
Loading…
Reference in New Issue
Block a user