Package pulp :: Package client :: Module connection
[hide private]
[frames] | no frames]

Source Code for Module pulp.client.connection

  1  # 
  2  # A proxy interface to initiate and interact communication with Pulp Server. 
  3  # 
  4  # Copyright (c) 2010 Red Hat, Inc. 
  5  # 
  6  # This software is licensed to you under the GNU General Public License, 
  7  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  8  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  9  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
 10  # along with this software; if not, see 
 11  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 12  # 
 13  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 14  # granted to use or replicate Red Hat trademarks that are incorporated 
 15  # in this software or its documentation. 
 16  # 
 17   
 18  import base64 
 19  import httplib 
 20  import locale 
 21  import sys 
 22  import os 
 23   
 24  from gettext import gettext as _ 
 25   
 26  try: 
 27      import json 
 28  except ImportError: 
 29      import simplejson as json 
 30   
 31  from M2Crypto import SSL, httpslib 
 32   
 33  from pulp.client.logutil import getLogger 
 34   
 35   
 36  log = getLogger(__name__) 
 37   
 38  consumer_deferred_fields = ['package_profile', 'repoids'] 
 39  package_deferred_fields = [] 
 40  repository_deferred_fields = ['packages', 'packagegroups', 'packagegroupcategories'] 
 41   
 42   
