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

Source Code for Module pulp.server.api.consumer_history

  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  ''' 
 17  Consumer history related API methods. 
 18  ''' 
 19   
 20  # Python 
 21  import logging 
 22   
 23  # 3rd Party 
 24  import pymongo 
 25   
 26  # Pulp 
 27  from pulp.server.api.base import BaseApi 
 28  from pulp.server.db.connection import get_object_db 
 29  from pulp.server.db.model import ConsumerHistoryEvent 
 30  from pulp.server.pexceptions import PulpException 
 31   
 32   
 33  # -- constants ---------------------------------------- 
 34   
 35  LOG = logging.getLogger(__name__) 
 36   
 37  # Event Types 
 38  TYPE_CONSUMER_CREATED = 'consumer_created' 
 39  TYPE_CONSUMER_DELETED = 'consumer_deleted' 
 40  TYPE_REPO_BOUND = 'repo_bound' 
 41  TYPE_REPO_UNBOUND = 'repo_unbound' 
 42  TYPE_PACKAGE_INSTALLED = 'package_installed' 
 43  TYPE_PACKAGE_UNINSTALLED = 'package_uninstalled' 
 44  TYPE_PROFILE_CHANGED = 'profile_changed' 
 45   
 46  TYPES = (TYPE_CONSUMER_CREATED, TYPE_CONSUMER_DELETED, TYPE_REPO_BOUND, 
 47           TYPE_REPO_UNBOUND, TYPE_PACKAGE_INSTALLED, TYPE_PACKAGE_UNINSTALLED, 
 48           TYPE_PROFILE_CHANGED) 
 49   
 50  # Used to identify an event as triggered by the consumer (as compared to an admin) 
 51  ORIGINATOR_CONSUMER = 'consumer' 
 52   
 53  # Maps user entered query sort parameters to the pymongo representation 
 54  SORT_ASCENDING = 'ascending' 
 55  SORT_DESCENDING = 'descending' 
 56  SORT_DIRECTION = { 
 57      SORT_ASCENDING : pymongo.ASCENDING, 
 58      SORT_DESCENDING : pymongo.DESCENDING, 
 59  } 
 60   
 61   
