Package entropy :: Package client :: Package services :: Package ugc :: Module commands

Source Code for Module entropy.client.services.ugc.commands

  1  # -*- coding: utf-8 -*- 
  2  """ 
  3   
  4      @author: Fabio Erculiani <lxnay@sabayonlinux.org> 
  5      @contact: lxnay@sabayonlinux.org 
  6      @copyright: Fabio Erculiani 
  7      @license: GPL-2 
  8   
  9      B{Entropy Client Services UGC Base Commands}. 
 10   
 11  """ 
 12   
 13  import os 
 14  from entropy.exceptions import * 
 15  from entropy.const import etpConst, const_get_stringtype, const_debug_write 
 16  from entropy.output import darkblue, bold, blue, darkgreen, darkred, brown 
 17  from entropy.i18n import _ 
 18  from entropy.core.settings.base import SystemSettings 
 19   
20 -class Base:
21
22 - def __init__(self, OutputInterface, Service):
23 24 if not hasattr(OutputInterface, 'updateProgress'): 25 mytxt = _("OutputInterface does not have an updateProgress method") 26 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface, mytxt,)) 27 elif not hasattr(OutputInterface.updateProgress, '__call__'): 28 mytxt = _("OutputInterface does not have an updateProgress method") 29 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface, mytxt,)) 30 31 from entropy.services.ugc.interfaces import Client as Cl 32 if not isinstance(Service, Cl): 33 mytxt = _("A valid entropy.services.ugc.interfaces.Client based instance is needed") 34 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (Service, mytxt,)) 35 36 import socket, zlib, struct 37 import entropy.tools as entropyTools 38 import entropy.dump as dumpTools 39 self.entropyTools, self.socket, self.zlib, self.struct, \ 40 self.dumpTools = entropyTools, socket, zlib, struct, dumpTools 41 self.Output = OutputInterface 42 self.Service = Service 43 self.output_header = '' 44 self.SystemSettings = SystemSettings() 45 self.standard_answers_map = { 46 'all_fine': 0, 47 'not_supported_remotely': 1, 48 'service_temp_not_avail': 2, 49 'command_failed': 3, 50 'wrong_answer': 4, 51 }
52 53
54 - def handle_standard_answer(self, data, repository = None, arch = None, 55 product = None):
56 57 do_skip = False 58 answer_id = self.standard_answers_map['all_fine'] 59 60 # elaborate answer 61 if data == None: 62 mytxt = _("feature not supported remotely") 63 self.Output.updateProgress( 64 "[%s:%s|%s:%s|%s:%s] %s" % ( 65 darkblue(_("repo")), 66 bold(str(repository)), 67 darkred(_("arch")), 68 bold(str(arch)), 69 darkgreen(_("product")), 70 bold(str(product)), 71 blue(mytxt), 72 ), 73 importance = 1, 74 type = "error", 75 header = self.output_header 76 ) 77 do_skip = True 78 answer_id = self.standard_answers_map['not_supported_remotely'] 79 elif not data: 80 mytxt = _("service temporarily not available") 81 self.Output.updateProgress( 82 "[%s:%s|%s:%s|%s:%s] %s" % ( 83 darkblue(_("repo")), 84 bold(str(repository)), 85 darkred(_("arch")), 86 bold(str(arch)), 87 darkgreen(_("product")), 88 bold(str(product)), 89 blue(mytxt), 90 ), 91 importance = 1, 92 type = "error", 93 header = self.output_header 94 ) 95 do_skip = True 96 answer_id = self.standard_answers_map['service_temp_not_avail'] 97 elif data == self.Service.answers['no']: 98 # command failed 99 mytxt = _("command failed") 100 self.Output.updateProgress( 101 "[%s:%s|%s:%s|%s:%s] %s" % ( 102 darkblue(_("repo")), 103 bold(str(repository)), 104 darkred(_("arch")), 105 bold(str(arch)), 106 darkgreen(_("product")), 107 bold(str(product)), 108 blue(mytxt), 109 ), 110 importance = 1, 111 type = "error", 112 header = self.output_header 113 ) 114 do_skip = True 115 answer_id = self.standard_answers_map['command_failed'] 116 elif data != self.Service.answers['ok']: 117 mytxt = _("received wrong answer") 118 119 # do not spam terminal 120 if isinstance(data, const_get_stringtype()): 121 if len(data) > 10: 122 data = data[:10] + "[...]" 123 124 self.Output.updateProgress( 125 "[%s:%s|%s:%s|%s:%s] %s: %s" % ( 126 darkblue(_("repo")), 127 bold(str(repository)), 128 darkred(_("arch")), 129 bold(str(arch)), 130 darkgreen(_("product")), 131 bold(str(product)), 132 blue(mytxt), 133 repr(data), 134 ), 135 importance = 1, 136 type = "error", 137 header = self.output_header 138 ) 139 do_skip = True 140 answer_id = self.standard_answers_map['wrong_answer'] 141 142 return do_skip, answer_id
143
144 - def get_result(self, session):
145 # get the information 146 cmd = "%s rc" % (session,) 147 self.Service.transmit(cmd) 148 try: 149 data = self.Service.receive() 150 return data 151 except: 152 self.entropyTools.print_traceback() 153 return None
154
155 - def convert_stream_to_object(self, data, gzipped, repository = None, arch = None, product = None):
156 157 # unstream object 158 error = False 159 try: 160 data = self.Service.stream_to_object(data, gzipped) 161 except (EOFError, IOError, self.zlib.error, self.dumpTools.pickle.UnpicklingError,): 162 const_debug_write(__name__, self.entropyTools.get_traceback()) 163 mytxt = _("cannot convert stream into object") 164 self.Output.updateProgress( 165 "[%s:%s|%s:%s|%s:%s] %s" % ( 166 darkblue(_("repo")), 167 bold(str(repository)), 168 darkred(_("arch")), 169 bold(str(arch)), 170 darkgreen(_("product")), 171 bold(str(product)), 172 blue(mytxt), 173 ), 174 importance = 1, 175 type = "error", 176 header = self.output_header 177 ) 178 data = None 179 error = True 180 return data, error
181
182 - def retrieve_command_answer(self, cmd, session_id, repository = None, arch = None, product = None, compression = False):
183 184 tries = 3 185 lasterr = None 186 while True: 187 188 if tries <= 0: 189 return lasterr 190 tries -= 1 191 192 try: 193 # send command 194 self.Service.transmit(cmd) 195 except (SSLError,): 196 return None 197 # receive answer 198 data = self.Service.receive() 199 200 skip, answer_id = self.handle_standard_answer(data, repository, 201 arch, product) 202 if skip: 203 if tries <= 0: 204 const_debug_write(__name__, 205 darkred("skipping command, NOT reconnecting")) 206 else: 207 const_debug_write(__name__, 208 darkred("skipping command, reconnect+retry!")) 209 const_debug_write(__name__, str(answer_id)) 210 # reconnect host and retry 211 self.Service.reconnect_socket() 212 continue 213 214 data = self.get_result(session_id) 215 if data == None: 216 lasterr = None 217 continue 218 elif not data: 219 lasterr = False 220 continue 221 222 objdata, error = self.convert_stream_to_object(data, compression, repository, arch, product) 223 if not error: 224 return objdata
225
226 - def do_generic_handler(self, cmd, session_id, tries = 10, compression = False):
227 228 self.Service.check_socket_connection() 229 230 while True: 231 try: 232 result = self.retrieve_command_answer(cmd, session_id, compression = compression) 233 if result == None: 234 return False, 'command not supported' # untranslated on purpose 235 return result 236 except (self.socket.error, self.struct.error,): 237 self.Service.reconnect_socket() 238 tries -= 1 239 if tries < 1: 240 raise
241
242 - def set_gzip_compression(self, session, do):
243 self.Service.check_socket_connection() 244 cmd = "%s %s %s %s zlib" % (session, 'session_config', 'compression', do,) 245 self.Service.transmit(cmd) 246 data = self.Service.receive() 247 if data == self.Service.answers['ok']: 248 return True 249 return False
250
251 - def service_login(self, username, password, session_id):
252 253 cmd = "%s %s %s %s" % ( 254 session_id, 255 'login', 256 username, 257 password, 258 ) 259 return self.do_generic_handler(cmd, session_id)
260
261 - def service_logout(self, username, session_id):
262 263 cmd = "%s %s %s" % ( 264 session_id, 265 'logout', 266 username, 267 ) 268 return self.do_generic_handler(cmd, session_id)
269
270 - def get_logged_user_data(self, session_id):
271 272 cmd = "%s %s" % ( 273 session_id, 274 'user_data', 275 ) 276 return self.do_generic_handler(cmd, session_id)
277
278 - def is_user(self, session_id):
279 280 cmd = "%s %s" % ( 281 session_id, 282 'is_user', 283 ) 284 return self.do_generic_handler(cmd, session_id)
285
286 - def is_developer(self, session_id):
287 288 cmd = "%s %s" % ( 289 session_id, 290 'is_developer', 291 ) 292 return self.do_generic_handler(cmd, session_id)
293
294 - def is_moderator(self, session_id):
295 296 cmd = "%s %s" % ( 297 session_id, 298 'is_moderator', 299 ) 300 return self.do_generic_handler(cmd, session_id)
301
302 - def is_administrator(self, session_id):
303 304 cmd = "%s %s" % ( 305 session_id, 306 'is_administrator', 307 ) 308 return self.do_generic_handler(cmd, session_id)
309
310 - def available_commands(self, session_id):
311 312 cmd = "%s %s" % ( 313 session_id, 314 'available_commands', 315 ) 316 return self.do_generic_handler(cmd, session_id)
317 318
319 -class Client(Base):
320
321 - def __init__(self, EntropyInterface, ServiceInterface):
322 Base.__init__(self, EntropyInterface, ServiceInterface)
323
324 - def differential_packages_comparison(self, session_id, idpackages, repository, arch, product):
325 326 myidlist = ' '.join([str(x) for x in idpackages]) 327 cmd = "%s %s %s %s %s %s %s" % ( 328 session_id, 329 'repository_server:dbdiff', 330 repository, 331 arch, 332 product, 333 self.SystemSettings['repositories']['branch'], 334 myidlist, 335 ) 336 337 # enable zlib compression 338 compression = self.set_gzip_compression(session_id, True) 339 340 data = self.do_generic_handler(cmd, session_id, tries = 5, compression = compression) 341 342 # disable compression 343 self.set_gzip_compression(session_id, False) 344 345 return data
346
347 - def get_repository_treeupdates(self, session_id, repository, arch, product):
348 349 cmd = "%s %s %s %s %s %s" % ( 350 session_id, 351 'repository_server:treeupdates', 352 repository, 353 arch, 354 product, 355 self.SystemSettings['repositories']['branch'], 356 ) 357 return self.do_generic_handler(cmd, session_id, tries = 5)
358
359 - def get_package_sets(self, session_id, repository, arch, product):
360 361 cmd = "%s %s %s %s %s %s" % ( 362 session_id, 363 'repository_server:get_package_sets', 364 repository, 365 arch, 366 product, 367 self.SystemSettings['repositories']['branch'], 368 ) 369 return self.do_generic_handler(cmd, session_id, tries = 5)
370
371 - def get_repository_metadata(self, session_id, repository, arch, product):
372 373 cmd = "%s %s %s %s %s %s" % ( 374 session_id, 375 'repository_server:get_repository_metadata', 376 repository, 377 arch, 378 product, 379 self.SystemSettings['repositories']['branch'], 380 ) 381 return self.do_generic_handler(cmd, session_id, tries = 5)
382
383 - def get_strict_package_information(self, session_id, idpackages, repository, arch, product):
384 385 cmd = "%s %s %s %s %s %s %s %s" % ( 386 session_id, 387 'repository_server:pkginfo_strict', 388 True, 389 repository, 390 arch, 391 product, 392 self.SystemSettings['repositories']['branch'], 393 ' '.join([str(x) for x in idpackages]), 394 ) 395 396 # enable zlib compression 397 compression = self.set_gzip_compression(session_id, True) 398 399 data = self.do_generic_handler(cmd, session_id, compression = compression) 400 401 # disable compression 402 self.set_gzip_compression(session_id, False) 403 404 return data
405
406 - def ugc_do_downloads(self, session_id, pkgkeys):
407 408 cmd = "%s %s %s" % ( 409 session_id, 410 'ugc:do_downloads', 411 ' '.join(pkgkeys), 412 ) 413 return self.do_generic_handler(cmd, session_id)
414
415 - def ugc_do_download_stats(self, session_id, package_names):
416 417 sub_lists = self.entropyTools.split_indexable_into_chunks( 418 package_names, 100) 419 420 last_srv_rc_data = None 421 for pkgkeys in sub_lists: 422 423 release_string = '--N/A--' 424 rel_file = etpConst['systemreleasefile'] 425 if os.path.isfile(rel_file) and os.access(rel_file, os.R_OK): 426 with open(rel_file, "r") as f: 427 release_string = f.read(512) 428 429 hw_hash = self.SystemSettings['hw_hash'] 430 if not hw_hash: 431 hw_hash = '' 432 433 mydict = { 434 'branch': self.SystemSettings['repositories']['branch'], 435 'release_string': release_string, 436 'hw_hash': hw_hash, 437 'pkgkeys': ' '.join(pkgkeys), 438 } 439 xml_string = self.entropyTools.xml_from_dict(mydict) 440 441 cmd = "%s %s %s" % ( 442 session_id, 443 'ugc:do_download_stats', 444 xml_string, 445 ) 446 last_srv_rc_data = self.do_generic_handler(cmd, session_id) 447 if not isinstance(last_srv_rc_data, tuple): 448 return last_srv_rc_data 449 elif last_srv_rc_data[0] != True: 450 return last_srv_rc_data 451 return last_srv_rc_data
452
453 - def ugc_get_downloads(self, session_id, pkgkey):
454 455 cmd = "%s %s %s" % ( 456 session_id, 457 'ugc:get_downloads', 458 pkgkey, 459 ) 460 return self.do_generic_handler(cmd, session_id)
461
462 - def ugc_get_alldownloads(self, session_id):
463 464 cmd = "%s %s" % ( 465 session_id, 466 'ugc:get_alldownloads', 467 ) 468 469 # enable zlib compression 470 compression = self.set_gzip_compression(session_id, True) 471 472 rc = self.do_generic_handler(cmd, session_id, compression = compression) 473 474 # disable compression 475 self.set_gzip_compression(session_id, False) 476 477 return rc
478
479 - def ugc_do_vote(self, session_id, pkgkey, vote):
480 481 cmd = "%s %s %s %s" % ( 482 session_id, 483 'ugc:do_vote', 484 pkgkey, 485 vote, 486 ) 487 return self.do_generic_handler(cmd, session_id)
488
489 - def ugc_get_vote(self, session_id, pkgkey):
490 491 cmd = "%s %s %s" % ( 492 session_id, 493 'ugc:get_vote', 494 pkgkey, 495 ) 496 return self.do_generic_handler(cmd, session_id)
497
498 - def ugc_get_allvotes(self, session_id):
499 500 cmd = "%s %s" % ( 501 session_id, 502 'ugc:get_allvotes', 503 ) 504 505 # enable zlib compression 506 compression = self.set_gzip_compression(session_id, True) 507 508 rc = self.do_generic_handler(cmd, session_id, compression = compression) 509 510 # disable compression 511 self.set_gzip_compression(session_id, False) 512 513 return rc
514
515 - def ugc_add_comment(self, session_id, pkgkey, comment, title, keywords):
516 517 mydict = { 518 'comment': comment, 519 'title': title, 520 'keywords': keywords, 521 } 522 xml_string = self.entropyTools.xml_from_dict(mydict) 523 524 cmd = "%s %s %s %s" % ( 525 session_id, 526 'ugc:add_comment', 527 pkgkey, 528 xml_string, 529 ) 530 531 return self.do_generic_handler(cmd, session_id)
532
533 - def ugc_edit_comment(self, session_id, iddoc, new_comment, new_title, new_keywords):
534 535 mydict = { 536 'comment': new_comment, 537 'title': new_title, 538 'keywords': new_keywords, 539 } 540 xml_string = self.entropyTools.xml_from_dict(mydict) 541 542 cmd = "%s %s %s %s" % ( 543 session_id, 544 'ugc:edit_comment', 545 iddoc, 546 xml_string, 547 ) 548 return self.do_generic_handler(cmd, session_id)
549
550 - def ugc_remove_comment(self, session_id, iddoc):
551 552 cmd = "%s %s %s" % ( 553 session_id, 554 'ugc:remove_comment', 555 iddoc, 556 ) 557 return self.do_generic_handler(cmd, session_id)
558
559 - def ugc_remove_image(self, session_id, iddoc):
560 561 cmd = "%s %s %s" % ( 562 session_id, 563 'ugc:remove_image', 564 iddoc, 565 ) 566 return self.do_generic_handler(cmd, session_id)
567
568 - def ugc_remove_file(self, session_id, iddoc):
569 570 cmd = "%s %s %s" % ( 571 session_id, 572 'ugc:remove_file', 573 iddoc, 574 ) 575 return self.do_generic_handler(cmd, session_id)
576
577 - def ugc_remove_youtube_video(self, session_id, iddoc):
578 579 cmd = "%s %s %s" % ( 580 session_id, 581 'ugc:remove_youtube_video', 582 iddoc, 583 ) 584 return self.do_generic_handler(cmd, session_id)
585
586 - def ugc_get_docs(self, session_id, pkgkey):
587 588 cmd = "%s %s %s" % ( 589 session_id, 590 'ugc:get_alldocs', 591 pkgkey, 592 ) 593 return self.do_generic_handler(cmd, session_id)
594
595 - def ugc_get_textdocs(self, session_id, pkgkey):
596 597 cmd = "%s %s %s" % ( 598 session_id, 599 'ugc:get_textdocs', 600 pkgkey, 601 ) 602 return self.do_generic_handler(cmd, session_id)
603
604 - def ugc_get_textdocs_by_identifiers(self, session_id, identifiers):
605 606 cmd = "%s %s %s" % ( 607 session_id, 608 'ugc:get_textdocs_by_identifiers', 609 ' '.join([str(x) for x in identifiers]), 610 ) 611 return self.do_generic_handler(cmd, session_id)
612
613 - def ugc_get_documents_by_identifiers(self, session_id, identifiers):
614 615 cmd = "%s %s %s" % ( 616 session_id, 617 'ugc:get_documents_by_identifiers', 618 ' '.join([str(x) for x in identifiers]), 619 ) 620 return self.do_generic_handler(cmd, session_id)
621
622 - def ugc_send_file_stream(self, session_id, file_path):
623 624 if not (os.path.isfile(file_path) and os.access(file_path, os.R_OK)): 625 return False, False, 'cannot read file_path' 626 627 import zlib 628 # enable stream 629 cmd = "%s %s %s on" % ( 630 session_id, 631 'session_config', 632 'stream', 633 ) 634 status, msg = self.do_generic_handler(cmd, session_id) 635 if not status: 636 return False, status, msg 637 638 # enable zlib compression 639 compression = self.set_gzip_compression(session_id, True) 640 641 # start streamer 642 stream_status = True 643 stream_msg = 'ok' 644 f = open(file_path, "rb") 645 chunk = f.read(8192) 646 base_path = os.path.basename(file_path) 647 transferred = len(chunk) 648 max_size = self.entropyTools.get_file_size(file_path) 649 while chunk: 650 651 if (not self.Service.quiet) or self.Service.show_progress: 652 self.Output.updateProgress( 653 "%s, %s: %s" % ( 654 blue(_("User Generated Content")), 655 darkgreen(_("sending file")), 656 darkred(base_path), 657 ), 658 importance = 1, 659 type = "info", 660 header = brown(" @@ "), 661 back = True, 662 count = (transferred, max_size,), 663 percent = True 664 ) 665 666 chunk = zlib.compress(chunk, 7) # compression level 1-9 667 cmd = "%s %s %s" % ( 668 session_id, 669 'stream', 670 chunk, 671 ) 672 status, msg = self.do_generic_handler(cmd, session_id, compression = compression) 673 if not status: 674 stream_status = status 675 stream_msg = msg 676 break 677 chunk = f.read(8192) 678 transferred += len(chunk) 679 680 f.close() 681 682 # disable compression 683 self.set_gzip_compression(session_id, False) 684 685 # disable config 686 cmd = "%s %s %s off" % ( 687 session_id, 688 'session_config', 689 'stream', 690 ) 691 status, msg = self.do_generic_handler(cmd, session_id) 692 if not status: 693 return False, status, msg 694 695 return True, stream_status, stream_msg
696
697 - def ugc_send_file(self, session_id, pkgkey, file_path, doc_type, title, description, keywords):
698 699 status, rem_status, err_msg = self.ugc_send_file_stream(session_id, file_path) 700 if not (status and rem_status): 701 return False, err_msg 702 703 mydict = { 704 'doc_type': str(doc_type), 705 'title': title, 706 'description': description, 707 'keywords': keywords, 708 'file_name': os.path.join(pkgkey, os.path.basename(file_path)), 709 'real_filename': os.path.basename(file_path), 710 } 711 xml_string = self.entropyTools.xml_from_dict(mydict) 712 713 cmd = "%s %s %s %s" % ( 714 session_id, 715 'ugc:register_stream', 716 pkgkey, 717 xml_string, 718 ) 719 return self.do_generic_handler(cmd, session_id)
720
721 - def report_error(self, session_id, error_data):
722 723 import zlib 724 xml_string = self.entropyTools.xml_from_dict_extended(error_data) 725 xml_comp_string = zlib.compress(xml_string) 726 727 cmd = "%s %s %s" % ( 728 session_id, 729 'ugc:report_error', 730 xml_comp_string, 731 ) 732 733 return self.do_generic_handler(cmd, session_id)
734