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