62 -class ConsumerHistoryApi(BaseApi):
63 64 # -- setup ---------------------------------------- 65
66 - def __init__(self):
67 BaseApi.__init__(self)
68
69 - def _getcollection(self):
70 return get_object_db('consumer_history', 71 self._unique_indexes, 72 self._indexes)
73
74 - def _get_consumer_collection(self):
75 ''' 76 The circular dependency of requiring the consumer API causes issues, so 77 when looking up a consumer as a validation check we go directly to the consumer 78 collection. This method returns a hook to that collection. 79 80 @return: pymongo database connection to the consumer connection 81 @rtype: ? 82 ''' 83 return get_object_db('consumers', 84 ['id'], 85 [])
86 87 # -- public api ---------------------------------------- 88
89 - def query(self, consumer_id=None, event_type=None, limit=None, sort='descending', 90 start_date=None, end_date=None):
91 ''' 92 Queries the consumer history storage. 93 94 @param consumer_id: if specified, events will only be returned for the the 95 consumer referenced; an error is raised if there is no 96 consumer for the given ID 97 @type consumer_id: string or number 98 99 @param event_type: if specified, only events of the given type are returned; 100 an error is raised if the event type mentioned is not listed 101 in the results of the L{event_types} call 102 @type event_type: string (enumeration found in TYPES) 103 104 @param limit: if specified, the query will only return up to this amount of 105 entries; default is to not limit the entries returned 106 @type limit: number greater than zero 107 108 @param sort: indicates the sort direction of the results; results are sorted 109 by timestamp 110 @type sort: string; valid values are 'ascending' and 'descending' 111 112 @param start_date: if specified, no events prior to this date will be returned 113 @type start_date: L{datetime.datetime} 114 115 @param end_date: if specified, no events after this date will be returned 116 @type end_date: L{datetime.datetime} 117 118 @return: list of consumer history entries that match the given parameters; 119 empty list (not None) if no matching entries are found 120 @rtype: list of L{pulp.server.db.model.ConsumerHistoryEvent} instances 121 122 @raise PulpException: if any of the input values are invalid 123 ''' 124 125 # Verify the consumer ID represents a valid consumer 126 if consumer_id: 127 consumer_db = self._get_consumer_collection() 128 if len(list(consumer_db.find({'id' : consumer_id}))) == 0: 129 raise PulpException('Invalid consumer ID [%s]' % consumer_id) 130 131 # Verify the event type is valid 132 if event_type and event_type not in TYPES: 133 raise PulpException('Invalid event type [%s]' % event_type) 134 135 # Verify the limit makes sense 136 if limit is not None and limit < 1: 137 raise PulpException('Invalid limit [%s], limit must be greater than zero' % limit) 138 139 # Verify the sort direction was valid 140 if not sort in SORT_DIRECTION: 141 valid_sorts = ', '.join(SORT_DIRECTION) 142 raise PulpException('Invalid sort direction [%s], valid values [%s]' % (sort, valid_sorts)) 143 144 # Assemble the mongo search parameters 145 search_params = {} 146 if consumer_id: 147 search_params['consumer_id'] = consumer_id 148 if event_type: 149 search_params['type_name'] = event_type 150 151 # Add in date range limits if specified 152 date_range = {} 153 if start_date: 154 date_range['$gt'] = start_date 155 if end_date: 156 date_range['$lt'] = end_date 157 158 if len(date_range) > 0: 159 search_params['timestamp'] = date_range 160 161 # Determine the correct mongo cursor to retrieve 162 if len(search_params) == 0: 163 cursor = self.objectdb.find() 164 else: 165 cursor = self.objectdb.find(search_params) 166 167 # Sort by most recent entry first 168 cursor.sort('timestamp', direction=SORT_DIRECTION[sort]) 169 170 # If a limit was specified, add it to the cursor 171 if limit: 172 cursor.limit(limit) 173 174 # Finally convert to a list before returning 175 return list(cursor)
176
177 - def event_types(self):
178 return TYPES
179 180 # -- internal ---------------------------------------- 181
182 - def consumer_created(self, consumer_id, originator=ORIGINATOR_CONSUMER):
183 ''' 184 Creates a new event to represent a consumer being created. 185 186 @param consumer_id: identifies the newly created consumer 187 @type consumer_id: string or number 188 189 @param originator: if specified, should be the username of the admin who created 190 the consumer through the admin API; defaults to indicate the 191 create was triggered by the consumer itself 192 @type originator: string 193 ''' 194 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_CONSUMER_CREATED, None) 195 self.insert(event)
196
197 - def consumer_deleted(self, consumer_id, originator=ORIGINATOR_CONSUMER):
198 ''' 199 Creates a new event to represent a consumer being deleted. 200 201 @param consumer_id: identifies the deleted consumer 202 @type consumer_id: string or number 203 204 @param originator: if specified, should be the username of the admin who deleted 205 the consumer through the admin API; defaults to indicate the 206 create was triggered by the consumer itself 207 @type originator: string 208 ''' 209 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_CONSUMER_DELETED, None) 210 self.insert(event)
211
212 - def repo_bound(self, consumer_id, repo_id, originator=ORIGINATOR_CONSUMER):
213 ''' 214 Creates a new event to represent a consumer binding to a repo. 215 216 @param consumer_id: identifies the consumer being modified 217 @type consumer_id: string or number 218 219 @param repo_id: identifies the repo being bound to the consumer 220 @type repo_id: string or number 221 222 @param originator: if specified, should be the username of the admin who bound 223 the repo through the admin API; defaults to indicate the 224 create was triggered by the consumer itself 225 @type originator: string 226 ''' 227 details = {'repo_id' : repo_id} 228 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_REPO_BOUND, details) 229 self.insert(event)
230
231 - def repo_unbound(self, consumer_id, repo_id, originator=ORIGINATOR_CONSUMER):
232 ''' 233 Creates a new event to represent removing a binding from a repo. 234 235 @param consumer_id: identifies the consumer being modified 236 @type consumer_id: string or number 237 238 @param repo_id: identifies the repo being unbound from the consumer 239 @type repo_id: string or number 240 241 @param originator: if specified, should be the username of the admin who unbound 242 the repo through the admin API; defaults to indicate the 243 create was triggered by the consumer itself 244 @type originator: string 245 ''' 246 details = {'repo_id' : repo_id} 247 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_REPO_UNBOUND, details) 248 self.insert(event)
249
250 - def packages_installed(self, consumer_id, package_nveras, originator=ORIGINATOR_CONSUMER):
251 ''' 252 Creates a new event to represent packages that were installed on a consumer. 253 254 @param consumer_id: identifies the consumer being modified 255 @type consumer_id: string or number 256 257 @param package_nveras: identifies the packages that were installed on the consumer 258 @type package_nveras: list or string; a single string will automatically be wrapped 259 in a list 260 261 @param originator: if specified, should be the username of the admin who installed 262 packages through the admin API; defaults to indicate the 263 create was triggered by the consumer itself 264 @type originator: string 265 ''' 266 if type(package_nveras) != list: 267 package_nveras = [package_nveras] 268 269 details = {'package_nveras' : package_nveras} 270 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_PACKAGE_INSTALLED, details) 271 self.insert(event)
272
273 - def packages_removed(self, consumer_id, package_nveras, originator=ORIGINATOR_CONSUMER):
274 ''' 275 Creates a new event to represent packages that were removed from a consumer. 276 277 @param consumer_id: identifies the consumer being modified 278 @type consumer_id: string or number 279 280 @param package_nveras: identifies the packages that were removed from the consumer 281 @type package_nveras: list or string; a single string will automatically be wrapped 282 in a list 283 284 @param originator: if specified, should be the username of the admin who removed 285 packages through the admin API; defaults to indicate the 286 create was triggered by the consumer itself 287 @type originator: string 288 ''' 289 if type(package_nveras) != list: 290 package_nveras = [package_nveras] 291 292 details = {'package_nveras' : package_nveras} 293 event = ConsumerHistoryEvent(consumer_id, originator, TYPE_PACKAGE_UNINSTALLED, details) 294 self.insert(event)
295