1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22
23 from __future__ import with_statement
24 import os
25 import tempfile
26 import shutil
27 import time
28 from entropy.exceptions import OnlineMirrorError, IncorrectParameter, \
29 ConnectionError, InvalidDataType, EntropyPackageException, FtpError
30 from entropy.output import red, darkgreen, bold, brown, blue, darkred, \
31 darkblue, purple
32 from entropy.const import etpConst, etpSys
33 from entropy.i18n import _
34 from entropy.misc import RSS
35 from entropy.transceivers import FtpInterface
36 from entropy.db import dbapi2
37
39
40 import socket
41 import entropy.dump as dumpTools
42 import entropy.tools as entropyTools
43 - def __init__(self, ServerInstance, repo = None):
44
45 from entropy.server.interfaces.main import Server as MainServer
46 if not isinstance(ServerInstance, MainServer):
47 mytxt = _("entropy.server.interfaces.main.Server needed")
48 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
49
50 self.Entropy = ServerInstance
51 from entropy.transceivers import FtpServerHandler
52 self.FtpServerHandler = FtpServerHandler
53 from entropy.cache import EntropyCacher
54 self.Cacher = EntropyCacher()
55 self.sys_settings_plugin_id = \
56 etpConst['system_settings_plugins_ids']['server_plugin']
57 self.SystemSettings = self.Entropy.SystemSettings
58
59 mytxt = blue("%s:") % (_("Entropy Server Mirrors Interface loaded"),)
60 self.Entropy.updateProgress(
61 mytxt,
62 importance = 2,
63 type = "info",
64 header = red(" @@ ")
65 )
66 mytxt = _("mirror")
67 for mirror in self.Entropy.get_remote_mirrors(repo):
68 mirror = self.entropyTools.hide_ftp_password(mirror)
69 self.Entropy.updateProgress(
70 blue("%s: %s") % (mytxt, darkgreen(mirror),),
71 importance = 0,
72 type = "info",
73 header = brown(" # ")
74 )
75
77 """
78 Returns a list of remotely available branches for the provided
79 repository identifier.
80
81 @keyword repo: repository identifier
82 @type repo: string
83 @return: list of valid, available remote branches
84 @rtype: set
85 """
86
87 if repo == None:
88 repo = self.Entropy.default_repository
89
90 remote_branches = set()
91
92 ts_file = etpConst['etpdatabasetimestampfile']
93 mirrors = self.Entropy.get_remote_mirrors(repo)
94 for uri in mirrors:
95
96 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
97
98 self.Entropy.updateProgress(
99 "[repo:%s] %s: %s" % (
100 brown(repo),
101 blue(_("listing branches in mirror")),
102 darkgreen(crippled_uri),
103 ),
104 importance = 1,
105 type = "info",
106 header = brown(" @@ ")
107 )
108
109 ftp = FtpInterface(uri, self.Entropy, verbose = False)
110 try:
111
112 branches_path = self.Entropy.get_remote_database_relative_path(
113 repo)
114 try:
115 ftp.set_cwd(branches_path)
116 except FtpError:
117 continue
118
119 branches = ftp.list_dir()
120 for branch in branches:
121 mypath = os.path.join("/", branches_path, branch)
122 try:
123 ftp.set_cwd(mypath)
124 except FtpError:
125
126 continue
127 if ftp.is_file_available(ts_file):
128 remote_branches.add(branch)
129
130 finally:
131 ftp.close()
132
133 return remote_branches
134
137 """
138 Reads a file remotely located in all the available branches.
139
140 @param filename: name of the file that should be located inside
141 repository database directory
142 @type filename: string
143 @keyword repo: repository identifier
144 @type repo: string
145 @keyword excluded_branches: list of branch identifiers excluded or None
146 @type excluded_branches: list or None
147 @return: dictionary with branches as key and raw file content as value:
148 {'4': 'abcd\n', '5': 'defg\n'}
149 @rtype: dict
150 """
151 if repo == None:
152 repo = self.Entropy.default_repository
153 if excluded_branches == None:
154 excluded_branches = []
155
156 branch_data = {}
157 mirrors = self.Entropy.get_remote_mirrors(repo)
158 for uri in mirrors:
159
160 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
161
162 self.Entropy.updateProgress(
163 "[repo:%s] %s: %s => %s" % (
164 brown(repo),
165 blue(_("looking for file in mirror")),
166 darkgreen(crippled_uri),
167 filename,
168 ),
169 importance = 1,
170 type = "info",
171 header = brown(" @@ ")
172 )
173
174 ftp = FtpInterface(uri, self.Entropy, verbose = False)
175 try:
176
177 branches_path = self.Entropy.get_remote_database_relative_path(
178 repo)
179 try:
180 ftp.set_cwd(branches_path)
181 except FtpError:
182 continue
183
184 branches = ftp.list_dir()
185 for branch in branches:
186
187
188 if branch in excluded_branches:
189 continue
190
191 if branch_data.get(branch) != None:
192
193 continue
194
195 mypath = os.path.join("/", branches_path, branch)
196 try:
197 ftp.set_cwd(mypath)
198 except FtpError:
199
200 continue
201
202 if not ftp.is_file_available(filename):
203
204 continue
205
206 tmp_dir = tempfile.mkdtemp()
207 tries = 4
208 success = False
209 while tries:
210 downloaded = ftp.download_file(filename, tmp_dir)
211 if not downloaded:
212 tries -= 1
213 continue
214 success = True
215 break
216
217 down_path = os.path.join(tmp_dir, filename)
218 if success and os.access(down_path, os.F_OK):
219 down_f = open(down_path)
220 branch_data[branch] = down_f.read()
221 down_f.close()
222 shutil.rmtree(tmp_dir)
223
224 finally:
225 ftp.close()
226
227 return branch_data
228
229 - def lock_mirrors(self, lock = True, mirrors = None, repo = None):
230
231 if repo == None:
232 repo = self.Entropy.default_repository
233
234 if not mirrors:
235 mirrors = self.Entropy.get_remote_mirrors(repo)
236
237 issues = False
238 for uri in mirrors:
239
240 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
241
242 lock_text = _("unlocking")
243 if lock:
244 lock_text = _("locking")
245 self.Entropy.updateProgress(
246 "[repo:%s|%s] %s %s" % (
247 brown(repo),
248 darkgreen(crippled_uri),
249 bold(lock_text),
250 blue("%s...") % (_("mirror"),),
251 ),
252 importance = 1,
253 type = "info",
254 header = brown(" * "),
255 back = True
256 )
257
258 try:
259 ftp = FtpInterface(uri, self.Entropy)
260 except ConnectionError:
261 self.entropyTools.print_traceback()
262 return True
263 my_path = os.path.join(
264 self.Entropy.get_remote_database_relative_path(repo),
265 self.SystemSettings['repositories']['branch'])
266 ftp.set_cwd(my_path, dodir = True)
267
268 lock_file = etpConst['etpdatabaselockfile']
269 if lock and ftp.is_file_available(lock_file):
270 self.Entropy.updateProgress(
271 "[repo:%s|%s] %s" % (
272 brown(repo),
273 darkgreen(crippled_uri),
274 blue(_("mirror already locked")),
275 ),
276 importance = 1,
277 type = "info",
278 header = darkgreen(" * ")
279 )
280 ftp.close()
281 continue
282 elif not lock and not ftp.is_file_available(lock_file):
283 self.Entropy.updateProgress(
284 "[repo:%s|%s] %s" % (
285 brown(repo),
286 darkgreen(crippled_uri),
287 blue(_("mirror already unlocked")),
288 ),
289 importance = 1,
290 type = "info",
291 header = darkgreen(" * ")
292 )
293 ftp.close()
294 continue
295
296 if lock:
297 rc_lock = self.do_mirror_lock(uri, ftp, repo = repo)
298 else:
299 rc_lock = self.do_mirror_unlock(uri, ftp, repo = repo)
300 ftp.close()
301 if not rc_lock:
302 issues = True
303
304 if not issues:
305 db_taint_file = self.Entropy.get_local_database_taint_file(repo)
306 if os.path.isfile(db_taint_file):
307 os.remove(db_taint_file)
308
309 return issues
310
311
314
315
316
317
318 if mirrors == None:
319 mirrors = []
320
321 if repo == None:
322 repo = self.Entropy.default_repository
323
324 if not mirrors:
325 mirrors = self.Entropy.get_remote_mirrors(repo)
326
327 issues = False
328 for uri in mirrors:
329
330 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
331
332 lock_text = _("unlocking")
333 if lock:
334 lock_text = _("locking")
335 self.Entropy.updateProgress(
336 "[repo:%s|%s] %s %s..." % (
337 blue(repo),
338 red(crippled_uri),
339 bold(lock_text),
340 blue(_("mirror for download")),
341 ),
342 importance = 1,
343 type = "info",
344 header = red(" @@ "),
345 back = True
346 )
347
348 try:
349 ftp = FtpInterface(uri, self.Entropy)
350 except ConnectionError:
351 self.entropyTools.print_traceback()
352 return True
353 my_path = os.path.join(
354 self.Entropy.get_remote_database_relative_path(repo),
355 self.SystemSettings['repositories']['branch'])
356 ftp.set_cwd(my_path, dodir = True)
357
358 lock_file = etpConst['etpdatabasedownloadlockfile']
359
360 if lock and ftp.is_file_available(lock_file):
361 self.Entropy.updateProgress(
362 "[repo:%s|%s] %s" % (
363 blue(repo),
364 red(crippled_uri),
365 blue(_("mirror already locked for download")),
366 ),
367 importance = 1,
368 type = "info",
369 header = red(" @@ ")
370 )
371 ftp.close()
372 continue
373
374 elif not lock and not ftp.is_file_available(lock_file):
375 self.Entropy.updateProgress(
376 "[repo:%s|%s] %s" % (
377 blue(repo),
378 red(crippled_uri),
379 blue(_("mirror already unlocked for download")),
380 ),
381 importance = 1,
382 type = "info",
383 header = red(" @@ ")
384 )
385 ftp.close()
386 continue
387
388 if lock:
389 rc_lock = self.do_mirror_lock(uri, ftp, dblock = False,
390 repo = repo)
391 else:
392 rc_lock = self.do_mirror_unlock(uri, ftp, dblock = False,
393 repo = repo)
394 ftp.close()
395 if not rc_lock:
396 issues = True
397
398 return issues
399
400 - def do_mirror_lock(self, uri, ftp_connection = None, dblock = True,
401 repo = None):
402
403 if repo == None:
404 repo = self.Entropy.default_repository
405
406 my_path = os.path.join(
407 self.Entropy.get_remote_database_relative_path(repo),
408 self.SystemSettings['repositories']['branch'])
409 if not ftp_connection:
410 try:
411 ftp_connection = FtpInterface(uri, self.Entropy)
412 except ConnectionError:
413 self.entropyTools.print_traceback()
414 return False
415 ftp_connection.set_cwd(my_path, dodir = True)
416 else:
417 mycwd = ftp_connection.get_cwd()
418 if mycwd != my_path:
419 ftp_connection.set_basedir()
420 ftp_connection.set_cwd(my_path, dodir = True)
421
422 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
423 lock_string = u''
424
425 if dblock:
426 self.create_local_database_lockfile(repo)
427 lock_file = self.get_database_lockfile(repo)
428 else:
429
430 lock_string = _('for download')
431 self.create_local_database_download_lockfile(repo)
432 lock_file = self.get_database_download_lockfile(repo)
433
434 rc_upload = ftp_connection.upload_file(lock_file, ascii = True)
435 if rc_upload:
436 self.Entropy.updateProgress(
437 "[repo:%s|%s] %s %s" % (
438 blue(repo),
439 red(crippled_uri),
440 blue(_("mirror successfully locked")),
441 blue(lock_string),
442 ),
443 importance = 1,
444 type = "info",
445 header = red(" @@ ")
446 )
447 else:
448 self.Entropy.updateProgress(
449 "[repo:%s|%s] %s: %s - %s %s" % (
450 blue(repo),
451 red(crippled_uri),
452 blue("lock error"),
453 rc_upload,
454 blue(_("mirror not locked")),
455 blue(lock_string),
456 ),
457 importance = 1,
458 type = "error",
459 header = darkred(" * ")
460 )
461 self.remove_local_database_lockfile(repo)
462
463 return rc_upload
464
465
467
468 if repo == None:
469 repo = self.Entropy.default_repository
470
471 my_path = os.path.join(
472 self.Entropy.get_remote_database_relative_path(repo),
473 self.SystemSettings['repositories']['branch'])
474 if not ftp_connection:
475 try:
476 ftp_connection = FtpInterface(uri, self.Entropy)
477 except ConnectionError:
478 self.entropyTools.print_traceback()
479 return False
480 ftp_connection.set_cwd(my_path)
481 else:
482 mycwd = ftp_connection.get_cwd()
483 if mycwd != my_path:
484 ftp_connection.set_basedir()
485 ftp_connection.set_cwd(my_path)
486
487 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
488
489 if dblock:
490 dbfile = etpConst['etpdatabaselockfile']
491 else:
492 dbfile = etpConst['etpdatabasedownloadlockfile']
493 rc_delete = ftp_connection.delete_file(dbfile)
494 if rc_delete:
495 self.Entropy.updateProgress(
496 "[repo:%s|%s] %s" % (
497 blue(repo),
498 red(crippled_uri),
499 blue(_("mirror successfully unlocked")),
500 ),
501 importance = 1,
502 type = "info",
503 header = darkgreen(" * ")
504 )
505 if dblock:
506 self.remove_local_database_lockfile(repo)
507 else:
508 self.remove_local_database_download_lockfile(repo)
509 else:
510 self.Entropy.updateProgress(
511 "[repo:%s|%s] %s: %s - %s" % (
512 blue(repo),
513 red(crippled_uri),
514 blue(_("unlock error")),
515 rc_delete,
516 blue(_("mirror not unlocked")),
517 ),
518 importance = 1,
519 type = "error",
520 header = darkred(" * ")
521 )
522
523 return rc_delete
524
526 if repo == None:
527 repo = self.Entropy.default_repository
528 return os.path.join(self.Entropy.get_local_database_dir(repo),
529 etpConst['etpdatabaselockfile'])
530
532 if repo == None:
533 repo = self.Entropy.default_repository
534 return os.path.join(self.Entropy.get_local_database_dir(repo),
535 etpConst['etpdatabasedownloadlockfile'])
536
545
547 if repo == None:
548 repo = self.Entropy.default_repository
549 lock_file = self.get_database_lockfile(repo)
550 f_lock = open(lock_file, "w")
551 f_lock.write("database locked")
552 f_lock.flush()
553 f_lock.close()
554
556 if repo == None:
557 repo = self.Entropy.default_repository
558 lock_file = self.get_database_lockfile(repo)
559 if os.path.isfile(lock_file):
560 os.remove(lock_file)
561
563 if repo == None:
564 repo = self.Entropy.default_repository
565 lock_file = self.get_database_download_lockfile(repo)
566 if os.path.isfile(lock_file):
567 os.remove(lock_file)
568
570
571 if repo == None:
572 repo = self.Entropy.default_repository
573
574 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
575
576 tries = 0
577
578 try:
579 ftp = FtpInterface(uri, self.Entropy)
580 except ConnectionError:
581 self.entropyTools.print_traceback()
582 return False
583
584 while tries < 5:
585 tries += 1
586
587 pkg_to_join_path = '/'.join(pkg_relative_path.split('/')[2:])
588 pkg_to_join_dirpath = os.path.dirname(pkg_to_join_path)
589 pkgfile = os.path.basename(pkg_relative_path)
590
591 self.Entropy.updateProgress(
592 "[repo:%s|%s|#%s] %s: %s" % (
593 brown(repo),
594 darkgreen(crippled_uri),
595 brown(str(tries)),
596 blue(_("connecting to download package")),
597 darkgreen(pkg_to_join_path),
598 ),
599 importance = 1,
600 type = "info",
601 header = darkgreen(" * "),
602 back = True
603 )
604
605 dirpath = os.path.join(
606 self.Entropy.get_remote_packages_relative_path(repo),
607 pkg_to_join_dirpath)
608 ftp.set_cwd(dirpath, dodir = True)
609
610 self.Entropy.updateProgress(
611 "[repo:%s|%s|#%s] %s: %s" % (
612 brown(repo),
613 darkgreen(crippled_uri),
614 brown(str(tries)),
615 blue(_("downloading package")),
616 darkgreen(pkg_to_join_path),
617 ),
618 importance = 1,
619 type = "info",
620 header = darkgreen(" * ")
621 )
622
623 download_path = os.path.join(
624 self.Entropy.get_local_packages_directory(repo),
625 pkg_to_join_dirpath)
626 if (not os.path.isdir(download_path)) and \
627 (not os.access(download_path, os.R_OK)):
628 os.makedirs(download_path)
629 rc_download = ftp.download_file(pkgfile, download_path)
630 if not rc_download:
631 self.Entropy.updateProgress(
632 "[repo:%s|%s|#%s] %s: %s %s" % (
633 brown(repo),
634 darkgreen(crippled_uri),
635 brown(str(tries)),
636 blue(_("package")),
637 darkgreen(pkg_to_join_path),
638 blue(_("does not exist")),
639 ),
640 importance = 1,
641 type = "error",
642 header = darkred(" !!! ")
643 )
644 ftp.close()
645 return rc_download
646
647 dbconn = self.Entropy.open_server_repository(read_only = True,
648 no_upload = True, repo = repo)
649 idpackage = dbconn.getIDPackageFromDownload(pkg_relative_path)
650 if idpackage == -1:
651 self.Entropy.updateProgress(
652 "[repo:%s|%s|#%s] %s: %s %s" % (
653 brown(repo),
654 darkgreen(crippled_uri),
655 brown(str(tries)),
656 blue(_("package")),
657 darkgreen(pkgfile),
658 blue(_("is not listed in the repository !")),
659 ),
660 importance = 1,
661 type = "error",
662 header = darkred(" !!! ")
663 )
664 ftp.close()
665 return False
666
667 storedmd5 = dbconn.retrieveDigest(idpackage)
668 self.Entropy.updateProgress(
669 "[repo:%s|%s|#%s] %s: %s" % (
670 brown(repo),
671 darkgreen(crippled_uri),
672 brown(str(tries)),
673 blue(_("verifying checksum of package")),
674 darkgreen(pkgfile),
675 ),
676 importance = 1,
677 type = "info",
678 header = darkgreen(" * "),
679 back = True
680 )
681
682 pkg_path = os.path.join(download_path, pkgfile)
683 md5check = self.entropyTools.compare_md5(pkg_path, storedmd5)
684 if md5check:
685 self.Entropy.updateProgress(
686 "[repo:%s|%s|#%s] %s: %s %s" % (
687 brown(repo),
688 darkgreen(crippled_uri),
689 brown(str(tries)),
690 blue(_("package")),
691 darkgreen(pkgfile),
692 blue(_("downloaded successfully")),
693 ),
694 importance = 1,
695 type = "info",
696 header = darkgreen(" * ")
697 )
698 ftp.close()
699 return True
700 else:
701 self.Entropy.updateProgress(
702 "[repo:%s|%s|#%s] %s: %s %s" % (
703 brown(repo),
704 darkgreen(crippled_uri),
705 brown(str(tries)),
706 blue(_("package")),
707 darkgreen(pkgfile),
708 blue(_("checksum does not match. re-downloading...")),
709 ),
710 importance = 1,
711 type = "warning",
712 header = darkred(" * ")
713 )
714 if os.path.isfile(pkg_path):
715 os.remove(pkg_path)
716
717 continue
718
719
720 self.Entropy.updateProgress(
721 "[repo:%s|%s|#%s] %s: %s %s" % (
722 brown(repo),
723 darkgreen(crippled_uri),
724 brown(str(tries)),
725 blue(_("package")),
726 darkgreen(pkgfile),
727 blue(_("seems broken. Consider to re-package it. Giving up!")),
728 ),
729 importance = 1,
730 type = "error",
731 header = darkred(" !!! ")
732 )
733 ftp.close()
734 return False
735
736
738
739 if repo == None:
740 repo = self.Entropy.default_repository
741
742 if not mirrors:
743 mirrors = self.Entropy.get_remote_mirrors(repo)
744
745 data = []
746 for uri in mirrors:
747
748
749 ftp = FtpInterface(uri, self.Entropy)
750 try:
751 my_path = os.path.join(
752 self.Entropy.get_remote_database_relative_path(repo),
753 self.SystemSettings['repositories']['branch'])
754 ftp.set_cwd(my_path, dodir = True)
755 except ftp.ftplib.error_perm:
756 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
757 self.Entropy.updateProgress(
758 "[repo:%s|%s] %s !" % (
759 brown(repo),
760 darkgreen(crippled_uri),
761 blue(_("mirror has invalid directory structure")),
762 ),
763 importance = 1,
764 type = "warning",
765 header = darkred(" !!! ")
766 )
767 ftp.close()
768 continue
769 sys_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
770 db_format = sys_set['database_file_format']
771 cmethod = etpConst['etpdatabasecompressclasses'].get(db_format)
772 if cmethod == None:
773 raise InvalidDataType("InvalidDataType: %s." % (
774 _("Wrong database compression method passed"),
775 )
776 )
777 compressedfile = etpConst[cmethod[2]]
778
779 revision = 0
780 rc1 = ftp.is_file_available(compressedfile)
781 revfilename = os.path.basename(
782 self.Entropy.get_local_database_revision_file(repo))
783 rc2 = ftp.is_file_available(revfilename)
784 if rc1 and rc2:
785 revision_localtmppath = os.path.join(etpConst['packagestmpdir'],
786 revfilename)
787 dlcount = 5
788 while dlcount:
789 dled = ftp.download_file(revfilename,
790 etpConst['packagestmpdir'], True)
791 if dled:
792 break
793 dlcount -= 1
794
795 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
796 if os.access(revision_localtmppath, os.R_OK | os.F_OK):
797 f_rev = open(revision_localtmppath,"r")
798 try:
799 revision = int(f_rev.readline().strip())
800 except ValueError:
801 mytxt = _("mirror hasn't valid database revision file")
802 self.Entropy.updateProgress(
803 "[repo:%s|%s] %s: %s" % (
804 brown(repo),
805 darkgreen(crippled_uri),
806 blue(mytxt),
807 bold(revision),
808 ),
809 importance = 1,
810 type = "error",
811 header = darkred(" !!! ")
812 )
813 revision = 0
814 f_rev.close()
815 elif dlcount == 0:
816 self.Entropy.updateProgress(
817 "[repo:%s|%s] %s: %s" % (
818 brown(repo),
819 darkgreen(crippled_uri),
820 blue(_("unable to download repository revision")),
821 bold(revision),
822 ),
823 importance = 1,
824 type = "error",
825 header = darkred(" !!! ")
826 )
827 revision = 0
828 else:
829 self.Entropy.updateProgress(
830 "[repo:%s|%s] %s: %s" % (
831 brown(repo),
832 darkgreen(crippled_uri),
833 blue(_("mirror doesn't have valid revision file")),
834 bold(revision),
835 ),
836 importance = 1,
837 type = "error",
838 header = darkred(" !!! ")
839 )
840 revision = 0
841 if os.path.isfile(revision_localtmppath):
842 os.remove(revision_localtmppath)
843
844 info = [uri, revision]
845 data.append(info)
846 ftp.close()
847
848 return data
849
851 local_repo = repo
852 if local_repo == None:
853 local_repo = self.Entropy.default_repository
854 lock_file = self.get_database_lockfile(local_repo)
855 return os.path.isfile(lock_file)
856
880
882
883 if repo == None:
884 repo = self.Entropy.default_repository
885 mirrors = self.Entropy.get_remote_mirrors(repo)
886 rss_path = self.Entropy.get_local_database_notice_board_file(repo)
887 mytmpdir = self.entropyTools.get_random_temp_file()
888 os.makedirs(mytmpdir)
889
890 self.Entropy.updateProgress(
891 "[repo:%s] %s %s" % (
892 brown(repo),
893 blue(_("downloading notice board from mirrors to")),
894 red(rss_path),
895 ),
896 importance = 1,
897 type = "info",
898 header = blue(" @@ ")
899 )
900
901 downloaded = False
902 for uri in mirrors:
903 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
904 downloader = self.FtpServerHandler(
905 FtpInterface, self.Entropy, [uri],
906 [rss_path], download = True,
907 local_basedir = mytmpdir, critical_files = [rss_path],
908 repo = repo
909 )
910 errors, m_fine_uris, m_broken_uris = downloader.go()
911 if not errors:
912 self.Entropy.updateProgress(
913 "[repo:%s] %s: %s" % (
914 brown(repo),
915 blue(_("notice board downloaded successfully from")),
916 red(crippled_uri),
917 ),
918 importance = 1,
919 type = "info",
920 header = blue(" @@ ")
921 )
922 downloaded = True
923 break
924
925 if downloaded:
926 shutil.move(os.path.join(mytmpdir, os.path.basename(rss_path)),
927 rss_path)
928
929 return downloaded
930
932
933 if repo == None:
934 repo = self.Entropy.default_repository
935 mirrors = self.Entropy.get_remote_mirrors(repo)
936 rss_path = self.Entropy.get_local_database_notice_board_file(repo)
937
938 self.Entropy.updateProgress(
939 "[repo:%s] %s %s" % (
940 brown(repo),
941 blue(_("uploading notice board from")),
942 red(rss_path),
943 ),
944 importance = 1,
945 type = "info",
946 header = blue(" @@ ")
947 )
948
949 uploader = self.FtpServerHandler(
950 FtpInterface,
951 self.Entropy,
952 mirrors,
953 [rss_path],
954 critical_files = [rss_path],
955 repo = repo
956 )
957 errors, m_fine_uris, m_broken_uris = uploader.go()
958 if errors:
959 m_broken_uris = sorted(m_broken_uris)
960 m_broken_uris = [self.entropyTools.extract_ftp_host_from_uri(x) \
961 for x in m_broken_uris]
962 self.Entropy.updateProgress(
963 "[repo:%s] %s %s" % (
964 brown(repo),
965 blue(_("notice board upload failed on")),
966 red(', '.join(m_broken_uris)),
967 ),
968 importance = 1,
969 type = "info",
970 header = blue(" @@ ")
971 )
972 return False
973 self.Entropy.updateProgress(
974 "[repo:%s] %s" % (
975 brown(repo),
976 blue(_("notice board upload success")),
977 ),
978 importance = 1,
979 type = "info",
980 header = blue(" @@ ")
981 )
982 return True
983
984
1001
1011
1013
1014 rss_path = self.Entropy.get_local_database_notice_board_file(repo)
1015 rss_title = "%s Notice Board" % (self.SystemSettings['system']['name'],)
1016 rss_description = "Inform about important distribution activities."
1017 if not (os.path.isfile(rss_path) and os.access(rss_path, os.R_OK)):
1018 return 0
1019 rss_main = RSS(rss_path, rss_title, rss_description)
1020 data = rss_main.remove_entry(identifier)
1021 rss_main.write_changes()
1022 return data
1023
1025
1026 if repo == None:
1027 repo = self.Entropy.default_repository
1028
1029 product = self.SystemSettings['repositories']['product']
1030
1031 rss_path = self.Entropy.get_local_database_rss_file(repo)
1032 rss_light_path = self.Entropy.get_local_database_rsslight_file(repo)
1033 rss_dump_name = repo + etpConst['rss-dump-name']
1034 db_revision_path = self.Entropy.get_local_database_revision_file(repo)
1035
1036 rss_title = u"%s Online Repository Status" % (
1037 self.SystemSettings['system']['name'],)
1038 rss_description = \
1039 u"Keep you updated on what's going on in the %s Repository." % (
1040 self.SystemSettings['system']['name'],)
1041
1042 srv_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
1043
1044 rss_main = RSS(rss_path, rss_title, rss_description,
1045 maxentries = srv_set['rss']['max_entries'])
1046
1047 db_actions = self.Cacher.pop(rss_dump_name)
1048 if db_actions:
1049 try:
1050 f_rev = open(db_revision_path)
1051 revision = f_rev.readline().strip()
1052 f_rev.close()
1053 except (IOError, OSError):
1054 revision = u"N/A"
1055 commitmessage = u''
1056 if self.Entropy.rssMessages['commitmessage']:
1057 commitmessage = u' :: ' + \
1058 self.Entropy.rssMessages['commitmessage']
1059
1060 title = u": " + self.SystemSettings['system']['name'] + u" " + \
1061 product[0].upper() + product[1:] + " " + \
1062 self.SystemSettings['repositories']['branch'] + \
1063 " :: Revision: " + revision + commitmessage
1064
1065 link = srv_set['rss']['base_url']
1066
1067 added_items = db_actions.get("added")
1068
1069 if added_items:
1070 for atom in sorted(added_items):
1071 mylink = link + "?search=" + atom.split("~")[0] + \
1072 "&arch=" + etpConst['currentarch'] + "&product="+product
1073 description = atom + ": " + added_items[atom]['description']
1074 rss_main.add_item(title = "Added/Updated" + title,
1075 link = mylink, description = description)
1076 removed_items = db_actions.get("removed")
1077
1078 if removed_items:
1079 for atom in sorted(removed_items):
1080 description = atom + ": " + \
1081 removed_items[atom]['description']
1082 rss_main.add_item(title = "Removed" + title, link = link,
1083 description = description)
1084
1085 light_items = db_actions.get('light')
1086 if light_items:
1087 rss_light = RSS(rss_light_path, rss_title, rss_description,
1088 maxentries = srv_set['rss']['light_max_entries'])
1089 for atom in sorted(light_items):
1090 mylink = link + "?search=" + atom.split("~")[0] + \
1091 "&arch=" + etpConst['currentarch'] + "&product=" + \
1092 product
1093 description = light_items[atom]['description']
1094 rss_light.add_item(title = "[" + revision + "] " + atom,
1095 link = mylink, description = description)
1096 rss_light.write_changes()
1097
1098 rss_main.write_changes()
1099 self.Entropy.rssMessages.clear()
1100 self.dumpTools.removeobj(rss_dump_name)
1101
1102
1103 - def dump_database_to_file(self, db_path, destination_path, opener,
1104 exclude_tables = None, repo = None):
1105
1106 if not exclude_tables:
1107 exclude_tables = []
1108
1109 f_out = opener(destination_path, "wb")
1110 dbconn = self.Entropy.open_server_repository(db_path,
1111 just_reading = True, repo = repo, do_treeupdates = False)
1112 dbconn.doDatabaseExport(f_out, exclude_tables = exclude_tables)
1113 self.Entropy.close_server_database(dbconn)
1114 f_out.close()
1115
1117 mydigest = self.entropyTools.md5sum(file_path)
1118 f_ck = open(checksum_path, "w")
1119 mystring = "%s %s\n" % (mydigest, os.path.basename(file_path),)
1120 f_ck.write(mystring)
1121 f_ck.flush()
1122 f_ck.close()
1123
1125 f_out = opener(destination_path, "wb")
1126 f_in = open(file_path,"rb")
1127 data = f_in.read(8192)
1128 while data:
1129 f_out.write(data)
1130 data = f_in.read(8192)
1131 f_in.close()
1132 if hasattr(f_out,'flush'):
1133 f_out.flush()
1134 f_out.close()
1135
1136 - def get_files_to_sync(self, cmethod, download = False, repo = None,
1137 disabled_eapis = None):
1138
1139 if disabled_eapis == None:
1140 disabled_eapis = []
1141
1142 critical = []
1143 extra_text_files = []
1144 data = {}
1145 data['database_revision_file'] = \
1146 self.Entropy.get_local_database_revision_file(repo)
1147 extra_text_files.append(data['database_revision_file'])
1148 critical.append(data['database_revision_file'])
1149
1150
1151
1152 post_branch_mig_file = self.Entropy.get_local_post_branch_mig_script(
1153 repo)
1154 if os.path.isfile(post_branch_mig_file) or download:
1155 data['database_post_branch_hop_script'] = post_branch_mig_file
1156 extra_text_files.append(data['database_post_branch_hop_script'])
1157
1158 post_branch_upg_file = self.Entropy.get_local_post_branch_upg_script(
1159 repo)
1160 if os.path.isfile(post_branch_upg_file) or download:
1161 data['database_post_branch_upgrade_script'] = post_branch_upg_file
1162 extra_text_files.append(data['database_post_branch_upgrade_script'])
1163
1164
1165 database_ts_file = self.Entropy.get_local_database_timestamp_file(repo)
1166 if os.path.isfile(database_ts_file) or download:
1167 data['database_timestamp_file'] = database_ts_file
1168 if not download:
1169 critical.append(database_ts_file)
1170
1171 database_package_mask_file = \
1172 self.Entropy.get_local_database_mask_file(repo)
1173 extra_text_files.append(database_package_mask_file)
1174 if os.path.isfile(database_package_mask_file) or download:
1175 data['database_package_mask_file'] = database_package_mask_file
1176 if not download:
1177 critical.append(data['database_package_mask_file'])
1178
1179 database_package_system_mask_file = \
1180 self.Entropy.get_local_database_system_mask_file(repo)
1181 extra_text_files.append(database_package_system_mask_file)
1182 if os.path.isfile(database_package_system_mask_file) or download:
1183 data['database_package_system_mask_file'] = \
1184 database_package_system_mask_file
1185 if not download:
1186 critical.append(data['database_package_system_mask_file'])
1187
1188 database_package_confl_tagged_file = \
1189 self.Entropy.get_local_database_confl_tagged_file(repo)
1190 extra_text_files.append(database_package_confl_tagged_file)
1191 if os.path.isfile(database_package_confl_tagged_file) or download:
1192 data['database_package_confl_tagged_file'] = \
1193 database_package_confl_tagged_file
1194 if not download:
1195 critical.append(data['database_package_confl_tagged_file'])
1196
1197 database_license_whitelist_file = \
1198 self.Entropy.get_local_database_licensewhitelist_file(repo)
1199 extra_text_files.append(database_license_whitelist_file)
1200 if os.path.isfile(database_license_whitelist_file) or download:
1201 data['database_license_whitelist_file'] = \
1202 database_license_whitelist_file
1203 if not download:
1204 critical.append(data['database_license_whitelist_file'])
1205
1206 exp_based_pkgs_removal_file = \
1207 self.Entropy.get_local_exp_based_pkgs_rm_whitelist_file(repo)
1208 extra_text_files.append(exp_based_pkgs_removal_file)
1209 if os.path.isfile(exp_based_pkgs_removal_file) or download:
1210 data['exp_based_pkgs_removal_file'] = exp_based_pkgs_removal_file
1211 if not download:
1212 critical.append(data['exp_based_pkgs_removal_file'])
1213
1214 database_rss_file = self.Entropy.get_local_database_rss_file(repo)
1215 if os.path.isfile(database_rss_file) or download:
1216 data['database_rss_file'] = database_rss_file
1217 if not download:
1218 critical.append(data['database_rss_file'])
1219 database_rss_light_file = \
1220 self.Entropy.get_local_database_rsslight_file(repo)
1221
1222 extra_text_files.append(database_rss_light_file)
1223 if os.path.isfile(database_rss_light_file) or download:
1224 data['database_rss_light_file'] = database_rss_light_file
1225 if not download:
1226 critical.append(data['database_rss_light_file'])
1227
1228 pkglist_file = self.Entropy.get_local_pkglist_file(repo)
1229 data['pkglist_file'] = pkglist_file
1230 if not download:
1231 critical.append(data['pkglist_file'])
1232
1233
1234 if not download:
1235
1236 if 3 not in disabled_eapis:
1237
1238 data['metafiles_path'] = \
1239 self.Entropy.get_local_database_compressed_metafiles_file(
1240 repo)
1241 critical.append(data['metafiles_path'])
1242
1243 if 2 not in disabled_eapis:
1244
1245 data['dump_path_light'] = os.path.join(
1246 self.Entropy.get_local_database_dir(repo),
1247 etpConst[cmethod[5]])
1248 critical.append(data['dump_path_light'])
1249
1250 data['dump_path_digest_light'] = os.path.join(
1251 self.Entropy.get_local_database_dir(repo),
1252 etpConst[cmethod[6]])
1253 critical.append(data['dump_path_digest_light'])
1254
1255
1256 if 1 not in disabled_eapis:
1257
1258 data['compressed_database_path'] = os.path.join(
1259 self.Entropy.get_local_database_dir(repo), etpConst[cmethod[2]])
1260 critical.append(data['compressed_database_path'])
1261 data['compressed_database_path_light'] = os.path.join(
1262 self.Entropy.get_local_database_dir(repo), etpConst[cmethod[7]])
1263
1264 data['database_path_digest'] = os.path.join(
1265 self.Entropy.get_local_database_dir(repo),
1266 etpConst['etpdatabasehashfile']
1267 )
1268 critical.append(data['database_path_digest'])
1269
1270 data['compressed_database_path_digest'] = os.path.join(
1271 self.Entropy.get_local_database_dir(repo),
1272 etpConst[cmethod[2]] + etpConst['packagesmd5fileext']
1273 )
1274 critical.append(data['compressed_database_path_digest'])
1275
1276 data['compressed_database_path_digest_light'] = os.path.join(
1277 self.Entropy.get_local_database_dir(repo),
1278 etpConst[cmethod[8]]
1279 )
1280 critical.append(data['compressed_database_path_digest_light'])
1281
1282
1283
1284 ssl_ca_cert = self.Entropy.get_local_database_ca_cert_file()
1285 extra_text_files.append(ssl_ca_cert)
1286 if os.path.isfile(ssl_ca_cert):
1287 data['ssl_ca_cert_file'] = ssl_ca_cert
1288 if not download:
1289 critical.append(ssl_ca_cert)
1290 ssl_server_cert = self.Entropy.get_local_database_server_cert_file()
1291 extra_text_files.append(ssl_server_cert)
1292 if os.path.isfile(ssl_server_cert):
1293 data['ssl_server_cert_file'] = ssl_server_cert
1294 if not download:
1295 critical.append(ssl_server_cert)
1296
1297
1298 spm_files = [
1299 (etpConst['spm']['global_make_conf'], "global_make_conf"),
1300 (etpConst['spm']['global_package_keywords'],
1301 "global_package_keywords"),
1302 (etpConst['spm']['global_package_use'], "global_package_use"),
1303 (etpConst['spm']['global_package_mask'], "global_package_mask"),
1304 (etpConst['spm']['global_package_unmask'], "global_package_unmask"),
1305 ]
1306 for myfile, myname in spm_files:
1307 if os.path.isfile(myfile) and os.access(myfile, os.R_OK):
1308 data[myname] = myfile
1309 extra_text_files.append(myfile)
1310
1311 make_profile = etpConst['spm']['global_make_profile']
1312 rnd_tmp_file = self.Entropy.entropyTools.get_random_temp_file()
1313 mytmpdir = os.path.dirname(rnd_tmp_file)
1314 mytmpfile = os.path.join(mytmpdir,
1315 etpConst['spm']['global_make_profile_link_name'])
1316 extra_text_files.append(mytmpfile)
1317
1318 if os.path.islink(make_profile):
1319 mylink = os.readlink(make_profile)
1320 f_mkp = open(mytmpfile,"w")
1321 f_mkp.write(mylink)
1322 f_mkp.flush()
1323 f_mkp.close()
1324 data['global_make_profile'] = mytmpfile
1325
1326 return data, critical, extra_text_files
1327
1329
1330 self.Entropy.updateProgress(
1331 "[repo:%s] %s:" % (
1332 brown(repo),
1333 blue(_("configured package sets")),
1334 ),
1335 importance = 0,
1336 type = "info",
1337 header = darkgreen(" * ")
1338 )
1339 sets_data = self.Entropy.package_set_list(matchRepo = [repo])
1340 if not sets_data:
1341 self.Entropy.updateProgress(
1342 "%s" % (_("None configured"),),
1343 importance = 0,
1344 type = "info",
1345 header = brown(" # ")
1346 )
1347 return
1348 for s_repo, s_name, s_sets in sets_data:
1349 self.Entropy.updateProgress(
1350 blue("%s" % (s_name,)),
1351 importance = 0,
1352 type = "info",
1353 header = brown(" # ")
1354 )
1355
1357
1358 self.Entropy.updateProgress(
1359 "[repo:%s|%s|%s:%s] %s" % (
1360 brown(repo),
1361 darkgreen(crippled_uri),
1362 red("EAPI"),
1363 bold("3"),
1364 blue(_("preparing uncompressed database for the upload")),
1365 ),
1366 importance = 0,
1367 type = "info",
1368 header = darkgreen(" * ")
1369 )
1370 self.Entropy.updateProgress(
1371 "%s: %s" % (_("database path"), blue(database_path),),
1372 importance = 0,
1373 type = "info",
1374 header = brown(" # ")
1375 )
1376
1379
1380 if repo == None:
1381 repo = self.Entropy.default_repository
1382
1383 self.Entropy.updateProgress(
1384 "[repo:%s|%s|%s:%s] %s" % (
1385 brown(repo),
1386 darkgreen(crippled_uri),
1387 red("EAPI"),
1388 bold("2"),
1389 blue(_("creating compressed database dump + checksum")),
1390 ),
1391 importance = 0,
1392 type = "info",
1393 header = darkgreen(" * ")
1394 )
1395 self.Entropy.updateProgress(
1396 "%s: %s" % (_("database path"), blue(database_path),),
1397 importance = 0,
1398 type = "info",
1399 header = brown(" # ")
1400 )
1401 self.Entropy.updateProgress(
1402 "%s: %s" % (
1403 _("dump light"),
1404 blue(upload_data['dump_path_light']),
1405 ),
1406 importance = 0,
1407 type = "info",
1408 header = brown(" # ")
1409 )
1410 self.Entropy.updateProgress(
1411 "%s: %s" % (
1412 _("dump light checksum"),
1413 blue(upload_data['dump_path_digest_light']),
1414 ),
1415 importance = 0,
1416 type = "info",
1417 header = brown(" # ")
1418 )
1419
1420 self.Entropy.updateProgress(
1421 "%s: %s" % (_("opener"), blue(str(cmethod[0])),),
1422 importance = 0,
1423 type = "info",
1424 header = brown(" # ")
1425 )
1426
1429
1430 self.Entropy.updateProgress(
1431 "[repo:%s|%s|%s:%s] %s" % (
1432 brown(repo),
1433 darkgreen(crippled_uri),
1434 red("EAPI"),
1435 bold("1"),
1436 blue(_("compressing database + checksum")),
1437 ),
1438 importance = 0,
1439 type = "info",
1440 header = darkgreen(" * "),
1441 back = True
1442 )
1443 self.Entropy.updateProgress(
1444 "%s: %s" % (_("database path"), blue(database_path),),
1445 importance = 0,
1446 type = "info",
1447 header = brown(" # ")
1448 )
1449 self.Entropy.updateProgress(
1450 "%s: %s" % (
1451 _("compressed database path"),
1452 blue(upload_data['compressed_database_path']),
1453 ),
1454 importance = 0,
1455 type = "info",
1456 header = brown(" # ")
1457 )
1458 self.Entropy.updateProgress(
1459 "%s: %s" % (
1460 _("database checksum"),
1461 blue(upload_data['database_path_digest']),
1462 ),
1463 importance = 0,
1464 type = "info",
1465 header = brown(" # ")
1466 )
1467 self.Entropy.updateProgress(
1468 "%s: %s" % (
1469 _("compressed checksum"),
1470 blue(upload_data['compressed_database_path_digest']),
1471 ),
1472 importance = 0,
1473 type = "info",
1474 header = brown(" # ")
1475 )
1476 self.Entropy.updateProgress(
1477 "%s: %s" % (_("opener"), blue(str(cmethod[0])),),
1478 importance = 0,
1479 type = "info",
1480 header = brown(" # ")
1481 )
1482
1500
1502 bdir = ""
1503 for mydir in path_to_create.split("/"):
1504 bdir += "/"+mydir
1505 if not ftp_connection.is_file_available(bdir):
1506 try:
1507 ftp_connection.mkdir(bdir)
1508 except Exception, err:
1509 error = unicode(err)
1510 if (error.find("550") == -1) and \
1511 (error.find("File exist") == -1):
1512
1513 mytxt = "%s %s, %s: %s" % (
1514 _("cannot create mirror directory"),
1515 bdir,
1516 _("error"),
1517 err,
1518 )
1519 raise OnlineMirrorError("OnlineMirrorError: %s" % (
1520 mytxt,))
1521 raise
1522
1524
1525 if repo == None:
1526 repo = self.Entropy.default_repository
1527
1528 gave_up = False
1529 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
1530 try:
1531 ftp = FtpInterface(uri, self.Entropy)
1532 except ConnectionError:
1533 self.entropyTools.print_traceback()
1534 return True
1535 my_path = os.path.join(
1536 self.Entropy.get_remote_database_relative_path(repo),
1537 self.SystemSettings['repositories']['branch'])
1538 ftp.set_cwd(my_path, dodir = True)
1539
1540 lock_file = self.get_database_lockfile(repo)
1541 lock_filename = os.path.basename(lock_file)
1542 if not os.path.isfile(lock_file) and \
1543 ftp.is_file_available(lock_filename):
1544
1545 self.Entropy.updateProgress(
1546 "[repo:%s|%s|%s] %s, %s" % (
1547 brown(str(repo)),
1548 darkgreen(crippled_uri),
1549 red(_("locking")),
1550 darkblue(_("mirror already locked")),
1551 blue(_("waiting up to 2 minutes before giving up")),
1552 ),
1553 importance = 1,
1554 type = "warning",
1555 header = brown(" * "),
1556 back = True
1557 )
1558 unlocked = False
1559 count = 0
1560 while count < 120:
1561 count += 1
1562 time.sleep(1)
1563 if not ftp.is_file_available(os.path.basename(lock_file)):
1564 self.Entropy.updateProgress(
1565 red("[repo:%s|%s|%s] %s !" % (
1566 repo,
1567 crippled_uri,
1568 _("locking"),
1569 _("mirror unlocked"),
1570 )
1571 ),
1572 importance = 1,
1573 type = "info",
1574 header = darkgreen(" * ")
1575 )
1576 unlocked = True
1577 break
1578 if not unlocked:
1579 gave_up = True
1580
1581 ftp.close()
1582 return gave_up
1583
1593
1603
1605
1606 if repo == None:
1607 repo = self.Entropy.default_repository
1608 dbconn = self.Entropy.open_server_repository(read_only = False,
1609 no_upload = True, repo = repo, do_treeupdates = False)
1610
1611 srv_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
1612 server_repos = srv_set['repositories'].keys()
1613 all_actions = set()
1614 for myrepo in server_repos:
1615
1616
1617 if myrepo == etpConst['clientserverrepoid']:
1618 continue
1619
1620 mydbc = self.Entropy.open_server_repository(just_reading = True,
1621 repo = myrepo)
1622 actions = mydbc.listAllTreeUpdatesActions(no_ids_repos = True)
1623 for data in actions:
1624 all_actions.add(data)
1625 if not actions:
1626 continue
1627 backed_up_entries = dbconn.listAllTreeUpdatesActions()
1628 try:
1629
1630 dbconn.removeTreeUpdatesActions(repo)
1631 dbconn.insertTreeUpdatesActions(all_actions, repo)
1632 except dbapi2.Error, err:
1633 self.entropyTools.print_traceback()
1634 mytxt = "%s, %s: %s. %s" % (
1635 _("Troubles with treeupdates"),
1636 _("error"),
1637 err,
1638 _("Bumping old data back"),
1639 )
1640 self.Entropy.updateProgress(
1641 mytxt,
1642 importance = 1,
1643 type = "warning"
1644 )
1645
1646 dbconn.bumpTreeUpdatesActions(backed_up_entries)
1647
1648 dbconn.commitChanges()
1649 self.Entropy.close_server_database(dbconn)
1650
1651 - def upload_database(self, uris, lock_check = False, pretend = False,
1652 repo = None):
1653
1654 if repo == None:
1655 repo = self.Entropy.default_repository
1656
1657 srv_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
1658 if srv_set['rss']['enabled']:
1659 self.update_rss_feed(repo = repo)
1660
1661 upload_errors = False
1662 broken_uris = set()
1663 fine_uris = set()
1664
1665 disabled_eapis = sorted(srv_set['disabled_eapis'])
1666
1667 for uri in uris:
1668
1669 db_format = srv_set['database_file_format']
1670 cmethod = etpConst['etpdatabasecompressclasses'].get(db_format)
1671 if cmethod == None:
1672 raise InvalidDataType("InvalidDataType: %s." % (
1673 _("wrong database compression method passed"),
1674 )
1675 )
1676
1677 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
1678 database_path = self.Entropy.get_local_database_file(repo)
1679
1680 if disabled_eapis:
1681 self.Entropy.updateProgress(
1682 "[repo:%s|%s|%s] %s: %s" % (
1683 blue(repo),
1684 red(crippled_uri),
1685 darkgreen(_("upload")),
1686 darkred(_("disabled EAPI")),
1687 bold(', '.join(disabled_eapis)),
1688 ),
1689 importance = 1,
1690 type = "warning",
1691 header = darkgreen(" * ")
1692 )
1693
1694
1695 self.update_repository_timestamp(repo)
1696
1697 self.Entropy.create_repository_pkglist(repo)
1698
1699 upload_data, critical, text_files = self.get_files_to_sync(cmethod,
1700 repo = repo, disabled_eapis = disabled_eapis)
1701
1702 if lock_check:
1703 given_up = self.mirror_lock_check(uri, repo = repo)
1704 if given_up:
1705 upload_errors = True
1706 broken_uris.add(uri)
1707 continue
1708
1709 self.lock_mirrors_for_download(True, [uri], repo = repo)
1710
1711 self.Entropy.updateProgress(
1712 "[repo:%s|%s|%s] %s" % (
1713 blue(repo),
1714 red(crippled_uri),
1715 darkgreen(_("upload")),
1716 darkgreen(_("preparing to upload database to mirror")),
1717 ),
1718 importance = 1,
1719 type = "info",
1720 header = darkgreen(" * ")
1721 )
1722
1723
1724 self._show_package_sets_messages(repo)
1725 self.sync_database_treeupdates(repo)
1726 self.Entropy.update_database_package_sets(repo)
1727 self.Entropy.close_server_databases()
1728
1729
1730 old_dbpath = self.Entropy.get_local_database_file(repo)
1731 backup_dbpath = old_dbpath + ".up_backup"
1732 copy_back = False
1733 if not pretend:
1734 try:
1735 if os.access(backup_dbpath, os.R_OK | os.F_OK):
1736 os.remove(backup_dbpath)
1737 shutil.copy2(old_dbpath, backup_dbpath)
1738 copy_back = True
1739 except shutil.Error:
1740 copy_back = False
1741
1742 self.shrink_database_and_close(repo)
1743
1744
1745 if 3 not in disabled_eapis:
1746 self._create_metafiles_file(upload_data['metafiles_path'],
1747 text_files, repo)
1748 self._show_eapi3_upload_messages(crippled_uri, database_path,
1749 repo)
1750
1751
1752 if 2 not in disabled_eapis:
1753 self._show_eapi2_upload_messages(crippled_uri, database_path,
1754 upload_data, cmethod, repo)
1755
1756
1757 self.dump_database_to_file(database_path,
1758 upload_data['dump_path_light'], cmethod[0],
1759 exclude_tables = ["content"], repo = repo)
1760 self.create_file_checksum(upload_data['dump_path_light'],
1761 upload_data['dump_path_digest_light'])
1762
1763
1764
1765 if 1 not in disabled_eapis:
1766 self._show_eapi1_upload_messages(crippled_uri, database_path,
1767 upload_data, cmethod, repo)
1768
1769
1770
1771 self.compress_file(database_path,
1772 upload_data['compressed_database_path'], cmethod[0])
1773 self.create_file_checksum(database_path,
1774 upload_data['database_path_digest'])
1775
1776
1777 self.create_file_checksum(
1778 upload_data['compressed_database_path'],
1779 upload_data['compressed_database_path_digest'])
1780
1781
1782 eapi1_dbfile = self.Entropy.get_local_database_file(repo)
1783 temp_eapi1_dbfile = eapi1_dbfile+".light"
1784 shutil.copy2(eapi1_dbfile, temp_eapi1_dbfile)
1785
1786 eapi1_tmp_dbconn = \
1787 self.Entropy.ClientService.open_generic_database(
1788 temp_eapi1_dbfile, indexing_override = False,
1789 xcache = False)
1790 eapi1_tmp_dbconn.dropContent()
1791 eapi1_tmp_dbconn.commitChanges()
1792 eapi1_tmp_dbconn.vacuum()
1793 eapi1_tmp_dbconn.closeDB()
1794
1795
1796 self.compress_file(temp_eapi1_dbfile,
1797 upload_data['compressed_database_path_light'], cmethod[0])
1798
1799 os.remove(temp_eapi1_dbfile)
1800
1801 self.create_file_checksum(
1802 upload_data['compressed_database_path_light'],
1803 upload_data['compressed_database_path_digest_light'])
1804
1805 if not pretend:
1806
1807 uploader = self.FtpServerHandler(
1808 FtpInterface,
1809 self.Entropy,
1810 [uri],
1811 [upload_data[x] for x in upload_data],
1812 critical_files = critical,
1813 repo = repo
1814 )
1815 errors, m_fine_uris, m_broken_uris = uploader.go()
1816 if errors:
1817 my_broken_uris = sorted([
1818 (self.entropyTools.extract_ftp_host_from_uri(x[0]),
1819 x[1]) for x in m_broken_uris])
1820 self.Entropy.updateProgress(
1821 "[repo:%s|%s|%s] %s" % (
1822 repo,
1823 crippled_uri,
1824 _("errors"),
1825 _("upload failed, not unlocking and continuing"),
1826 ),
1827 importance = 0,
1828 type = "error",
1829 header = darkred(" !!! ")
1830 )
1831
1832 reason = my_broken_uris[0][1]
1833 self.Entropy.updateProgress(
1834 blue("%s: %s" % (_("reason"), reason,)),
1835 importance = 0,
1836 type = "error",
1837 header = blue(" # ")
1838 )
1839 upload_errors = True
1840 broken_uris |= m_broken_uris
1841 continue
1842
1843
1844 if copy_back and os.path.isfile(backup_dbpath):
1845 self.Entropy.close_server_databases()
1846 further_backup_dbpath = old_dbpath+".security_backup"
1847 if os.path.isfile(further_backup_dbpath):
1848 os.remove(further_backup_dbpath)
1849 shutil.copy2(old_dbpath, further_backup_dbpath)
1850 shutil.move(backup_dbpath, old_dbpath)
1851
1852
1853 self.lock_mirrors_for_download(False, [uri], repo = repo)
1854 fine_uris |= m_fine_uris
1855
1856 if not fine_uris:
1857 upload_errors = True
1858 return upload_errors, broken_uris, fine_uris
1859
1860
1861 - def download_database(self, uris, lock_check = False, pretend = False,
1862 repo = None):
1863
1864 if repo == None:
1865 repo = self.Entropy.default_repository
1866
1867 download_errors = False
1868 broken_uris = set()
1869 fine_uris = set()
1870 srv_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
1871 disabled_eapis = sorted(srv_set['disabled_eapis'])
1872
1873 for uri in uris:
1874
1875 db_format = srv_set['database_file_format']
1876 cmethod = etpConst['etpdatabasecompressclasses'].get(db_format)
1877 if cmethod == None:
1878 raise InvalidDataType("InvalidDataType: %s." % (
1879 _("wrong database compression method passed"),
1880 )
1881 )
1882
1883 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
1884 database_path = self.Entropy.get_local_database_file(repo)
1885 database_dir_path = os.path.dirname(
1886 self.Entropy.get_local_database_file(repo))
1887 download_data, critical, text_files = self.get_files_to_sync(
1888 cmethod, download = True,
1889 repo = repo, disabled_eapis = disabled_eapis)
1890 mytmpdir = self.entropyTools.get_random_temp_file()
1891 os.makedirs(mytmpdir)
1892
1893 self.Entropy.updateProgress(
1894 "[repo:%s|%s|%s] %s" % (
1895 brown(repo),
1896 darkgreen(crippled_uri),
1897 red(_("download")),
1898 blue(_("preparing to download database from mirror")),
1899 ),
1900 importance = 1,
1901 type = "info",
1902 header = darkgreen(" * ")
1903 )
1904 files_to_sync = sorted(download_data.keys())
1905 for myfile in files_to_sync:
1906 self.Entropy.updateProgress(
1907 "%s: %s" % (
1908 blue(_("download path")),
1909 brown(unicode(download_data[myfile])),
1910 ),
1911 importance = 0,
1912 type = "info",
1913 header = brown(" # ")
1914 )
1915
1916 if lock_check:
1917 given_up = self.mirror_lock_check(uri, repo = repo)
1918 if given_up:
1919 download_errors = True
1920 broken_uris.add(uri)
1921 continue
1922
1923
1924 self.lock_mirrors(True, [uri], repo = repo)
1925
1926 if not pretend:
1927
1928 downloader = self.FtpServerHandler(
1929 FtpInterface, self.Entropy, [uri],
1930 [download_data[x] for x in download_data], download = True,
1931 local_basedir = mytmpdir, critical_files = critical,
1932 repo = repo
1933 )
1934 errors, m_fine_uris, m_broken_uris = downloader.go()
1935 if errors:
1936 my_broken_uris = sorted([
1937 (self.entropyTools.extract_ftp_host_from_uri(x[0]),
1938 x[1]) for x in m_broken_uris])
1939 self.Entropy.updateProgress(
1940 "[repo:%s|%s|%s] %s" % (
1941 brown(repo),
1942 darkgreen(crippled_uri),
1943 red(_("errors")),
1944 blue(_("failed to download from mirror")),
1945 ),
1946 importance = 0,
1947 type = "error",
1948 header = darkred(" !!! ")
1949 )
1950
1951 reason = my_broken_uris[0][1]
1952 self.Entropy.updateProgress(
1953 blue("%s: %s" % (_("reason"), reason,)),
1954 importance = 0,
1955 type = "error",
1956 header = blue(" # ")
1957 )
1958 download_errors = True
1959 broken_uris |= m_broken_uris
1960 self.lock_mirrors(False, [uri], repo = repo)
1961 continue
1962
1963
1964
1965
1966
1967 if 1 not in disabled_eapis:
1968 compressed_db_filename = os.path.basename(
1969 download_data['compressed_database_path'])
1970 uncompressed_db_filename = os.path.basename(database_path)
1971 compressed_file = os.path.join(mytmpdir,
1972 compressed_db_filename)
1973 uncompressed_file = os.path.join(mytmpdir,
1974 uncompressed_db_filename)
1975 self.entropyTools.uncompress_file(compressed_file,
1976 uncompressed_file, cmethod[0])
1977
1978
1979 for myfile in os.listdir(mytmpdir):
1980 fromfile = os.path.join(mytmpdir, myfile)
1981 tofile = os.path.join(database_dir_path, myfile)
1982 shutil.move(fromfile, tofile)
1983 self.Entropy.ClientService.setup_default_file_perms(tofile)
1984
1985 if os.path.isdir(mytmpdir):
1986 shutil.rmtree(mytmpdir)
1987 if os.path.isdir(mytmpdir):
1988 os.rmdir(mytmpdir)
1989
1990
1991 fine_uris.add(uri)
1992 self.lock_mirrors(False, [uri], repo = repo)
1993
1994 return download_errors, fine_uris, broken_uris
1995
1997
1998 if repo == None:
1999 repo = self.Entropy.default_repository
2000
2001 remote_status = self.get_remote_databases_status(repo)
2002 local_revision = self.Entropy.get_local_database_revision(repo)
2003 upload_queue = []
2004 download_latest = ()
2005
2006
2007 if not [x for x in remote_status if x[1]]:
2008 upload_queue = remote_status[:]
2009 else:
2010 highest_remote_revision = max([x[1] for x in remote_status])
2011
2012 if local_revision < highest_remote_revision:
2013 for remote_item in remote_status:
2014 if remote_item[1] == highest_remote_revision:
2015 download_latest = x
2016 break
2017
2018 if download_latest:
2019 upload_queue = [x for x in remote_status if \
2020 (x[1] < highest_remote_revision)]
2021 else:
2022 upload_queue = [x for x in remote_status if \
2023 (x[1] < local_revision)]
2024
2025 return download_latest, upload_queue
2026
2027 - def sync_databases(self, no_upload = False, unlock_mirrors = False,
2028 repo = None):
2029
2030 if repo == None:
2031 repo = self.Entropy.default_repository
2032
2033 while 1:
2034
2035 db_locked = False
2036 if self.is_local_database_locked(repo):
2037 db_locked = True
2038
2039 lock_data = self.get_mirrors_lock(repo)
2040 mirrors_locked = [x for x in lock_data if x[1]]
2041
2042 if not mirrors_locked and db_locked:
2043
2044 mylock_file = self.get_database_lockfile(repo)
2045 if os.access(mylock_file, os.W_OK | os.F_OK):
2046 os.remove(mylock_file)
2047 continue
2048
2049 break
2050
2051 if mirrors_locked and not db_locked:
2052 mytxt = "%s, %s %s" % (
2053 _("Mirrors are locked, someone is working on the repository"),
2054 _("try again later"),
2055 "...",
2056 )
2057 raise OnlineMirrorError("OnlineMirrorError: %s" % (mytxt,))
2058
2059 download_latest, upload_queue = self.calculate_database_sync_queues(
2060 repo)
2061
2062 if not download_latest and not upload_queue:
2063 self.Entropy.updateProgress(
2064 "[repo:%s|%s] %s" % (
2065 brown(repo),
2066 red(_("sync")),
2067 blue(_("database already in sync")),
2068 ),
2069 importance = 1,
2070 type = "info",
2071 header = blue(" @@ ")
2072 )
2073 return 0, set(), set()
2074
2075 if download_latest:
2076 download_uri = download_latest[0]
2077 download_errors, fine_uris, broken_uris = self.download_database(
2078 [download_uri], repo = repo)
2079 if download_errors:
2080 self.Entropy.updateProgress(
2081 "[repo:%s|%s] %s: %s" % (
2082 brown(repo),
2083 red(_("sync")),
2084 blue(_("database sync failed")),
2085 red(_("download issues")),
2086 ),
2087 importance = 1,
2088 type = "error",
2089 header = darkred(" !!! ")
2090 )
2091 return 1, fine_uris, broken_uris
2092
2093 if upload_queue and not no_upload:
2094
2095
2096
2097 deps_not_found = self.Entropy.dependencies_test(repo = repo)
2098 if deps_not_found and not self.Entropy.community_repo:
2099 self.Entropy.updateProgress(
2100 "[repo:%s|%s] %s: %s" % (
2101 brown(repo),
2102 red(_("sync")),
2103 blue(_("database sync forbidden")),
2104 red(_("dependencies_test() reported errors")),
2105 ),
2106 importance = 1,
2107 type = "error",
2108 header = darkred(" !!! ")
2109 )
2110 return 3, set(), set()
2111
2112 problems = self.Entropy.check_config_file_updates()
2113 if problems:
2114 return 4, set(), set()
2115
2116 self.Entropy.updateProgress(
2117 "[repo:%s|%s] %s" % (
2118 brown(repo),
2119 red(_("config files")),
2120 blue(_("no configuration files to commit. All fine.")),
2121 ),
2122 importance = 1,
2123 type = "info",
2124 header = blue(" @@ "),
2125 back = True
2126 )
2127
2128 uris = [x[0] for x in upload_queue]
2129 errors, fine_uris, broken_uris = self.upload_database(uris,
2130 repo = repo)
2131 if errors:
2132 self.Entropy.updateProgress(
2133 "[repo:%s|%s] %s: %s" % (
2134 brown(repo),
2135 red(_("sync")),
2136 blue(_("database sync failed")),
2137 red(_("upload issues")),
2138 ),
2139 importance = 1,
2140 type = "error",
2141 header = darkred(" !!! ")
2142 )
2143 return 2, fine_uris, broken_uris
2144
2145
2146 self.Entropy.updateProgress(
2147 "[repo:%s|%s] %s" % (
2148 brown(repo),
2149 red(_("sync")),
2150 blue(_("database sync completed successfully")),
2151 ),
2152 importance = 1,
2153 type = "info",
2154 header = darkgreen(" * ")
2155 )
2156
2157 if unlock_mirrors:
2158 self.lock_mirrors(False, repo = repo)
2159 return 0, set(), set()
2160
2161
2163 upload_files = 0
2164 upload_packages = set()
2165 upload_dir = os.path.join(self.Entropy.get_local_upload_directory(repo),
2166 branch)
2167
2168
2169 if not os.path.isdir(upload_dir):
2170 return upload_files, upload_packages
2171
2172 pkg_ext = etpConst['packagesext']
2173 pkg_md5_ext = etpConst['packagesmd5fileext']
2174 for package in os.listdir(upload_dir):
2175 if package.endswith(pkg_ext) or package.endswith(pkg_md5_ext):
2176 upload_packages.add(package)
2177 if package.endswith(pkg_ext):
2178 upload_files += 1
2179
2180 return upload_files, upload_packages
2181
2183 local_files = 0
2184 local_packages = set()
2185 packages_dir = os.path.join(
2186 self.Entropy.get_local_packages_directory(repo), branch)
2187
2188 if not os.path.isdir(packages_dir):
2189 os.makedirs(packages_dir)
2190
2191 pkg_ext = etpConst['packagesext']
2192 pkg_md5_ext = etpConst['packagesmd5fileext']
2193 for package in os.listdir(packages_dir):
2194 if package.endswith(pkg_ext) or package.endswith(pkg_md5_ext):
2195 local_packages.add(package)
2196 if package.endswith(pkg_ext):
2197 local_files += 1
2198
2199 return local_files, local_packages
2200
2201
2203 self.Entropy.updateProgress(
2204 "%s:" % (
2205 blue(_("Local statistics")),
2206 ),
2207 importance = 1,
2208 type = "info",
2209 header = red(" @@ ")
2210 )
2211 self.Entropy.updateProgress(
2212 red("%s:\t\t%s %s" % (
2213 blue(_("upload directory")),
2214 bold(str(upload_files)),
2215 red(_("files ready")),
2216 )
2217 ),
2218 importance = 0,
2219 type = "info",
2220 header = red(" @@ ")
2221 )
2222 self.Entropy.updateProgress(
2223 red("%s:\t\t%s %s" % (
2224 blue(_("packages directory")),
2225 bold(str(local_files)),
2226 red(_("files ready")),
2227 )
2228 ),
2229 importance = 0,
2230 type = "info",
2231 header = red(" @@ ")
2232 )
2233
2234 - def _show_sync_queues(self, upload, download, removal, copy, metainfo,
2235 branch):
2236
2237
2238 for package, size in upload:
2239 package = darkgreen(os.path.basename(package))
2240 size = blue(self.entropyTools.bytes_into_human(size))
2241 self.Entropy.updateProgress(
2242 "[branch:%s|%s] %s [%s]" % (
2243 brown(branch),
2244 blue(_("upload")),
2245 darkgreen(package),
2246 size,
2247 ),
2248 importance = 0,
2249 type = "info",
2250 header = red(" # ")
2251 )
2252 for package, size in download:
2253 package = darkred(os.path.basename(package))
2254 size = blue(self.entropyTools.bytes_into_human(size))
2255 self.Entropy.updateProgress(
2256 "[branch:%s|%s] %s [%s]" % (
2257 brown(branch),
2258 darkred(_("download")),
2259 blue(package),
2260 size,
2261 ),
2262 importance = 0,
2263 type = "info",
2264 header = red(" # ")
2265 )
2266 for package, size in copy:
2267 package = darkblue(os.path.basename(package))
2268 size = blue(self.entropyTools.bytes_into_human(size))
2269 self.Entropy.updateProgress(
2270 "[branch:%s|%s] %s [%s]" % (
2271 brown(branch),
2272 darkgreen(_("copy")),
2273 brown(package),
2274 size,
2275 ),
2276 importance = 0,
2277 type = "info",
2278 header = red(" # ")
2279 )
2280 for package, size in removal:
2281 package = brown(os.path.basename(package))
2282 size = blue(self.entropyTools.bytes_into_human(size))
2283 self.Entropy.updateProgress(
2284 "[branch:%s|%s] %s [%s]" % (
2285 brown(branch),
2286 red(_("remove")),
2287 red(package),
2288 size,
2289 ),
2290 importance = 0,
2291 type = "info",
2292 header = red(" # ")
2293 )
2294
2295 self.Entropy.updateProgress(
2296 "%s:\t\t\t%s" % (
2297 blue(_("Packages to be removed")),
2298 darkred(str(len(removal))),
2299 ),
2300 importance = 0,
2301 type = "info",
2302 header = blue(" @@ ")
2303 )
2304 self.Entropy.updateProgress(
2305 "%s:\t\t%s" % (
2306 darkgreen(_("Packages to be moved locally")),
2307 darkgreen(str(len(copy))),
2308 ),
2309 importance = 0,
2310 type = "info",
2311 header = blue(" @@ ")
2312 )
2313 self.Entropy.updateProgress(
2314 "%s:\t\t\t%s" % (
2315 bold(_("Packages to be uploaded")),
2316 bold(str(len(upload))),
2317 ),
2318 importance = 0,
2319 type = "info",
2320 header = blue(" @@ ")
2321 )
2322
2323 self.Entropy.updateProgress(
2324 "%s:\t\t\t%s" % (
2325 darkred(_("Total removal size")),
2326 darkred(
2327 self.entropyTools.bytes_into_human(metainfo['removal'])
2328 ),
2329 ),
2330 importance = 0,
2331 type = "info",
2332 header = blue(" @@ ")
2333 )
2334
2335 self.Entropy.updateProgress(
2336 "%s:\t\t\t%s" % (
2337 blue(_("Total upload size")),
2338 blue(self.entropyTools.bytes_into_human(metainfo['upload'])),
2339 ),
2340 importance = 0,
2341 type = "info",
2342 header = blue(" @@ ")
2343 )
2344 self.Entropy.updateProgress(
2345 "%s:\t\t\t%s" % (
2346 brown(_("Total download size")),
2347 brown(self.entropyTools.bytes_into_human(metainfo['download'])),
2348 ),
2349 importance = 0,
2350 type = "info",
2351 header = blue(" @@ ")
2352 )
2353
2354
2357
2358 remote_files = 0
2359 close_conn = False
2360 remote_packages_data = {}
2361
2362 my_path = os.path.join(
2363 self.Entropy.get_remote_packages_relative_path(repo), branch)
2364 if ftp_connection == None:
2365 close_conn = True
2366
2367 ftp_connection = FtpInterface(uri, self.Entropy)
2368 ftp_connection.set_cwd(my_path, dodir = True)
2369
2370 remote_packages = ftp_connection.list_dir()
2371 remote_packages_info = ftp_connection.get_raw_list()
2372 if close_conn:
2373 ftp_connection.close()
2374
2375 for tbz2 in remote_packages:
2376 if tbz2.endswith(etpConst['packagesext']):
2377 remote_files += 1
2378
2379 for remote_package in remote_packages_info:
2380 remote_packages_data[remote_package.split()[8]] = \
2381 int(remote_package.split()[4])
2382
2383 return remote_files, remote_packages, remote_packages_data
2384
2386
2387 if repo == None:
2388 repo = self.Entropy.default_repository
2389
2390 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
2391 upload_files, upload_packages = self.calculate_local_upload_files(
2392 branch, repo)
2393 local_files, local_packages = self.calculate_local_package_files(branch,
2394 repo)
2395 self._show_local_sync_stats(upload_files, local_files)
2396
2397 self.Entropy.updateProgress(
2398 "%s: %s" % (blue(_("Remote statistics for")), red(crippled_uri),),
2399 importance = 1,
2400 type = "info",
2401 header = red(" @@ ")
2402 )
2403 remote_files, remote_packages, remote_packages_data = \
2404 self.calculate_remote_package_files(uri, branch, repo = repo)
2405 self.Entropy.updateProgress(
2406 "%s:\t\t\t%s %s" % (
2407 blue(_("remote packages")),
2408 bold(str(remote_files)),
2409 red(_("files stored")),
2410 ),
2411 importance = 0,
2412 type = "info",
2413 header = red(" @@ ")
2414 )
2415
2416 mytxt = blue("%s ...") % (
2417 _("Calculating queues"),
2418 )
2419 self.Entropy.updateProgress(
2420 mytxt,
2421 importance = 1,
2422 type = "info",
2423 header = red(" @@ ")
2424 )
2425
2426 upload_queue, download_queue, removal_queue, fine_queue = \
2427 self.calculate_sync_queues(upload_packages, local_packages,
2428 remote_packages, remote_packages_data, branch, repo)
2429 return upload_queue, download_queue, removal_queue, fine_queue, \
2430 remote_packages_data
2431
2432 - def calculate_sync_queues(
2433 self,
2434 upload_packages,
2435 local_packages,
2436 remote_packages,
2437 remote_packages_data,
2438 branch,
2439 repo = None
2440 ):
2441
2442 upload_queue = set()
2443 download_queue = set()
2444 removal_queue = set()
2445 fine_queue = set()
2446
2447 for local_package in upload_packages:
2448 if local_package in remote_packages:
2449
2450 local_filepath = os.path.join(
2451 self.Entropy.get_local_upload_directory(repo), branch,
2452 local_package)
2453
2454 local_size = self.entropyTools.get_file_size(local_filepath)
2455 remote_size = remote_packages_data.get(local_package)
2456 if remote_size == None:
2457 remote_size = 0
2458 if (local_size != remote_size):
2459
2460 upload_queue.add(local_package)
2461 else:
2462
2463 fine_queue.add(local_package)
2464 else:
2465
2466 upload_queue.add(local_package)
2467
2468
2469
2470 for local_package in local_packages:
2471 if local_package in remote_packages:
2472 local_filepath = os.path.join(
2473 self.Entropy.get_local_packages_directory(repo), branch,
2474 local_package)
2475 local_size = self.entropyTools.get_file_size(local_filepath)
2476 remote_size = remote_packages_data.get(local_package)
2477 if remote_size == None:
2478 remote_size = 0
2479 if (local_size != remote_size) and (local_size != 0):
2480
2481 if local_package not in fine_queue:
2482 upload_queue.add(local_package)
2483 else:
2484
2485
2486 upload_queue.add(local_package)
2487
2488
2489 for remote_package in remote_packages:
2490 if remote_package in local_packages:
2491 local_filepath = os.path.join(
2492 self.Entropy.get_local_packages_directory(repo), branch,
2493 remote_package)
2494 local_size = self.entropyTools.get_file_size(local_filepath)
2495 remote_size = remote_packages_data.get(remote_package)
2496 if remote_size == None:
2497 remote_size = 0
2498 if (local_size != remote_size) and (local_size != 0):
2499
2500
2501
2502 if remote_package not in upload_queue:
2503
2504
2505
2506 removal_queue.add(remote_package)
2507
2508 download_queue.add(remote_package)
2509 else:
2510
2511
2512
2513 if not remote_package.endswith(".tmp"):
2514 download_queue.add(remote_package)
2515
2516
2517
2518 dbconn = self.Entropy.open_server_repository(just_reading = True,
2519 repo = repo)
2520 db_files = dbconn.listAllDownloads(do_sort = False,
2521 full_path = True)
2522 db_files = set([os.path.basename(x) for x in db_files if \
2523 (self.Entropy.get_branch_from_download_relative_uri(x) == branch)])
2524
2525 exclude = set()
2526 for myfile in download_queue:
2527 if myfile.endswith(etpConst['packagesext']):
2528 if myfile not in db_files:
2529 exclude.add(myfile)
2530 download_queue -= exclude
2531
2532 exclude = set()
2533 for myfile in upload_queue:
2534 if myfile.endswith(etpConst['packagesext']):
2535 if myfile not in db_files:
2536 exclude.add(myfile)
2537 upload_queue -= exclude
2538
2539 exclude = set()
2540 for myfile in download_queue:
2541 if myfile in upload_queue:
2542 exclude.add(myfile)
2543 download_queue -= exclude
2544
2545 return upload_queue, download_queue, removal_queue, fine_queue
2546
2547
2548 - def expand_queues(self, upload_queue, download_queue, removal_queue,
2549 remote_packages_data, branch, repo):
2550
2551 metainfo = {
2552 'removal': 0,
2553 'download': 0,
2554 'upload': 0,
2555 }
2556 removal = []
2557 download = []
2558 do_copy = []
2559 upload = []
2560
2561 for item in removal_queue:
2562 if not item.endswith(etpConst['packagesext']):
2563 continue
2564 local_filepath = os.path.join(
2565 self.Entropy.get_local_packages_directory(repo), branch, item)
2566 size = self.entropyTools.get_file_size(local_filepath)
2567 metainfo['removal'] += size
2568 removal.append((local_filepath, size))
2569
2570 for item in download_queue:
2571 if not item.endswith(etpConst['packagesext']):
2572 continue
2573 local_filepath = os.path.join(
2574 self.Entropy.get_local_upload_directory(repo), branch, item)
2575 if not os.path.isfile(local_filepath):
2576 size = remote_packages_data.get(item)
2577 if size == None:
2578 size = 0
2579 size = int(size)
2580 metainfo['removal'] += size
2581 download.append((local_filepath, size))
2582 else:
2583 size = self.entropyTools.get_file_size(local_filepath)
2584 do_copy.append((local_filepath, size))
2585
2586 for item in upload_queue:
2587 if not item.endswith(etpConst['packagesext']):
2588 continue
2589 local_filepath = os.path.join(
2590 self.Entropy.get_local_upload_directory(repo), branch, item)
2591 local_filepath_pkgs = os.path.join(
2592 self.Entropy.get_local_packages_directory(repo), branch, item)
2593 if os.path.isfile(local_filepath):
2594 size = self.entropyTools.get_file_size(local_filepath)
2595 upload.append((local_filepath, size))
2596 else:
2597 size = self.entropyTools.get_file_size(local_filepath_pkgs)
2598 upload.append((local_filepath_pkgs, size))
2599 metainfo['upload'] += size
2600
2601 return upload, download, removal, do_copy, metainfo
2602
2603
2605
2606 if repo == None:
2607 repo = self.Entropy.default_repository
2608
2609 for itemdata in removal_queue:
2610
2611 remove_filename = itemdata[0]
2612 remove_filepath = os.path.join(
2613 self.Entropy.get_local_packages_directory(repo), branch,
2614 remove_filename)
2615 remove_filepath_hash = remove_filepath + \
2616 etpConst['packagesmd5fileext']
2617 self.Entropy.updateProgress(
2618 "[repo:%s|%s|%s] %s: %s [%s]" % (
2619 brown(repo),
2620 red("sync"),
2621 brown(branch),
2622 blue(_("removing package+hash")),
2623 darkgreen(remove_filename),
2624 blue(self.entropyTools.bytes_into_human(itemdata[1])),
2625 ),
2626 importance = 0,
2627 type = "info",
2628 header = darkred(" * ")
2629 )
2630
2631 if os.path.isfile(remove_filepath):
2632 os.remove(remove_filepath)
2633 if os.path.isfile(remove_filepath_hash):
2634 os.remove(remove_filepath_hash)
2635
2636 self.Entropy.updateProgress(
2637 "[repo:%s|%s|%s] %s" % (
2638 brown(repo),
2639 red(_("sync")),
2640 brown(branch),
2641 blue(_("removal complete")),
2642 ),
2643 importance = 0,
2644 type = "info",
2645 header = darkred(" * ")
2646 )
2647
2648
2650
2651 if repo == None:
2652 repo = self.Entropy.default_repository
2653
2654 for itemdata in copy_queue:
2655
2656 from_file = itemdata[0]
2657 from_file_hash = from_file + etpConst['packagesmd5fileext']
2658 to_file = os.path.join(
2659 self.Entropy.get_local_packages_directory(repo), branch,
2660 os.path.basename(from_file))
2661 to_file_hash = to_file+etpConst['packagesmd5fileext']
2662 expiration_file = to_file+etpConst['packagesexpirationfileext']
2663 self.Entropy.updateProgress(
2664 "[repo:%s|%s|%s] %s: %s" % (
2665 brown(repo),
2666 red("sync"),
2667 brown(branch),
2668 blue(_("copying file+hash to repository")),
2669 darkgreen(from_file),
2670 ),
2671 importance = 0,
2672 type = "info",
2673 header = darkred(" * ")
2674 )
2675
2676 if not os.path.isdir(os.path.dirname(to_file)):
2677 os.makedirs(os.path.dirname(to_file))
2678
2679 shutil.copy2(from_file, to_file)
2680 if not os.path.isfile(from_file_hash):
2681 self.create_file_checksum(from_file, from_file_hash)
2682 shutil.copy2(from_file_hash, to_file_hash)
2683
2684
2685 if os.path.isfile(expiration_file):
2686 os.remove(expiration_file)
2687
2688
2690
2691 if repo == None:
2692 repo = self.Entropy.default_repository
2693
2694 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
2695 myqueue = []
2696 for itemdata in upload_queue:
2697 upload_item = itemdata[0]
2698 hash_file = upload_item + etpConst['packagesmd5fileext']
2699 if not os.path.isfile(hash_file):
2700 self.entropyTools.create_md5_file(upload_item)
2701 myqueue.append(hash_file)
2702 myqueue.append(upload_item)
2703
2704 ftp_basedir = os.path.join(
2705 self.Entropy.get_remote_packages_relative_path(repo), branch)
2706 uploader = self.FtpServerHandler(FtpInterface,
2707 self.Entropy, [uri], myqueue, critical_files = myqueue,
2708 use_handlers = True, ftp_basedir = ftp_basedir,
2709 handlers_data = {'branch': branch }, repo = repo)
2710 errors, m_fine_uris, m_broken_uris = uploader.go()
2711 if errors:
2712 my_broken_uris = [
2713 (self.entropyTools.extract_ftp_host_from_uri(x[0]), x[1]) for \
2714 x in m_broken_uris]
2715 reason = my_broken_uris[0][1]
2716 self.Entropy.updateProgress(
2717 "[branch:%s] %s: %s, %s: %s" % (
2718 brown(branch),
2719 blue(_("upload errors")),
2720 red(crippled_uri),
2721 blue(_("reason")),
2722 darkgreen(unicode(reason)),
2723 ),
2724 importance = 1,
2725 type = "error",
2726 header = darkred(" !!! ")
2727 )
2728 return errors, m_fine_uris, m_broken_uris
2729
2730 self.Entropy.updateProgress(
2731 "[branch:%s] %s: %s" % (
2732 brown(branch),
2733 blue(_("upload completed successfully")),
2734 red(crippled_uri),
2735 ),
2736 importance = 1,
2737 type = "info",
2738 header = blue(" @@ ")
2739 )
2740 return errors, m_fine_uris, m_broken_uris
2741
2742
2745
2746 if repo == None:
2747 repo = self.Entropy.default_repository
2748
2749 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
2750 myqueue = []
2751 for package in download_queue:
2752 hash_file = package + etpConst['packagesmd5fileext']
2753 myqueue.append(package)
2754 myqueue.append(hash_file)
2755
2756 ftp_basedir = os.path.join(
2757 self.Entropy.get_remote_packages_relative_path(repo), branch)
2758 local_basedir = os.path.join(
2759 self.Entropy.get_local_packages_directory(repo), branch)
2760 downloader = self.FtpServerHandler(
2761 FtpInterface, self.Entropy, [uri], myqueue,
2762 critical_files = myqueue, use_handlers = True,
2763 ftp_basedir = ftp_basedir, local_basedir = local_basedir,
2764 handlers_data = {'branch': branch }, download = True, repo = repo)
2765
2766 errors, m_fine_uris, m_broken_uris = downloader.go()
2767 if errors:
2768 my_broken_uris = [
2769 (self.entropyTools.extract_ftp_host_from_uri(x), y,) \
2770 for x, y in m_broken_uris]
2771 reason = my_broken_uris[0][1]
2772 self.Entropy.updateProgress(
2773 "[repo:%s|%s|%s] %s: %s, %s: %s" % (
2774 brown(repo),
2775 red(_("sync")),
2776 brown(branch),
2777 blue(_("download errors")),
2778 darkgreen(crippled_uri),
2779 blue(_("reason")),
2780 reason,
2781 ),
2782 importance = 1,
2783 type = "error",
2784 header = darkred(" !!! ")
2785 )
2786 return errors, m_fine_uris, m_broken_uris
2787
2788 self.Entropy.updateProgress(
2789 "[repo:%s|%s|%s] %s: %s" % (
2790 brown(repo),
2791 red(_("sync")),
2792 brown(branch),
2793 blue(_("download completed successfully")),
2794 darkgreen(crippled_uri),
2795 ),
2796 importance = 1,
2797 type = "info",
2798 header = darkgreen(" * ")
2799 )
2800 return errors, m_fine_uris, m_broken_uris
2801
2803
2804 if repo == None:
2805 repo = self.Entropy.default_repository
2806
2807 my_qa = self.Entropy.QA()
2808
2809 qa_total = len(packages_list)
2810 qa_count = 0
2811 qa_some_faulty = []
2812
2813 for upload_package in packages_list:
2814 qa_count += 1
2815
2816 self.Entropy.updateProgress(
2817 "%s: %s" % (
2818 purple(_("QA checking package file")),
2819 darkgreen(os.path.basename(upload_package)),
2820 ),
2821 importance = 0,
2822 type = "info",
2823 header = purple(" @@ "),
2824 back = True,
2825 count = (qa_count, qa_total,)
2826 )
2827
2828 result = my_qa.entropy_package_checks(upload_package)
2829 if not result:
2830
2831 qa_some_faulty.append(os.path.basename(upload_package))
2832
2833 if qa_some_faulty:
2834
2835 for qa_faulty_pkg in qa_some_faulty:
2836 self.Entropy.updateProgress(
2837 "[repo:%s|branch:%s] %s: %s" % (
2838 brown(repo),
2839 self.SystemSettings['repositories']['branch'],
2840 red(_("faulty package file, please fix")),
2841 blue(os.path.basename(qa_faulty_pkg)),
2842 ),
2843 importance = 1,
2844 type = "error",
2845 header = darkred(" @@ ")
2846 )
2847 raise EntropyPackageException(
2848 'EntropyPackageException: cannot continue')
2849
2850
2851 - def sync_packages(self, ask = True, pretend = False, packages_check = False,
2852 repo = None):
2853
2854 if repo == None:
2855 repo = self.Entropy.default_repository
2856
2857 self.Entropy.updateProgress(
2858 "[repo:%s|%s] %s" % (
2859 repo,
2860 red(_("sync")),
2861 darkgreen(_("starting packages sync")),
2862 ),
2863 importance = 1,
2864 type = "info",
2865 header = red(" @@ "),
2866 back = True
2867 )
2868
2869
2870 successfull_mirrors = set()
2871 broken_mirrors = set()
2872 check_data = ()
2873 upload_queue_qa_checked = set()
2874 mirrors_tainted = False
2875 mirror_errors = False
2876 mirrors_errors = False
2877
2878 for uri in self.Entropy.get_remote_mirrors(repo):
2879
2880 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
2881 mirror_errors = False
2882
2883 self.Entropy.updateProgress(
2884 "[repo:%s|%s|branch:%s] %s: %s" % (
2885 repo,
2886 red(_("sync")),
2887 brown(self.SystemSettings['repositories']['branch']),
2888 blue(_("packages sync")),
2889 bold(crippled_uri),
2890 ),
2891 importance = 1,
2892 type = "info",
2893 header = red(" @@ ")
2894 )
2895
2896 try:
2897 upload_queue, download_queue, removal_queue, fine_queue, \
2898 remote_packages_data = self.calculate_packages_to_sync(uri,
2899 self.SystemSettings['repositories']['branch'], repo)
2900 except self.socket.error, err:
2901 self.Entropy.updateProgress(
2902 "[repo:%s|%s|branch:%s] %s: %s, %s %s" % (
2903 repo,
2904 red(_("sync")),
2905 self.SystemSettings['repositories']['branch'],
2906 darkred(_("socket error")),
2907 err,
2908 darkred(_("on")),
2909 crippled_uri,
2910 ),
2911 importance = 1,
2912 type = "error",
2913 header = darkgreen(" * ")
2914 )
2915 continue
2916
2917 if (not upload_queue) and (not download_queue) and \
2918 (not removal_queue):
2919 self.Entropy.updateProgress(
2920 "[repo:%s|%s|branch:%s] %s: %s" % (
2921 repo,
2922 red(_("sync")),
2923 self.SystemSettings['repositories']['branch'],
2924 darkgreen(_("nothing to do on")),
2925 crippled_uri,
2926 ),
2927 importance = 1,
2928 type = "info",
2929 header = darkgreen(" * ")
2930 )
2931 successfull_mirrors.add(uri)
2932 continue
2933
2934 self.Entropy.updateProgress(
2935 "%s:" % (blue(_("Expanding queues")),),
2936 importance = 1,
2937 type = "info",
2938 header = red(" ** ")
2939 )
2940
2941 upload, download, removal, copy, metainfo = self.expand_queues(
2942 upload_queue,
2943 download_queue,
2944 removal_queue,
2945 remote_packages_data,
2946 self.SystemSettings['repositories']['branch'],
2947 repo
2948 )
2949 del upload_queue, download_queue, removal_queue, \
2950 remote_packages_data
2951 self._show_sync_queues(upload, download, removal, copy, metainfo,
2952 self.SystemSettings['repositories']['branch'])
2953
2954 if not len(upload)+len(download)+len(removal)+len(copy):
2955
2956 self.Entropy.updateProgress(
2957 "[repo:%s|%s|branch:%s] %s %s" % (
2958 self.Entropy.default_repository,
2959 red(_("sync")),
2960 self.SystemSettings['repositories']['branch'],
2961 blue(_("nothing to sync for")),
2962 crippled_uri,
2963 ),
2964 importance = 1,
2965 type = "info",
2966 header = darkgreen(" @@ ")
2967 )
2968
2969 successfull_mirrors.add(uri)
2970 continue
2971
2972 if pretend:
2973 successfull_mirrors.add(uri)
2974 continue
2975
2976 if ask:
2977 rc_sync = self.Entropy.askQuestion(
2978 _("Would you like to run the steps above ?"))
2979 if rc_sync == "No":
2980 continue
2981
2982 try:
2983
2984
2985 qa_package_files = [x[0] for x in upload if x[0] \
2986 not in upload_queue_qa_checked]
2987 upload_queue_qa_checked |= set(qa_package_files)
2988
2989 self.run_package_files_qa_checks(qa_package_files, repo = repo)
2990
2991 if removal:
2992 self._sync_run_removal_queue(removal,
2993 self.SystemSettings['repositories']['branch'], repo)
2994
2995 if copy:
2996 self._sync_run_copy_queue(copy,
2997 self.SystemSettings['repositories']['branch'], repo)
2998
2999 if upload or download:
3000 mirrors_tainted = True
3001
3002 if upload:
3003 d_errors, m_fine_uris, \
3004 m_broken_uris = self._sync_run_upload_queue(
3005 uri, upload,
3006 self.SystemSettings['repositories']['branch'], repo)
3007
3008 if d_errors:
3009 mirror_errors = True
3010
3011 if download:
3012 my_downlist = [x[0] for x in download]
3013 d_errors, m_fine_uris, \
3014 m_broken_uris = self._sync_run_download_queue(
3015 uri, my_downlist,
3016 self.SystemSettings['repositories']['branch'], repo)
3017
3018 if d_errors:
3019 mirror_errors = True
3020 if not mirror_errors:
3021 successfull_mirrors.add(uri)
3022 else:
3023 mirrors_errors = True
3024
3025 except KeyboardInterrupt:
3026 self.Entropy.updateProgress(
3027 "[repo:%s|%s|branch:%s] %s" % (
3028 repo,
3029 red(_("sync")),
3030 self.SystemSettings['repositories']['branch'],
3031 darkgreen(_("keyboard interrupt !")),
3032 ),
3033 importance = 1,
3034 type = "info",
3035 header = darkgreen(" * ")
3036 )
3037 continue
3038
3039 except EntropyPackageException:
3040
3041 mirrors_errors = True
3042 broken_mirrors.add(uri)
3043 successfull_mirrors.clear()
3044
3045 self.Entropy.updateProgress(
3046 "[repo:%s|%s|branch:%s] %s: %s, %s: %s" % (
3047 repo,
3048 red(_("sync")),
3049 self.SystemSettings['repositories']['branch'],
3050 darkred(_("you must package them again")),
3051 Exception,
3052 _("error"),
3053 err,
3054 ),
3055 importance = 1,
3056 type = "error",
3057 header = darkred(" !!! ")
3058 )
3059 return mirrors_tainted, mirrors_errors, successfull_mirrors, \
3060 broken_mirrors, check_data
3061
3062 except Exception, err:
3063
3064 self.entropyTools.print_traceback()
3065 mirrors_errors = True
3066 broken_mirrors.add(uri)
3067 self.Entropy.updateProgress(
3068 "[repo:%s|%s|branch:%s] %s: %s, %s: %s" % (
3069 repo,
3070 red(_("sync")),
3071 self.SystemSettings['repositories']['branch'],
3072 darkred(_("exception caught")),
3073 Exception,
3074 _("error"),
3075 err,
3076 ),
3077 importance = 1,
3078 type = "error",
3079 header = darkred(" !!! ")
3080 )
3081
3082 exc_txt = self.Entropy.entropyTools.print_exception(
3083 returndata = True)
3084 for line in exc_txt:
3085 self.Entropy.updateProgress(
3086 unicode(line),
3087 importance = 1,
3088 type = "error",
3089 header = darkred(": ")
3090 )
3091
3092 if len(successfull_mirrors) > 0:
3093 self.Entropy.updateProgress(
3094 "[repo:%s|%s|branch:%s] %s" % (
3095 repo,
3096 red(_("sync")),
3097 self.SystemSettings['repositories']['branch'],
3098 darkred(
3099 _("at least one mirror synced properly!")),
3100 ),
3101 importance = 1,
3102 type = "error",
3103 header = darkred(" !!! ")
3104 )
3105 continue
3106
3107
3108 if (len(successfull_mirrors) > 0) and not pretend:
3109 self.remove_expiration_files(
3110 self.SystemSettings['repositories']['branch'], repo)
3111
3112 if packages_check:
3113 check_data = self.Entropy.verify_local_packages([], ask = ask,
3114 repo = repo)
3115
3116 return mirrors_tainted, mirrors_errors, successfull_mirrors, \
3117 broken_mirrors, check_data
3118
3120
3121 if repo == None:
3122 repo = self.Entropy.default_repository
3123
3124 branch_dir = os.path.join(
3125 self.Entropy.get_local_upload_directory(repo), branch)
3126
3127
3128 if not os.path.isdir(branch_dir):
3129 return None
3130
3131 branchcontent = os.listdir(branch_dir)
3132 for xfile in branchcontent:
3133 source = os.path.join(self.Entropy.get_local_upload_directory(repo),
3134 branch, xfile)
3135 destdir = os.path.join(
3136 self.Entropy.get_local_packages_directory(repo), branch)
3137 if not os.path.isdir(destdir):
3138 os.makedirs(destdir)
3139 dest = os.path.join(destdir, xfile)
3140 shutil.move(source, dest)
3141
3142 dest_expiration = dest + etpConst['packagesexpirationfileext']
3143 if os.path.isfile(dest_expiration):
3144 os.remove(dest_expiration)
3145
3146
3148
3149 pkg_path = os.path.join(
3150 self.Entropy.get_local_packages_directory(repo), branch,
3151 package_file)
3152 pkg_path += etpConst['packagesexpirationfileext']
3153 if not os.path.isfile(pkg_path):
3154 return False
3155
3156 srv_set = self.SystemSettings[self.sys_settings_plugin_id]['server']
3157 mtime = self.entropyTools.get_file_unix_mtime(pkg_path)
3158 days = srv_set['packages_expiration_days']
3159 delta = int(days)*24*3600
3160 currmtime = time.time()
3161 file_delta = currmtime - mtime
3162
3163 if file_delta > delta:
3164 return True
3165 return False
3166
3169
3170 pkg_path = os.path.join(
3171 self.Entropy.get_local_packages_directory(repo), branch,
3172 package_file)
3173 pkg_path += etpConst['packagesexpirationfileext']
3174 if gentle and os.path.isfile(pkg_path):
3175 return
3176 f_exp = open(pkg_path,"w")
3177 f_exp.flush()
3178 f_exp.close()
3179
3180
3182
3183 dbconn = self.Entropy.open_server_repository(just_reading = True,
3184 repo = repo)
3185 database_bins = dbconn.listAllDownloads(do_sort = False,
3186 full_path = True)
3187 bins_dir = os.path.join(
3188 self.Entropy.get_local_packages_directory(repo), branch)
3189 repo_bins = set()
3190
3191 if os.path.isdir(bins_dir):
3192 repo_bins = os.listdir(bins_dir)
3193 repo_bins = set([
3194 os.path.join('packages', etpSys['arch'], branch, x) for x \
3195 in repo_bins if x.endswith(etpConst['packagesext'])])
3196 repo_bins -= database_bins
3197
3198 return set([os.path.basename(x) for x in repo_bins])
3199
3200
3201 - def tidy_mirrors(self, ask = True, pretend = False, repo = None):
3202
3203 if repo == None:
3204 repo = self.Entropy.default_repository
3205
3206 self.Entropy.updateProgress(
3207 "[repo:%s|%s|branch:%s] %s" % (
3208 brown(repo),
3209 red(_("tidy")),
3210 blue(self.SystemSettings['repositories']['branch']),
3211 blue(_("collecting expired packages")),
3212 ),
3213 importance = 1,
3214 type = "info",
3215 header = red(" @@ ")
3216 )
3217
3218 branch_data = {}
3219 errors = False
3220 branch_data['errors'] = False
3221 branch = self.SystemSettings['repositories']['branch']
3222
3223 self.Entropy.updateProgress(
3224 "[branch:%s] %s" % (
3225 brown(branch),
3226 blue(_("collecting expired packages in the selected branches")),
3227 ),
3228 importance = 1,
3229 type = "info",
3230 header = blue(" @@ ")
3231 )
3232
3233
3234 expiring_packages = self.collect_expiring_packages(branch, repo)
3235 if expiring_packages:
3236
3237
3238
3239
3240
3241
3242 branch_pkglist_data = self.read_remote_file_in_branches(
3243 etpConst['etpdatabasepkglist'], repo = repo,
3244 excluded_branches = [branch])
3245
3246 for key, val in branch_pkglist_data.items():
3247 branch_pkglist_data[key] = val.split("\n")
3248
3249
3250 remote_relpath = os.path.join(etpConst['packagesrelativepath'],
3251 branch)
3252 my_expiring_pkgs = set([os.path.join(remote_relpath, x) for x in \
3253 expiring_packages])
3254
3255 for other_branch in branch_pkglist_data:
3256 branch_pkglist = set(branch_pkglist_data[other_branch])
3257 my_expiring_pkgs -= branch_pkglist
3258
3259
3260 expiring_packages = [os.path.basename(x) for x in my_expiring_pkgs]
3261
3262 removal = []
3263 for package in expiring_packages:
3264 expired = self.is_package_expired(package, branch, repo)
3265 if expired:
3266 removal.append(package)
3267 else:
3268 self.create_expiration_file(package, branch, repo,
3269 gentle = True)
3270
3271
3272 branch_data['removal'] = removal[:]
3273
3274 if not removal:
3275 self.Entropy.updateProgress(
3276 "[branch:%s] %s" % (
3277 brown(branch),
3278 blue(_("nothing to remove on this branch")),
3279 ),
3280 importance = 1,
3281 type = "info",
3282 header = blue(" @@ ")
3283 )
3284 return errors, branch_data
3285 else:
3286 self.Entropy.updateProgress(
3287 "[branch:%s] %s:" % (
3288 brown(branch),
3289 blue(_("these are the expired packages")),
3290 ),
3291 importance = 1,
3292 type = "info",
3293 header = blue(" @@ ")
3294 )
3295 for package in removal:
3296 self.Entropy.updateProgress(
3297 "[branch:%s] %s: %s" % (
3298 brown(branch),
3299 blue(_("remove")),
3300 darkgreen(package),
3301 ),
3302 importance = 1,
3303 type = "info",
3304 header = brown(" # ")
3305 )
3306
3307 if pretend:
3308 return errors, branch_data
3309
3310 if ask:
3311 rc_question = self.Entropy.askQuestion(
3312 _("Would you like to continue ?"))
3313 if rc_question == "No":
3314 return errors, branch_data
3315
3316 myqueue = []
3317 for package in removal:
3318 myqueue.append(package+etpConst['packagesmd5fileext'])
3319 myqueue.append(package)
3320
3321 ftp_basedir = os.path.join(
3322 self.Entropy.get_remote_packages_relative_path(repo), branch)
3323 for uri in self.Entropy.get_remote_mirrors(repo):
3324
3325 self.Entropy.updateProgress(
3326 "[branch:%s] %s..." % (
3327 brown(branch),
3328 blue(_("removing packages remotely")),
3329 ),
3330 importance = 1,
3331 type = "info",
3332 header = blue(" @@ ")
3333 )
3334
3335 crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri)
3336 destroyer = self.FtpServerHandler(
3337 FtpInterface,
3338 self.Entropy,
3339 [uri],
3340 myqueue,
3341 critical_files = [],
3342 ftp_basedir = ftp_basedir,
3343 remove = True,
3344 repo = repo
3345 )
3346 errors, m_fine_uris, m_broken_uris = destroyer.go()
3347 if errors:
3348 my_broken_uris = [
3349 (self.entropyTools.extract_ftp_host_from_uri(x[0]), x[1]) \
3350 for x in m_broken_uris]
3351
3352 reason = my_broken_uris[0][1]
3353 self.Entropy.updateProgress(
3354 "[branch:%s] %s: %s, %s: %s" % (
3355 brown(branch),
3356 blue(_("remove errors")),
3357 red(crippled_uri),
3358 blue(_("reason")),
3359 reason,
3360 ),
3361 importance = 1,
3362 type = "warning",
3363 header = brown(" !!! ")
3364 )
3365 branch_data['errors'] = True
3366 errors = True
3367
3368 self.Entropy.updateProgress(
3369 "[branch:%s] %s..." % (
3370 brown(branch),
3371 blue(_("removing packages locally")),
3372 ),
3373 importance = 1,
3374 type = "info",
3375 header = blue(" @@ ")
3376 )
3377
3378 branch_data['removed'] = set()
3379 for package in removal:
3380 package_path = os.path.join(
3381 self.Entropy.get_local_packages_directory(repo),
3382 branch, package)
3383 package_path_hash = package_path + \
3384 etpConst['packagesmd5fileext']
3385 package_path_expired = package_path + \
3386 etpConst['packagesexpirationfileext']
3387
3388 my_rm_list = (package_path_hash, package_path,
3389 package_path_expired)
3390 for myfile in my_rm_list:
3391 if os.path.isfile(myfile):
3392 self.Entropy.updateProgress(
3393 "[branch:%s] %s: %s" % (
3394 brown(branch),
3395 blue(_("removing")),
3396 darkgreen(myfile),
3397 ),
3398 importance = 1,
3399 type = "info",
3400 header = brown(" @@ ")
3401 )
3402 os.remove(myfile)
3403 branch_data['removed'].add(myfile)
3404
3405 return errors, branch_data
3406