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])
122 def post(self, path, data=None, **kwargs):
123 """Just a wrapper over request.post, just in case
125 :rtype : request.Response
126 :param str path: remaining path from root url;
127 empty if desired path equal to rooturl.
128 :param dict[str, str] kwargs: arguments to requests.post
131 c = Client("http://localhost:8080/service")
134 '{ "id": "1", "name": "provider-a" }',
136 "content-type": "application/json",
137 "accept": "application/xml"
141 url = _buildpath_(self.rooturl, path)
142 kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER, settings.SLA_MANAGER_PASSWORD)
143 result = requests.post(url, data, **kwargs)
144 location = result.headers["location"] \
145 if "location" in result.headers else "<null>"
146 print "POST {} {} Location: {}".format(
147 result.url, result.status_code, location)
152 class _Resource(object):
154 def __init__(self, url, converter):
155 """Provides some common operations over resources.
157 The operations return a structured representation of the resource.
159 :param str url: url to the resource
160 :param Converter converter: resouce xml converter
162 Some attributes are initialized to be used from the owner if needed:
163 * client: Client instance
164 * converter: resource xml converter
165 * listconverter: list of resources xml converter
167 self.client = Client(url)
168 self.converter = converter
169 self.listconverter = xmlconverter.ListConverter(self.converter)
172 def _processresult(r, converter):
174 """Generic processing of the REST call.
176 If no errors, tries to convert the result to a destination entity.
179 :param converter Converter:
181 if r.status_code == 404:
184 content_type = r.headers.get('content-type', '')
186 print("content-type = " + content_type)
187 if content_type == 'application/json':
189 elif content_type == 'application/xml':
191 result = xmlconverter.convertstring(converter, xml)
200 r = self.client.get("")
201 resources = self._processresult(r, self.listconverter)
204 def getbyid(self, id):
205 """Get resource 'id'"""
206 r = self.client.get(id)
207 resource = _Resource._processresult(r, self.converter)
210 def get(self, params):
211 """Generic query over resource: GET /resource?q1=v1&q2=v2...
213 :param dict[str,str] params: values to pass as get parameters
215 r = self.client.get("", params=params)
216 resources = self._processresult(r, self.listconverter)
219 def create(self, body, **kwargs):
220 """Creates (POST method) a resource.
222 It should be convenient to set content-type header.
225 resource.create(body, headers={'content-type': 'application/xml'})
227 r = self.client.post("", body, **kwargs)
232 class Agreements(object):
234 def __init__(self, root_url, path=_AGREEMENTS_PATH):
235 """Business methods for Agreement resource
236 :param str root_url: url to the root of resources
237 :param str path: path to resource from root_url
239 The final url to the resource is root_url + "/" + path
241 resourceurl = _buildpath_(root_url, path)
242 converter = xmlconverter.AgreementConverter()
243 self.res = _Resource(resourceurl, converter)
249 :rtype : list[wsag_model.Agreement]
251 return self.res.getall()
253 def getbyid(self, agreementid):
256 :rtype : wsag_model.Agreement
258 return self.res.getbyid(agreementid)
260 def getbyconsumer(self, consumerid):
261 """Get a consumer's agreements
263 :rtype : list[wsag_model.Agreement]
265 return self.res.get(dict(consumerId=consumerid))
267 def getbyprovider(self, providerid):
268 """Get the agreements served by a provider
270 :rtype : list[wsag_model.Agreement]
272 return self.res.get(dict(providerId=providerid))
274 def getstatus(self, agreementid):
275 """Get guarantee status of an agreement
277 :param str agreementid :
278 :rtype : wsag_model.AgreementStatus
280 path = _buildpath_(agreementid, "guaranteestatus")
281 r = self.res.client.get(path, headers={'accept': 'application/json'})
283 status = wsag_model.AgreementStatus.json_decode(json_obj)
287 def create(self, agreement):
288 """Create a new agreement
290 :param str agreement: sla template in ws-agreement format.
292 return self.res.create(agreement)
294 class Templates(object):
296 def __init__(self, root_url, path=_TEMPLATES_PATH):
297 """Business methods for Templates resource
298 :param str root_url: url to the root of resources
299 :param str path: path to resource from root_url
301 The final url to the resource is root_url + "/" + path
303 resourceurl = _buildpath_(root_url, path)
304 converter = xmlconverter.AgreementConverter()
305 self.res = _Resource(resourceurl, converter)
308 """ Get all templates
310 :rtype : list[wsag_model.Template]
312 return self.res.getall()
314 def getbyid(self, provider_id):
317 :rtype: wsag_model.Template
319 return self.res.getbyid(provider_id)
321 def create(self, template):
322 """Create a new template
324 :param str template: sla template in ws-agreement format.
326 self.res.create(template)
328 class Providers(object):
330 def __init__(self, root_url, path=_PROVIDERS_PATH):
331 """Business methods for Providers resource
332 :param str root_url: url to the root of resources
333 :param str path: path to resource from root_url
335 The final url to the resource is root_url + "/" + path
337 resourceurl = _buildpath_(root_url, path)
338 converter = xmlconverter.ProviderConverter()
339 self.res = _Resource(resourceurl, converter)
342 """ Get all providers
344 :rtype : list[wsag_model.Provider]
346 return self.res.getall()
348 def getbyid(self, provider_id):
351 :rtype: wsag_model.Provider
353 return self.res.getbyid(provider_id)
355 def create(self, provider):
356 """Create a new provider
358 :type provider: wsag_model.Provider
360 body = provider.to_xml()
361 return self.res.create(body)
363 class Violations(object):
365 def __init__(self, root_url, path=_VIOLATIONS_PATH):
366 """Business methods for Violation resource
367 :param str root_url: url to the root of resources
368 :param str path: path to resource from root_url
370 The final url to the resource is root_url + "/" + path
372 resourceurl = _buildpath_(root_url, path)
373 converter = xmlconverter.ViolationConverter()
374 self.res = _Resource(resourceurl, converter)
377 """ Get all violations
378 :rtype : list[wsag_model.Violation]
380 return self.res.getall()
382 def getbyid(self, violationid):
385 :rtype : wsag_model.Violation
387 return self.res.getbyid(violationid)
389 def getbyagreement(self, agreement_id, term=None):
390 """Get the violations of an agreement.
392 :param str agreement_id:
393 :param str term: optional GuaranteeTerm name. If not specified,
394 violations from all terms will be returned
395 :rtype: list[wsag_model.Violation]
398 {"agreementId": agreement_id, "guaranteeTerm": term})
401 class Enforcements(object):
403 def __init__(self, root_url, path=_ENFORCEMENTJOBS_PATH):
404 """Business methods for Violation resource
405 :param str root_url: url to the root of resources
406 :param str path: path to resource from root_url
408 The final url to the resource is root_url + "/" + path
410 resourceurl = _buildpath_(root_url, path)
411 converter = xmlconverter.EnforcementConverter()
412 self.res = _Resource(resourceurl, converter)
415 """ Get all Enforcements
416 :rtype : list[wsag_model.Violation]
418 return self.res.getall()
420 def getbyagreement(self, agreement_id):
421 """Get the enforcement of an agreement.
423 :param str agreement_id:
425 :rtype: list[wsag_model.Enforcement]
427 return self.res.getbyid(agreement_id)
430 def _buildpath_(*paths):
431 return "/".join(paths)
439 rooturl = "http://127.0.0.1:8080/sla-service"
442 c = Factory.templates()
444 #r = c.getbyid("noexiste")
445 #r = c.getstatus("agreement03")
448 #r = c.getbyconsumer('RandomClient')
449 r = c.getbyid("template02")
455 if __name__ == "__main__":