¡@

Home 

OpenStack Study: ncc_client.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2014 Citrix Systems

#

# 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 base64

import requests

from neutron.common import exceptions as n_exc

from neutron.openstack.common import jsonutils

from neutron.openstack.common import log as logging

LOG = logging.getLogger(__name__)

CONTENT_TYPE_HEADER = 'Content-type'

ACCEPT_HEADER = 'Accept'

AUTH_HEADER = 'Authorization'

DRIVER_HEADER = 'X-OpenStack-LBaaS'

TENANT_HEADER = 'X-Tenant-ID'

JSON_CONTENT_TYPE = 'application/json'

DRIVER_HEADER_VALUE = 'netscaler-openstack-lbaas'

**** CubicPower OpenStack Study ****

class NCCException(n_exc.NeutronException):

"""Represents exceptions thrown by NSClient."""

CONNECTION_ERROR = 1

REQUEST_ERROR = 2

RESPONSE_ERROR = 3

UNKNOWN_ERROR = 4

**** CubicPower OpenStack Study ****

    def __init__(self, error):

        self.message = _("NCC Error %d") % error

        super(NCCException, self).__init__()

        self.error = error

**** CubicPower OpenStack Study ****

class NSClient(object):

"""Client to operate on REST resources of NetScaler Control Center."""

**** CubicPower OpenStack Study ****

    def __init__(self, service_uri, username, password):

        if not service_uri:

            msg = _("No NetScaler Control Center URI specified. "

                    "Cannot connect.")

            LOG.exception(msg)

            raise NCCException(NCCException.CONNECTION_ERROR)

        self.service_uri = service_uri.strip('/')

        self.auth = None

        if username and password:

            base64string = base64.encodestring("%s:%s" % (username, password))

            base64string = base64string[:-1]

            self.auth = 'Basic %s' % base64string

**** CubicPower OpenStack Study ****

    def create_resource(self, tenant_id, resource_path, object_name,

                        object_data):

        """Create a resource of NetScaler Control Center."""

        return self._resource_operation('POST', tenant_id,

                                        resource_path,

                                        object_name=object_name,

                                        object_data=object_data)

**** CubicPower OpenStack Study ****

    def retrieve_resource(self, tenant_id, resource_path, parse_response=True):

        """Retrieve a resource of NetScaler Control Center."""

        return self._resource_operation('GET', tenant_id, resource_path)

**** CubicPower OpenStack Study ****

    def update_resource(self, tenant_id, resource_path, object_name,

                        object_data):

        """Update a resource of the NetScaler Control Center."""

        return self._resource_operation('PUT', tenant_id,

                                        resource_path,

                                        object_name=object_name,

                                        object_data=object_data)

**** CubicPower OpenStack Study ****

    def remove_resource(self, tenant_id, resource_path, parse_response=True):

        """Remove a resource of NetScaler Control Center."""

        return self._resource_operation('DELETE', tenant_id, resource_path)

**** CubicPower OpenStack Study ****

    def _resource_operation(self, method, tenant_id, resource_path,

                            object_name=None, object_data=None):

        resource_uri = "%s/%s" % (self.service_uri, resource_path)

        headers = self._setup_req_headers(tenant_id)

        request_body = None

        if object_data:

            if isinstance(object_data, str):

                request_body = object_data

            else:

                obj_dict = {object_name: object_data}

                request_body = jsonutils.dumps(obj_dict)

        response_status, resp_dict = self._execute_request(method,

                                                           resource_uri,

                                                           headers,

                                                           body=request_body)

        return response_status, resp_dict

**** CubicPower OpenStack Study ****

    def _is_valid_response(self, response_status):

        # when status is less than 400, the response is fine

        return response_status < requests.codes.bad_request

**** CubicPower OpenStack Study ****

    def _setup_req_headers(self, tenant_id):

        headers = {ACCEPT_HEADER: JSON_CONTENT_TYPE,

                   CONTENT_TYPE_HEADER: JSON_CONTENT_TYPE,

                   DRIVER_HEADER: DRIVER_HEADER_VALUE,

                   TENANT_HEADER: tenant_id,

                   AUTH_HEADER: self.auth}

        return headers

**** CubicPower OpenStack Study ****

    def _get_response_dict(self, response):

        response_dict = {'status': response.status_code,

                         'body': response.text,

                         'headers': response.headers}

        if self._is_valid_response(response.status_code):

            if response.text:

                response_dict['dict'] = response.json()

        return response_dict

**** CubicPower OpenStack Study ****

    def _execute_request(self, method, resource_uri, headers, body=None):

        try:

            response = requests.request(method, url=resource_uri,

                                        headers=headers, data=body)

        except requests.exceptions.ConnectionError:

            msg = (_("Connection error occurred while connecting to %s") %

                   self.service_uri)

            LOG.exception(msg)

            raise NCCException(NCCException.CONNECTION_ERROR)

        except requests.exceptions.SSLError:

            msg = (_("SSL error occurred while connecting to %s") %

                   self.service_uri)

            LOG.exception(msg)

            raise NCCException(NCCException.CONNECTION_ERROR)

        except requests.exceptions.Timeout:

            msg = _("Request to %s timed out") % self.service_uri

            LOG.exception(msg)

            raise NCCException(NCCException.CONNECTION_ERROR)

        except (requests.exceptions.URLRequired,

                requests.exceptions.InvalidURL,

                requests.exceptions.MissingSchema,

                requests.exceptions.InvalidSchema):

            msg = _("Request did not specify a valid URL")

            LOG.exception(msg)

            raise NCCException(NCCException.REQUEST_ERROR)

        except requests.exceptions.TooManyRedirects:

            msg = _("Too many redirects occurred for request to %s")

            LOG.exception(msg)

            raise NCCException(NCCException.REQUEST_ERROR)

        except requests.exceptions.RequestException:

            msg = (_("A request error while connecting to %s") %

                   self.service_uri)

            LOG.exception(msg)

            raise NCCException(NCCException.REQUEST_ERROR)

        except Exception:

            msg = (_("A unknown error occurred during request to %s") %

                   self.service_uri)

            LOG.exception(msg)

            raise NCCException(NCCException.UNKNOWN_ERROR)

        resp_dict = self._get_response_dict(response)

        LOG.debug(_("Response: %s"), resp_dict['body'])

        response_status = resp_dict['status']

        if response_status == requests.codes.unauthorized:

            LOG.exception(_("Unable to login. Invalid credentials passed."

                          "for: %s"), self.service_uri)

            raise NCCException(NCCException.RESPONSE_ERROR)

        if not self._is_valid_response(response_status):

            msg = (_("Failed %(method)s operation on %(url)s "

                   "status code: %(response_status)s") %

                   {"method": method,

                    "url": resource_uri,

                    "response_status": response_status})

            LOG.exception(msg)

            raise NCCException(NCCException.RESPONSE_ERROR)

        return response_status, resp_dict