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"]
118 if "headers" not in kwargs:
119 kwargs["headers"] = {"accept": "application/xml"}
120 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
121 settings.SLA_MANAGER_PASSWORD)
123 # for key, values in kwargs.iteritems():
126 result = requests.get(url, **kwargs)
127 print "GET {} {} {}".format(
128 result.url, result.status_code, result.text[0:70])
129 print result.encoding
133 def post(self, path, data=None, **kwargs):
134 """Just a wrapper over request.post, just in case
136 :rtype : request.Response
137 :param str path: remaining path from root url;
138 empty if desired path equal to rooturl.
139 :param dict[str, str] kwargs: arguments to requests.post
142 c = Client("http://localhost:8080/service")
145 '{ "id": "1", "name": "provider-a" }',
147 "content-type": "application/json",
148 "accept": "application/xml"
152 url = _buildpath_(self.rooturl, path)
153 url = url + "?testbed=iminds" # TODO remove hardcoded string
154 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
155 settings.SLA_MANAGER_PASSWORD)
156 if "headers" not in kwargs:
157 kwargs = {"accept": "application/xml",
158 "content-type": "application/xml"}
159 result = requests.post(url, data, **kwargs)
160 location = result.headers["location"] \
161 if "location" in result.headers else "<null>"
162 print "POST {} {} Location: {}".format(
163 result.url, result.status_code, location)
167 class _Resource(object):
169 def __init__(self, url, converter):
170 """Provides some common operations over resources.
172 The operations return a structured representation of the resource.
174 :param str url: url to the resource
175 :param Converter converter: resouce xml converter
177 Some attributes are initialized to be used from the owner if needed:
178 * client: Client instance
179 * converter: resource xml converter
180 * listconverter: list of resources xml converter
182 self.client = Client(url)
183 self.converter = converter
184 self.listconverter = xmlconverter.ListConverter(self.converter)
187 def _processresult(r, converter):
189 """Generic processing of the REST call.
191 If no errors, tries to convert the result to a destination entity.
194 :param converter Converter:
196 if r.status_code == 404:
199 content_type = r.headers.get('content-type', '')
201 #print("content-type = " + content_type)
202 if content_type == 'application/json':
204 elif content_type == 'application/xml':
206 result = xmlconverter.convertstring(converter, xml)
215 r = self.client.get("")
216 resources = self._processresult(r, self.listconverter)
219 def getbyid(self, id, params):
220 """Get resource 'id'"""
221 r = self.client.get(id, params=params)
222 resource = _Resource._processresult(r, self.converter)
225 def get(self, path, params):
226 """Generic query over resource: GET /resource?q1=v1&q2=v2...
228 :param dict[str,str] params: values to pass as get parameters
233 r = self.client.get(path, params=params)
234 resources = self._processresult(r, self.listconverter)
237 def create(self, body, **kwargs):
238 """Creates (POST method) a resource.
240 It should be convenient to set content-type header.
243 resource.create(body, headers={'content-type': 'application/xml'})
245 r = self.client.post("", body, **kwargs)
250 class Agreements(object):
252 def __init__(self, root_url, path=_AGREEMENTS_PATH):
253 """Business methods for Agreement resource
254 :param str root_url: url to the root of resources
255 :param str path: path to resource from root_url
257 The final url to the resource is root_url + "/" + path
259 resourceurl = _buildpath_(root_url, path)
260 converter = xmlconverter.AgreementConverter()
261 self.res = _Resource(resourceurl, converter)
267 :rtype : list[wsag_model.Agreement]
269 return self.res.getall()
271 def getbyid(self, agreementid):
274 :rtype : wsag_model.Agreement
276 return self.res.getbyid(agreementid)
278 def getbyconsumer(self, consumerid):
279 """Get a consumer's agreements
281 :rtype : list[wsag_model.Agreement]
283 return self.res.get(dict(consumerId=consumerid))
285 def getbyprovider(self, providerid):
286 """Get the agreements served by a provider
288 :rtype : list[wsag_model.Agreement]
290 return self.res.get(dict(providerId=providerid))
292 def getstatus(self, agreementid, testbed):
293 """Get guarantee status of an agreement
295 :param str agreementid :
296 :rtype : wsag_model.AgreementStatus
298 path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
299 r = self.res.client.get(path, headers={'accept': 'application/json'},
300 params={'testbed': testbed})
304 status = wsag_model.AgreementStatus.json_decode(json_obj)
308 def getbyslice(self, slicename):
309 """Get the agreements corresponding to a slice
311 :rtype : list[wsag_model.Agreement]
313 return self.res.get(slicename, dict())
315 def create(self, agreement):
316 """Create a new agreement
318 :param str agreement: sla template in ws-agreement format.
320 return self.res.create(agreement)
323 class Templates(object):
325 def __init__(self, root_url, path=_TEMPLATES_PATH):
326 """Business methods for Templates resource
327 :param str root_url: url to the root of resources
328 :param str path: path to resource from root_url
330 The final url to the resource is root_url + "/" + path
332 resourceurl = _buildpath_(root_url, path)
333 converter = xmlconverter.AgreementConverter()
334 self.res = _Resource(resourceurl, converter)
337 """ Get all templates
339 :rtype : list[wsag_model.Template]
341 return self.res.getall()
343 def getbyid(self, provider_id):
346 :rtype: wsag_model.Template
348 return self.res.getbyid(provider_id, None)
350 def create(self, template):
351 """Create a new template
353 :param str template: sla template in ws-agreement format.
355 self.res.create(template)
358 class Providers(object):
360 def __init__(self, root_url, path=_PROVIDERS_PATH):
361 """Business methods for Providers resource
362 :param str root_url: url to the root of resources
363 :param str path: path to resource from root_url
365 The final url to the resource is root_url + "/" + path
367 resourceurl = _buildpath_(root_url, path)
368 converter = xmlconverter.ProviderConverter()
369 self.res = _Resource(resourceurl, converter)
372 """ Get all providers
374 :rtype : list[wsag_model.Provider]
376 return self.res.getall()
378 def getbyid(self, provider_id):
381 :rtype: wsag_model.Provider
383 return self.res.getbyid(provider_id)
385 def create(self, provider):
386 """Create a new provider
388 :type provider: wsag_model.Provider
390 body = provider.to_xml()
391 return self.res.create(body)
394 class Violations(object):
396 def __init__(self, root_url, path=_VIOLATIONS_PATH):
397 """Business methods for Violation resource
398 :param str root_url: url to the root of resources
399 :param str path: path to resource from root_url
401 The final url to the resource is root_url + "/" + path
403 resourceurl = _buildpath_(root_url, path)
404 converter = xmlconverter.ViolationConverter()
405 self.res = _Resource(resourceurl, converter)
408 """ Get all violations
409 :rtype : list[wsag_model.Violation]
411 return self.res.getall()
413 def getbyid(self, violationid):
416 :rtype : wsag_model.Violation
418 return self.res.getbyid(violationid)
420 def getbyagreement(self, agreement_id, testbed, term=None):
421 """Get the violations of an agreement.
423 :param str agreement_id:
424 :param str term: optional GuaranteeTerm name. If not specified,
425 violations from all terms will be returned
426 :rtype: list[wsag_model.Violation]
428 return self.res.get("", params={"agreementId": agreement_id,
429 "guaranteeTerm": term,
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__":