1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import itertools
18 import logging
19
20 import web
21
22 from pulp.server.api.repo import RepoApi
23 from pulp.server.api.repo_sync import yum_rhn_progress_callback
24 from pulp.server.webservices import http
25 from pulp.server.webservices import mongo
26 from pulp.server.webservices.controllers.base import JSONController, AsyncController
27 from pulp.server.webservices.role_check import RoleCheck
28
29
30
31 api = RepoApi()
32 log = logging.getLogger('pulp')
33
34
35 default_fields = [
36 'id',
37 'source',
38 'name',
39 'arch',
40 'sync_schedule',
41 'use_symlinks',
42 'productid',
43 'relative_path',]
48
49 @JSONController.error_handler
50 @RoleCheck(admin=True)
69
70 @JSONController.error_handler
71 @RoleCheck(admin=True)
73 """
74 Create a new repository.
75 @return: repository meta data on successful creation of repository
76 """
77 repo_data = self.params()
78
79 id = repo_data['id']
80 if api.repository(id, default_fields) is not None:
81 return self.conflict('A repository with the id, %s, already exists' % id)
82
83 repo = api.create(id,
84 repo_data['name'],
85 repo_data['arch'],
86 feed=repo_data.get('feed', None),
87 symlinks=repo_data.get('use_symlinks', False),
88 sync_schedule=repo_data.get('sync_schedule', None),
89 cert_data=repo_data.get('cert_data', None))
90
91 path = http.extend_uri_path(repo.id)
92 repo['uri_ref'] = path
93 return self.created(path, repo)
94
95 @JSONController.error_handler
96 @RoleCheck(admin=True)
98 """
99 @return: True on successful deletion of all repositories
100 """
101 api.clean()
102 return self.ok(True)
103
106
107 @JSONController.error_handler
108 @RoleCheck(consumer=True, admin=True)
122
123 @JSONController.error_handler
124 @RoleCheck(admin=True, consumer=True)
126 """
127 Change a repository.
128 @param id: repository id
129 @return: True on successful update of repository meta data
130 """
131 repo_data = self.params()
132 if repo_data['id'] != id:
133 return self.bad_request('You cannot change a repository id')
134
135
136 for field in itertools.chain(['uri_ref'],
137 RepositoryDeferredFields.exposed_fields):
138 if field in repo_data and isinstance(repo_data[field], basestring):
139 repo_data.pop(field, None)
140 api.update(repo_data)
141 return self.ok(True)
142
143 @JSONController.error_handler
144 @RoleCheck(admin=True)
146 """
147 Delete a repository.
148 @param id: repository id
149 @return: True on successful deletion of repository
150 """
151 api.delete(id=id)
152 return self.ok(True)
153
156
157
158 exposed_fields = (
159 'packages',
160 'packagegroups',
161 'packagegroupcategories',
162 'errata'
163 )
164
165 @JSONController.error_handler
174
175 @JSONController.error_handler
181
182 @JSONController.error_handler
188
189 @JSONController.error_handler
191 """
192 list applicable errata for a given repo.
193 filter by errata type if any
194 """
195 valid_filters = ('type')
196 types = self.filters(valid_filters)['type']
197 return self.ok(api.errata(id, types))
198
199 @JSONController.error_handler
200 @RoleCheck(consumer=True, admin=True)
201 - def GET(self, id, field_name):
202 field = getattr(self, field_name, None)
203 if field is None:
204 return self.internal_server_error('No implementation for %s found' % field_name)
205 return field(id)
206
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223 exposed_actions = (
224 'sync',
225 'upload',
226 'add_package',
227 'get_package',
228 'add_packages_to_group',
229 'delete_package_from_group',
230 'delete_packagegroup',
231 'create_packagegroup',
232 'add_errata',
233 'list_errata',
234 'delete_errata',
235 )
236
237 @JSONController.error_handler
238 @RoleCheck(admin=True)
239 - def sync(self, id):
255
256 @JSONController.error_handler
257 @RoleCheck(admin=True)
259 """
260 Upload a package to a repository.
261 @param id: repository id
262 @return: True on successful upload
263 """
264 data = self.params()
265 api.upload(id,
266 data['pkginfo'],
267 data['pkgstream'])
268 return self.ok(True)
269
270 @JSONController.error_handler
271 @RoleCheck(admin=True)
273 """
274 @param id: repository id
275 @return: True on successful addition of package to repository
276 """
277 data = self.params()
278 api.add_package(id, data['packageid'])
279 return self.ok(True)
280
281 @JSONController.error_handler
282 @RoleCheck(admin=True)
284 """
285 Get package info from a repository.
286 @deprecated: user deferred fields: packages with filters instead
287 @param id: repository id
288 @return: matched package object available in corresponding repository
289 """
290 name = self.params()
291 return self.ok(api.get_package(id, name))
292
293 @JSONController.error_handler
294 @RoleCheck(admin=True)
296 """
297 Add a package to an existing package group
298 @param id: repository id
299 @return: True/False
300 """
301 p = self.params()
302 if "groupid" not in p:
303 return self.not_found('No groupid specified')
304 if "packagenames" not in p:
305 return self.not_found('No package name specified')
306 groupid = p["groupid"]
307 pkg_names = p.get('packagenames', [])
308 gtype = "default"
309 if p.has_key("type"):
310 gtype = p["type"]
311 return self.ok(api.add_packages_to_group(id, groupid, pkg_names, gtype))
312
313 @JSONController.error_handler
314 @RoleCheck(admin=True)
316 """
317 Removes a package from an existing package group
318 @param id: repository id
319 @return: True/False
320 """
321 p = self.params()
322 if "groupid" not in p:
323 return self.not_found('No groupid specified')
324 if "name" not in p:
325 return self.not_found('No package name specified')
326 groupid = p["groupid"]
327 pkg_name = p["name"]
328 gtype = "default"
329 if p.has_key("type"):
330 gtype = p["type"]
331 return self.ok(api.delete_package_from_group(id, groupid, pkg_name, gtype))
332
333 @JSONController.error_handler
334 @RoleCheck(admin=True)
336 """
337 Creates a packagegroup in the referenced repository
338 @param id: repository id
339 @return:
340 """
341 p = self.params()
342 if "groupid" not in p:
343 return self.not_found('No groupid specified')
344 groupid = p["groupid"]
345 if "groupname" not in p:
346 return self.not_found('No groupname specified')
347 groupname = p["groupname"]
348 if "description" not in p:
349 return self.not_found('No description specified')
350 descrp = p["description"]
351 return self.ok(api.create_packagegroup(id, groupid, groupname,
352 descrp))
353
354 @JSONController.error_handler
355 @RoleCheck(admin=True)
357 """
358 Removes a packagegroup from a repository
359 @param id: repository id
360 @return:
361 """
362 p = self.params()
363 if "groupid" not in p:
364 return self.not_found('No groupid specified')
365 groupid = p["groupid"]
366 return self.ok(api.delete_packagegroup(id, groupid))
367
368 @JSONController.error_handler
369 @RoleCheck(admin=True)
371 """
372 @param id: repository id
373 @return: True on successful addition of errata to repository
374 """
375 data = self.params()
376 api.add_errata(id, data['errataid'])
377 return self.ok(True)
378
379 @JSONController.error_handler
380 @RoleCheck(admin=True)
382 """
383 @param id: repository id
384 @return: True on successful deletion of errata from repository
385 """
386 data = self.params()
387 api.delete_errata(id, data['errataid'])
388 return self.ok(True)
389
390 @JSONController.error_handler
391 @RoleCheck(admin=True)
393 """
394 list applicable errata for a given repo.
395 filter by errata type if any
396 """
397 data = self.params()
398 return self.ok(api.errata(id, data['types']))
399
400 @JSONController.error_handler
401 @RoleCheck(admin=True)
402 - def POST(self, id, action_name):
403 """
404 Action dispatcher. This method checks to see if the action is exposed,
405 and if so, implemented. It then calls the corresponding method (named
406 the same as the action) to handle the request.
407 @type id: str
408 @param id: repository id
409 @type action_name: str
410 @param action_name: name of the action
411 @return: http response
412 """
413 repo = api.repository(id, fields=['id'])
414 if not repo:
415 return self.not_found('No repository with id %s found' % id)
416 action = getattr(self, action_name, None)
417 if action is None:
418 return self.internal_server_error('No implementation for %s found' % action_name)
419 return action(id)
420
423
424 @JSONController.error_handler
425 @RoleCheck(admin=True)
426 - def GET(self, id, action_name, action_id):
427 """
428 Check the status of a sync operation.
429 @param id: repository id
430 @param action_name: name of the action
431 @param action_id: action id
432 @return: action status information
433 """
434 task_info = self.task_status(action_id)
435 if task_info is None:
436 return self.not_found('No %s with id %s found' % (action_name, action_id))
437 return self.ok(task_info)
438
439 @JSONController.error_handler
440 @RoleCheck(admin=True)
441 - def DELETE(self, id, action_name, action_id):
454
457
458 @JSONController.error_handler
459 @RoleCheck(admin=True)
461 '''
462 Retrieve a map of all repository IDs to their associated synchronization
463 schedules.
464
465 @return: key - repository ID, value - synchronization schedule
466 '''
467
468
469 schedules = api.all_schedules()
470 return self.ok(schedules)
471
472
473
474 urls = (
475 '/$', 'Repositories',
476 '/schedules/', 'Schedules',
477 '/([^/]+)/$', 'Repository',
478
479 '/([^/]+)/(%s)/$' % '|'.join(RepositoryDeferredFields.exposed_fields),
480 'RepositoryDeferredFields',
481
482 '/([^/]+)/(%s)/$' % '|'.join(RepositoryActions.exposed_actions),
483 'RepositoryActions',
484
485 '/([^/]+)/(%s)/([^/]+)/$' % '|'.join(RepositoryActions.exposed_actions),
486 'RepositoryActionStatus',
487 )
488
489 application = web.application(urls, globals())
490