From 54682e5ca1260955eefd92bee872a66dfd946a31 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Thu, 16 Feb 2017 00:26:16 +0200 Subject: [PATCH] NSX|V: add in a cleanup method for host-groups There are cases when one may update edge_ha mode or change hostgroups or want to rebalance things. Here the admin should do the following: 1. Clean the host groups 2. Create all For example: nsxadmin -r edges -o nsx-update --property hostgroup=clean nsxadmin -r edges -o nsx-update --property hostgroup=all Change-Id: I4d4302f87e9c8dceaf16e960d0e5c705331088ca --- doc/source/admin_util.rst | 3 + vmware_nsx/dvs/dvs.py | 70 +++++++++++++++++-- .../plugins/nsx_v/vshield/edge_utils.py | 10 +++ .../admin/plugins/nsxv/resources/edges.py | 10 ++- 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index ef46e6b4fd..5f07ef81df 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -72,6 +72,9 @@ Edges nsxadmin -o nsx-update -r edges --property hostgroup=all +- Clean all DRS hostgroups for all edges:: + + nsxadmin -o nsx-update -r edges --property hostgroup=clean Orphaned Edges ~~~~~~~~~~~~~~ diff --git a/vmware_nsx/dvs/dvs.py b/vmware_nsx/dvs/dvs.py index d9e83ad745..d2e1bd2017 100644 --- a/vmware_nsx/dvs/dvs.py +++ b/vmware_nsx/dvs/dvs.py @@ -553,7 +553,7 @@ class DvsManager(object): if hasattr(cluster_config, 'group'): groups = cluster_config.group for group in groups: - if 'neutron-group-%s' % entry_id in group.name: + if 'neutron-group-%s' % entry_id == group.name: vm_group = group break if vm_group and hasattr(vm_group, 'vm'): @@ -584,7 +584,7 @@ class DvsManager(object): if hasattr(cluster_config, 'group'): groups = cluster_config.group for group in groups: - if 'neutron-group-%s' % index in group.name: + if 'neutron-group-%s' % index == group.name: vmGroup = group break # Create/update the VM group @@ -599,7 +599,7 @@ class DvsManager(object): rules = cluster_config.rule # Create the config rule if it does not exist for rule in rules: - if 'neutron-rule-%s' % index in rule.name: + if 'neutron-rule-%s' % index == rule.name: config_rule = rule break if config_rule is None and index <= num_host_groups: @@ -643,7 +643,7 @@ class DvsManager(object): if hasattr(cluster_config, 'group'): groups = cluster_config.group for group in groups: - if 'neutron-group-%s' % entry_id in group.name: + if 'neutron-group-%s' % entry_id == group.name: vmGroup = group break if vmGroup is None: @@ -660,7 +660,7 @@ class DvsManager(object): rules = cluster_config.rule # Create the config rule if it does not exist for rule in rules: - if 'neutron-rule-%s' % entry_id in rule.name: + if 'neutron-rule-%s' % entry_id == rule.name: config_rule = rule break if config_rule is None and index < num_host_groups: @@ -676,3 +676,63 @@ class DvsManager(object): except Exception as e: LOG.error(_LE('Unable to update cluster for host groups %s'), e) + + def _delete_vm_group_spec(self, client_factory, name): + group_spec = client_factory.create('ns0:ClusterGroupSpec') + group = client_factory.create('ns0:ClusterVmGroup') + group.name = name + group_spec.operation = 'remove' + group_spec.removeKey = name + group_spec.info = group + return [group_spec] + + def _delete_cluster_rules_spec(self, client_factory, rule): + rules_spec = client_factory.create('ns0:ClusterRuleSpec') + rules_spec.operation = 'remove' + rules_spec.removeKey = int(rule.key) + policy_class = 'ns0:ClusterVmHostRuleInfo' + rules_info = client_factory.create(policy_class) + rules_info.name = rule.name + rules_info.vmGroupName = rule.vmGroupName + rules_info.affineHostGroupName = rule.affineHostGroupName + rules_spec.info = rules_info + return rules_spec + + def cluster_host_group_cleanup(self, resource_id): + session = self._session + resource = vim_util.get_moref(resource_id, 'ResourcePool') + # TODO(garyk): cache the cluster details + cluster = session.invoke_api( + vim_util, "get_object_property", self._session.vim, resource, + "owner") + client_factory = session.vim.client.factory + config_spec = client_factory.create('ns0:ClusterConfigSpecEx') + cluster_config = session.invoke_api( + vim_util, "get_object_property", self._session.vim, cluster, + "configurationEx") + groupSpec = [] + ruleSpec = [] + for index in range(2): + entry_id = index + 1 + groups = [] + if hasattr(cluster_config, 'group'): + groups = cluster_config.group + for group in groups: + if 'neutron-group-%s' % entry_id == group.name: + groupSpec.append(self._delete_vm_group_spec( + client_factory, group.name)) + rules = [] + if hasattr(cluster_config, 'rule'): + rules = cluster_config.rule + # Create the config rule if it does not exist + for rule in rules: + if 'neutron-rule-%s' % entry_id == rule.name: + ruleSpec.append(self._delete_cluster_rules_spec( + client_factory, rule)) + + if groupSpec: + config_spec.groupSpec = groupSpec + if ruleSpec: + config_spec.rulesSpec = ruleSpec + if groupSpec or ruleSpec: + self._reconfigure_cluster(session, cluster, config_spec) diff --git a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py index c646b59dc2..6413cc6251 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py +++ b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py @@ -2612,6 +2612,16 @@ def update_edge_host_groups(vcns, edge_id, dvs, availability_zone, 'e': e}) +def clean_host_groups(dvs, availability_zone): + try: + LOG.info(_LI('Cleaning up host groups for AZ %s'), + availability_zone.name) + dvs.cluster_host_group_cleanup( + availability_zone.resource_pool) + except Exception as e: + LOG.error(_LE('Unable to cleanup. Error: %s'), e) + + class NsxVCallbacks(object): """Edge callback implementation Callback functions for asynchronous tasks. diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py index 1d25416568..6dd974e671 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py @@ -397,6 +397,13 @@ def change_edge_hostgroup(properties): edge_id = edge['id'] _update_host_group_for_edge(nsxv, dvs_mng, edge_id, edge) + elif properties.get('hostgroup').lower() == "clean": + azs = nsx_az.ConfiguredAvailabilityZones() + for az in azs.availability_zones.values(): + try: + edge_utils.clean_host_groups(dvs_mng, az) + except Exception: + LOG.error(_LE("Failed to clean AZ %s"), az.name) else: LOG.error(_LE('Currently not supported')) @@ -427,7 +434,8 @@ def nsx_update_edge(resource, event, trigger, **kwargs): return properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) if (not properties.get('edge-id') and - not properties.get('hostgroup', '').lower() == "all"): + not properties.get('hostgroup', '').lower() == "all" and + not properties.get('hostgroup', '').lower() == "clean"): LOG.error(_LE("Need to specify edge-id. " "Add --property edge-id=")) return