Package pulp :: Package server :: Package api :: Module consumer
[hide private]
[frames] | no frames]

Source Code for Module pulp.server.api.consumer

  1  #!/usr/bin/python 
  2  # 
  3  # Copyright (c) 2010 Red Hat, Inc. 
  4  # 
  5  # This software is licensed to you under the GNU General Public License, 
  6  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  7  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  8  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  9  # along with this software; if not, see 
 10  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 11  # 
 12  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 13  # granted to use or replicate Red Hat trademarks that are incorporated 
 14  # in this software or its documentation. 
 15   
 16  import logging 
 17   
 18  # Pulp 
 19  import pulp.server.auth.cert_generator as cert_generator 
 20  from pulp.server.agent import Agent 
 21  from pulp.server.api.base import BaseApi 
 22  from pulp.server.api.consumer_history import ConsumerHistoryApi 
 23  from pulp.server.api.errata import ErrataApi 
 24  from pulp.server.api.package import PackageApi 
 25  from pulp.server.api.repo import RepoApi 
 26  from pulp.server.auditing import audit 
 27  from pulp.server.db import model 
 28  from pulp.server.db.connection import get_object_db 
 29  from pulp.server.pexceptions import PulpException 
 30  from pulp.server.util import chunks, compare_packages 
 31   
 32   
 33  log = logging.getLogger(__name__) 
 34       
 35  consumer_fields = model.Consumer(None, None).keys() 
