text: #
  # Copyright 2017 Canonical Ltd
  #
  # 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.
  
  from charmhelpers.fetch import apt_install
  from charmhelpers.contrib.openstack.context import IdentityServiceContext
  from charmhelpers.core.hookenv import (
      log,
      ERROR,
  )
  
  
  def get_api_suffix(api_version):
      """Return the formatted api suffix for the given version
      @param api_version: version of the keystone endpoint
      @returns the api suffix formatted according to the given api
      version
      """
      return 'v2.0' if api_version in (2, "2", "2.0") else 'v3'
  
  
  def format_endpoint(schema, addr, port, api_version):
      """Return a formatted keystone endpoint
      @param schema: http or https
      @param addr: ipv4/ipv6 host of the keystone service
      @param port: port of the keystone service
      @param api_version: 2 or 3
      @returns a fully formatted keystone endpoint
      """
      return '{}://{}:{}/{}/'.format(schema, addr, port,
                                     get_api_suffix(api_version))
  
  
  def get_keystone_manager(endpoint, api_version, **kwargs):
      """Return a keystonemanager for the correct API version
  
      @param endpoint: the keystone endpoint to point client at
      @param api_version: version of the keystone api the client should use
      @param kwargs: token or username/tenant/password information
      @returns keystonemanager class used for interrogating keystone
      """
      if api_version == 2:
          return KeystoneManager2(endpoint, **kwargs)
      if api_version == 3:
          return KeystoneManager3(endpoint, **kwargs)
      raise ValueError('No manager found for api version {}'.format(api_version))
  
  
  def get_keystone_manager_from_identity_service_context():
      """Return a keystonmanager generated from a
      instance of charmhelpers.contrib.openstack.context.IdentityServiceContext
      @returns keystonamenager instance
     """
      context = IdentityServiceContext()()
      if not context:
          msg = "Identity service context cannot be generated"
          log(msg, level=ERROR)
          raise ValueError(msg)
  
      endpoint = format_endpoint(context['service_protocol'],
                                 context['service_host'],
                                 context['service_port'],
                                 context['api_version'])
  
      if context['api_version'] in (2, "2.0"):
          api_version = 2
      else:
          api_version = 3
  
      return get_keystone_manager(endpoint, api_version,
                                  username=context['admin_user'],
                                  password=context['admin_password'],
                                  tenant_name=context['admin_tenant_name'])
  
  
  class KeystoneManager(object):
  
      def resolve_service_id(self, service_name=None, service_type=None):
          """Find the service_id of a given service"""
          services = [s._info for s in self.api.services.list()]
  
          service_name = service_name.lower()
          for s in services:
              name = s['name'].lower()
              if service_type and service_name:
                  if (service_name == name and service_type == s['type']):
                      return s['id']
              elif service_name and service_name == name:
                  return s['id']
              elif service_type and service_type == s['type']:
                  return s['id']
          return None
  
      def service_exists(self, service_name=None, service_type=None):
          """Determine if the given service exists on the service list"""
          return self.resolve_service_id(service_name, service_type) is not None
  
  
  class KeystoneManager2(KeystoneManager):
  
      def __init__(self, endpoint, **kwargs):
          try:
              from keystoneclient.v2_0 import client
              from keystoneclient.auth.identity import v2
              from keystoneclient import session
          except ImportError:
              apt_install(["python3-keystoneclient"], fatal=True)
  
              from keystoneclient.v2_0 import client
              from keystoneclient.auth.identity import v2
              from keystoneclient import session
  
          self.api_version = 2
  
          token = kwargs.get("token", None)
          if token:
              api = client.Client(endpoint=endpoint, token=token)
          else:
              auth = v2.Password(username=kwargs.get("username"),
                                 password=kwargs.get("password"),
                                 tenant_name=kwargs.get("tenant_name"),
                                 auth_url=endpoint)
              sess = session.Session(auth=auth)
              api = client.Client(session=sess)
  
          self.api = api
  
  
  class KeystoneManager3(KeystoneManager):
  
      def __init__(self, endpoint, **kwargs):
          try:
              from keystoneclient.v3 import client
              from keystoneclient.auth import token_endpoint
              from keystoneclient import session
              from keystoneclient.auth.identity import v3
          except ImportError:
              apt_install(["python3-keystoneclient"], fatal=True)
  
              from keystoneclient.v3 import client
              from keystoneclient.auth import token_endpoint
              from keystoneclient import session
              from keystoneclient.auth.identity import v3
  
          self.api_version = 3
  
          token = kwargs.get("token", None)
          if token:
              auth = token_endpoint.Token(endpoint=endpoint,
                                          token=token)
              sess = session.Session(auth=auth)
          else:
              auth = v3.Password(auth_url=endpoint,
                                 user_id=kwargs.get("username"),
                                 password=kwargs.get("password"),
                                 project_id=kwargs.get("tenant_name"))
              sess = session.Session(auth=auth)
  
          self.api = client.Client(session=sess)
  