anchor.diff:                                        "password" (password ,os-c)))))))))
        ,@body))
   
  -(defun make-credential (hostname username password &optional tenant-name)
  -  "Makes and returns a new instant of os-credential class."
  -  (make-instance 'os-credential
  +;;; User's OpenStack credential payload object
  +
  +(defclass openstack-credential ()
  +  ((keystone-hostname :initarg :keystone-hostname
  +                      :reader keystone-hostname)
  +   (username :initarg :username
  +             :reader username)
  +   (password :initarg :password
  +             :reader password)
  +   (tenant-name :initarg :tenant-name
  +                :initform nil
  +                :accessor tenant-name))
  +  (:documentation "An OpenStack credential payload, with all the
  +necessary information to authenticate a user.
  +
  +Requires a hostname of the Keystone identity service, a username, and
  +a password. The tenant-name is an optional argument that will default
  +to username if not provided."))
  +
  +(defun make-openstack-credential (hostname username password &optional tenant-name)
  +  "Makes and returns a new instant of OpenStack credential class."
  +  (make-instance 'openstack-credential
                    :keystone-hostname hostname
                    :username username
                    :password password
                    :tenant-name tenant-name))
   
  -(defclass connection ()
  +;;; OpenStack authentication token object
  +
  +(defclass openstack-token ()
     ((credential :initarg :credential
                  :reader credential)
  -   (service-endpoints :accessor service-endpoints)
      (token :accessor token)
      (token-expiration-time :accessor token-expiration-time))
  -  (:documentation "A connection object containing the currently active
  -service endpoints as well as an authentication token along with all
  -the necessary information to reacquire the token once it expires.
  +  (:documentation "An OpenStack token object containing an
  +authentication token along with all the necessary information to
  +reacquire the token once it expires.
   
   Only requires an instant of user credential payload, other slots will
   be initialized when we instantiate the object."))
   
  -(defmethod initialize-instance :after ((conn connection) &key)
  +(defmethod initialize-instance :after ((token openstack-token) &key)
     "Uses an instant of user credential payload to authenticate and
  -retrieve the currently active service endpoints, a token and its
  -expiration time, then store three of them into their respective
  -slots."
  -  (with-accessors ((os-c credential) (endpoints service-endpoints) (token token)
  -                   (token-expiration-time token-expiration-time)) conn
  +retrieve a token and its expiration time, then stores them into their
  +respective slots.
  +
  +Also retrieves currently active service catalog endpoints, parses them
  +into an alist map, and binds the alist map to the global special
  +variable."
  +  (with-accessors ((os-c credential) (token token)
  +                   (token-expiration-time token-expiration-time)) token
       (with-keystone-response response (os-c)
         (let* ((access-jso (st-json:getjso "access" (st-json:read-json response)))
                (token-jso (st-json:getjso "token" access-jso))
                (service-catalog-jso (st-json:getjso "serviceCatalog" access-jso)))
  -        (setf endpoints (parse-endpoints service-catalog-jso))
           (setf token (st-json:getjso "id" token-jso))
           (setf token-expiration-time
  -              (local-time:parse-timestring (st-json:getjso "expires" token-jso)))))))
  +              (local-time:parse-timestring (st-json:getjso "expires" token-jso)))
  +        (setf *service-catalog* (parse-endpoints service-catalog-jso))))))
   
  -(defmethod token :before ((conn connection))
  +(defmethod token :before ((token openstack-token))
     "Before reading a value of the token's slot, check if it has already
   expired. If it does, then uses the credential payload to
   re-authenticate and reacquire the token."
     (with-accessors ((os-c credential) (token token)
  -                   (token-expiration-time token-expiration-time)) conn
  +                   (token-expiration-time token-expiration-time)) token
       (when (local-time:timestamp>= (local-time:now) token-expiration-time)
         (with-keystone-response response (os-c)
           (let ((token-jso (st-json:getjso
  
positive.code: 
  ;;; Bindings for OpenStack Keystone identity API are defined here
  
  ;;; Helper functions
  
  (defun parse-endpoints (service-catalog-jso)
    "Parses a JSON containing currently active service endpoints."
    (mapcar
     #'(lambda (jso)
         (cons (st-json:getjso "name" jso)
  
negative.code:           (setf token-expiration-time
                  (local-time:parse-timestring (st-json:getjso "expires" token-jso))))))))
  
  (defun make-openstack-token (keystone-hostname username password &optional tenant-name)
    "Creates and returns a new instant of the OpenStack token object."
    (let ((os-c (make-openstack-credential keystone-hostname
                                           username
                                           password
                                           tenant-name)))
      (make-instance 'openstack-token :credential os-c)))
  
  (defun authenticate (keystone-hostname username password &optional tenant-name)
    "Authenticates a user, and initializes the default global special
  variables."
    (setf *openstack-token*
          (make-openstack-token keystone-hostname username password tenant-name)))
  