Source code for hcpsdk.mapi.chargeback

# -*- coding: utf-8 -*-
# The MIT License (MIT)
#
# Copyright (c) 2014-2018 Thorsten Simons (sw@snomis.de)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from datetime import datetime, timedelta
from time import strftime
from io import StringIO
import logging
import hcpsdk


__all__ = ['ChargebackError', 'Chargeback']

logging.getLogger('hcpsdk.mapi.chargeback').addHandler(logging.NullHandler())

[docs]class ChargebackError(Exception): """ Base Exception used by the *hcpsdk.mapi.Chargeback()* class. """ def __init__(self, reason): """ :param reason: An error description """ self.args = (reason,)
[docs]class Chargeback(object): ''' Access to HCP chargeback reports ''' # the granularity modes allowed for chargeback collection CBG_DAY = 'day' CBG_HOUR = 'hour' CBG_TOTAL = 'total' CBG_ALL = [CBG_DAY, CBG_HOUR, CBG_TOTAL] # the output formats available CBM_CSV = 'text/csv' CBM_JSON = 'application/json' CBM_XML = 'application/xml' CBM_ALL = [CBM_CSV, CBM_JSON, CBM_XML] def __init__(self, target, timeout=600, debuglevel=0): ''' :param target: an hcpsdk.Target object pointing to an HCP FQDN starting with **admin.** for access from a system level account or **<tenant>.** for a tenant level account :param timeout: the connection timeout; relatively high per default, as generating the report can take longer than **hcpsdk**\ s default of 30 seconds on a busy system :param debuglevel: 0..9 (used in *http.client*) ''' self.logger = logging.getLogger(__name__ + '.Chargeback') hcpsdk.checkport(target, hcpsdk.P_MAPI) self.connect_time = 0.0 self.service_time = 0.0 try: self.con = hcpsdk.Connection(target, timeout=timeout, debuglevel=debuglevel) except Exception as e: raise hcpsdk.HcpsdkError(str(e))
[docs] def request(self, tenant=None, start=None, end=None, granularity=CBG_TOTAL, fmt=CBM_JSON): ''' Request a chargeback report for a Tenant. :param tenant: the *Tenant* to collect from :param start: starttime (a datetime object) :param end: endtime (a datetime object) :param granularity: one out of CBG_ALL :param fmt: output format, one out of CBM_ALL :return: a file-like object in text-mode containing the report ''' if not tenant: raise ValueError('no tenant given') else: self.tenant = tenant if start and type(start) != datetime: raise ValueError('start not of type(datetime.datetime)') else: self.start = start or datetime.now() - timedelta(days=180) if end and type(end) != datetime: raise ValueError('end not of type(datetime.datetime)') else: self.end = end or datetime.now() if granularity not in Chargeback.CBG_ALL: raise ValueError('granularity not in {}' .format(Chargeback.CBG_ALL)) else: self.granularity = granularity if fmt not in Chargeback.CBM_ALL: raise ValueError('fmt not in {}'.format(Chargeback.CBM_ALL)) else: self.fmt = fmt self.logger.debug('request for {} ({} - {}), {}, {}' .format(self.tenant, self.start.isoformat(), self.end.isoformat(), self.granularity, self.fmt)) try: self.con.GET('/mapi/tenants/{}/chargebackReport'.format(self.tenant), params={'start': self.start.strftime('%Y-%m-%dT%H:%M:%S')+strftime('%z'), 'end': self.end.strftime('%Y-%m-%dT%H:%M:%S')+strftime('%z'), 'granularity': self.granularity, 'prettyprint': 'true'}, headers={'Accept': self.fmt}) except Exception as e: self.logger.error(e) raise ChargebackError(e) else: self.logger.debug('result: {} - {}'.format(self.con.response_status, self.con.response_reason)) self.logger.debug('returned headers: {}'.format(self.con.getheaders())) if self.con.response_status == 200: ret = StringIO(initial_value=self.con.read().decode()) ret.seek(0) return ret else: # session cleanup! self.con.read() raise ChargebackError('{} - {} ({})' .format(self.con.response_status, self.con.response_reason, self.con.getheader('X-HCP-ErrorMessage', default='?')))
[docs] def close(self): ''' Close the underlying *hcpsdk.Connection* object. ''' self.con.close()