1 # -*- coding: utf-8 -*-
5 from requests.auth import HTTPBasicAuth
10 from django.conf import settings
13 """REST client to SLA Manager.
15 Contains a generic rest client and wrappers over this generic client
18 Each resource client implements business-like() functions, but
19 returns a tuple (output, requests.Response)
21 The resource clients are initialized with the rooturl and a path, which
22 are combined to build the resource url. The path is defaulted to the known
23 resource path. So, for example, to create a agreements client:
25 c = Agreements("http://localhost/slagui-service")
27 A Factory facility is provided to create resource client instances. The
28 Factory uses "rooturl" module variable to use as rooturl parameter.
30 restclient.rooturl = "http://localhost/slagui-service"
31 c = restclient.Factory.agreements()
35 _PROVIDERS_PATH = "providerso"
36 _AGREEMENTS_PATH = "agreementso"
37 _TEMPLATES_PATH = "templateso"
38 _VIOLATIONS_PATH = "violationso"
39 _ENFORCEMENTJOBS_PATH = "enforcements"
41 rooturl = settings.SLA_MANAGER_URL
43 # SLA_MANAGER_USER = "normal_user"
44 # SLA_MANAGER_PASSWORD = "password"
46 class Factory(object):
49 """Returns aREST client for Agreements
53 return Agreements(rooturl)
57 """Returns aREST client for Providers
61 return Providers(rooturl)
65 """Returns aREST client for Violations
69 return Violations(rooturl)
73 """Returns aREST client for Violations
77 return Templates(rooturl)
81 """Returns aREST client for Enforcements jobs
85 return Enforcements(rooturl)
89 def __init__(self, root_url):
91 """Generic rest client using requests library
93 Each operation mimics the corresponding "requests" operation (arguments
96 :param str root_url: this url is used as prefix in all subsequent
99 self.rooturl = root_url
101 def get(self, path, **kwargs):
102 """Just a wrapper over request.get, just in case.
104 Returns a requests.Response
106 :rtype : request.Response
107 :param str path: remaining path from root url;
108 empty if desired path equal to rooturl.
109 :param kwargs: arguments to requests.get
112 c = Client("http://localhost:8080/service")
113 c.get("/resource", headers = { "accept": "application/json" })
115 url = _buildpath_(self.rooturl, path)
116 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
117 result = requests.get(url, **kwargs)
118 print "GET {} {} {}".format(
119 result.url, result.status_code, result.text[0:70])
123 def post(self, path, data=None, **kwargs):
124 """Just a wrapper over request.post, just in case
126 :rtype : request.Response
127 :param str path: remaining path from root url;
128 empty if desired path equal to rooturl.
129 :param dict[str, str] kwargs: arguments to requests.post
132 c = Client("http://localhost:8080/service")
135 '{ "id": "1", "name": "provider-a" }',
137 "content-type": "application/json",
138 "accept": "application/xml"
142 url = _buildpath_(self.rooturl, path)
143 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
144 result = requests.post(url, data, **kwargs)
145 location = result.headers["location"] \
146 if "location" in result.headers else "<null>"
147 print "POST {} {} Location: {}".format(
148 result.url, result.status_code, location)
153 class _Resource(object):
155 def __init__(self, url, converter):
156 """Provides some common operations over resources.
158 The operations return a structured representation of the resource.
160 :param str url: url to the resource
161 :param Converter converter: resouce xml converter
163 Some attributes are initialized to be used from the owner if needed:
164 * client: Client instance
165 * converter: resource xml converter
166 * listconverter: list of resources xml converter
168 self.client = Client(url)
169 self.converter = converter
170 self.listconverter = xmlconverter.ListConverter(self.converter)
173 def _processresult(r, converter):
175 """Generic processing of the REST call.
177 If no errors, tries to convert the result to a destination entity.
180 :param converter Converter:
182 if r.status_code == 404:
185 content_type = r.headers.get('content-type', '')
187 print("content-type = " + content_type)
188 if content_type == 'application/json':
190 elif content_type == 'application/xml':
192 result = xmlconverter.convertstring(converter, xml)
201 r = self.client.get("")
202 resources = self._processresult(r, self.listconverter)
205 def getbyid(self, id):
206 """Get resource 'id'"""
207 r = self.client.get(id)
208 resource = _Resource._processresult(r, self.converter)
211 def get(self, params):
212 """Generic query over resource: GET /resource?q1=v1&q2=v2...
214 :param dict[str,str] params: values to pass as get parameters
216 r = self.client.get("", params=params)
217 resources = self._processresult(r, self.listconverter)
220 def create(self, body, **kwargs):
221 """Creates (POST method) a resource.
223 It should be convenient to set content-type header.
226 resource.create(body, headers={'content-type': 'application/xml'})
228 r = self.client.post("", body, **kwargs)
233 class Agreements(object):
235 def __init__(self, root_url, path=_AGREEMENTS_PATH):
236 """Business methods for Agreement resource
237 :param str root_url: url to the root of resources
238 :param str path: path to resource from root_url
240 The final url to the resource is root_url + "/" + path
242 resourceurl = _buildpath_(root_url, path)
243 converter = xmlconverter.AgreementConverter()
244 self.res = _Resource(resourceurl, converter)
250 :rtype : list[wsag_model.Agreement]
252 return self.res.getall()
254 def getbyid(self, agreementid):
257 :rtype : wsag_model.Agreement
259 return self.res.getbyid(agreementid)
261 def getbyconsumer(self, consumerid):
262 """Get a consumer's agreements
264 :rtype : list[wsag_model.Agreement]
266 return self.res.get(dict(consumerId=consumerid))
268 def getbyprovider(self, providerid):
269 """Get the agreements served by a provider
271 :rtype : list[wsag_model.Agreement]
273 return self.res.get(dict(providerId=providerid))
275 def getstatus(self, agreementid):
276 """Get guarantee status of an agreement
278 :param str agreementid :
279 :rtype : wsag_model.AgreementStatus
281 path = _buildpath_(agreementid, "guaranteestatus")
282 r = self.res.client.get(path, headers={'accept': 'application/json'})
284 print "---- JSON Response ----"
288 print "-- json_obj() --"
292 status = wsag_model.AgreementStatus.json_decode(json_obj)
294 print "---- STATUS ----"
299 def create(self, agreement):
300 """Create a new agreement
302 :param str agreement: sla template in ws-agreement format.
304 return self.res.create(agreement)
306 class Templates(object):
308 def __init__(self, root_url, path=_TEMPLATES_PATH):
309 """Business methods for Templates resource
310 :param str root_url: url to the root of resources
311 :param str path: path to resource from root_url
313 The final url to the resource is root_url + "/" + path
315 resourceurl = _buildpath_(root_url, path)
316 converter = xmlconverter.AgreementConverter()
317 self.res = _Resource(resourceurl, converter)
320 """ Get all templates
322 :rtype : list[wsag_model.Template]
324 return self.res.getall()
326 def getbyid(self, provider_id):
329 :rtype: wsag_model.Template
331 return self.res.getbyid(provider_id)
333 def create(self, template):
334 """Create a new template
336 :param str template: sla template in ws-agreement format.
338 self.res.create(template)
340 class Providers(object):
342 def __init__(self, root_url, path=_PROVIDERS_PATH):
343 """Business methods for Providers resource
344 :param str root_url: url to the root of resources
345 :param str path: path to resource from root_url
347 The final url to the resource is root_url + "/" + path
349 resourceurl = _buildpath_(root_url, path)
350 converter = xmlconverter.ProviderConverter()
351 self.res = _Resource(resourceurl, converter)
354 """ Get all providers
356 :rtype : list[wsag_model.Provider]
358 return self.res.getall()
360 def getbyid(self, provider_id):
363 :rtype: wsag_model.Provider
365 return self.res.getbyid(provider_id)
367 def create(self, provider):
368 """Create a new provider
370 :type provider: wsag_model.Provider
372 body = provider.to_xml()
373 return self.res.create(body)
375 class Violations(object):
377 def __init__(self, root_url, path=_VIOLATIONS_PATH):
378 """Business methods for Violation resource
379 :param str root_url: url to the root of resources
380 :param str path: path to resource from root_url
382 The final url to the resource is root_url + "/" + path
384 resourceurl = _buildpath_(root_url, path)
385 converter = xmlconverter.ViolationConverter()
386 self.res = _Resource(resourceurl, converter)
389 """ Get all violations
390 :rtype : list[wsag_model.Violation]
392 return self.res.getall()
394 def getbyid(self, violationid):
397 :rtype : wsag_model.Violation
399 return self.res.getbyid(violationid)
401 def getbyagreement(self, agreement_id, term=None):
402 """Get the violations of an agreement.
404 :param str agreement_id:
405 :param str term: optional GuaranteeTerm name. If not specified,
406 violations from all terms will be returned
407 :rtype: list[wsag_model.Violation]
410 {"agreementId": agreement_id, "guaranteeTerm": term})
413 class Enforcements(object):
415 def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
416 """Business methods for Violation resource
417 :param str root_url: url to the root of resources
418 :param str path: path to resource from root_url
420 The final url to the resource is root_url + "/" + path
422 resourceurl = _buildpath_(root_url, path)
423 converter = xmlconverter.EnforcementConverter()
424 self.res = _Resource(resourceurl, converter)
427 """ Get all Enforcements
428 :rtype : list[wsag_model.Violation]
430 return self.res.getall()
432 def getbyagreement(self, agreement_id):
433 """Get the enforcement of an agreement.
435 :param str agreement_id:
437 :rtype: list[wsag_model.Enforcement]
439 return self.res.getbyid(agreement_id)
442 def _buildpath_(*paths):
443 return "/".join(paths)
451 rooturl = "http://127.0.0.1:8080/sla-service"
454 c = Factory.templates()
456 #r = c.getbyid("noexiste")
457 #r = c.getstatus("agreement03")
460 #r = c.getbyconsumer('RandomClient')
461 r = c.getbyid("template02")
467 if __name__ == "__main__":