43 -def realpath(path):
44 if os.path.exists(path): 45 return path 46 else: 47 return None
48 49
50 -class RestlibException(Exception):
51 - def __init__(self, code, msg=""):
52 self.code = code 53 self.msg = msg
54
55 - def __str__(self):
56 return '%s: %s' % (str(self.code), self.msg)
57
58 -class Restlib(object):
59 """ 60 A wrapper around httplib to make rest calls easier 61 """
62 - def __init__(self, host, port, apihandler, cert_file=None, key_file=None, 63 username=None, password=None):
64 self.host = host 65 # ensure we have an integer, httpslib is picky about the type 66 # passed in for the port 67 self.port = int(port) 68 self.apihandler = apihandler 69 self.username = username 70 self.password = password 71 if (self.username != None): 72 raw = "%s:%s" % (self.username, self.password) 73 base64string = base64.encodestring(raw)[:-1] 74 auth = "Basic %s" % base64string 75 else: 76 auth = None 77 default_locale = locale.getdefaultlocale()[0] 78 if default_locale: 79 default_locale = default_locale.lower().replace('_', '-') 80 self.headers = {"Content-type":"application/json", 81 "Authorization": auth, 82 "Accept": "application/json", 83 "Accept-Language": default_locale} 84 self.cert_file = cert_file 85 self.key_file = key_file
86
87 - def _request(self, request_type, method, info=None):
88 handler = method 89 if not handler.startswith(self.apihandler): 90 #handler = self.apihandler + handler 91 handler = '/'.join((self.apihandler, handler)) 92 log.debug("_request calling: %s to host:port : %s:%s" % 93 (handler, self.host, self.port)) 94 if self.cert_file: 95 log.info("Using SSLv3 context") 96 context = SSL.Context("sslv3") 97 context.load_cert(self.cert_file, keyfile=self.key_file) 98 conn = httpslib.HTTPSConnection(self.host, self.port, ssl_context=context) 99 else: 100 conn = httplib.HTTPSConnection(self.host, self.port) 101 log.debug("Request_type: %s" % request_type) 102 log.debug("info: %s" % info) 103 log.debug("headers: %s" % self.headers) 104 conn.request(request_type, handler, body=json.dumps(info), 105 headers=self.headers) 106 response = conn.getresponse() 107 if response.status == 404: 108 return None 109 self.validateResponse(response) 110 rinfo = response.read() 111 if not len(rinfo): 112 return None 113 return json.loads(rinfo)
114
115 - def validateResponse(self, response):
116 if response.status not in [200, 201, 202, 204]: 117 raise RestlibException(response.status, response.read())
118 #parsed = json.loads(response.read()) 119
120 - def request_get(self, method):
121 return self._request("GET", method)
122
123 - def request_post(self, method, params=""):
124 return self._request("POST", method, params)
125
126 - def request_head(self, method):
127 return self._request("HEAD", method)
128
129 - def request_put(self, method, params=""):
130 return self._request("PUT", method, params)
131
132 - def request_delete(self, method):
133 return self._request("DELETE", method)
134
135 -class PulpConnection:
136 """ 137 Proxy connection to Pulp Server 138 """ 139 140 CERT_PATH = "/etc/pki/consumer/cert.pem" 141 KEY_PATH = "/etc/pki/consumer/key.pem" 142
143 - def __init__(self, host='localhost', port=443, handler="/pulp/api", 144 cert_file=realpath(CERT_PATH), key_file=realpath(KEY_PATH), 145 username=None, password=None):
146 self.host = host 147 self.port = port 148 self.handler = handler 149 self.conn = None 150 self.cert_file = cert_file 151 self.key_file = key_file 152 self.username = username 153 self.password = password 154 # initialize connection 155 self.setUp()
156
157 - def setUp(self):
158 self.conn = Restlib(self.host, self.port, self.handler, self.cert_file, 159 self.key_file, self.username, self.password) 160 log.info("Connection Established for cli: Host: %s, Port: %s, handler: %s" % 161 (self.host, self.port, self.handler)) 162 log.info("Using cert_file: %s and key_file: %s" % 163 (self.cert_file, self.key_file))
164
165 - def shutDown(self):
166 self.conn.close() 167 log.info("remote connection closed")
168 169
170 -class RepoConnection(PulpConnection):
171 """ 172 Connection class to access repo specific calls 173 """
174 - def create(self, id, name, arch, feed=None, symlinks=False, 175 sync_schedule=None, cert_data=None):
176 method = "/repositories/" 177 repodata = {"id" : id, 178 "name" : name, 179 "arch" : arch, 180 "feed" : feed, 181 "use_symlinks" : symlinks, 182 "sync_schedule" : sync_schedule, 183 "cert_data" : cert_data} 184 return self.conn.request_put(method, params=repodata)
185
186 - def repository(self, id, fields=None):
187 method = "/repositories/%s/" % str(id) 188 repo = self.conn.request_get(method) 189 if repo is None: 190 return None 191 for field in repository_deferred_fields: 192 repo[field] = self.conn.request_get('%s%s/' % (method, field)) 193 return repo
194
195 - def repositories(self):
196 method = "/repositories/" 197 return self.conn.request_get(method)
198
199 - def update(self, repo):
200 method = "/repositories/%s/" % repo['id'] 201 return self.conn.request_put(method, params=repo)
202
203 - def delete(self, id):
204 method = "/repositories/%s/" % id 205 return self.conn.request_delete(method)
206
207 - def clean(self):
208 method = "/repositories/" 209 return self.conn.request_delete(method)
210
211 - def sync(self, repoid, timeout=None):
212 method = "/repositories/%s/sync/" % repoid 213 return self.conn.request_post(method, params={"timeout":timeout})
214
215 - def cancel_sync(self, repoid, taskid):
216 method = "/repositories/%s/sync/%s" % (repoid, taskid) 217 return self.conn.request_delete(method)
218
219 - def add_package(self, repoid, packageid):
220 addinfo = {'repoid' : repoid, 221 'packageid' : packageid} 222 method = "/repositories/%s/add_package/" % repoid 223 return self.conn.request_post(method, params=addinfo)
224
225 - def get_package(self, repoid, pkg_name):
226 method = "/repositories/%s/get_package/" % repoid 227 return self.conn.request_post(method, params=pkg_name)
228
229 - def packages(self, repoid):
230 method = "/repositories/%s/packages/" % repoid 231 return self.conn.request_get(method)
232
233 - def packagegroups(self, repoid):
234 method = "/repositories/%s/packagegroups/" % repoid 235 return self.conn.request_get(method)
236
237 - def create_packagegroup(self, repoid, groupid, groupname, description):
238 method = "/repositories/%s/create_packagegroup/" % repoid 239 return self.conn.request_post(method, params={"groupid":groupid, 240 "groupname":groupname, "description":description})
241
242 - def delete_packagegroup(self, repoid, groupid):
243 method = "/repositories/%s/delete_packagegroup/" % repoid 244 return self.conn.request_post(method, params={"groupid":groupid})
245
246 - def add_packages_to_group(self, repoid, groupid, packagenames, gtype):
247 method = "/repositories/%s/add_packages_to_group/" % repoid 248 return self.conn.request_post(method, 249 params={"groupid":groupid, "packagenames":packagenames, "type":gtype})
250
251 - def delete_package_from_group(self, repoid, groupid, pkgname, gtype):
252 method = "/repositories/%s/delete_package_from_group/" % repoid 253 return self.conn.request_post(method, 254 params={"groupid":groupid, "name":pkgname, "type":gtype})
255
256 - def upload(self, id, pkginfo, pkgstream):
257 uploadinfo = {'repo' : id, 258 'pkginfo' : pkginfo, 259 'pkgstream' : pkgstream} 260 method = "/repositories/%s/upload/" % id 261 return self.conn.request_post(method, params=uploadinfo)
262
263 - def all_schedules(self):
264 method = "/repositories/schedules/" 265 return self.conn.request_get(method)
266
267 - def sync_status(self, status_path):
268 return self.conn.request_get(str(status_path))
269
270 - def add_errata(self, id, errataids):
271 erratainfo = {'repoid' : id, 272 'errataid' : errataids} 273 method = "/repositories/%s/add_errata/" % id 274 return self.conn.request_post(method, params=erratainfo)
275
276 - def delete_errata(self, id, errataids):
277 erratainfo = {'repoid' : id, 278 'errataid' : errataids} 279 method = "/repositories/%s/delete_errata/" % id 280 return self.conn.request_post(method, params=erratainfo)
281
282 - def errata(self, id, types=[]):
283 erratainfo = {'repoid' : id, 284 'types' : types} 285 method = "/repositories/%s/list_errata/" % id 286 return self.conn.request_post(method, params=erratainfo)
287 288
289 -class ConsumerConnection(PulpConnection):
290 """ 291 Connection class to access repo specific calls 292 """
293 - def create(self, id, description):
294 consumerdata = {"id" : id, "description" : description} 295 method = "/consumers/" 296 return self.conn.request_put(method, params=consumerdata)
297
298 - def update(self, consumer):
299 method = "/consumers/%s/" % consumer['id'] 300 return self.conn.request_put(method, params=consumer)
301
302 - def bulkcreate(self, consumers):
303 method = "/consumers/bulk/" 304 return self.conn.request_post(method, params=consumers)
305
306 - def delete(self, id):
307 method = "/consumers/%s/" % id 308 return self.conn.request_delete(method)
309
310 - def clean(self):
311 method = "/consumers/" 312 return self.conn.request_delete(method)
313
314 - def consumer(self, id):
315 method = "/consumers/%s/" % str(id) 316 consumer = self.conn.request_get(method) 317 for field in consumer_deferred_fields: 318 consumer[field] = self.conn.request_get('%s%s/' % (method, field)) 319 return consumer
320
321 - def packages(self, id):
322 method = "/consumers/%s/packages/" % str(id) 323 return self.conn.request_get(method)
324
325 - def certificate(self, id):
326 method = "/consumers/%s/certificate/" % str(id) 327 cert_dict = self.conn.request_get(method) 328 return cert_dict
329
330 - def consumers(self):
331 method = "/consumers/" 332 return self.conn.request_get(method)
333
334 - def consumers_with_package_name(self, name):
335 method = '/consumers/?package_name=%s' % name 336 return self.conn.request_get(method)
337
338 - def bind(self, id, repoid):
339 method = "/consumers/%s/bind/" % id 340 return self.conn.request_post(method, params=repoid)
341
342 - def unbind(self, id, repoid):
343 method = "/consumers/%s/unbind/" % id 344 return self.conn.request_post(method, params=repoid)
345
346 - def profile(self, id, profile):
347 method = "/consumers/%s/profile/" % id 348 return self.conn.request_post(method, params=profile)
349
350 - def installpackages(self, id, packagenames):
351 method = "/consumers/%s/installpackages/" % id 352 body = dict(packagenames=packagenames) 353 return self.conn.request_post(method, params=body)
354
355 - def installpackagegroups(self, id, packageids):
356 method = "/consumers/%s/installpackagegroups/" % id 357 body = dict(packageids=packageids) 358 return self.conn.request_post(method, params=body)
359
360 - def errata(self, id, types=None):
361 method = "/consumers/%s/listerrata/" % id 362 body = dict(types=types) 363 return self.conn.request_post(method, params=body)
364
365 - def installerrata(self, id, errataids, types=()):
366 erratainfo = {'consumerid' : id, 367 'errataids' : errataids, 368 'types' : types} 369 method = "/consumers/%s/installerrata/" % id 370 return self.conn.request_post(method, params=erratainfo)
371
372 - def history(self, id, query_params):
373 method = "/consumers/%s/history/" % id 374 return self.conn.request_post(method, params=query_params)
375 376
377 -class ConsumerGroupConnection(PulpConnection):
378 """ 379 Connection class to access consumer group related calls 380 """
381 - def create(self, id, description, consumerids=[]):
382 consumergroup_data = {"id" : id, "description" : description, 383 "consumerids" : consumerids} 384 method = "/consumergroups/" 385 return self.conn.request_put(method, params=consumergroup_data)
386
387 - def update(self, consumergroup):
388 method = "/consumergroups/%s/" % consumergroup['id'] 389 return self.conn.request_put(method, params=consumergroup)
390
391 - def delete(self, id):
392 method = "/consumergroups/%s/" % id 393 return self.conn.request_delete(method)
394
395 - def clean(self):
396 method = "/consumergroups/" 397 return self.conn.request_delete(method)
398
399 - def consumergroups(self):
400 method = "/consumergroups/" 401 return self.conn.request_get(method)
402
403 - def consumergroup(self, id):
404 method = "/consumergroups/%s/" % str(id) 405 return self.conn.request_get(method)
406
407 - def add_consumer(self, id, consumerid):
408 method = "/consumergroups/%s/add_consumer/" % id 409 return self.conn.request_post(method, params=consumerid)
410
411 - def delete_consumer(self, id, consumerid):
412 method = "/consumers/%s/delete_consumer/" % id 413 return self.conn.request_post(method, params=consumerid)
414
415 - def bind(self, id, repoid):
416 method = "/consumergroups/%s/bind/" % id 417 return self.conn.request_post(method, params=repoid)
418
419 - def unbind(self, id, repoid):
420 method = "/consumergroups/%s/unbind/" % id 421 return self.conn.request_post(method, params=repoid)
422
423 - def installpackages(self, id, packagenames):
424 method = "/consumergroups/%s/installpackages/" % id 425 body = dict(packagenames=packagenames) 426 return self.conn.request_post(method, params=body)
427
428 - def installerrata(self, id, errataids, types=[]):
429 erratainfo = {'consumerid' : id, 430 'errataids' : errataids, 431 'types' : types} 432 method = "/consumergroups/%s/installerrata/" % id 433 return self.conn.request_post(method, params=erratainfo)
434
435 -class PackageConnection(PulpConnection):
436
437 - def clean(self):
438 method = "/packages/" 439 return self.conn.request_delete(method)
440
441 - def create(self, name, epoch, version, release, arch, description, 442 checksum_type, checksum, filename):
443 method = "/packages/" 444 repodata = {"name" : name, 445 "epoch" : epoch, 446 "version" : version, 447 "release" : release, 448 "arch" : arch, 449 "description" : description, 450 "checksum_type" : checksum_type, 451 "checksum": checksum, 452 "filename": filename, } 453 return self.conn.request_put(method, params=repodata)
454
455 - def packages(self):
456 method = "/packages/" 457 return self.conn.request_get(method)
458
459 - def package(self, id, filter=None):
460 method = "/packages/%s/" % id 461 return self.conn.request_get(method)
462
463 - def delete(self, packageid):
464 method = "/packages/%s/" % packageid 465 return self.conn.request_delete(method)
466
467 - def package_by_ivera(self, name, version, release, epoch, arch):
468 method = "/packages/%s/%s/%s/%s/%s/" % (name, version, release, epoch, arch) 469 return self.conn.request_get(method)
470
471 -class PackageGroupConnection(PulpConnection):
472
473 - def clean(self):
474 pass
475 476
477 -class PackageGroupCategoryConnection(PulpConnection):
478
479 - def clean(self):
480 pass
481 482
483 -class UserConnection(PulpConnection):
484 """ 485 Connection class to access consumer group related calls 486 """
487 - def create(self, login, password=None, name=None):
488 user_data = {"login" : login, "password" : password, 489 "name" : name} 490 method = "/users/" 491 return self.conn.request_put(method, params=user_data)
492
493 - def update(self, user):
494 method = "/users/%s/" % user['id'] 495 return self.conn.request_put(method, params=user)
496
497 - def delete(self, **kwargs):
498 login = kwargs['login'] 499 method = "/users/%s/" % login 500 return self.conn.request_delete(method)
501
502 - def clean(self):
503 method = "/users/" 504 return self.conn.request_delete(method)
505
506 - def users(self):
507 method = "/users/" 508 return self.conn.request_get(method)
509
510 - def user(self, login):
511 method = "/users/%s/" % str(login) 512 return self.conn.request_get(method)
513
514 - def admin_certificate(self):
515 method = '/users/admin_certificate/' 516 return self.conn.request_get(method)
517
518 -class ErrataConnection(PulpConnection):
519 """ 520 Connection class to access errata related calls 521 """
522 - def clean(self):
523 pass
524
525 - def create(self, id, title, description, version, release, type, 526 status="", updated="", issued="", pushcount="", update_id="", 527 from_str="", reboot_suggested="", references=[], 528 pkglist=[]):
529 pass
530
531 - def erratum(self, id):
532 method = "/errata/%s/" % id 533 return self.conn.request_get(method)
534
535 - def errata(self, id=None, title=None, description=None, version=None, 536 release=None, type=None, status=None, updated=None, issued=None, 537 pushcount=None, from_str=None, reboot_suggested=None):
538 pass
539 540 if __name__ == '__main__': 541 rconn = RepoConnection() 542 print "+--------------------------------+" 543 print " Repo API Tests " 544 print "+--------------------------------+" 545 546 repo = rconn.create('test-f12', 'f12', 'i386', 'yum:http://mmccune.fedorapeople.org/pulp/') 547 print "create Repos", repo['id'] 548 print "list repos:", rconn.repositories() 549 print "Get repo By Id: ", rconn.repository(repo['id']) 550 newdata = {'id' : 'test-f12', 551 'name' : 'f12', 552 'arch' : 'noarch', 553 'feed' : 'yum:http://mmccune.fedorapeople.org/pulp/'} 554 #print "update Repo:",rconn.update(repo['id'], newdata) 555 print "Sync Repos:", rconn.sync(repo['id']) 556 print "list Repo Packages: ", rconn.packages(repo['id']) 557 print "delete Repo:", rconn.delete(repo['id']) 558 print "+--------------------------------+" 559 print " Consumer API Tests " 560 print "+--------------------------------+" 561 cconn = ConsumerConnection() 562 print "Create Consumer", cconn.create("test", 'prad.rdu.redhat.com') 563 print "List Consumers", cconn.consumers() 564