text: # Copyright 2011 Grid Dynamics
  # Copyright 2011 OpenStack Foundation
  # All Rights Reserved.
  #
  #    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 itertools
  import os
  
  from oslo_config import cfg
  import six
  from webob import exc
  
  from nova.api.openstack import common
  from nova.api.openstack import extensions
  from nova.api.openstack import wsgi
  from nova import compute
  from nova.i18n import _
  from nova import utils
  
  ALIAS = "os-fping"
  
  authorize = extensions.os_compute_authorizer(ALIAS)
  
  CONF = cfg.CONF
  CONF.import_opt('fping_path', 'nova.api.openstack.compute.contrib.fping')
  
  
  class FpingController(wsgi.Controller):
  
      def __init__(self, network_api=None):
          self.compute_api = compute.API(skip_policy_check=True)
          self.last_call = {}
  
      def check_fping(self):
          if not os.access(CONF.fping_path, os.X_OK):
              raise exc.HTTPServiceUnavailable(
                  explanation=_("fping utility is not found."))
  
      @staticmethod
      def fping(ips):
          fping_ret = utils.execute(CONF.fping_path, *ips,
                                    check_exit_code=False)
          if not fping_ret:
              return set()
          alive_ips = set()
          for line in fping_ret[0].split("\n"):
              ip = line.split(" ", 1)[0]
              if "alive" in line:
                  alive_ips.add(ip)
          return alive_ips
  
      @staticmethod
      def _get_instance_ips(context, instance):
          ret = []
          for network in common.get_networks_for_instance(
                  context, instance).values():
              all_ips = itertools.chain(network["ips"], network["floating_ips"])
              ret += [ip["address"] for ip in all_ips]
          return ret
  
      @extensions.expected_errors(503)
      def index(self, req):
          context = req.environ["nova.context"]
          search_opts = dict(deleted=False)
          if "all_tenants" in req.GET:
              authorize(context, action='all_tenants')
          else:
              authorize(context)
              if context.project_id:
                  search_opts["project_id"] = context.project_id
              else:
                  search_opts["user_id"] = context.user_id
          self.check_fping()
          include = req.GET.get("include", None)
          if include:
              include = set(include.split(","))
              exclude = set()
          else:
              include = None
              exclude = req.GET.get("exclude", None)
              if exclude:
                  exclude = set(exclude.split(","))
              else:
                  exclude = set()
  
          instance_list = self.compute_api.get_all(
              context, search_opts=search_opts, want_objects=True)
          ip_list = []
          instance_ips = {}
          instance_projects = {}
  
          for instance in instance_list:
              uuid = instance.uuid
              if uuid in exclude or (include is not None and
                                     uuid not in include):
                  continue
              ips = [str(ip) for ip in self._get_instance_ips(context, instance)]
              instance_ips[uuid] = ips
              instance_projects[uuid] = instance.project_id
              ip_list += ips
          alive_ips = self.fping(ip_list)
          res = []
          for instance_uuid, ips in six.iteritems(instance_ips):
              res.append({
                  "id": instance_uuid,
                  "project_id": instance_projects[instance_uuid],
                  "alive": bool(set(ips) & alive_ips),
              })
          return {"servers": res}
  
      @extensions.expected_errors((404, 503))
      def show(self, req, id):
          context = req.environ["nova.context"]
          authorize(context)
          self.check_fping()
          instance = common.get_instance(self.compute_api, context, id)
          ips = [str(ip) for ip in self._get_instance_ips(context, instance)]
          alive_ips = self.fping(ips)
          return {
              "server": {
                  "id": instance.uuid,
                  "project_id": instance.project_id,
                  "alive": bool(set(ips) & alive_ips),
              }
          }
  
  
  class Fping(extensions.V3APIExtensionBase):
      """Fping Management Extension."""
  
      name = "Fping"
      alias = ALIAS
      version = 1
  
      def get_resources(self):
          res = extensions.ResourceExtension(ALIAS, FpingController())
          return [res]
  
      def get_controller_extensions(self):
          return []
  