36 37 38 -class ConsumerApi(BaseApi):
39
40 - def __init__(self):
41 BaseApi.__init__(self) 42 self.errataapi = ErrataApi() 43 self.repoapi = RepoApi() 44 self.packageapi = PackageApi() 45 self.consumer_history_api = ConsumerHistoryApi()
46
47 - def _getcollection(self):
48 return get_object_db('consumers', 49 self._unique_indexes, 50 self._indexes)
51 52 @property
53 - def _unique_indexes(self):
54 return ["id"]
55 56 @property
57 - def _indexes(self):
58 return ["package_profile.name", "repoids"]
59 60 @audit(params=['id'])
61 - def create(self, id, description):
62 """ 63 Create a new Consumer object and return it 64 """ 65 consumer = self.consumer(id) 66 if(consumer): 67 raise PulpException("Consumer [%s] already exists" % id) 68 c = model.Consumer(id, description) 69 self.insert(c) 70 self.consumer_history_api.consumer_created(c.id) 71 return c
72 73 @audit()
74 - def delete(self, id):
75 consumer = self.consumer(id) 76 if not consumer: 77 raise PulpException('Consumer [%s] does not exist', id) 78 self.objectdb.remove(consumer, safe=True) 79 self.consumer_history_api.consumer_deleted(id)
80 81 @audit()
82 - def certificate(self, id):
83 """ 84 Create a X509 Consumer Identity Certificate to associate with the 85 given Consumer 86 """ 87 consumer = self.consumer(id) 88 if not consumer: 89 raise PulpException('Consumer [%s] not found', id) 90 private_key, cert = cert_generator.make_cert(id) 91 return (private_key, cert)
92 93 @audit()
94 - def bulkcreate(self, consumers):
95 """ 96 Create a set of Consumer objects in a bulk manner 97 @type consumers: list of dictionaries 98 @param consumers: dictionaries representing new consumers 99 """ 100 ## Have to chunk this because of issue with PyMongo and network 101 ## See: http://tinyurl.com/2eyumnc 102 chunksize = 50 103 chunked = chunks(consumers, chunksize) 104 inserted = 0 105 for chunk in chunked: 106 self.objectdb.insert(chunk, check_keys=False, safe=False) 107 inserted = inserted + chunksize
108
109 - def consumers(self, spec=None, fields=None):
110 """ 111 List all consumers. Can be quite large 112 """ 113 return list(self.objectdb.find(spec=spec, fields=fields))
114
115 - def consumer(self, id, fields=None):
116 """ 117 Return a single Consumer object 118 """ 119 consumers = self.consumers({'id': id}, fields) 120 if not consumers: 121 return None 122 return consumers[0]
123
124 - def packages(self, id):
125 consumer = self.consumer(id) 126 if consumer is None: 127 raise PulpException('Consumer [%s] not found', id) 128 return consumer.get('package_profile', [])
129
130 - def consumers_with_package_names(self, names, fields=None):
131 """ 132 List consumers using passed in names 133 """ 134 consumers = [] 135 for name in names: 136 #consumers.extend(self.objectdb.find({'package_profile.name': name}, fields)) 137 consumers.extend(self.consumers({'package_profile.name': name}, fields)) 138 return consumers
139 140 @audit()
141 - def bind(self, id, repoid):
142 """ 143 Bind (subscribe) a consumer to a repo. 144 @param id: A consumer id. 145 @type id: str 146 @param repoid: A repo id to bind. 147 @type repoid: str 148 @raise PulpException: When consumer not found. 149 """ 150 consumer = self.consumer(id) 151 if consumer is None: 152 raise PulpException('Consumer [%s] not found', id) 153 repoids = consumer.setdefault('repoids', []) 154 if repoid in repoids: 155 return 156 repoids.append(repoid) 157 self.update(consumer) 158 self.consumer_history_api.repo_bound(id, repoid)
159 160 @audit()
161 - def unbind(self, id, repoid):
162 """ 163 Unbind (unsubscribe) a consumer to a repo. 164 @param id: A consumer id. 165 @type id: str 166 @param repoid: A repo id to unbind. 167 @type repoid: str 168 @raise PulpException: When consumer not found. 169 """ 170 consumer = self.consumer(id) 171 if consumer is None: 172 raise PulpException('Consumer [%s] not found', id) 173 repoids = consumer.setdefault('repoids', []) 174 if repoid not in repoids: 175 return 176 repoids.remove(repoid) 177 self.update(consumer) 178 self.consumer_history_api.repo_unbound(id, repoid)
179 180 @audit(params=['id'])
181 - def profile_update(self, id, package_profile):
182 """ 183 Update the consumer information such as package profile 184 """ 185 consumer = self.consumer(id) 186 if consumer is None: 187 raise PulpException('Consumer [%s] not found', id) 188 consumer["package_profile"] = package_profile 189 self.update(consumer)
190 191 @audit()
192 - def installpackages(self, id, packagenames=()):
193 """ 194 Install packages on the consumer. 195 @param id: A consumer id. 196 @type id: str 197 @param packagenames: The package names to install. 198 @type packagenames: [str,..] 199 """ 200 agent = Agent(id) 201 data = [] 202 for pkg in packagenames: 203 info = pkg.split('.') 204 if len(info) > 1: 205 data.append(('.'.join(info[:-1]), info[-1])) 206 else: 207 data.append(pkg) 208 log.debug("Packages to Install: %s" % data) 209 installed_packages = agent.packages.install(data) 210 self.consumer_history_api.packages_installed(id, installed_packages) 211 return installed_packages
212 213 @audit()
214 - def installpackagegroups(self, id, packageids=()):
215 """ 216 Install package groups on the consumer. 217 @param id: A consumer id. 218 @type id: str 219 @param packageids: The package ids to install. 220 @type packageids: [str,..] 221 """ 222 agent = Agent(id) 223 agent.packagegroups.install(packageids) 224 return packageids
225
226 - def installerrata(self, id, errataids=(), types=()):
227 """ 228 Install errata on the consumer. 229 @param id: A consumer id. 230 @type id: str 231 @param errataids: The errata ids to install. 232 @type errataids: [str,..] 233 @param types: Errata type filter 234 @type types: str 235 """ 236 agent = Agent(id) 237 consumer = self.consumer(id) 238 pkgs = [] 239 if errataids: 240 applicable_errata = self._applicable_errata(consumer, types) 241 for eid in errataids: 242 for pobj in applicable_errata[eid]: 243 if pobj["arch"] != "src": 244 pkgs.append(pobj["name"]) 245 else: 246 #apply all updates 247 pkgobjs = self.list_package_updates(id, types) 248 for pobj in pkgobjs: 249 if pobj["arch"] != "src": 250 pkgs.append(pobj["name"]) 251 log.error("Packages to install [%s]" % pkgs) 252 agent.packages.install(pkgs) 253 return pkgs
254
255 - def listerrata(self, id, types=()):
256 """ 257 List applicable errata for a given consumer id 258 """ 259 consumer = self.consumer(id) 260 return self._applicable_errata(consumer, types).keys()
261
262 - def list_package_updates(self, id, types=()):
263 """ 264 List applicable package updates for a given consumer id 265 """ 266 consumer = self.consumer(id) 267 return [ item for etype in self._applicable_errata(consumer, types).values() \ 268 for item in etype ]
269
270 - def _applicable_errata(self, consumer, types=()):
271 """ 272 Logic to filter applicable errata for a consumer 273 """ 274 applicable_errata = {} 275 pkg_profile = consumer["package_profile"] 276 277 pkg_profile_dict = [dict(pkg) for pkg in pkg_profile] 278 pkg_profile_names = [pkg['name'] for pkg in pkg_profile] 279 280 #Compute applicable errata by subscribed repos 281 errataids = [eid for repoid in consumer["repoids"] \ 282 for eid in self.repoapi.errata(repoid, types) ] 283 for erratumid in errataids: 284 # compare errata packages to consumer package profile and 285 # extract applicable errata 286 erratum = self.errataapi.erratum(erratumid) 287 for epkg in erratum["pkglist"]: 288 for pkg in epkg["packages"]: 289 epkg_info = { 290 'name': pkg["name"], 291 'version': pkg["version"], 292 'arch': pkg["arch"], 293 'epoch': pkg["epoch"] or 0, 294 'release': pkg["release"], 295 } 296 if epkg_info['name'] not in pkg_profile_names: 297 #if errata pkg not in installed profile, update is not 298 # applicable move on 299 continue 300 for ppkg in pkg_profile_dict: 301 if epkg_info['name'] != ppkg['name']: 302 continue 303 304 status = compare_packages(epkg_info, ppkg) 305 if status == 1: 306 # erratum pkg is newer, add to update list 307 if not applicable_errata.has_key(erratumid): 308 applicable_errata[erratumid] = [] 309 applicable_errata[erratumid].append(pkg) 310 return applicable_errata
311