diff options
-rw-r--r-- | plugins/config_generator.py | 34 | ||||
-rwxr-xr-x | plugins/discovery.py | 59 | ||||
-rw-r--r-- | tests/test_config_generator.py | 14 | ||||
-rw-r--r-- | tests/test_discovery.py | 93 |
4 files changed, 151 insertions, 49 deletions
diff --git a/plugins/config_generator.py b/plugins/config_generator.py index 1d0ed37..a5e52f8 100644 --- a/plugins/config_generator.py +++ b/plugins/config_generator.py @@ -23,6 +23,7 @@ from pynag import Model import server_utils from glusternagios.glustercli import HostStatus + """ Change mode helps to identify the change in the defintion. "ADD" means the entity and all its sub entities are added. @@ -30,14 +31,17 @@ Change mode helps to identify the change in the defintion. "UPDATE" means the entity is changes. It may also means sub entities are added or removed to the entity. """ +CHANGE_MODE = 'changeMode' CHANGE_MODE_ADD = "ADD" CHANGE_MODE_REMOVE = "REMOVE" CHANGE_MODE_UPDATE = "UPDATE" +HOST_SERVICES = 'host_services' GENERATED_BY_AUTOCONFIG = "__GENERATED_BY_AUTOCONFIG" VOL_NAME = '_VOL_NAME' BRICK_DIR = '_BRICK_DIR' HOST_UUID = '_HOST_UUID' NOTES = 'notes' +GLUSTER_AUTO_CONFIG = "Cluster Auto Config" SERVICE_FIELDS_TO_FORCE_SYNC = [VOL_NAME, NOTES] @@ -61,7 +65,7 @@ class GlusterNagiosConfManager: #Host service is not a field in host configuration. It helps to #aggregate all the host services under the host if services: - host['host_services'] = services + host[HOST_SERVICES] = services if uuid: host[HOST_UUID] = uuid return host @@ -149,7 +153,7 @@ class GlusterNagiosConfManager: service['host_name'] = clusterName service['use'] = 'gluster-service' service['check_interval'] = '1440' - service['service_description'] = 'Cluster Auto Config' + service['service_description'] = GLUSTER_AUTO_CONFIG service['check_command'] = "gluster_auto_discovery!%s" % (hostIp) return service @@ -265,7 +269,7 @@ class GlusterNagiosConfManager: #Host group should contain the delta to be written to the configuration. #Delta will be processed using the change mode. def writeHostGroup(self, hostgroup): - changeMode = hostgroup['changeMode'] + changeMode = hostgroup[CHANGE_MODE] if changeMode == CHANGE_MODE_ADD: hostgroupModel = Model.Hostgroup() hostgroupModel['hostgroup_name'] = hostgroup['hostgroup_name'] @@ -285,25 +289,25 @@ class GlusterNagiosConfManager: #used to represent the config model and changes. def fillModel(self, model, values): for key, value in values.iteritems(): - if key not in ['changeMode', 'host_services']: + if key not in [CHANGE_MODE, HOST_SERVICES]: model[key] = value return model #Write service to nagios config def writeService(self, service, hostname): - if service['changeMode'] == CHANGE_MODE_ADD: + if service[CHANGE_MODE] == CHANGE_MODE_ADD: serviceModel = Model.Service() serviceModel = self.fillModel(serviceModel, service) serviceModel.set_filename(self.getCfgFileName(hostname)) serviceModel[GENERATED_BY_AUTOCONFIG] = 1 serviceModel.save() - elif service['changeMode'] == CHANGE_MODE_REMOVE: + elif service[CHANGE_MODE] == CHANGE_MODE_REMOVE: serviceModel = Model.Service.objects.filter( host_name=hostname, service_description=service['service_description']) if serviceModel: serviceModel[0].delete() - elif service['changeMode'] == CHANGE_MODE_UPDATE: + elif service[CHANGE_MODE] == CHANGE_MODE_UPDATE: serviceModel = server_utils.getServiceConfig( service['service_description'], service['host_name']) self.fillModel(serviceModel, service) @@ -313,32 +317,32 @@ class GlusterNagiosConfManager: #host_services filed contains the list of services to be written to #nagios configuration def writeHostServices(self, host): - for service in host['host_services']: - if service.get('changeMode') is None: - service['changeMode'] = host['changeMode'] + for service in host[HOST_SERVICES]: + if service.get(CHANGE_MODE) is None: + service[CHANGE_MODE] = host[CHANGE_MODE] self.writeService(service, host['host_name']) #Write the host configuration with list of services to nagios configuration def writeHost(self, host): - if host['changeMode'] == CHANGE_MODE_REMOVE: + if host[CHANGE_MODE] == CHANGE_MODE_REMOVE: hostModel = Model.Host.objects.filter( host_name=host['host_name']) if hostModel: hostModel[0].delete(recursive=True) return - if host['changeMode'] == CHANGE_MODE_ADD: + if host[CHANGE_MODE] == CHANGE_MODE_ADD: hostModel = Model.Host() hostModel = self.fillModel(hostModel, host) hostModel.set_filename(self.getCfgFileName(host['host_name'])) hostModel.save() - if host.get('host_services'): + if host.get(HOST_SERVICES): self.writeHostServices(host) def writeHosts(self, hosts, chageMode): for host in hosts: - if host.get('changeMode') is None: - host['changeMode'] = chageMode + if host.get(CHANGE_MODE) is None: + host[CHANGE_MODE] = chageMode self.writeHost(host) #Write the hostgroup delta to nagios configuration. diff --git a/plugins/discovery.py b/plugins/discovery.py index 514dc22..18dc714 100755 --- a/plugins/discovery.py +++ b/plugins/discovery.py @@ -30,11 +30,14 @@ import submit_external_command from constants import DEFAULT_AUTO_CONFIG_DIR +from config_generator import CHANGE_MODE from config_generator import CHANGE_MODE_ADD from config_generator import CHANGE_MODE_REMOVE from config_generator import CHANGE_MODE_UPDATE from config_generator import GENERATED_BY_AUTOCONFIG from config_generator import SERVICE_FIELDS_TO_FORCE_SYNC +from config_generator import HOST_SERVICES +from config_generator import GLUSTER_AUTO_CONFIG #Discovers volumes info one by one. @@ -167,12 +170,12 @@ def findDeletedServices(host): #Consider only the service generated by autoconfig if not serviceConfig[GENERATED_BY_AUTOCONFIG]: continue - service = findServiceInList(host.get('host_services', []), + service = findServiceInList(host.get(HOST_SERVICES, []), serviceConfig['service_description']) if service is None: deletedService.append( {'service_description': serviceConfig['service_description'], - 'changeMode': CHANGE_MODE_REMOVE}) + CHANGE_MODE: CHANGE_MODE_REMOVE}) return deletedService @@ -187,7 +190,7 @@ def findChangeInService(newService, oldService): changes['service_description'] = \ newService['service_description'] changes['host_name'] = newService['host_name'] - changes['changeMode'] = CHANGE_MODE_UPDATE + changes[CHANGE_MODE] = CHANGE_MODE_UPDATE changes[field] = newService.get(field) return changes @@ -204,7 +207,7 @@ def findChangeInAutoConfig(newService, oldService): changes['check_command'] = "!".join(checkCommand) changes['service_description'] = newService['service_description'] changes['host_name'] = newService['host_name'] - changes['changeMode'] = CHANGE_MODE_UPDATE + changes[CHANGE_MODE] = CHANGE_MODE_UPDATE return changes return None @@ -215,13 +218,13 @@ def findChangeInAutoConfig(newService, oldService): #have to update the host ip in existing auto-config service. def findServiceDelta(host): serviceDelta = [] - for service in host.get('host_services', []): + for service in host.get(HOST_SERVICES, []): serviceConfig = server_utils.getServiceConfig( service['service_description'], service['host_name']) if serviceConfig is None: - service['changeMode'] = CHANGE_MODE_ADD + service[CHANGE_MODE] = CHANGE_MODE_ADD serviceDelta.append(service) - elif serviceConfig['service_description'] == "Cluster Auto Config": + elif serviceConfig['service_description'] == GLUSTER_AUTO_CONFIG: changes = findChangeInAutoConfig(service, serviceConfig) if changes: serviceDelta.append(changes) @@ -239,13 +242,13 @@ def findAddUpdateHosts(hosts): for host in hosts: hostConfing = server_utils.getHostConfigByName(host['host_name']) if hostConfing is None: - host['changeMode'] = CHANGE_MODE_ADD + host[CHANGE_MODE] = CHANGE_MODE_ADD delta.append(host) else: serviceDelta = findServiceDelta(host) if serviceDelta: - host['changeMode'] = CHANGE_MODE_UPDATE - host['host_services'] = serviceDelta + host[CHANGE_MODE] = CHANGE_MODE_UPDATE + host[HOST_SERVICES] = serviceDelta delta.append(host) return delta @@ -259,7 +262,7 @@ def findDeletedHosts(hostgroup, hosts, ignoredHosts): host = findHostInList(hosts, hostConfig['host_name']) if host is None: deletedHosts.append({'host_name': hostConfig['host_name'], - 'changeMode': CHANGE_MODE_REMOVE}) + CHANGE_MODE: CHANGE_MODE_REMOVE}) return deletedHosts @@ -281,14 +284,14 @@ def findDelta(clusterConfig, ignoredHosts): hostgroup = server_utils.getHostGroup(clusterConfig['hostgroup_name']) if hostgroup is None: - delta['changeMode'] = CHANGE_MODE_ADD + delta[CHANGE_MODE] = CHANGE_MODE_ADD delta['_hosts'] = clusterConfig['_hosts'] return delta hostDelta = findHostDelta(clusterConfig, ignoredHosts) delta['_hosts'] = hostDelta if hostDelta: - delta['changeMode'] = CHANGE_MODE_UPDATE + delta[CHANGE_MODE] = CHANGE_MODE_UPDATE return delta @@ -330,18 +333,18 @@ def cleanConfigDir(dir): #string to get the proper format in mail. def getSummary(clusterDelta): summary = "\nChanges :" - clusterChangeMode = clusterDelta['changeMode'] + clusterChangeMode = clusterDelta[CHANGE_MODE] summary += "\nHostgroup %s - %s" % (clusterDelta['hostgroup_name'], clusterChangeMode) for host in clusterDelta['_hosts']: - if host.get('changeMode'): - changeMode = host.get('changeMode') + if host.get(CHANGE_MODE): + changeMode = host.get(CHANGE_MODE) else: changeMode = clusterChangeMode summary += "\nHost %s - %s" % (host['host_name'], changeMode) - for service in host.get('host_services', []): - if service.get('changeMode'): - changeMode = service.get('changeMode') + for service in host.get(HOST_SERVICES, []): + if service.get(CHANGE_MODE): + changeMode = service.get(CHANGE_MODE) summary += "\n\t Service - %s -%s " % \ (service['service_description'], changeMode) return summary @@ -358,8 +361,8 @@ def formatTextForMail(text): def configureNodes(clusterDelta, nagiosServerAddress, mode, timeout): for host in clusterDelta['_hosts']: #Only when a new node is added or whole cluster is added freshly. - if (clusterDelta.get('changeMode') == CHANGE_MODE_ADD or - host.get('changeMode') == CHANGE_MODE_ADD) \ + if (clusterDelta.get(CHANGE_MODE) == CHANGE_MODE_ADD or + host.get(CHANGE_MODE) == CHANGE_MODE_ADD) \ and (host['use'] == 'gluster-host'): if not nagiosServerAddress: #Nagios server address should be specified as arg in auto mode @@ -388,8 +391,8 @@ def configureNodes(clusterDelta, nagiosServerAddress, mode, timeout): #server address. This is needed for the auto config to configure nodes in #'auto' mode. def updateNagiosAddressInAutoConfig(clusterHostConfig, nagiosServerAddress): - autoConfigService = findServiceInList(clusterHostConfig['host_services'], - "Cluster Auto Config") + autoConfigService = findServiceInList(clusterHostConfig[HOST_SERVICES], + GLUSTER_AUTO_CONFIG) if autoConfigService and nagiosServerAddress: checkCommandParams = autoConfigService['check_command'].split("!") if len(checkCommandParams) == 2: @@ -423,7 +426,7 @@ def writeDelta(clusterDelta, def getNagiosAddress(clusterName): #If there is an auto config service exist for the cluster, then we have #to use the previously entered nagios server address - autoConfigService = server_utils.getServiceConfig("Cluster Auto Config", + autoConfigService = server_utils.getServiceConfig(GLUSTER_AUTO_CONFIG, clusterName) if autoConfigService: nagiosAddress = autoConfigService['check_command'].split("!")[2] @@ -465,8 +468,8 @@ def getConfirmation(message, default): #Send a custom notification about the config changes to admin def sendCustomNotification(cluster, summary): now = datetime.datetime.now() - cmdStr = "[%s] SEND_CUSTOM_SVC_NOTIFICATION;%s;Cluster Auto Config;0;" \ - "Nagios Admin;%s\n" % (now, cluster, summary) + cmdStr = "[%s] SEND_CUSTOM_SVC_NOTIFICATION;%s;%s;0;" \ + "Nagios Admin;%s\n" % (now, cluster, GLUSTER_AUTO_CONFIG, summary) submit_external_command.submitExternalCommand(cmdStr) @@ -504,12 +507,12 @@ if __name__ == '__main__': configManager = getConfigManager(args) clusterDelta = configManager.generateNagiosConfig(clusterdata) if args.force: - clusterDelta['changeMode'] = CHANGE_MODE_ADD + clusterDelta[CHANGE_MODE] = CHANGE_MODE_ADD else: nonConnectedHosts = getAllNonConnectedHosts(clusterdata['hosts']) clusterDelta = findDelta(clusterDelta, nonConnectedHosts) - if clusterDelta.get('changeMode') is None: + if clusterDelta.get(CHANGE_MODE) is None: print "Cluster configurations are in sync" sys.exit(utils.PluginStatusCode.OK) #When auto config is run in manual mode, we will ask confirmation diff --git a/tests/test_config_generator.py b/tests/test_config_generator.py index d2bc2a1..aa9db1b 100644 --- a/tests/test_config_generator.py +++ b/tests/test_config_generator.py @@ -17,6 +17,8 @@ # from plugins import config_generator +from plugins.config_generator import GLUSTER_AUTO_CONFIG +from plugins.config_generator import HOST_SERVICES from glusternagios.glustercli import HostStatus from testrunner import PluginsTestCase as TestCaseBase @@ -49,10 +51,10 @@ class TestGlusterNagiosConfManager(TestCaseBase): def _verifyHostServices(self, hostConfig, hostData): for brick in hostData['bricks']: self._checkServiceExists("Brick - %s" % brick['brickpath'], - hostConfig['host_services']) + hostConfig[HOST_SERVICES]) self._checkServiceExists( "Brick Utilization - %s" % brick['brickpath'], - hostConfig['host_services']) + hostConfig[HOST_SERVICES]) def _verifyClusterConfig(self, config, clusterData): self.assertEqual(config['host_name'], clusterData['name']) @@ -69,17 +71,17 @@ class TestGlusterNagiosConfManager(TestCaseBase): def _verifyClusterServices(self, clusterConfig, clusterData): totalServices = 0 - services = clusterConfig['host_services'] + services = clusterConfig[HOST_SERVICES] self._checkServiceExists("Cluster - Quorum", services) - self._checkServiceExists("Cluster Auto Config", services) + self._checkServiceExists(GLUSTER_AUTO_CONFIG, services) self._checkServiceExists("Cluster Utilization", services) totalServices += 3 for volume in clusterData['volumes']: totalServices += self._verifyVolumeServices( - clusterConfig['host_services'], volume) - self.assertEqual(len(clusterConfig['host_services']), totalServices) + clusterConfig[HOST_SERVICES], volume) + self.assertEqual(len(clusterConfig[HOST_SERVICES]), totalServices) def _verifyVolumeServices(self, serviceList, volume): serviceDesc = 'Volume Utilization - %s' % (volume['name']) diff --git a/tests/test_discovery.py b/tests/test_discovery.py index a3d1347..68d3cbd 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -16,7 +16,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # +from pynag import Model + from plugins import discovery, server_utils +from plugins.config_generator import GLUSTER_AUTO_CONFIG +from plugins.config_generator import HOST_SERVICES +from plugins.config_generator import VOL_NAME +from plugins.config_generator import CHANGE_MODE +from plugins.config_generator import CHANGE_MODE_ADD +from plugins.config_generator import CHANGE_MODE_REMOVE +from plugins.config_generator import CHANGE_MODE_UPDATE +from plugins.config_generator import NOTES from glusternagios.glustercli import HostStatus from testrunner import PluginsTestCase as TestCaseBase @@ -103,3 +113,86 @@ class TestDiscovery(TestCaseBase): clusterName, timeout=None) self._verifyClusterData(clusterdata, clusterName, host) + + def mockFindDeletedServices(self, hostConfig): + return [{'service_description': 'Brick - /bricks/v1-deleted', + CHANGE_MODE: CHANGE_MODE_REMOVE}] + + def mockGetServiceConfig(self, serviceDesc, hostName): + if serviceDesc == 'Brick - /bricks/v1-no-change': + return self.fillServiceModel({'service_description': serviceDesc, + 'host_name': hostName, + 'use': + 'gluster-brick-status-service', + VOL_NAME: 'V1'}) + elif serviceDesc == 'Brick - /bricks/v1-new': + return None + elif serviceDesc == 'Brick - /bricks/v1-update': + return self.fillServiceModel({'service_description': serviceDesc, + 'host_name': hostName, + 'use': + 'gluster-brick-status-service', + VOL_NAME: 'V1', + NOTES: 'Volume Type : Replicate'}) + elif serviceDesc == GLUSTER_AUTO_CONFIG: + return self.fillServiceModel({'service_description': serviceDesc, + 'host_name': hostName, + 'use': 'gluster-service', + 'check_command': + 'gluster_auto_discovery!' + '10.70.43.0!10.70.43.57'}) + + def fillServiceModel(self, values): + serviceModel = Model.Service() + for key, value in values.iteritems(): + serviceModel[key] = value + return serviceModel + + def testFindServiceDelta(self): + server_utils.getServiceConfig = self.mockGetServiceConfig + discovery.findDeletedServices = self.mockFindDeletedServices + serviceDelta = discovery.findServiceDelta(self.getDummyHostConfig()) + self.assertEqual(len(serviceDelta), 4) + service = discovery.findServiceInList( + serviceDelta, 'Brick - /bricks/v1-no-change') + self.assertEqual(service, None) + service = discovery.findServiceInList( + serviceDelta, 'Brick - /bricks/v1-new') + self.assertEqual(service[CHANGE_MODE], CHANGE_MODE_ADD) + service = discovery.findServiceInList( + serviceDelta, 'Brick - /bricks/v1-update') + self.assertEqual(service[CHANGE_MODE], CHANGE_MODE_UPDATE) + self.assertEqual(service[VOL_NAME], 'V2') + service = discovery.findServiceInList( + serviceDelta, 'Brick - /bricks/v1-deleted') + self.assertEqual(service[CHANGE_MODE], CHANGE_MODE_REMOVE) + service = discovery.findServiceInList( + serviceDelta, GLUSTER_AUTO_CONFIG) + self.assertEqual(service[CHANGE_MODE], CHANGE_MODE_UPDATE) + self.assertEqual(service['check_command'], + 'gluster_auto_discovery!10.70.43.57!10.70.43.57') + + def getDummyHostConfig(self): + hostServices = [] + hostServices.append({'service_description': + 'Brick - /bricks/v1-no-change', + 'host_name': 'host-1', + 'use': 'gluster-brick-status-service', + VOL_NAME: 'V1'}) + hostServices.append({'service_description': 'Brick - /bricks/v1-new', + 'host_name': 'host-1', + 'use': 'gluster-brick-status-service', + VOL_NAME: 'V1'}) + hostServices.append({'service_description': + 'Brick - /bricks/v1-update', + 'host_name': 'host-1', + 'use': 'gluster-brick-status-service', + VOL_NAME: 'V2', + NOTES: 'Volume Type : Replicate'}) + hostServices.append({'service_description': GLUSTER_AUTO_CONFIG, + 'host_name': 'host-1', + 'use': 'gluster-service', + 'check_command': + 'gluster_auto_discovery!10.70.43.57!10.70.43.57'}) + hostConfig = {HOST_SERVICES: hostServices} + return hostConfig |