1 # -*- coding: utf-8 -*-
5 from requests.auth import HTTPBasicAuth
6 from myslice.settings import logger
11 from django.conf import settings
14 """REST client to SLA Manager.
16 Contains a generic rest client and wrappers over this generic client
19 Each resource client implements business-like() functions, but
20 returns a tuple (output, requests.Response)
22 The resource clients are initialized with the rooturl and a path, which
23 are combined to build the resource url. The path is defaulted to the known
24 resource path. So, for example, to create a agreements client:
26 c = Agreements("http://localhost/slagui-service")
28 A Factory facility is provided to create resource client instances. The
29 Factory uses "rooturl" module variable to use as rooturl parameter.
31 restclient.rooturl = "http://localhost/slagui-service"
32 c = restclient.Factory.agreements()
36 _PROVIDERS_PATH = "providers"
37 _AGREEMENTS_PATH = "agreements"
38 _TEMPLATES_PATH = "templates"
39 _VIOLATIONS_PATH = "violations"
40 _ENFORCEMENTJOBS_PATH = "enforcements"
42 rooturl = settings.SLA_COLLECTOR_URL
45 class Factory(object):
48 """Returns a REST client for Agreements
52 return Agreements(rooturl)
56 """Returns a REST client for Providers
60 return Providers(rooturl)
64 """Returns a REST client for Violations
68 return Violations(rooturl)
72 """Returns a REST client for Violations
76 return Templates(rooturl)
80 """Returns a REST client for Enforcements jobs
84 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 if "testbed" in kwargs:
117 url = url + "?testbed=" + kwargs["testbed"]
119 if "headers" not in kwargs:
120 kwargs["headers"] = {"accept": "application/xml"}
123 kwargs["auth"] = HTTPBasicAuth(settings.SLA_COLLECTOR_USER,
124 settings.SLA_COLLECTOR_PASSWORD)
126 # for key, values in kwargs.iteritems():
129 logger.debug('SLA GET {}'.format(url))
130 result = requests.get(url, **kwargs)
131 logger.debug('SLA GET {} - result: {}'.format(result.url, result.status_code))
132 # print "GET {} {} {}".format(
133 # result.url, result.status_code, result.text[0:70])
134 # print result.encoding
138 def post(self, path, data=None, **kwargs):
139 """Just a wrapper over request.post, just in case
141 :rtype : request.Response
142 :param str path: remaining path from root url;
143 empty if desired path equal to rooturl.
144 :param dict[str, str] kwargs: arguments to requests.post
147 c = Client("http://localhost:8080/service")
150 '{ "id": "1", "name": "provider-a" }',
152 "content-type": "application/json",
153 "accept": "application/xml"
157 url = _buildpath(self.rooturl, path)
159 if "testbed" in kwargs:
160 url = url + "?testbed=" + kwargs["testbed"]
161 del kwargs["testbed"]
163 if "headers" not in kwargs:
164 kwargs["headers"] = {"accept": "application/xml",
165 "content-type": "application/xml"}
167 kwargs["auth"] = HTTPBasicAuth(settings.SLA_COLLECTOR_USER,
168 settings.SLA_COLLECTOR_PASSWORD)
170 result = requests.post(url, data, **kwargs)
171 location = result.headers["location"] \
172 if "location" in result.headers else "<null>"
173 print "POST {} {} Location: {}".format(
174 result.url, result.status_code, location)
178 class _Resource(object):
180 def __init__(self, url, converter):
181 """Provides some common operations over resources.
183 The operations return a structured representation of the resource.
185 :param str url: url to the resource
186 :param Converter converter: resouce xml converter
188 Some attributes are initialized to be used from the owner if needed:
189 * client: Client instance
190 * converter: resource xml converter
191 * listconverter: list of resources xml converter
193 self.client = Client(url)
194 self.converter = converter
195 self.listconverter = xmlconverter.ListConverter(self.converter)
198 def _processresult(r, converter):
200 """Generic processing of the REST call.
202 If no errors, tries to convert the result to a destination entity.
205 :param converter Converter:
207 if r.status_code == 404:
210 content_type = r.headers.get('content-type', '')
212 #print("content-type = " + content_type)
213 if content_type == 'application/json':
215 elif content_type == 'application/xml':
217 result = xmlconverter.convertstring(converter, xml)
226 r = self.client.get("")
227 resources = self._processresult(r, self.listconverter)
230 def getbyid(self, id, params):
231 """Get resource 'id'"""
232 r = self.client.get(id, params=params)
233 resource = _Resource._processresult(r, self.converter)
236 def get(self, path="", params={}):
237 """Generic query over resource: GET /resource?q1=v1&q2=v2...
239 :param dict[str,str] params: values to pass as get parameters
242 r = self.client.get(path, params=params)
243 resources = self._processresult(r, self.listconverter)
246 def create(self, body, **kwargs):
247 """Creates (POST method) a resource.
249 It should be convenient to set content-type header.
252 resource.create(body, headers={'content-type': 'application/xml'})
254 r = self.client.post("", body, **kwargs)
259 class Agreements(object):
261 def __init__(self, root_url, path=_AGREEMENTS_PATH):
262 """Business methods for Agreement resource
263 :param str root_url: url to the root of resources
264 :param str path: path to resource from root_url
266 The final url to the resource is root_url + "/" + path
268 self.resourceurl = _buildpath(root_url, path)
269 self.converter = xmlconverter.AgreementConverter()
270 self.res = _Resource(self.resourceurl, self.converter)
276 :rtype : list[wsag_model.Agreement]
278 return self.res.getall()
280 def getbyid(self, agreementid):
283 :rtype : wsag_model.Agreement
285 return self.res.getbyid(agreementid)
287 def getbyconsumer(self, consumerid):
288 """Get a consumer's agreements
290 :rtype : list[wsag_model.Agreement]
292 return self.res.get(dict(consumerId=consumerid))
294 def getbyprovider(self, providerid):
295 """Get the agreements served by a provider
297 :rtype : list[wsag_model.Agreement]
299 return self.res.get(dict(providerId=providerid))
301 def getstatus(self, agreementid, testbed):
302 """Get guarantee status of an agreement
304 :param str agreementid :
305 :rtype : wsag_model.AgreementStatus
307 # path = _buildpath(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
308 path = _buildpath(agreementid, "guaranteestatus")
309 r = self.res.client.get(path, headers={'accept': 'application/json'},
310 params={'testbed': testbed})
313 status = wsag_model.AgreementStatus.json_decode(json_obj)
317 def getbyslice(self, slicename):
318 """Get the agreements corresponding to a slice
320 :rtype : list[wsag_model.Agreement]
322 self.resourceurl = _buildpath(rooturl, 'slice')
323 self.res = _Resource(self.resourceurl, self.converter)
324 return self.res.get(slicename)
326 def create(self, agreement, testbed):
327 """Create a new agreement
329 :param str agreement: sla template in ws-agreement format.
331 return self.res.create(agreement, params={'testbed': testbed})
334 class Templates(object):
336 def __init__(self, root_url, path=_TEMPLATES_PATH):
337 """Business methods for Templates resource
338 :param str root_url: url to the root of resources
339 :param str path: path to resource from root_url
341 The final url to the resource is root_url + "/" + path
343 resourceurl = _buildpath(root_url, path)
344 converter = xmlconverter.AgreementConverter()
345 self.res = _Resource(resourceurl, converter)
348 """ Get all templates
350 :rtype : list[wsag_model.Template]
352 return self.res.getall()
354 def getbyid(self, provider_id):
357 :rtype: wsag_model.Template
359 return self.res.getbyid(provider_id, {"testbed": provider_id})
361 def create(self, template):
362 """Create a new template
364 :param str template: sla template in ws-agreement format.
366 self.res.create(template)
369 class Providers(object):
371 def __init__(self, root_url, path=_PROVIDERS_PATH):
372 """Business methods for Providers resource
373 :param str root_url: url to the root of resources
374 :param str path: path to resource from root_url
376 The final url to the resource is root_url + "/" + path
378 resourceurl = _buildpath(root_url, path)
379 converter = xmlconverter.ProviderConverter()
380 self.res = _Resource(resourceurl, converter)
383 """ Get all providers
385 :rtype : list[wsag_model.Provider]
387 return self.res.getall()
389 def getbyid(self, provider_id):
392 :rtype: wsag_model.Provider
394 return self.res.getbyid(provider_id)
396 def create(self, provider):
397 """Create a new provider
399 :type provider: wsag_model.Provider
401 body = provider.to_xml()
402 return self.res.create(body)
405 class Violations(object):
407 def __init__(self, root_url, path=_VIOLATIONS_PATH):
408 """Business methods for Violation resource
409 :param str root_url: url to the root of resources
410 :param str path: path to resource from root_url
412 The final url to the resource is root_url + "/" + path
414 resourceurl = _buildpath(root_url, path)
415 converter = xmlconverter.ViolationConverter()
416 self.res = _Resource(resourceurl, converter)
419 """ Get all violations
420 :rtype : list[wsag_model.Violation]
422 return self.res.getall()
424 def getbyid(self, violationid):
427 :rtype : wsag_model.Violation
429 return self.res.getbyid(violationid)
431 def getbyagreement(self, agreement_id, testbed, term=None):
432 """Get the violations of an agreement.
434 :param str agreement_id:
435 :param str term: optional GuaranteeTerm name. If not specified,
436 violations from all terms will be returned
437 :rtype: list[wsag_model.Violation]
439 return self.res.get("", params={"agreementId": agreement_id,
440 "guaranteeTerm": term,
444 class Enforcements(object):
446 def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
447 """Business methods for Violation resource
448 :param str root_url: url to the root of resources
449 :param str path: path to resource from root_url
451 The final url to the resource is root_url + "/" + path
453 resourceurl = _buildpath(root_url, path)
454 converter = xmlconverter.EnforcementConverter()
455 self.res = _Resource(resourceurl, converter)
458 """ Get all Enforcements
459 :rtype : list[wsag_model.Violation]
461 return self.res.getall()
463 def getbyagreement(self, agreement_id, testbed):
464 """Get the enforcement of an agreement.
466 :param str agreement_id:
468 :rtype: list[wsag_model.Enforcement]
470 return self.res.getbyid(agreement_id, params={"testbed": testbed})
473 def _buildpath(*paths):
475 paths = [path for path in paths if path != ""]
477 return "/".join(paths)
485 rooturl = "http://127.0.0.1:8080/sla-service"
487 c = Factory.templates()
489 #r = c.getbyid("noexiste")
490 #r = c.getstatus("agreement03")
493 #r = c.getbyconsumer('RandomClient')
494 r = c.getbyid("template02")
499 if __name__ == "__main__":