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 = "providers"
36 _AGREEMENTS_PATH = "agreements"
37 _TEMPLATES_PATH = "templates"
38 _VIOLATIONS_PATH = "violations"
39 _ENFORCEMENTJOBS_PATH = "enforcements"
41 rooturl = settings.SLA_MANAGER_URL
44 class Factory(object):
46 def agreements(path=_AGREEMENTS_PATH):
47 """Returns a REST client for Agreements
51 return Agreements(rooturl, path)
55 """Returns a REST client for Providers
59 return Providers(rooturl)
63 """Returns a REST client for Violations
67 return Violations(rooturl)
71 """Returns a REST client for Violations
75 return Templates(rooturl)
79 """Returns a REST client for Enforcements jobs
83 return Enforcements(rooturl)
88 def __init__(self, root_url):
90 """Generic rest client using requests library
92 Each operation mimics the corresponding "requests" operation (arguments
95 :param str root_url: this url is used as prefix in all subsequent
98 self.rooturl = root_url
100 def get(self, path, **kwargs):
101 """Just a wrapper over request.get, just in case.
103 Returns a requests.Response
105 :rtype : request.Response
106 :param str path: remaining path from root url;
107 empty if desired path equal to rooturl.
108 :param kwargs: arguments to requests.get
111 c = Client("http://localhost:8080/service")
112 c.get("/resource", headers = { "accept": "application/json" })
114 url = _buildpath_(self.rooturl, path)
115 if "testbed" in kwargs:
116 url = url + "?testbed=" + kwargs["testbed"]
118 if "headers" not in kwargs:
119 kwargs["headers"] = {"accept": "application/xml"}
121 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
122 settings.SLA_MANAGER_PASSWORD)
124 # for key, values in kwargs.iteritems():
127 result = requests.get(url, **kwargs)
128 print "GET {} {} {}".format(
129 result.url, result.status_code, result.text[0:70])
130 print result.encoding
134 def post(self, path, data=None, **kwargs):
135 """Just a wrapper over request.post, just in case
137 :rtype : request.Response
138 :param str path: remaining path from root url;
139 empty if desired path equal to rooturl.
140 :param dict[str, str] kwargs: arguments to requests.post
143 c = Client("http://localhost:8080/service")
146 '{ "id": "1", "name": "provider-a" }',
148 "content-type": "application/json",
149 "accept": "application/xml"
153 url = _buildpath_(self.rooturl, path)
155 if "testbed" in kwargs:
156 url = url + "?testbed=" + kwargs["testbed"]
158 if "headers" not in kwargs:
159 kwargs["headers"] = {"accept": "application/xml",
160 "content-type": "application/xml"}
162 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
163 settings.SLA_MANAGER_PASSWORD)
165 result = requests.post(url, data, **kwargs)
166 location = result.headers["location"] \
167 if "location" in result.headers else "<null>"
168 print "POST {} {} Location: {}".format(
169 result.url, result.status_code, location)
173 class _Resource(object):
175 def __init__(self, url, converter):
176 """Provides some common operations over resources.
178 The operations return a structured representation of the resource.
180 :param str url: url to the resource
181 :param Converter converter: resouce xml converter
183 Some attributes are initialized to be used from the owner if needed:
184 * client: Client instance
185 * converter: resource xml converter
186 * listconverter: list of resources xml converter
188 self.client = Client(url)
189 self.converter = converter
190 self.listconverter = xmlconverter.ListConverter(self.converter)
193 def _processresult(r, converter):
195 """Generic processing of the REST call.
197 If no errors, tries to convert the result to a destination entity.
200 :param converter Converter:
202 if r.status_code == 404:
205 content_type = r.headers.get('content-type', '')
207 #print("content-type = " + content_type)
208 if content_type == 'application/json':
210 elif content_type == 'application/xml':
212 result = xmlconverter.convertstring(converter, xml)
221 r = self.client.get("")
222 resources = self._processresult(r, self.listconverter)
225 def getbyid(self, id, params):
226 """Get resource 'id'"""
227 r = self.client.get(id, params=params)
228 resource = _Resource._processresult(r, self.converter)
231 def get(self, path, params):
232 """Generic query over resource: GET /resource?q1=v1&q2=v2...
234 :param dict[str,str] params: values to pass as get parameters
239 r = self.client.get(path, params=params)
240 resources = self._processresult(r, self.listconverter)
243 def create(self, body, **kwargs):
244 """Creates (POST method) a resource.
246 It should be convenient to set content-type header.
249 resource.create(body, headers={'content-type': 'application/xml'})
251 r = self.client.post("", body, **kwargs)
256 class Agreements(object):
258 def __init__(self, root_url, path=_AGREEMENTS_PATH):
259 """Business methods for Agreement resource
260 :param str root_url: url to the root of resources
261 :param str path: path to resource from root_url
263 The final url to the resource is root_url + "/" + path
265 resourceurl = _buildpath_(root_url, path)
266 converter = xmlconverter.AgreementConverter()
267 self.res = _Resource(resourceurl, converter)
273 :rtype : list[wsag_model.Agreement]
275 return self.res.getall()
277 def getbyid(self, agreementid):
280 :rtype : wsag_model.Agreement
282 return self.res.getbyid(agreementid)
284 def getbyconsumer(self, consumerid):
285 """Get a consumer's agreements
287 :rtype : list[wsag_model.Agreement]
289 return self.res.get(dict(consumerId=consumerid))
291 def getbyprovider(self, providerid):
292 """Get the agreements served by a provider
294 :rtype : list[wsag_model.Agreement]
296 return self.res.get(dict(providerId=providerid))
298 def getstatus(self, agreementid, testbed):
299 """Get guarantee status of an agreement
301 :param str agreementid :
302 :rtype : wsag_model.AgreementStatus
304 path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
305 r = self.res.client.get(path, headers={'accept': 'application/json'},
306 params={'testbed': testbed})
310 status = wsag_model.AgreementStatus.json_decode(json_obj)
314 def getbyslice(self, slicename):
315 """Get the agreements corresponding to a slice
317 :rtype : list[wsag_model.Agreement]
319 return self.res.get(slicename, dict())
321 def create(self, agreement, testbed):
322 """Create a new agreement
324 :param str agreement: sla template in ws-agreement format.
326 return self.res.create(agreement, params={'testbed': testbed})
329 class Templates(object):
331 def __init__(self, root_url, path=_TEMPLATES_PATH):
332 """Business methods for Templates resource
333 :param str root_url: url to the root of resources
334 :param str path: path to resource from root_url
336 The final url to the resource is root_url + "/" + path
338 resourceurl = _buildpath_(root_url, path)
339 converter = xmlconverter.AgreementConverter()
340 self.res = _Resource(resourceurl, converter)
343 """ Get all templates
345 :rtype : list[wsag_model.Template]
347 return self.res.getall()
349 def getbyid(self, provider_id):
352 :rtype: wsag_model.Template
354 return self.res.getbyid(provider_id, {"testbed": provider_id})
356 def create(self, template):
357 """Create a new template
359 :param str template: sla template in ws-agreement format.
361 self.res.create(template)
364 class Providers(object):
366 def __init__(self, root_url, path=_PROVIDERS_PATH):
367 """Business methods for Providers resource
368 :param str root_url: url to the root of resources
369 :param str path: path to resource from root_url
371 The final url to the resource is root_url + "/" + path
373 resourceurl = _buildpath_(root_url, path)
374 converter = xmlconverter.ProviderConverter()
375 self.res = _Resource(resourceurl, converter)
378 """ Get all providers
380 :rtype : list[wsag_model.Provider]
382 return self.res.getall()
384 def getbyid(self, provider_id):
387 :rtype: wsag_model.Provider
389 return self.res.getbyid(provider_id)
391 def create(self, provider):
392 """Create a new provider
394 :type provider: wsag_model.Provider
396 body = provider.to_xml()
397 return self.res.create(body)
400 class Violations(object):
402 def __init__(self, root_url, path=_VIOLATIONS_PATH):
403 """Business methods for Violation resource
404 :param str root_url: url to the root of resources
405 :param str path: path to resource from root_url
407 The final url to the resource is root_url + "/" + path
409 resourceurl = _buildpath_(root_url, path)
410 converter = xmlconverter.ViolationConverter()
411 self.res = _Resource(resourceurl, converter)
414 """ Get all violations
415 :rtype : list[wsag_model.Violation]
417 return self.res.getall()
419 def getbyid(self, violationid):
422 :rtype : wsag_model.Violation
424 return self.res.getbyid(violationid)
426 def getbyagreement(self, agreement_id, testbed, term=None):
427 """Get the violations of an agreement.
429 :param str agreement_id:
430 :param str term: optional GuaranteeTerm name. If not specified,
431 violations from all terms will be returned
432 :rtype: list[wsag_model.Violation]
434 return self.res.get("", params={"agreementId": agreement_id,
435 "guaranteeTerm": term,
439 class Enforcements(object):
441 def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
442 """Business methods for Violation resource
443 :param str root_url: url to the root of resources
444 :param str path: path to resource from root_url
446 The final url to the resource is root_url + "/" + path
448 resourceurl = _buildpath_(root_url, path)
449 converter = xmlconverter.EnforcementConverter()
450 self.res = _Resource(resourceurl, converter)
453 """ Get all Enforcements
454 :rtype : list[wsag_model.Violation]
456 return self.res.getall()
458 def getbyagreement(self, agreement_id, testbed):
459 """Get the enforcement of an agreement.
461 :param str agreement_id:
463 :rtype: list[wsag_model.Enforcement]
465 return self.res.getbyid(agreement_id, params={"testbed": testbed})
468 def _buildpath_(*paths):
470 paths = [path for path in paths if path != ""]
472 return "/".join(paths)
480 rooturl = "http://127.0.0.1:8080/sla-service"
482 c = Factory.templates()
484 #r = c.getbyid("noexiste")
485 #r = c.getstatus("agreement03")
488 #r = c.getbyconsumer('RandomClient')
489 r = c.getbyid("template02")
494 if __name__ == "__main__":