12. 12. 2019 Valentina Da Rold NetEye, Unified Monitoring

How to Deliver a Service with a Custom Command During IcingaWeb2 Director Deployment: The Case of Shutdown Manager

The NetEye 4.9 release introduced a brand new module called Shutdown Manager. My aim in this blog is not to explain how the Shutdown Manager works, but instead to introduce the logic behind it in order to better explain when you should use it, and how you can deliver a configuration file during Icingaweb2 Director deployment.

The Shutdown Manager module is used for shutting down hosts following a pre-determined order and using a dedicated command. The host is linked to its “Shutdown Command” using a custom variable in the Director module. During Director deployment, a dedicated service with an individualized command is created for each host belonging to the Shutdown Manager (i.e., with a linked Shutdown Command).

To be able to shut down a host, we must ensure that the service and its related command will not change over time. In other words, that you should not be able to update its name or configuration, or accidentally delete them. In addition, we have to deploy them in the zone where the host is defined. In a distributed environment, it’s essential that Director be able to ship some elements of the configuration to specific zones and other elements to a global zone.

What follows is a step-by-step guide for delivering just such a configuration.

  1. The first step is to extend the Icingaweb2 Director ShipConfigFilesHook class. Remember to then add the hook to the run.php file of your module.
    <?php
    
    namespace Icinga\Module\Shutdownmanager\Director;
    
    use Icinga\Module\Director\Hook\ShipConfigFilesHook;
    
    class ShipShutdownServiceConfigFile extends ShipConfigFilesHook
    {
    }
    
  2. You should define the structure of the desired services and command. In the case of the Shutdown Manager module, we had to define a command with an empty command line such as:
    object CheckCommand "shutdown-command" {
        import "plugin-check-command"
        command = [ "" ]
    }
    
    Here’s a service that should run on the Icinga master node:
    object Service "neteye-shutdown-manager-enabled" {
        check_command = "shutdown-command"
        enable_active_checks = false
        enable_passive_checks = true
        host_name = "' . $hostname . '"
    }
    
    And finally, a service that runs on agents. This means that the service should contain the host endpoint:
    object Service "neteye-shutdown-manager-enabled" {
        check_command = "shutdown-command"
        enable_active_checks = false
        enable_passive_checks = true
        host_name = "' . $hostname . '"
        command_endpoint = host_name
    }
    
    Regardless of whether it’s a local service or a remote “Run on Agent” service, the host_name parameter will be dynamically set by the fetchFiles() function below.
  3. Implement the logic that for each host belonging to the shutdownmanager, add the related service writing the service definition to a dedicated file. We want to add a single file for each zone that contains all the service definitions. Director will then create a subdirectory for each Zone it wants to deploy a configuration to. Each one of these files should be saved in the correct zone. Every command is rendered to the global zone by default. For this reason, the command definition should be saved in the director-global directory.
    public function fetchFiles()
    {
        $files = [];
    
        // get all the Shutdownmanager hosts
        $hostsWithCommand = $this->getAllHostsWithShutdownCommand();
    
        // create command file in director-global zone
        $commandZonePath = 'zones.d/director-global/shutdown-manager-command.conf';
        $files[$commandZonePath] = $this->renderShutdownCheckCommandDefinition();
    
        /** @var IcingaHost $host */
        foreach ($hostsWithCommand as $host) {
            // set the correct zone path based on host zone
            $zonePath = sprintf('zones.d/%s/shutdown-manager-services.conf', $host->getRenderingZone());
            // in the case of first service set $files to empty string
            $files = $this->initializeZonePath($zonePath, $files);
    
            $hostVars = (array) $host->getVars();
            /** @var ShutdownCommandModel $command */
            $command = $this->getCommandById($hostVars['shutdown_command']);
    
            if ($command->getRunOnAgent() === 1) {
                $files[$zonePath] .= $this->renderServiceForRunOnAgentHost($host->getObjectName());
            } else {
                $files[$zonePath] .= $this->renderServiceForNotRunOnAgentHost($host->getObjectName());
            }
        }
    
        return $files;
    }
    
  4. Finally, after a successful Director deployment, all your new services will be shown in the monitoring module.
Valentina Da Rold

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Author

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.

Leave a Reply

Your email address will not be published.

Archive