zabbix_export:
  version: '6.0'
  date: '2023-07-07T13:30:27Z'
  groups:
    - uuid: c2c162144c2d4c5491c8801193af4945
      name: Templates/Cloud
    - uuid: 137f19e6e2dc4219b33553b812627bc2
      name: 'Virtual machines'
  templates:
    - uuid: 4e3fb27f028e4c35b8c9fc43b11c07d7
      template: 'OpenStack by HTTP'
      name: 'OpenStack by HTTP'
      description: |
        Requests OpenStack API access token and discovers available OpenStack services using OpenStack Identity API by HTTP using script item and creates host prototypes for them.
        
        Template uses OpenStack application credentials for authorization.
        
        Zabbix currently supports OpenStack Nova service.
        
        Read the template documentation prior to using this template.
        
        You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
        
        Generated by official Zabbix template tool "Templator" 2.0.0
      groups:
        - name: Templates/Cloud
      items:
        - uuid: 0518d08edbf2480abf15f4ef0e7a251a
          name: 'OpenStack: Get access token and service catalog'
          type: SCRIPT
          key: openstack.identity.auth
          delay: '{$OPENSTACK.AUTH.INTERVAL}'
          history: '0'
          trends: '0'
          value_type: TEXT
          params: |
            // Script for authenticating, receiving API token and supported service catalog from OpenStack Identity service.
            
            const request_path = '/v3/auth/tokens';
            
            function checkParams(params) {
                ['api_url', 'app_cred_id', 'app_cred_secret'].forEach(function (field) {
                    if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
                        throw 'Required param is not set: ' + field + '.';
                    }
                });
                return params;
            }
            
            function getHttpData(url, params, app_cred_id, app_cred_secret) {
                const request = new HttpRequest();
            
                request.addHeader('Content-Type: application/json');
            
                // use correct format for authenticating with application credential
                const request_body = {
                    "auth": {
                        "identity": {
                            "methods": [
                                "application_credential"
                            ],
                            "application_credential": {
                                "id": app_cred_id,
                                "secret": app_cred_secret
                            }
                        }
                    }
                };
            
                // set proxy if needed
                if (params['http_proxy']) {
                    request.setProxy(params['http_proxy'])
                    Zabbix.log(4, '[ Openstack Nova API ] Using http proxy: ' + params['http_proxy']);
                }
            
                const response = request.post(url, JSON.stringify(request_body));
                Zabbix.log(4, '[ Openstack Identity API ] [ ' + url + ' ] Received response with status code ' + request.getStatus() + ': ' + response);
            
                // check if request status is OK
                if (request.getStatus() !== 201) {
                    if (typeof (response.error && response.error.message) !== 'undefined') {
                        throw response.error.message;
                    } else {
                        throw 'Failed to receive data: invalid response status code. Check debug log for more information.';
                    }
                }
            
                // return a list with request and response objects
                return {'request': request, 'response': response};
            }
            
            function parseHttpData(http_data) {
                // parse header and check if it is valid
                var token;
                const headers = http_data['request'].getHeaders(true);
                if (typeof headers === "object") {
                    if (headers !== null) {
                        try {
                            token = headers["X-Subject-Token"][0]; // save received token
                        } catch (error) {
                            throw 'Failed to parse response received from OpenStack Identity API. Check debug log for more information.';
                        }
                    } else {
                        throw 'Response object is empty. Check debug log for more information.';
                    }
                } else {
                    throw 'Cannot process response data: received data is not an object. Check debug log for more information.';
                }
            
                // define supported OpenStack services in Zabbix
                const supported_services = ['nova'];
            
                // parse the response body and filter out only the services supported by Zabbix with the needed data only
                var ret = [];
                const data = JSON.parse(http_data['response']);
                // check if service catalog exists
                if (data['token']['catalog']) {
                    const service_catalog = data['token']['catalog'];
                } else {
                    throw 'Cannot find service catalog in HTTP response.'
                }
            
                service_catalog.forEach(function (service) {                // loop through service catalog
                    if (supported_services.indexOf(service.name) > -1) {    // check if service is supported by Zabbix
                        service.endpoints.forEach(function (endpoint) {     // loop through each endpoint for catalog
                            if (endpoint.interface === 'public') {          // check if service has a public interface
                                ret.push({                                  // if true, save service name, service url and token
                                    'service_name': service.name[0].toUpperCase() + service.name.slice(1),  // capitalize first char in service_name
                                    'service_url': endpoint.url,
                                    'token': token
                                });
                            }
                        })
                    }
                });
            
                // return list of dictionaries of service name, url and access token
                return JSON.stringify(ret);
            }
            
            const params = checkParams(JSON.parse(value)),
                url = params.api_url,
                auth_cred_id = params.app_cred_id,
                auth_cred_secret = params.app_cred_secret;
            
            const httpData = getHttpData(url + request_path, params, auth_cred_id, auth_cred_secret);
            return parseHttpData(httpData);
          description: 'Authorizes user on the OpenStack Identity service and gets the service catalog.'
          timeout: 10s
          parameters:
            - name: api_url
              value: '{$OPENSTACK.KEYSTONE.API.ENDPOINT}'
            - name: app_cred_id
              value: '{$OPENSTACK.APP.CRED.ID}'
            - name: app_cred_secret
              value: '{$OPENSTACK.APP.CRED.SECRET}'
            - name: http_proxy
              value: '{$OPENSTACK.HTTP.PROXY}'
          tags:
            - tag: component
              value: raw
      discovery_rules:
        - uuid: f827e364d7bd4013b02504a58fdc2d39
          name: 'OpenStack: Nova discovery'
          type: DEPENDENT
          key: openstack.services.nova.discovery
          delay: '0'
          filter:
            conditions:
              - macro: '{#SERVICE_NAME}'
                value: ^Nova$
                formulaid: A
          description: 'Discovers OpenStack services from the monitoring user''s services catalog.'
          host_prototypes:
            - uuid: 580d769292ec48379c5b84cd5c72533b
              host: 'OpenStack {#SERVICE_NAME}'
              name: 'OpenStack {#SERVICE_NAME}'
              group_links:
                - group:
                    name: 'Virtual machines'
              templates:
                - name: 'OpenStack Nova by HTTP'
              macros:
                - macro: '{$OPENSTACK.NOVA.SERVICE.URL}'
                  value: '{#SERVICE_URL}'
                  description: 'OpenStack Nova service path.'
                - macro: '{$OPENSTACK.TOKEN}'
                  type: SECRET_TEXT
                  description: 'OpenStack authorization token.'
          master_item:
            key: openstack.identity.auth
          lld_macro_paths:
            - lld_macro: '{#SERVICE_NAME}'
              path: $.service_name
            - lld_macro: '{#SERVICE_URL}'
              path: $.service_url
            - lld_macro: '{#TOKEN}'
              path: $.token
      tags:
        - tag: class
          value: cloud
        - tag: target
          value: openstack
      macros:
        - macro: '{$OPENSTACK.APP.CRED.ID}'
          description: 'Application credential ID for monitoring user access.'
        - macro: '{$OPENSTACK.APP.CRED.SECRET}'
          type: SECRET_TEXT
          description: 'Application credential password for monitoring user access.'
        - macro: '{$OPENSTACK.AUTH.INTERVAL}'
          value: 50m
          description: 'API token regeneration interval, in minutes. By default, OpenStack API tokens expire after 60m.'
        - macro: '{$OPENSTACK.HTTP.PROXY}'
          description: 'Sets the HTTP proxy for the authorization item. Host prototypes will also use this value for HTTP proxy. If this parameter is empty, then no proxy is used.'
        - macro: '{$OPENSTACK.KEYSTONE.API.ENDPOINT}'
          description: 'API endpoint for Identity Service, e.g., https://local.openstack:5000.'
