From 2bbf4b9e987c9cdcc0b4fa951c632e1d89e1f9b6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 28 Feb 2019 12:59:41 -0500 Subject: [PATCH 1/8] Implement direct add switches Allow addition of switches without associated nodes. This allows populating mac database without requiring associated nodes. --- confluent_server/confluent/config/attributes.py | 7 ++++--- confluent_server/confluent/networking/macmap.py | 4 +++- confluent_server/confluent/networking/netutil.py | 4 +++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index a83520f0..1a14d887 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -93,9 +93,10 @@ node = { 'description': ('List of static groups for which this node is ' 'considered a member'), }, - #'type': { - # 'description': ('Classification of node as system, vm, etc') - #}, + 'type': { + 'description': ('Classification of node as server or switch'), + 'validvalues': ('switch', 'server'), + }, #'id': { # 'description': ('Numeric identifier for node') #}, diff --git a/confluent_server/confluent/networking/macmap.py b/confluent_server/confluent/networking/macmap.py index 2522a030..0a374d5a 100644 --- a/confluent_server/confluent/networking/macmap.py +++ b/confluent_server/confluent/networking/macmap.py @@ -315,10 +315,12 @@ def _full_updatemacmap(configmanager): 'Network topology not available to tenants') # here's a list of switches... need to add nodes that are switches nodelocations = configmanager.get_node_attributes( - configmanager.list_nodes(), ('net*.switch', 'net*.switchport')) + configmanager.list_nodes(), ('type', 'net*.switch', 'net*.switchport')) switches = set([]) for node in nodelocations: cfg = nodelocations[node] + if cfg.get('type', {}).get('value', None) == 'switch': + switches.add(node) for attr in cfg: if not attr.endswith('.switch') or 'value' not in cfg[attr]: continue diff --git a/confluent_server/confluent/networking/netutil.py b/confluent_server/confluent/networking/netutil.py index 60106c34..508c8662 100644 --- a/confluent_server/confluent/networking/netutil.py +++ b/confluent_server/confluent/networking/netutil.py @@ -42,10 +42,12 @@ def get_switchcreds(configmanager, switches): def list_switches(configmanager): nodelocations = configmanager.get_node_attributes( - configmanager.list_nodes(), ('net*.switch', 'net*.switchport')) + configmanager.list_nodes(), ('type', 'net*.switch', 'net*.switchport')) switches = set([]) for node in nodelocations: cfg = nodelocations[node] + if cfg.get('type', {}).get('value', None) == 'switch': + switches.add(node) for attr in cfg: if not attr.endswith('.switch') or 'value' not in cfg[attr]: continue From 23c9e6315ac836d12323fb51cc0947957d6ef264 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 28 Feb 2019 15:56:15 -0500 Subject: [PATCH 2/8] Update node collection handlers for renamed Rename support will provide a map of old to new name. Have the existing node collection watchers accept a new argument. --- confluent_server/confluent/config/configmanager.py | 4 ++-- confluent_server/confluent/consoleserver.py | 2 +- confluent_server/confluent/discovery/core.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 9bf9ed86..4f6ba68d 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -290,7 +290,7 @@ def logException(): def _do_add_watcher(watcher, added, configmanager): try: - watcher(added=added, deleting=[], configmanager=configmanager) + watcher(added=added, deleting=(), renamed=(), configmanager=configmanager) except Exception: logException() @@ -1705,7 +1705,7 @@ class ConfigManager(object): def _true_del_nodes(self, nodes): if self.tenant in self._nodecollwatchers: for watcher in self._nodecollwatchers[self.tenant].itervalues(): - watcher(added=[], deleting=nodes, configmanager=self) + watcher(added=(), deleting=nodes, renamed=(), configmanager=self) changeset = {} for node in nodes: # set a reserved attribute for the sake of the change notification diff --git a/confluent_server/confluent/consoleserver.py b/confluent_server/confluent/consoleserver.py index 3baba74d..6dd65441 100644 --- a/confluent_server/confluent/consoleserver.py +++ b/confluent_server/confluent/consoleserver.py @@ -621,7 +621,7 @@ def disconnect_node(node, configmanager): del _handled_consoles[consk] -def _nodechange(added, deleting, configmanager): +def _nodechange(added, deleting, renamed, configmanager, renamed=()): for node in added: connect_node(node, configmanager) for node in deleting: diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 065a2437..9d1f3031 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -1129,7 +1129,7 @@ def _handle_nodelist_change(configmanager): nodeaddhandler = None -def newnodes(added, deleting, configmanager): +def newnodes(added, deleting, renamed, configmanager): global attribwatcher global needaddhandled global nodeaddhandler From 8ce5a7dccfe9aec28076b68555f03888b4486695 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 13:21:57 -0500 Subject: [PATCH 3/8] Phase 1 of node rename support Provide foundation for node renaming, including updating groups and inheritance and notifying collection watchers of the change, and updating the existing watchers with the new notification fingerprint. --- .../confluent/config/configmanager.py | 55 ++++++++++++++++++- confluent_server/confluent/consoleserver.py | 7 ++- confluent_server/confluent/core.py | 1 + confluent_server/confluent/discovery/core.py | 3 +- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 4f6ba68d..ebb1dfd7 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -180,6 +180,8 @@ def _rpc_set_user(tenant, name, attributemap): def _rpc_master_set_node_attributes(tenant, attribmap, autocreate): ConfigManager(tenant).set_node_attributes(attribmap, autocreate) +def _rpc_master_rename_nodes(tenant, renamemap): + ConfigManager(tenant).rename_nodes(renamemap) def _rpc_master_clear_node_attributes(tenant, nodes, attributes): ConfigManager(tenant).clear_node_attributes(nodes, attributes) @@ -234,6 +236,10 @@ def _rpc_set_node_attributes(tenant, attribmap, autocreate): ConfigManager(tenant)._true_set_node_attributes(attribmap, autocreate) +def _rpc_rename_nodes(tenant, renamemap): + ConfigManager(tenant)._true_rename_nodes(renamemap) + + def _rpc_set_group_attributes(tenant, attribmap, autocreate): ConfigManager(tenant)._true_set_group_attributes(attribmap, autocreate) @@ -288,9 +294,9 @@ def logException(): event=confluent.log.Events.stacktrace) -def _do_add_watcher(watcher, added, configmanager): +def _do_add_watcher(watcher, added, configmanager, renamed=()): try: - watcher(added=added, deleting=(), renamed=(), configmanager=configmanager) + watcher(added=added, deleting=(), renamed=renamed, configmanager=configmanager) except Exception: logException() @@ -1789,6 +1795,51 @@ class ConfigManager(object): attribmap[node]['groups'] = [] self.set_node_attributes(attribmap, autocreate=True) + def rename_nodes(self, renamemap): + if cfgleader: + return exec_on_leader('_rpc_master_rename_nodes', self.tenant, + renamemap) + if cfgstreams: + exec_on_followers('_rpc_rename_nodes', self.tenant, renamemap) + self._true_rename_nodes(renamemap) + + def _true_rename_nodes(self, renamemap): + oldnames = set(renamemap) + exprmgr = None + currnodes = set(self._cfgstore['nodes']) + missingnodes = oldnames - currnodes + if missingnodes: + raise ValueError( + 'The following nodes to rename do not exist: {0}'.format( + ','.join(missingnodes))) + newnames = set([]) + for name in renamemap: + newnames.add(renamemap[name]) + if newnames & currnodes: + raise ValueError( + 'The following requested new names conflict with existing nodes: {0}'.format( + ','.join(newnames & currnodes))) + for name in renamemap: + self._cfgstore['nodes'][renamemap[name]] = self._cfgstore['nodes'][name] + del self._cfgstore['nodes'][name] + _mark_dirtykey('nodes', name, self.tenant) + _mark_dirtykey('nodes', renamemap[name], self.tenant) + for group in self._cfgstore['nodes'][renamemap[name]].get('groups', []): + self._cfgstore['nodegroups'][group]['nodes'].discard(name) + self._cfgstore['nodegroups'][group]['nodes'].add(renamemap[name]) + _mark_dirtykey('nodegroups', group, self.tenant) + cfgobj = self._cfgstore['nodes'][renamemap[name]] + node = renamemap[name] + changeset = {} + if exprmgr is None: + exprmgr = _ExpressionFormat(cfgobj, node) + self._recalculate_expressions(cfgobj, formatter=exprmgr, node=renamemap[name], changeset=changeset) + if self.tenant in self._nodecollwatchers: + nodecollwatchers = self._nodecollwatchers[self.tenant] + for watcher in nodecollwatchers.itervalues(): + eventlet.spawn_n(_do_add_watcher, watcher, None, self, renamemap) + self._bg_sync_to_file() + def set_node_attributes(self, attribmap, autocreate=False): if cfgleader: # currently config slave to another return exec_on_leader('_rpc_master_set_node_attributes', diff --git a/confluent_server/confluent/consoleserver.py b/confluent_server/confluent/consoleserver.py index 6dd65441..c973c039 100644 --- a/confluent_server/confluent/consoleserver.py +++ b/confluent_server/confluent/consoleserver.py @@ -622,10 +622,13 @@ def disconnect_node(node, configmanager): def _nodechange(added, deleting, renamed, configmanager, renamed=()): - for node in added: - connect_node(node, configmanager) for node in deleting: disconnect_node(node, configmanager) + for node in renamed: + disconnect_node(node, configmanager) + connect_node(renamed[node], configmanager) + for node in added: + connect_node(node, configmanager) def _start_tenant_sessions(cfm): diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index 47f2cec6..0d71bd9c 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -144,6 +144,7 @@ def _init_core(): # be enumerated in any collection noderesources = { 'attributes': { + 'rename': PluginRoute({'handler': 'attributes'}), 'all': PluginRoute({'handler': 'attributes'}), 'current': PluginRoute({'handler': 'attributes'}), 'expression': PluginRoute({'handler': 'attributes'}), diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 9d1f3031..0b445d64 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -1133,7 +1133,8 @@ def newnodes(added, deleting, renamed, configmanager): global attribwatcher global needaddhandled global nodeaddhandler - for node in deleting: + alldeleting = set(deleting) | set(renamed) + for node in alldeleting: if node not in known_nodes: continue for mac in known_nodes[node]: From f5b6d434f34d8bc78f81cbd2104598422a5c1276 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 13:37:13 -0500 Subject: [PATCH 4/8] Fix node collection function signature --- confluent_server/confluent/consoleserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/confluent_server/confluent/consoleserver.py b/confluent_server/confluent/consoleserver.py index c973c039..0413d1a6 100644 --- a/confluent_server/confluent/consoleserver.py +++ b/confluent_server/confluent/consoleserver.py @@ -621,7 +621,7 @@ def disconnect_node(node, configmanager): del _handled_consoles[consk] -def _nodechange(added, deleting, renamed, configmanager, renamed=()): +def _nodechange(added, deleting, renamed, configmanager): for node in deleting: disconnect_node(node, configmanager) for node in renamed: From 7703c6c2abd7fc1f6a494d253f55cfbd05110c1c Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 14:37:07 -0500 Subject: [PATCH 5/8] Enable Server Portion of renamae node This plumbs up through the messages and attributes plugin. --- .../confluent/config/configmanager.py | 2 +- confluent_server/confluent/messages.py | 15 +++++++++++++-- .../confluent/plugins/configuration/attributes.py | 11 +++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index ebb1dfd7..24b2dad4 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -1837,7 +1837,7 @@ class ConfigManager(object): if self.tenant in self._nodecollwatchers: nodecollwatchers = self._nodecollwatchers[self.tenant] for watcher in nodecollwatchers.itervalues(): - eventlet.spawn_n(_do_add_watcher, watcher, None, self, renamemap) + eventlet.spawn_n(_do_add_watcher, watcher, (), self, renamemap) self._bg_sync_to_file() def set_node_attributes(self, attribmap, autocreate=False): diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index 90382558..bf5acf46 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -267,6 +267,17 @@ class CreatedResource(ConfluentMessage): pass +class RenamedResource(ConfluentMessage): + notnode = True + readonly = True + + def __init__(self, oldname, newname): + self.kvpairs = {'oldname': oldname, 'newname': newname} + + def strip_node(self, node): + pass + + class AssignedResource(ConfluentMessage): notnode = True readonly = True @@ -381,6 +392,8 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False, return InputReseatMessage(path, nodes, inputdata) elif path == ['attributes', 'expression']: return InputExpression(path, inputdata, nodes) + elif path == ['attributes', 'rename']: + return InputConfigChangeSet(path, inputdata, nodes, configmanager) elif path[0] in ('attributes', 'users') and operation != 'retrieve': return InputAttributes(path, inputdata, nodes) elif path == ['boot', 'nextdevice'] and operation != 'retrieve': @@ -539,8 +552,6 @@ class InputConfigClear(ConfluentMessage): raise exc.InvalidArgumentException('Input must be {"clear":true}') class InputConfigChangeSet(InputExpression): - # For now, this is identical to InputExpression, later it may - # internalize formula expansion, but not now.. def __init__(self, path, inputdata, nodes=None, configmanager=None): self.cfm = configmanager super(InputConfigChangeSet, self).__init__(path, inputdata, nodes) diff --git a/confluent_server/confluent/plugins/configuration/attributes.py b/confluent_server/confluent/plugins/configuration/attributes.py index c9dda221..bf5a9e70 100644 --- a/confluent_server/confluent/plugins/configuration/attributes.py +++ b/confluent_server/confluent/plugins/configuration/attributes.py @@ -200,12 +200,23 @@ def create(nodes, element, configmanager, inputdata): if nodes is not None and element[-1] == 'expression': return _expand_expression(nodes, configmanager, inputdata) +def yield_rename_resources(namemap): + for node in namemap: + yield msg.RenamedResource(node, namemap[node]) + def update_nodes(nodes, element, configmanager, inputdata): updatedict = {} if not nodes: raise exc.InvalidArgumentException( 'No action to take, noderange is empty (if trying to define ' 'group attributes, use nodegroupattrib)') + if 'rename' in element: + namemap = {} + for node in nodes: + rename = inputdata.get_attributes(node) + namemap[node] = rename['rename'] + configmanager.rename_nodes(namemap) + return yield_rename_resources(namemap) for node in nodes: updatenode = inputdata.get_attributes(node, allattributes.node) clearattribs = [] From 4446308030b7b0bd29aecde83a1381bd5c08ec7e Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 15:03:43 -0500 Subject: [PATCH 6/8] Add ability to rename nodegroups If we can rename nodes, should be able to rename groups. --- .../confluent/config/configmanager.py | 45 +++++++++++++++++++ confluent_server/confluent/core.py | 1 + .../plugins/configuration/attributes.py | 5 +++ 3 files changed, 51 insertions(+) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 24b2dad4..9d67a6ab 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -180,9 +180,15 @@ def _rpc_set_user(tenant, name, attributemap): def _rpc_master_set_node_attributes(tenant, attribmap, autocreate): ConfigManager(tenant).set_node_attributes(attribmap, autocreate) + def _rpc_master_rename_nodes(tenant, renamemap): ConfigManager(tenant).rename_nodes(renamemap) + +def _rpc_master_rename_nodegroups(tenant, renamemap): + ConfigManager(tenant).rename_nodegroups(renamemap) + + def _rpc_master_clear_node_attributes(tenant, nodes, attributes): ConfigManager(tenant).clear_node_attributes(nodes, attributes) @@ -240,6 +246,10 @@ def _rpc_rename_nodes(tenant, renamemap): ConfigManager(tenant)._true_rename_nodes(renamemap) +def _rpc_rename_nodegroups(tenant, renamemap): + ConfigManager(tenant)._true_rename_nodegroups(renamemap) + + def _rpc_set_group_attributes(tenant, attribmap, autocreate): ConfigManager(tenant)._true_set_group_attributes(attribmap, autocreate) @@ -1840,6 +1850,41 @@ class ConfigManager(object): eventlet.spawn_n(_do_add_watcher, watcher, (), self, renamemap) self._bg_sync_to_file() + def rename_nodegroups(self, renamemap): + if cfgleader: + return exec_on_leader('_rpc_master_rename_nodegroups', self.tenant, renamemap) + if cfgstreams: + exec_on_followers('_rpc_rename_nodegroups', self.tenant, renamemap) + self._true_rename_groups(renamemap) + + def _true_rename_groups(self, renamemap): + oldnames = set(renamemap) + currgroups = set(self._cfgstore['nodegroups']) + missinggroups = oldnames - currgroups + if missinggroups: + raise ValueError( + 'The following groups to rename do not exist: {0}'.format( + ','.join(missinggroups))) + newnames = set([]) + for name in renamemap: + newnames.add(renamemap[name]) + if newnames & currgroups: + raise ValueError( + 'The following requested new names conflict with existing groups: {0}'.format( + ','.join(newnames & currgroups))) + for name in renamemap: + self._cfgstore['nodegroups'][renamemap[name]] = self._cfgstore['nodegroups'][name] + del self._cfgstore['nodegroups'][name] + _mark_dirtykey('nodegroups', name, self.tenant) + _mark_dirtykey('nodegroups', renamemap[name], self.tenant) + for node in self._cfgstore['nodegroups'][renamemap[name]].get('nodes', []): + lidx = self._cfgstore['nodes'][node]['groups'].index(name) + self._cfgstore['nodes'][node]['groups'][lidx] = renamemap[name] + _mark_dirtykey('nodes', node, self.tenant) + self._bg_sync_to_file() + + + def set_node_attributes(self, attribmap, autocreate=False): if cfgleader: # currently config slave to another return exec_on_leader('_rpc_master_set_node_attributes', diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index 0d71bd9c..7b897b46 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -380,6 +380,7 @@ def _init_core(): nodegroupresources = { 'attributes': { + 'rename': PluginRoute({'handler': 'attributes'}), 'all': PluginRoute({'handler': 'attributes'}), 'current': PluginRoute({'handler': 'attributes'}), }, diff --git a/confluent_server/confluent/plugins/configuration/attributes.py b/confluent_server/confluent/plugins/configuration/attributes.py index bf5a9e70..df9da5ae 100644 --- a/confluent_server/confluent/plugins/configuration/attributes.py +++ b/confluent_server/confluent/plugins/configuration/attributes.py @@ -161,6 +161,11 @@ def update(nodes, element, configmanager, inputdata): def update_nodegroup(group, element, configmanager, inputdata): + if 'rename' in element: + namemap = {} + namemap[group] = inputdata.attribs['rename'] + configmanager.rename_nodegroups(namemap) + return yield_rename_resources(namemap) try: clearattribs = [] for attrib in inputdata.attribs.iterkeys(): From 59aa23b2f5b4985305f809ba11124a8eeedf39b6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 15:21:29 -0500 Subject: [PATCH 7/8] Add noderename command --- confluent_client/bin/noderename | 52 +++++++++++++++++++ confluent_server/confluent/messages.py | 7 +++ .../plugins/configuration/attributes.py | 11 ++-- 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 confluent_client/bin/noderename diff --git a/confluent_client/bin/noderename b/confluent_client/bin/noderename new file mode 100644 index 00000000..3308a293 --- /dev/null +++ b/confluent_client/bin/noderename @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2019 Lenovo +# +# 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. + +import optparse +import os +import signal +import sys +try: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) +except AttributeError: + pass + +path = os.path.dirname(os.path.realpath(__file__)) +path = os.path.realpath(os.path.join(path, '..', 'lib', 'python')) +if path.startswith('/opt'): + sys.path.append(path) + +import confluent.client as client + +argparser = optparse.OptionParser(usage="Usage: %prog ") +(options, args) = argparser.parse_args() +try: + noderange = args[0] +except IndexError: + argparser.print_help() + sys.exit(1) +client.check_globbing(noderange) +identifystate = None +if len(sys.argv) > 2: + newname = sys.argv[2] +else: + argparser.print_help() + sys.exit(1) +session = client.Command() +exitcode = 0 +sys.exit( + session.simple_noderange_command(noderange, 'attributes/rename', newname)) + diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index bf5acf46..b317aa44 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -278,6 +278,13 @@ class RenamedResource(ConfluentMessage): pass +class RenamedNode(ConfluentMessage): + def __init__(self, name, rename): + self.desc = 'New Name' + kv = {'rename': {'value': rename}} + self.kvpairs = {name: kv} + + class AssignedResource(ConfluentMessage): notnode = True readonly = True diff --git a/confluent_server/confluent/plugins/configuration/attributes.py b/confluent_server/confluent/plugins/configuration/attributes.py index df9da5ae..e9b3b1fc 100644 --- a/confluent_server/confluent/plugins/configuration/attributes.py +++ b/confluent_server/confluent/plugins/configuration/attributes.py @@ -165,7 +165,7 @@ def update_nodegroup(group, element, configmanager, inputdata): namemap = {} namemap[group] = inputdata.attribs['rename'] configmanager.rename_nodegroups(namemap) - return yield_rename_resources(namemap) + return yield_rename_resources(namemap, isnode=False) try: clearattribs = [] for attrib in inputdata.attribs.iterkeys(): @@ -205,9 +205,12 @@ def create(nodes, element, configmanager, inputdata): if nodes is not None and element[-1] == 'expression': return _expand_expression(nodes, configmanager, inputdata) -def yield_rename_resources(namemap): +def yield_rename_resources(namemap, isnode): for node in namemap: - yield msg.RenamedResource(node, namemap[node]) + if isnode: + yield msg.RenamedNode(node, namemap[node]) + else: + yield msg.RenamedResource(node, namemap[node]) def update_nodes(nodes, element, configmanager, inputdata): updatedict = {} @@ -221,7 +224,7 @@ def update_nodes(nodes, element, configmanager, inputdata): rename = inputdata.get_attributes(node) namemap[node] = rename['rename'] configmanager.rename_nodes(namemap) - return yield_rename_resources(namemap) + return yield_rename_resources(namemap, isnode=True) for node in nodes: updatenode = inputdata.get_attributes(node, allattributes.node) clearattribs = [] From 6ea307d4150c85b0a870cd79b81da2b451f65d4d Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 1 Mar 2019 15:27:13 -0500 Subject: [PATCH 8/8] Add nodegrouprename command --- confluent_client/bin/nodegrouprename | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 confluent_client/bin/nodegrouprename diff --git a/confluent_client/bin/nodegrouprename b/confluent_client/bin/nodegrouprename new file mode 100644 index 00000000..55429046 --- /dev/null +++ b/confluent_client/bin/nodegrouprename @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2019 Lenovo +# +# 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. + +__author__ = 'jjohnson2,alin37,andywray' + +import optparse +import os +import signal +import sys + +try: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) +except AttributeError: + pass +path = os.path.dirname(os.path.realpath(__file__)) +path = os.path.realpath(os.path.join(path, '..', 'lib', 'python')) +if path.startswith('/opt'): + sys.path.append(path) + +import confluent.client as client + +def main(): + argparser = optparse.OptionParser( + usage="Usage: %prog \n") + (options, args) = argparser.parse_args() + noderange="" + nodelist="" + nodelist = '/nodegroups/' + session = client.Command() + exitcode = 0 + requestargs=args[1:] + nodetype='noderange' + if len(args) != 2: + argparser.print_help() + sys.exit(1) + else: + for res in session.update( + '/nodegroups/{0}/attributes/rename'.format(args[0]), + {'rename': args[1]}): + if 'error' in res: + sys.stderr.write(res['error'] + '\n') + exitcode = 1 + else: + print('{0}: {1}'.format(res['oldname'], res['newname'])) + + sys.exit(exitcode) + +if __name__ == '__main__': + main()