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):
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"]
117 #kwargs['params']['testbed'] = 'iminds'
119 if "headers" not in kwargs:
120 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)
154 url = url + "?testbed=iminds" # TODO remove hardcoded string
155 # kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
156 # settings.SLA_MANAGER_PASSWORD)
157 if "headers" not in kwargs:
158 kwargs = {"accept": "application/xml",
159 "content-type": "application/xml"}
160 result = requests.post(url, data, **kwargs)
161 location = result.headers["location"] \
162 if "location" in result.headers else "<null>"
163 print "POST {} {} Location: {}".format(
164 result.url, result.status_code, location)
168 class _Resource(object):
170 def __init__(self, url, converter):
171 """Provides some common operations over resources.
173 The operations return a structured representation of the resource.
175 :param str url: url to the resource
176 :param Converter converter: resouce xml converter
178 Some attributes are initialized to be used from the owner if needed:
179 * client: Client instance
180 * converter: resource xml converter
181 * listconverter: list of resources xml converter
183 self.client = Client(url)
184 self.converter = converter
185 self.listconverter = xmlconverter.ListConverter(self.converter)
188 def _processresult(r, converter):
190 """Generic processing of the REST call.
192 If no errors, tries to convert the result to a destination entity.
195 :param converter Converter:
197 if r.status_code == 404:
200 content_type = r.headers.get('content-type', '')
202 #print("content-type = " + content_type)
203 if content_type == 'application/json':
205 elif content_type == 'application/xml':
207 result = xmlconverter.convertstring(converter, xml)
216 r = self.client.get("")
217 resources = self._processresult(r, self.listconverter)
220 def getbyid(self, id, params):
221 """Get resource 'id'"""
222 r = self.client.get(id, params=params)
223 resource = _Resource._processresult(r, self.converter)
226 def get(self, path, params):
227 """Generic query over resource: GET /resource?q1=v1&q2=v2...
229 :param dict[str,str] params: values to pass as get parameters
234 r = self.client.get(path, params=params)
235 resources = self._processresult(r, self.listconverter)
238 def create(self, body, **kwargs):
239 """Creates (POST method) a resource.
241 It should be convenient to set content-type header.
244 resource.create(body, headers={'content-type': 'application/xml'})
246 r = self.client.post("", body, **kwargs)
251 class Agreements(object):
253 def __init__(self, root_url, path=_AGREEMENTS_PATH):
254 """Business methods for Agreement resource
255 :param str root_url: url to the root of resources
256 :param str path: path to resource from root_url
258 The final url to the resource is root_url + "/" + path
260 resourceurl = _buildpath_(root_url, path)
261 converter = xmlconverter.AgreementConverter()
262 self.res = _Resource(resourceurl, converter)
268 :rtype : list[wsag_model.Agreement]
270 return self.res.getall()
272 def getbyid(self, agreementid):
275 :rtype : wsag_model.Agreement
277 return self.res.getbyid(agreementid)
279 def getbyconsumer(self, consumerid):
280 """Get a consumer's agreements
282 :rtype : list[wsag_model.Agreement]
284 return self.res.get(dict(consumerId=consumerid))
286 def getbyprovider(self, providerid):
287 """Get the agreements served by a provider
289 :rtype : list[wsag_model.Agreement]
291 return self.res.get(dict(providerId=providerid))
293 def getstatus(self, agreementid, testbed):
294 """Get guarantee status of an agreement
296 :param str agreementid :
297 :rtype : wsag_model.AgreementStatus
299 path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
300 r = self.res.client.get(path, headers={'accept': 'application/json'},
301 params={'testbed': testbed})
305 status = wsag_model.AgreementStatus.json_decode(json_obj)
309 def getbyslice(self, slicename):
310 """Get the agreements corresponding to a slice
312 :rtype : list[wsag_model.Agreement]
314 return self.res.get(slicename, dict())
316 def create(self, agreement):
317 """Create a new agreement
319 :param str agreement: sla template in ws-agreement format.
321 return self.res.create(agreement)
324 class Templates(object):
326 def __init__(self, root_url, path=_TEMPLATES_PATH):
327 """Business methods for Templates resource
328 :param str root_url: url to the root of resources
329 :param str path: path to resource from root_url
331 The final url to the resource is root_url + "/" + path
333 resourceurl = _buildpath_(root_url, path)
334 converter = xmlconverter.AgreementConverter()
335 self.res = _Resource(resourceurl, converter)
338 """ Get all templates
340 :rtype : list[wsag_model.Template]
342 return self.res.getall()
344 def getbyid(self, provider_id):
347 :rtype: wsag_model.Template
349 return self.res.getbyid(provider_id)
351 def create(self, template):
352 """Create a new template
354 :param str template: sla template in ws-agreement format.
356 self.res.create(template)
359 class Providers(object):
361 def __init__(self, root_url, path=_PROVIDERS_PATH):
362 """Business methods for Providers resource
363 :param str root_url: url to the root of resources
364 :param str path: path to resource from root_url
366 The final url to the resource is root_url + "/" + path
368 resourceurl = _buildpath_(root_url, path)
369 converter = xmlconverter.ProviderConverter()
370 self.res = _Resource(resourceurl, converter)
373 """ Get all providers
375 :rtype : list[wsag_model.Provider]
377 return self.res.getall()
379 def getbyid(self, provider_id):
382 :rtype: wsag_model.Provider
384 return self.res.getbyid(provider_id)
386 def create(self, provider):
387 """Create a new provider
389 :type provider: wsag_model.Provider
391 body = provider.to_xml()
392 return self.res.create(body)
395 class Violations(object):
397 def __init__(self, root_url, path=_VIOLATIONS_PATH):
398 """Business methods for Violation resource
399 :param str root_url: url to the root of resources
400 :param str path: path to resource from root_url
402 The final url to the resource is root_url + "/" + path
404 resourceurl = _buildpath_(root_url, path)
405 converter = xmlconverter.ViolationConverter()
406 self.res = _Resource(resourceurl, converter)
409 """ Get all violations
410 :rtype : list[wsag_model.Violation]
412 return self.res.getall()
414 def getbyid(self, violationid):
417 :rtype : wsag_model.Violation
419 return self.res.getbyid(violationid)
421 def getbyagreement(self, agreement_id, testbed, term=None):
422 """Get the violations of an agreement.
424 :param str agreement_id:
425 :param str term: optional GuaranteeTerm name. If not specified,
426 violations from all terms will be returned
427 :rtype: list[wsag_model.Violation]
429 path = _buildpath_(agreement_id, term)
430 return self.res.get(path, params={"testbed": testbed})
433 class Enforcements(object):
435 def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
436 """Business methods for Violation resource
437 :param str root_url: url to the root of resources
438 :param str path: path to resource from root_url
440 The final url to the resource is root_url + "/" + path
442 resourceurl = _buildpath_(root_url, path)
443 converter = xmlconverter.EnforcementConverter()
444 self.res = _Resource(resourceurl, converter)
447 """ Get all Enforcements
448 :rtype : list[wsag_model.Violation]
450 return self.res.getall()
452 def getbyagreement(self, agreement_id, testbed):
453 """Get the enforcement of an agreement.
455 :param str agreement_id:
457 :rtype: list[wsag_model.Enforcement]
459 return self.res.getbyid(agreement_id, params={"testbed": testbed})
462 def _buildpath_(*paths):
464 paths = [path for path in paths if path != ""]
466 return "/".join(paths)
474 rooturl = "http://127.0.0.1:8080/sla-service"
476 c = Factory.templates()
478 #r = c.getbyid("noexiste")
479 #r = c.getstatus("agreement03")
482 #r = c.getbyconsumer('RandomClient')
483 r = c.getbyid("template02")
488 if __name__ == "__main__":