Package backend :: Package server :: Package handlers :: Package xmlrpc :: Module abrt
[hide private]
[frames] | no frames]

Source Code for Module backend.server.handlers.xmlrpc.abrt

  1  # 
  2  # Copyright (c) 2012--2016 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15   
 16  import base64 
 17  import os 
 18  import stat 
 19   
 20  from spacewalk.common.rhnException import rhnFault 
 21  from spacewalk.common.rhnConfig import CFG 
 22  from spacewalk.common.rhnLib import parseRPMName 
 23  from spacewalk.common.rhnLog import log_debug 
 24  from spacewalk.server import rhnSQL 
 25  from spacewalk.server.rhnHandler import rhnHandler 
 26  from spacewalk.server.rhnLib import get_crash_path, get_crashfile_path 
 27   
 28  _query_get_crash = rhnSQL.Statement(""" 
 29  select id 
 30    from rhnServerCrash 
 31   where server_id = :server_id and 
 32         crash = :crash 
 33  """) 
 34   
 35  _query_create_crash = rhnSQL.Statement(""" 
 36  insert into rhnServerCrash ( 
 37         id, 
 38         server_id, 
 39         crash, 
 40         path, 
 41         count, 
 42         storage_path) 
 43  values ( 
 44         sequence_nextval('rhn_server_crash_id_seq'), 
 45         :server_id, 
 46         :crash, 
 47         :path, 
 48         :crash_count, 
 49         :storage_path) 
 50  """) 
 51   
 52  _query_update_pkg_data1 = rhnSQL.Statement(""" 
 53  update rhnServerCrash 
 54     set package_name_id = lookup_package_name(:pkg_name), 
 55         package_evr_id = lookup_evr(:pkg_epoch, :pkg_version, :pkg_release) 
 56   where id = :crash_id 
 57  """) 
 58   
 59  _query_update_pkg_data2 = rhnSQL.Statement(""" 
 60  update rhnServerCrash 
 61     set package_name_id = lookup_package_name(:pkg_name), 
 62         package_evr_id = lookup_evr(:pkg_epoch, :pkg_version, :pkg_release), 
 63         package_arch_id = lookup_package_arch(:pkg_arch) 
 64   where id = :crash_id 
 65  """) 
 66   
 67  _query_update_watched_items = """ 
 68  update rhnServerCrash 
 69     set %s = :filecontent 
 70   where id = :crash_id 
 71  """ 
 72   
 73  _query_update_crash_count = """ 
 74  update rhnServerCrash 
 75     set count = :crash_count 
 76   where server_id = :server_id and 
 77         crash = :crash 
 78  """ 
 79   
 80  _query_get_crashfile_sizelimit = """ 
 81  select crash_file_sizelimit 
 82    from rhnOrgConfiguration 
 83   where org_id = :org_id 
 84  """ 
 85   
 86  _query_set_crashfile_upload_flag = """ 
 87  update rhnServerCrashFile 
 88     set is_uploaded = 'Y' 
 89   where id = ( 
 90         select scf.id as id 
 91           from rhnServerCrashFile scf, 
 92                rhnServerCrash sc 
 93          where scf.crash_id = sc.id and 
 94                scf.crash_id = :crash_id and 
 95                sc.server_id = :server_id and 
 96                scf.filename = :filename and 
 97                scf.path = :path and 
 98                scf.filesize = :filesize 
 99         ) 
100  """ 
101   
102  _query_get_crash_reporting_settings = """ 
103  select crash_reporting_enabled 
104    from rhnOrgConfiguration 
105   where org_id = :org_id 
106  """ 
107   
108  _query_get_crashfile_upload_settings = """ 
109  select crashfile_upload_enabled 
110    from rhnOrgConfiguration 
111   where org_id = :org_id 
112  """ 
113   
114   
115 -class Abrt(rhnHandler):
116
117 - def __init__(self):
118 rhnHandler.__init__(self) 119 self.functions.append('create_crash') 120 self.functions.append('update_crash_count') 121 self.functions.append('upload_crash_file') 122 self.functions.append('is_crashfile_upload_enabled') 123 self.functions.append('get_crashfile_uploadlimit') 124 125 self.watched_items = ['analyzer', 126 'architecture', 127 'cmdline', 128 'component', 129 'count', 130 'executable', 131 'kernel', 132 'reason', 133 'username', 134 'uuid']
135
136 - def _get_crash_id(self, server_id, crash):
137 h = rhnSQL.prepare(_query_get_crash) 138 h.execute(server_id=self.server_id, crash=crash) 139 r = h.fetchall_dict() 140 141 if (r is None): 142 return None 143 else: 144 return r[0]['id']
145
146 - def _create_or_update_crash_file(self, server_id, crash_id, filename, path, filesize):
147 insert_call = rhnSQL.Function("insert_crash_file", rhnSQL.types.NUMBER()) 148 return insert_call(crash_id, filename, path, filesize)
149
150 - def _update_package_data(self, crash_id, pkg_data):
151 log_debug(1, "_update_package_data: %s, %s" % (crash_id, pkg_data)) 152 # Older versions of abrt used to store the package info in a single 'package' file 153 if pkg_data and 'package' in pkg_data: 154 (n, e, v, r) = parseRPMName(pkg_data['package']) 155 if not all((n, e, v, r)): 156 return 0 157 158 h = rhnSQL.prepare(_query_update_pkg_data1) 159 r = h.execute( 160 crash_id=crash_id, 161 pkg_name=n, 162 pkg_epoch=e, 163 pkg_version=v, 164 pkg_release=r) 165 rhnSQL.commit() 166 167 return r 168 169 for item in ['pkg_name', 'pkg_epoch', 'pkg_version', 'pkg_release', 'pkg_arch']: 170 if not (item in pkg_data and pkg_data[item]): 171 return 0 172 173 h = rhnSQL.prepare(_query_update_pkg_data2) 174 r = h.execute( 175 crash_id=crash_id, 176 pkg_name=pkg_data['pkg_name'], 177 pkg_epoch=pkg_data['pkg_epoch'], 178 pkg_version=pkg_data['pkg_version'], 179 pkg_release=pkg_data['pkg_release'], 180 pkg_arch=pkg_data['pkg_arch']) 181 rhnSQL.commit() 182 183 return r
184
185 - def _get_crashfile_sizelimit(self):
186 h = rhnSQL.prepare(_query_get_crashfile_sizelimit) 187 h.execute(org_id=self.server.server['org_id']) 188 return h.fetchall_dict()[0]['crash_file_sizelimit']
189
190 - def _set_crashfile_upload_flag(self, server_id, crash_id, filename, path, filesize):
191 h = rhnSQL.prepare(_query_set_crashfile_upload_flag) 192 r = h.execute( 193 server_id=server_id, 194 crash_id=crash_id, 195 filename=filename, 196 path=path, 197 filesize=filesize) 198 rhnSQL.commit() 199 200 return r
201
202 - def _is_crash_reporting_enabled(self, org_id):
203 h = rhnSQL.prepare(_query_get_crash_reporting_settings) 204 h.execute(org_id=org_id) 205 r = h.fetchall_dict() 206 207 if (r[0]['crash_reporting_enabled'] == 'Y'): 208 return True 209 else: 210 return False
211
212 - def _is_crashfile_uploading_enabled(self, org_id):
213 h = rhnSQL.prepare(_query_get_crashfile_upload_settings) 214 h.execute(org_id=org_id) 215 r = h.fetchall_dict() 216 217 if (r[0]['crashfile_upload_enabled'] == 'Y'): 218 return True 219 else: 220 return False
221
223 if not self._is_crash_reporting_enabled(self.server.server['org_id']): 224 log_debug(1, "Crash reporting is disabled for this server's organization.") 225 raise rhnFault(5006)
226
227 - def create_crash(self, system_id, crash_data, pkg_data):
228 self.auth_system(system_id) 229 log_debug(1, self.server_id, crash_data, pkg_data) 230 231 self._check_crash_reporting_setting() 232 233 if not ('crash' in crash_data and 'path' in crash_data) or \ 234 not (crash_data['crash'] and crash_data['path']): 235 log_debug(1, self.server_id, "The crash information is invalid or incomplete: %s" % str(crash_data)) 236 raise rhnFault(5000) 237 238 server_org_id = self.server.server['org_id'] 239 server_crash_dir = get_crash_path(str(server_org_id), str(self.server_id), crash_data['crash']) 240 if not server_crash_dir: 241 log_debug(1, self.server_id, "Error composing crash directory path") 242 raise rhnFault(5002) 243 244 crash_id = self._get_crash_id(self.server_id, crash_data['crash']) 245 log_debug(1, "crash_id: %s" % crash_id) 246 247 if (crash_id is None): 248 if 'count' not in crash_data: 249 crash_data['count'] = 1 250 251 h = rhnSQL.prepare(_query_create_crash) 252 h.execute( 253 server_id=self.server_id, 254 crash=crash_data['crash'], 255 path=crash_data['path'], 256 crash_count=crash_data['count'], 257 storage_path=server_crash_dir) 258 rhnSQL.commit() 259 self._update_package_data(self._get_crash_id(self.server_id, crash_data['crash']), pkg_data) 260 return 1 261 else: 262 return 0
263
264 - def upload_crash_file(self, system_id, crash, crash_file):
265 self.auth_system(system_id) 266 self._check_crash_reporting_setting() 267 268 required_keys = ['filename', 'path', 'filesize', 'filecontent', 'content-encoding'] 269 for k in required_keys: 270 if k not in crash_file: 271 log_debug(1, self.server_id, "The crash file data is invalid or incomplete: %s" % crash_file) 272 raise rhnFault(5001, "Missing or invalid key: %s" % k) 273 274 log_debug(1, self.server_id, crash, crash_file['filename']) 275 276 server_org_id = self.server.server['org_id'] 277 server_crash_dir = get_crash_path(str(server_org_id), str(self.server_id), crash) 278 if not server_crash_dir: 279 log_debug(1, self.server_id, "Error composing crash directory path") 280 raise rhnFault(5002) 281 282 server_filename = get_crashfile_path(str(server_org_id), 283 str(self.server_id), 284 crash, 285 crash_file['filename']) 286 if not server_filename: 287 log_debug(1, self.server_id, "Error composing crash file path") 288 raise rhnFault(5003) 289 290 if not crash_file['content-encoding'] == 'base64': 291 log_debug(1, self.server_id, "Invalid content encoding: %s" % crash_file['content-encoding']) 292 raise rhnFault(5004, "Invalid content encodig: %s" % crash_file['content-encoding']) 293 294 crash_id = self._get_crash_id(self.server_id, crash) 295 if not crash_id: 296 log_debug(1, self.server_id, "No record for crash: %s" % crash) 297 raise rhnFault(5005, "Invalid crash name: %s" % crash) 298 299 # Create or update the crash file record in DB 300 self._create_or_update_crash_file(self.server_id, crash_id, crash_file['filename'], 301 crash_file['path'], crash_file['filesize']) 302 rhnSQL.commit() 303 304 # Create the file on filer 305 if not self._is_crashfile_uploading_enabled(server_org_id): 306 return 1 307 filecontent = base64.decodestring(crash_file['filecontent']) 308 claimed_filesize = crash_file['filesize'] 309 filesize = len(filecontent) 310 sizelimit = self._get_crashfile_sizelimit() 311 if (claimed_filesize > sizelimit or filesize > sizelimit) and sizelimit != 0: 312 if filesize == 0: 313 filesize = claimed_filesize 314 log_debug(1, "The file [%s] size (%s bytes) is more than allowed (%s bytes), skipping." 315 % (crash_file['path'], filesize, sizelimit)) 316 return 0 317 absolute_dir = os.path.join(CFG.MOUNT_POINT, server_crash_dir) 318 absolute_file = os.path.join(absolute_dir, crash_file['filename']) 319 320 if not os.path.exists(absolute_dir): 321 log_debug(1, self.server_id, "Creating crash directory: %s" % absolute_dir) 322 os.makedirs(absolute_dir) 323 mode = stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH 324 os.chmod(absolute_dir, mode) 325 os.chmod(os.path.dirname(os.path.normpath(absolute_dir)), mode) 326 327 log_debug(1, self.server_id, "Creating crash file: %s" % absolute_file) 328 f = open(absolute_file, 'w+') 329 f.write(filecontent) 330 f.close() 331 332 self._set_crashfile_upload_flag(self.server_id, crash_id, crash_file['filename'], 333 crash_file['path'], crash_file['filesize']) 334 335 if crash_file['filename'] in self.watched_items: 336 # 'username' contains an extra '\n' at the end 337 if crash_file['filename'] == 'username': 338 filecontent = filecontent.strip() 339 st = rhnSQL.Statement(_query_update_watched_items % crash_file['filename']) 340 h = rhnSQL.prepare(st) 341 h.execute(filecontent=filecontent, crash_id=crash_id) 342 rhnSQL.commit() 343 344 return 1
345
346 - def update_crash_count(self, system_id, crash, crash_count):
347 self.auth_system(system_id) 348 349 log_debug(1, self.server_id, "Updating crash count for %s to %s" % (crash, crash_count)) 350 351 server_org_id = self.server.server['org_id'] 352 server_crash_dir = get_crash_path(str(server_org_id), str(self.server_id), crash) 353 if not server_crash_dir: 354 log_debug(1, self.server_id, "Error composing crash directory path") 355 raise rhnFault(5002) 356 357 h = rhnSQL.prepare(_query_update_crash_count) 358 r = h.execute( 359 crash_count=crash_count, 360 server_id=self.server_id, 361 crash=crash) 362 rhnSQL.commit() 363 364 if r == 0: 365 log_debug(1, self.server_id, "No record for crash: %s" % crash) 366 raise rhnFault(5005, "Invalid crash name: %s" % crash) 367 368 absolute_dir = os.path.join(CFG.MOUNT_POINT, server_crash_dir) 369 absolute_file = os.path.join(absolute_dir, 'count') 370 371 log_debug(1, self.server_id, "Updating crash count file: %s" % absolute_file) 372 f = open(absolute_file, 'w+') 373 f.write(crash_count) 374 f.close() 375 376 return 1
377
378 - def is_crashfile_upload_enabled(self, system_id):
379 self.auth_system(system_id) 380 return self._is_crashfile_uploading_enabled(self.server.server['org_id'])
381
382 - def get_crashfile_uploadlimit(self, system_id):
383 self.auth_system(system_id) 384 return self._get_crashfile_sizelimit()
385