1 """
2
3 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
4 @contact: lxnay@sabayonlinux.org
5 @copyright: Fabio Erculiani
6 @license: GPL-2
7
8 B{Entropy Framework constants module}.
9
10 This module contains all the Entropy constants used all around
11 the "entropy" package.
12
13 Some of the constants in this module are used as "default" for
14 the SystemSettings interface. So, make sure to read the documentation
15 of SystemSettings in the "entropy.core" module.
16
17 Even if possible, etpConst, etpUi, etpCache and etpSys objects
18 *SHOULD* be I{never ever modified manually}. This freedom could change
19 in future, so, if you want to produce a stable code, DON'T do that at all!
20
21 Basic Entropy constants handling functions are available in this module
22 and are all prefixed with "I{const_*}" or "I{initconfig_*}".
23 If you are writing a third party application, you should always try
24 to avoid to deal directly with functions here unless specified otherwise.
25 In fact, usually these here are wrapper in upper-level modules
26 (entropy.client, entropy.server, entropy.services).
27
28
29 """
30
31
32 from __future__ import with_statement
33 import sys, os, stat
34 from entropy.i18n import _
35 import gzip
36 import bz2
37
38
39 ETP_ARCH_CONST = "x86"
40 if os.uname()[4] == "x86_64":
41 ETP_ARCH_CONST = "amd64"
42
43 etpSys = {
44 'archs': ["x86", "amd64"],
45 'keywords': set([ETP_ARCH_CONST,"~"+ETP_ARCH_CONST]),
46 'api': '3',
47 'arch': ETP_ARCH_CONST,
48 'rootdir': "",
49 'maxthreads': 100,
50 'dirstoclean': set(),
51 'serverside': False,
52 'killpids': set(),
53 }
54
55 etpUi = {
56 'debug': False,
57 'quiet': False,
58 'verbose': False,
59 'ask': False,
60 'pretend': False,
61 'mute': False,
62 'nolog': False,
63 'clean': False,
64 'warn': True,
65 }
66 if "--debug" in sys.argv:
67 etpUi['debug'] = True
68
69
70 ETP_LOGLEVEL_NORMAL = 1
71 ETP_LOGLEVEL_VERBOSE = 2
72 ETP_LOGPRI_INFO = "[ INFO ]"
73 ETP_LOGPRI_WARNING = "[ WARNING ]"
74 ETP_LOGPRI_ERROR = "[ ERROR ]"
75
76
77 etpCache = {
78
79
80 'configfiles': 'conf/scanfs',
81 'dbMatch': 'match/db',
82 'dbSearch': 'search/db',
83
84 'atomMatch': 'atom_match/atom_match_',
85 'install': 'resume/resume_install',
86 'remove': 'resume/resume_remove',
87 'world': 'resume/resume_world',
88 'world_update': 'world_update/world_cache_',
89 'critical_update': 'critical_update/critical_cache_',
90 'world_available': 'world_available/available_cache_',
91 'check_package_update': 'check_update/package_update_',
92 'advisories': 'security/advisories_cache_',
93 'dep_tree': 'deptree/dep_tree_',
94 'depends_tree': 'depends/depends_tree_',
95 'filter_satisfied_deps': 'depfilter/filter_satisfied_deps_',
96 'library_breakage': 'libs_break/library_breakage_',
97 'repolist': 'repos/repolist',
98 'repository_server': 'reposerver/item',
99 'eapi3_fetch': 'eapi3/segment_',
100 'ugc_votes': 'ugc/ugc_votes',
101 'ugc_downloads': 'ugc/ugc_downloads',
102 'ugc_docs': 'ugc/ugc_docs',
103 'ugc_srv_cache': 'ugc/ugc_srv_cache'
104 }
105
106 etpConst = {}
107
109
110 """
111 Main constants configurators, this is the only function that you should
112 call from the outside, anytime you want. it will reset all the variables
113 excluding those backed up previously.
114
115 @param rootdir: current root directory, if any, or ""
116 @type rootdir: string
117 @rtype: None
118 @return: None
119 @raise AttributeError: when specified rootdir is not a directory
120 """
121
122 if rootdir and not os.path.isdir(rootdir):
123 raise AttributeError("not a valid chroot.")
124
125
126 if etpConst.has_key('backed_up'):
127 backed_up_settings = etpConst.pop('backed_up')
128 else:
129 backed_up_settings = {}
130
131 const_default_settings(rootdir)
132 const_read_entropy_release()
133 const_create_working_dirs()
134 const_setup_entropy_pid()
135 const_configure_lock_paths()
136
137
138 etpConst.update(backed_up_settings)
139 etpConst['backed_up'] = backed_up_settings.copy()
140
141 if sys.excepthook == sys.__excepthook__:
142 sys.excepthook = __const_handle_exception
143
145
146 """
147 Initialization of all the Entropy base settings.
148
149 @param rootdir: current root directory, if any, or ""
150 @type rootdir: string
151 @rtype: None
152 @return: None
153 """
154
155 default_etp_dir = rootdir+"/var/lib/entropy"
156 default_etp_tmpdir = "/tmp"
157 default_etp_repodir = "/packages/"+ETP_ARCH_CONST
158 default_etp_portdir = rootdir+"/usr/portage"
159 default_etp_distfilesdir = "/distfiles"
160 default_etp_dbdir = "/database/"+ETP_ARCH_CONST
161 default_etp_dbfile = "packages.db"
162 default_etp_dbclientfile = "equo.db"
163 default_etp_client_repodir = "/client"
164 default_etp_triggersdir = "/triggers/"+ETP_ARCH_CONST
165 default_etp_smartappsdir = "/smartapps/"+ETP_ARCH_CONST
166 default_etp_smartpackagesdir = "/smartpackages/"+ETP_ARCH_CONST
167 default_etp_cachesdir = "/caches/"
168 default_etp_securitydir = "/glsa/"
169 default_etp_setsdirname = "sets"
170 default_etp_setsdir = "/%s/" % (default_etp_setsdirname,)
171 default_etp_logdir = default_etp_dir+"/"+"logs"
172 default_etp_confdir = rootdir+"/etc/entropy"
173 default_etp_packagesdir = default_etp_confdir+"/packages"
174 default_etp_ugc_confdir = default_etp_confdir+"/ugc"
175 default_etp_syslogdir = rootdir+"/var/log/entropy/"
176 default_etp_vardir = rootdir+"/var/tmp/entropy"
177 edb_counter = rootdir+"/var/cache/edb/counter"
178
179 cmdline = []
180 cmdline_file = "/proc/cmdline"
181 if os.access(cmdline_file, os.R_OK) and os.path.isfile(cmdline_file):
182 with open(cmdline_file, "r") as cmdline_f:
183 cmdline = cmdline_f.readline().strip().split()
184
185 etpConst.clear()
186 my_const = {
187 'server_repositories': {},
188 'community': {
189 'mode': False,
190 },
191 'cmdline': cmdline,
192 'backed_up': {},
193
194 'installdir': '/usr/lib/entropy',
195
196 'packagestmpdir': default_etp_dir+default_etp_tmpdir,
197
198
199
200
201
202 'packagesbindir': default_etp_dir+default_etp_repodir,
203
204 'smartappsdir': default_etp_dir+default_etp_smartappsdir,
205
206
207 'smartpackagesdir': default_etp_dir+default_etp_smartpackagesdir,
208
209 'triggersdir': default_etp_dir+default_etp_triggersdir,
210
211 'portagetreedir': default_etp_portdir,
212
213 'distfilesdir': default_etp_portdir+default_etp_distfilesdir,
214
215 'confdir': default_etp_confdir,
216
217 'confpackagesdir': default_etp_packagesdir,
218
219 'confsetsdir': default_etp_packagesdir+default_etp_setsdir,
220
221 'confsetsdirname': default_etp_setsdirname,
222
223 'entropyconf': default_etp_confdir+"/entropy.conf",
224
225 'repositoriesconf': default_etp_confdir+"/repositories.conf",
226
227 'serverconf': default_etp_confdir+"/server.conf",
228
229 'clientconf': default_etp_confdir+"/client.conf",
230
231 'socketconf': default_etp_confdir+"/socket.conf",
232
233 'packagesrelativepath': "packages/"+ETP_ARCH_CONST+"/",
234
235 'entropyworkdir': default_etp_dir,
236
237 'entropyunpackdir': default_etp_vardir,
238
239 'entropyimagerelativepath': "image",
240
241 'entropyxpakrelativepath': "xpak",
242
243 'entropyxpakdatarelativepath': "data",
244
245 'entropyxpakfilename': "metadata.xpak",
246
247
248 'etpdatabasetimestampfile': default_etp_dbfile+".timestamp",
249
250 'etpdatabasepkglist': default_etp_dbfile+".pkglist",
251 'etpdatabaseconflictingtaggedfile': default_etp_dbfile + \
252 ".conflicting_tagged",
253
254
255 'etpdatabasesytemmaskfile': default_etp_dbfile+".system_mask",
256 'etpdatabasemaskfile': default_etp_dbfile+".mask",
257 'etpdatabaseupdatefile': default_etp_dbfile+".repo_updates",
258 'etpdatabaselicwhitelistfile': default_etp_dbfile+".lic_whitelist",
259 'etpdatabasecriticalfile': default_etp_dbfile+".critical",
260
261 'etpdatabaserevisionfile': default_etp_dbfile+".revision",
262
263 'etpdatabasemissingdepsblfile': default_etp_dbfile + \
264 ".missing_deps_blacklist",
265
266
267 'etpdatabasemetafilesfile': default_etp_dbfile+".meta",
268
269
270 'etpdatabasemetafilesnotfound': default_etp_dbfile+".meta_notfound",
271 'etpdatabasehashfile': default_etp_dbfile+".md5",
272
273
274
275 'etpdatabaselockfile': default_etp_dbfile+".lock",
276
277 'etpdatabaseeapi3lockfile': default_etp_dbfile+".eapi3_lock",
278
279 'etpdatabasedownloadlockfile': default_etp_dbfile+".download.lock",
280 'etpdatabasecacertfile': "ca.cert",
281 'etpdatabaseservercertfile': "server.cert",
282
283
284 'etpdatabasetaintfile': default_etp_dbfile+".tainted",
285
286
287
288 'etpdatabasefile': default_etp_dbfile,
289
290 'etpdatabasefilegzip': default_etp_dbfile+".gz",
291
292 'etpdatabasefilebzip2': default_etp_dbfile+".bz2",
293
294
295 'etpdatabasefilegziplight': default_etp_dbfile+".light.gz",
296 'etpdatabasefilehashgziplight': default_etp_dbfile+".light.gz.md5",
297
298 'etpdatabasefilebzip2light': default_etp_dbfile+".light.bz2",
299 'etpdatabasefilehashbzip2light': default_etp_dbfile+".light.bz2.md5",
300
301
302 'etpdatabasedumpbzip2': default_etp_dbfile+".dump.bz2",
303 'etpdatabasedumphashfilebz2': default_etp_dbfile+".dump.bz2.md5",
304
305 'etpdatabasedumpgzip': default_etp_dbfile+".dump.gz",
306 'etpdatabasedumphashfilegzip': default_etp_dbfile+".dump.gz.md5",
307
308
309 'etpdatabasedump': default_etp_dbfile+".dump",
310
311
312 'etpdatabasedumplightbzip2': default_etp_dbfile+".dumplight.bz2",
313
314 'etpdatabasedumplightgzip': default_etp_dbfile+".dumplight.gz",
315
316 'etpdatabasedumplighthashfilebz2': default_etp_dbfile+".dumplight.bz2.md5",
317 'etpdatabasedumplighthashfilegzip': default_etp_dbfile+".dumplight.gz.md5",
318 'etpdatabasedumplight': default_etp_dbfile+".dumplight",
319
320
321 'etpdatabaseexpbasedpkgsrm': default_etp_dbfile+".fatscope",
322
323
324 'etpdatabasefileformat': "bz2",
325
326 'etpdatabasesupportedcformats': ["bz2", "gz"],
327 'etpdatabasecompressclasses': {
328 "bz2": (bz2.BZ2File, "unpack_bzip2", "etpdatabasefilebzip2",
329 "etpdatabasedumpbzip2", "etpdatabasedumphashfilebz2",
330 "etpdatabasedumplightbzip2", "etpdatabasedumplighthashfilebz2",
331 "etpdatabasefilebzip2light","etpdatabasefilehashbzip2light",),
332 "gz": (gzip.GzipFile, "unpack_gzip", "etpdatabasefilegzip",
333 "etpdatabasedumpgzip", "etpdatabasedumphashfilegzip",
334 "etpdatabasedumplightgzip", "etpdatabasedumplighthashfilegzip",
335 "etpdatabasefilegziplight","etpdatabasefilehashgziplight",)
336 },
337
338 'rss-feed': True,
339
340 'rss-name': "packages.rss",
341 'rss-light-name': "updates.rss",
342
343
344 'rss-base-url': "http://packages.sabayonlinux.org/",
345
346
347 'rss-website-url': "http://www.sabayonlinux.org/",
348
349 'rss-dump-name': "rss_database_actions",
350 'rss-max-entries': 10000,
351 'rss-light-max-entries': 300,
352 'rss-managing-editor': "lxnay@sabayonlinux.org",
353
354 'rss-notice-board': "notice.rss",
355
356 'packagesetprefix': "@",
357 'userpackagesetsid': "__user__",
358 'setsconffilename': "sets.conf",
359 'cachedumpext': ".dmp",
360 'packagesext': ".tbz2",
361 'smartappsext': ".esa",
362
363
364 'packagesmd5fileext': ".md5",
365 'packagessha512fileext': ".sha512",
366 'packagessha256fileext': ".sha256",
367 'packagessha1fileext': ".sha1",
368
369 'packagesexpirationfileext': ".expired",
370
371 'packagesexpirationdays': 15,
372
373
374 'triggername': "trigger",
375 'trigger_sh_interpreter': rootdir+"/usr/sbin/entropy.sh",
376
377 'etp_hw_hash_gen': rootdir+"/usr/bin/entropy_hwgen.sh",
378
379 'etp_post_branch_hop_script': default_etp_dbfile+".post_branch.sh",
380
381 'etp_post_branch_upgrade_script': default_etp_dbfile+".post_upgrade.sh",
382
383 'etp_previous_branch_file': default_etp_confdir+"/.previous_branch",
384
385 'proxy': {
386 'ftp': None,
387 'http': None,
388 'username': None,
389 'password': None
390 },
391
392 'entropyloglevel': 1,
393
394 'socketloglevel': 2,
395 'spmloglevel': 1,
396
397 'logdir': default_etp_logdir,
398
399 'syslogdir': default_etp_syslogdir,
400 'entropylogfile': default_etp_syslogdir+"entropy.log",
401 'equologfile': default_etp_syslogdir+"equo.log",
402 'spmlogfile': default_etp_syslogdir+"spm.log",
403 'socketlogfile': default_etp_syslogdir+"socket.log",
404
405 'etpdatabaseclientdir': default_etp_dir + default_etp_client_repodir + \
406 default_etp_dbdir,
407
408 'etpdatabaseclientfilepath': default_etp_dir + \
409 default_etp_client_repodir + default_etp_dbdir + "/" + \
410 default_etp_dbclientfile,
411
412
413 'dbnamerepoprefix': "repo_",
414
415 'dbbackupprefix': 'etp_backup_',
416
417
418 'etpapi': etpSys['api'],
419
420 'currentarch': etpSys['arch'],
421
422 'supportedarchs': etpSys['archs'],
423
424
425 'branch': "4",
426
427 'keywords': etpSys['keywords'].copy(),
428
429
430
431 'expiration_based_scope': False,
432 'edbcounter': edb_counter,
433
434 'officialserverrepositoryid': "sabayonlinux.org",
435
436 'officialrepositoryid': "sabayonlinux.org",
437 'conntestlink': "http://www.sabayonlinux.org",
438
439 'databasestarttag': "|ENTROPY:PROJECT:DB:MAGIC:START|",
440 'pidfile': default_etp_dir+"/entropy.lock",
441 'applicationlock': False,
442
443
444 'filesbackup': True,
445
446 'forcedupdates': True,
447
448 'collisionprotect': 1,
449
450
451 'configprotect': [],
452
453 'configprotectmask': [],
454
455
456 'configprotectskip': [],
457
458 'dbconfigprotect': [],
459
460 'dbconfigprotectmask': [],
461
462
463 'configprotectcounter': 0,
464
465 'entropyversion': "1.0",
466
467 'systemname': "Sabayon Linux",
468
469 'product': "standard",
470 'errorstatus': default_etp_confdir+"/code",
471 'systemroot': rootdir,
472 'uid': os.getuid(),
473 'entropygid': None,
474 'sysgroup': "entropy",
475 'defaultumask': 022,
476 'storeumask': 002,
477 'gentle_nice': 15,
478 'current_nice': 0,
479 'default_nice': 0,
480 'server_treeupdatescalled': set(),
481 'client_treeupdatescalled': set(),
482 'spm': {
483 '(r)depend_id': 0,
484 'pdepend_id': 1,
485 'mdepend_id': 2,
486 'ebuild_file_extension': "ebuild",
487 'preinst_phase': "preinst",
488 'postinst_phase': "postinst",
489 'prerm_phase': "prerm",
490 'postrm_phase': "postrm",
491 'setup_phase': "setup",
492 'compile_phase': "compile",
493 'install_phase': "install",
494 'unpack_phase': "unpack",
495 'ebuild_pkg_tag_var': "ENTROPY_PROJECT_TAG",
496 'global_make_conf': rootdir+"/etc/make.conf",
497 'global_package_keywords': rootdir+"/etc/portage/package.keywords",
498 'global_package_use': rootdir+"/etc/portage/package.use",
499 'global_package_mask': rootdir+"/etc/portage/package.mask",
500 'global_package_unmask': rootdir+"/etc/portage/package.unmask",
501 'global_make_profile': rootdir+"/etc/make.profile",
502 'global_make_profile_link_name' : "profile.link",
503
504 'exec': rootdir+"/usr/bin/emerge",
505 'env_update_cmd': rootdir+"/usr/sbin/env-update",
506 'source_profile': ["source", rootdir+"/etc/profile"],
507 'source_build_ext': ".ebuild",
508 'ask_cmd': "--ask",
509 'info_cmd': "--info",
510 'remove_cmd': "-C",
511 'nodeps_cmd': "--nodeps",
512 'fetchonly_cmd': "--fetchonly",
513 'buildonly_cmd': "--buildonly",
514 'oneshot_cmd': "--oneshot",
515 'pretend_cmd': "--pretend",
516 'verbose_cmd': "--verbose",
517 'nocolor_cmd': "--color=n",
518 'backend': "portage",
519 'available_backends': ["portage"],
520 'cache': {},
521 'xpak_entries': {
522 'description': "DESCRIPTION",
523 'homepage': "HOMEPAGE",
524 'chost': "CHOST",
525 'category': "CATEGORY",
526 'cflags': "CFLAGS",
527 'cxxflags': "CXXFLAGS",
528 'license': "LICENSE",
529 'src_uri': "SRC_URI",
530 'use': "USE",
531 'iuse': "IUSE",
532 'slot': "SLOT",
533 'provide': "PROVIDE",
534 'depend': "DEPEND",
535 'rdepend': "RDEPEND",
536 'pdepend': "PDEPEND",
537 'needed': "NEEDED",
538 'inherited': "INHERITED",
539 'keywords': "KEYWORDS",
540 'contents': "CONTENTS",
541 'counter': "COUNTER",
542 'defined_phases': "DEFINED_PHASES",
543 'pf': "PF",
544 },
545 'system_packages': [],
546 'ignore-spm-downgrades': False,
547 },
548
549
550 'downloadspeedlimit': None,
551
552
553
554 'dumpstoragedir': default_etp_dir+default_etp_cachesdir,
555
556 'securitydir': default_etp_dir+default_etp_securitydir,
557 'securityurl': "http://community.sabayonlinux.org/security"
558 "/security-advisories.tar.bz2",
559
560 'safemodeerrors': {
561 'clientdb': 1,
562 },
563 'safemodereasons': {
564 0: _("All fine"),
565 1: _("Corrupted Client Repository. Please restore a backup."),
566 },
567
568 'misc_counters': {
569 'forced_atoms_update_ids': {
570 '__idtype__': 1,
571 'kde': 1,
572 },
573 },
574
575 'system_settings_plugins_ids': {
576 'client_plugin': "client_plugin",
577 'server_plugin': "server_plugin",
578 'server_plugin_fatscope': "server_plugin_fatscope",
579 },
580
581 'clientserverrepoid': "__system__",
582 'clientdbid': "client",
583 'serverdbid': "etpdb:",
584 'genericdbid': "generic",
585 'systemreleasefile': "/etc/sabayon-release",
586
587
588
589 'socket_service': {
590 'hostname': "localhost",
591 'port': 1026,
592 'ssl_port': 1027,
593 'timeout': 200,
594 'forked_requests_timeout': 300,
595 'max_command_length': 768000,
596 'threads': 5,
597 'session_ttl': 15,
598 'default_uid': 0,
599 'max_connections': 5,
600 'max_connections_per_host': 15,
601 'max_connections_per_host_barrier': 8,
602 'disabled_cmds': set(),
603 'ip_blacklist': set(),
604 'ssl_key': default_etp_confdir+"/socket_server.key",
605 'ssl_cert': default_etp_confdir+"/socket_server.crt",
606 'ssl_ca_cert': default_etp_confdir+"/socket_server.CA.crt",
607 'ssl_ca_pkey': default_etp_confdir+"/socket_server.CA.key",
608 'answers': {
609 'ok': chr(0)+"OK"+chr(0),
610 'er': chr(0)+"ER"+chr(1),
611 'no': chr(0)+"NO"+chr(2),
612 'cl': chr(0)+"CL"+chr(3),
613 'mcr': chr(0)+"MCR"+chr(4),
614 'eos': chr(0),
615 'noop': chr(0)+"NOOP"+chr(0)
616 },
617 },
618
619 'install_sources': {
620 'unknown': 0,
621 'user': 1,
622 'automatic_dependency': 2,
623 },
624
625 'ugc_doctypes': {
626 'comments': 1,
627 'bbcode_doc': 2,
628 'image': 3,
629 'generic_file': 4,
630 'youtube_video': 5,
631 },
632 'ugc_doctypes_description': {
633 1: _('Comments'),
634 2: _('BBcode Documents'),
635 3: _('Images/Screenshots'),
636 4: _('Generic Files'),
637 5: _('YouTube(tm) Videos'),
638 },
639 'ugc_doctypes_description_singular': {
640 1: _('Comment'),
641 2: _('BBcode Document'),
642 3: _('Image/Screenshot'),
643 4: _('Generic File'),
644 5: _('YouTube(tm) Video'),
645 },
646 'ugc_accessfile': default_etp_ugc_confdir+"/access.xml",
647 'ugc_voterange': range(1, 6),
648
649
650 'handlers': {
651
652 'md5sum': "md5sum.php?arch="+etpSys['arch']+"&package=",
653 },
654
655 }
656
657
658 try:
659 my_const['current_nice'] = os.nice(0)
660 except OSError:
661 pass
662
663 etpConst.update(my_const)
664
666 """
667 Change current process scheduler "nice" level.
668
669 @param nice_level: new valid nice level
670 @type nice_level: int
671 @rtype: int
672 @return: current_nice new nice level
673 """
674 default_nice = etpConst['default_nice']
675 current_nice = etpConst['current_nice']
676 delta = current_nice - default_nice
677 try:
678 etpConst['current_nice'] = os.nice(delta*-1+nice_level)
679 except OSError:
680 pass
681 return current_nice
682
684
685 """
686 Extract repository information from the provided repository string,
687 usually contained in the repository settings file, repositories.conf.
688
689 @param repostring: valid repository identifier
690 @type repostring: string
691 @rtype: tuple (string, dict)
692 @return: tuple composed by (repository identifier, extracted repository
693 metadata)
694 """
695
696 if branch == None:
697 branch = etpConst['branch']
698 if product == None:
699 product = etpConst['product']
700
701 reponame = repostring.split("|")[1].strip()
702 repodesc = repostring.split("|")[2].strip()
703 repopackages = repostring.split("|")[3].strip()
704 repodatabase = repostring.split("|")[4].strip()
705
706 eapi3_port = int(etpConst['socket_service']['port'])
707 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
708 eapi3_formatcolon = repodatabase.rfind("#")
709 if eapi3_formatcolon != -1:
710 try:
711 ports = repodatabase[eapi3_formatcolon+1:].split(",")
712 eapi3_port = int(ports[0])
713 if len(ports) > 1:
714 eapi3_ssl_port = int(ports[1])
715 repodatabase = repodatabase[:eapi3_formatcolon]
716 except (ValueError, IndexError,):
717 eapi3_port = int(etpConst['socket_service']['port'])
718 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
719
720 dbformat = etpConst['etpdatabasefileformat']
721 dbformatcolon = repodatabase.rfind("#")
722 if dbformatcolon != -1:
723 if dbformat in etpConst['etpdatabasesupportedcformats']:
724 try:
725 dbformat = repodatabase[dbformatcolon+1:]
726 except (IndexError, ValueError, TypeError,):
727 pass
728 repodatabase = repodatabase[:dbformatcolon]
729
730 mydata = {}
731 mydata['repoid'] = reponame
732 mydata['service_port'] = eapi3_port
733 mydata['ssl_service_port'] = eapi3_ssl_port
734 mydata['description'] = repodesc
735 mydata['packages'] = []
736 mydata['plain_packages'] = []
737
738 mydata['dbpath'] = etpConst['etpdatabaseclientdir'] + "/" + reponame + \
739 "/" + product + "/" + etpConst['currentarch'] + "/" + branch
740
741 mydata['dbcformat'] = dbformat
742 if not dbformat in etpConst['etpdatabasesupportedcformats']:
743 mydata['dbcformat'] = etpConst['etpdatabasesupportedcformats'][0]
744
745 mydata['plain_database'] = repodatabase
746
747 mydata['database'] = repodatabase + "/" + product + "/" + \
748 reponame + "/database/" + etpConst['currentarch'] + \
749 "/" + branch
750
751 mydata['notice_board'] = mydata['database'] + "/" + \
752 etpConst['rss-notice-board']
753
754 mydata['local_notice_board'] = mydata['dbpath'] + "/" + \
755 etpConst['rss-notice-board']
756
757 mydata['dbrevision'] = "0"
758 dbrevision_file = os.path.join(mydata['dbpath'],
759 etpConst['etpdatabaserevisionfile'])
760 if os.path.isfile(dbrevision_file) and os.access(dbrevision_file, os.R_OK):
761 with open(dbrevision_file, "r") as dbrev_f:
762 mydata['dbrevision'] = dbrev_f.readline().strip()
763
764
765
766 mydata['post_branch_hop_script'] = mydata['dbpath'] + "/" + \
767 etpConst['etp_post_branch_hop_script']
768 mydata['post_branch_upgrade_script'] = mydata['dbpath'] + "/" + \
769 etpConst['etp_post_branch_upgrade_script']
770
771
772
773 mydata['configprotect'] = None
774 mydata['configprotectmask'] = None
775 repopackages = [x.strip() for x in repopackages.split() if x.strip()]
776 repopackages = [x for x in repopackages if (x.startswith('http://') or \
777 x.startswith('ftp://') or x.startswith('file://'))]
778
779 for repo_package in repopackages:
780 try:
781 repo_package = str(repo_package)
782 except (UnicodeDecodeError,UnicodeEncodeError,):
783 continue
784 mydata['plain_packages'].append(repo_package)
785 mydata['packages'].append(repo_package + "/" + product + "/" + reponame)
786
787 return reponame, mydata
788
790 """
791 Read Entropy release file content and fill etpConst['entropyversion']
792
793 @rtype: None
794 @return: None
795 """
796
797 revision_file = "../libraries/revision"
798 if not os.path.isfile(revision_file):
799 revision_file = os.path.join(etpConst['installdir'],
800 'libraries/revision')
801 if os.path.isfile(revision_file) and \
802 os.access(revision_file,os.R_OK):
803
804 with open(revision_file, "r") as rev_f:
805 myrev = rev_f.readline().strip()
806 etpConst['entropyversion'] = myrev
807
808
810
811 """
812 Setup Entropy pid file, if possible and if UID = 0 (root).
813 If the application is run with --no-pid-handling argument,
814 this function will have no effect. If just_read is specified,
815 this function will only try to read the current pid string in
816 the Entropy pid file (etpConst['pidfile']). If any other entropy
817 istance is currently owning the contained pid, etpConst['applicationlock']
818 becomes True.
819
820 @param just_read: only read the current pid file, if any and if possible
821 @type just_read: bool
822 @rtype: None
823 @return: None
824 """
825
826 if ("--no-pid-handling" in sys.argv) and (not just_read):
827 return
828
829
830 pid = os.getpid()
831 pid_file = etpConst['pidfile']
832 if os.path.isfile(pid_file) and os.access(pid_file, os.R_OK):
833
834 try:
835 with open(pid_file,"r") as pid_f:
836 found_pid = str(pid_f.readline().strip())
837 except (IOError, OSError, UnicodeEncodeError, UnicodeDecodeError,):
838 found_pid = "0000"
839
840 if found_pid != str(pid):
841
842 pid_path = "%s/proc/%s" % (etpConst['systemroot'], found_pid,)
843 if os.path.isdir(pid_path) and found_pid:
844 etpConst['applicationlock'] = True
845 elif not just_read:
846
847
848 if os.access(pid_file, os.W_OK):
849 try:
850 with open(pid_file,"w") as pid_f:
851 pid_f.write(str(pid))
852 pid_f.flush()
853 except IOError, err:
854 if err.errno == 30:
855 pass
856 else:
857 raise
858 try:
859 const_chmod_entropy_pid()
860 except OSError:
861 pass
862
863 elif not just_read:
864
865
866 if os.access(os.path.dirname(pid_file), os.W_OK):
867
868 if os.path.exists(pid_file):
869 if os.path.islink(pid_file):
870 os.remove(pid_file)
871 elif os.path.isdir(pid_file):
872 import shutil
873 shutil.rmtree(pid_file)
874
875 with open(pid_file,"w") as pid_fw:
876 pid_fw.write(str(pid))
877 pid_fw.flush()
878
879 try:
880 const_chmod_entropy_pid()
881 except OSError:
882 pass
883
885 """
886 Setup entropy file needing strict permissions, no world readable.
887
888 @param config_file: valid config file path
889 @type config_file: string
890 @rtype: None
891 @return: None
892 """
893 try:
894 mygid = const_get_entropy_gid()
895 except KeyError:
896 mygid = 0
897 try:
898 const_setup_file(config_file, mygid, 0660)
899 except (OSError, IOError,):
900 pass
901
903 """
904 Setup entropy pid file permissions, if possible.
905
906 @return: None
907 """
908 try:
909 mygid = const_get_entropy_gid()
910 except KeyError:
911 mygid = 0
912 const_setup_file(etpConst['pidfile'], mygid, 0664)
913
915
916 """
917 Setup Entropy directory structure, as much automagically as possible.
918
919 @rtype: None
920 @return: None
921 """
922
923
924 piddir = os.path.dirname(etpConst['pidfile'])
925 if not os.path.exists(piddir) and (etpConst['uid'] == 0):
926 os.makedirs(piddir)
927
928
929
930
931
932
933
934 gid = None
935 try:
936 gid = const_get_entropy_gid()
937 except KeyError:
938 if etpConst['uid'] == 0:
939
940
941 const_add_entropy_group()
942 try:
943 gid = const_get_entropy_gid()
944 except KeyError:
945 pass
946
947
948 keys = [x for x in etpConst if isinstance(etpConst[x], basestring)]
949 for key in keys:
950
951 if not etpConst[key] or \
952 etpConst[key].endswith(".conf") or \
953 not os.path.isabs(etpConst[key]) or \
954 etpConst[key].endswith(".cfg") or \
955 etpConst[key].endswith(".tmp") or \
956 etpConst[key].find(".db") != -1 or \
957 etpConst[key].find(".log") != -1 or \
958 os.path.isdir(etpConst[key]) or \
959 not key.endswith("dir"):
960 continue
961
962
963
964 try:
965 key_dir = etpConst[key]
966 d_paths = []
967 while not os.path.isdir(key_dir):
968 d_paths.append(key_dir)
969 key_dir = os.path.dirname(key_dir)
970 d_paths = sorted(d_paths)
971 for d_path in d_paths:
972 os.mkdir(d_path)
973 const_setup_file(d_path, gid, 0775)
974 except (OSError, IOError,):
975 pass
976
977 if gid:
978 etpConst['entropygid'] = gid
979 if not os.path.isdir(etpConst['entropyworkdir']):
980 try:
981 os.makedirs(etpConst['entropyworkdir'])
982 except OSError:
983 pass
984 w_gid = os.stat(etpConst['entropyworkdir'])[stat.ST_GID]
985 if w_gid != gid:
986 const_setup_perms(etpConst['entropyworkdir'], gid)
987
988 if not os.path.isdir(etpConst['entropyunpackdir']):
989 try:
990 os.makedirs(etpConst['entropyunpackdir'])
991 except OSError:
992 pass
993 try:
994 w_gid = os.stat(etpConst['entropyunpackdir'])[stat.ST_GID]
995 if w_gid != gid:
996 if os.path.isdir(etpConst['entropyunpackdir']):
997 const_setup_perms(etpConst['entropyunpackdir'], gid)
998 except OSError:
999 pass
1000
1001 if not const_islive():
1002
1003 const_setup_perms(etpConst['etpdatabaseclientdir'], gid)
1004
1016
1017
1019 """
1020 Analyze a server repository string (usually contained in server.conf),
1021 extracting all the parameters.
1022
1023 @param repostring: repository string
1024 @type repostring: string
1025 @keyword product: system product which repository belongs to
1026 @rtype: None
1027 @return: None
1028 """
1029
1030 if product == None:
1031 product = etpConst['product']
1032
1033 mydata = {}
1034 repoid = repostring.split("|")[1].strip()
1035 repodesc = repostring.split("|")[2].strip()
1036 repouris = repostring.split("|")[3].strip()
1037 repohandlers = repostring.split("|")[4].strip()
1038
1039 service_url = None
1040 eapi3_port = int(etpConst['socket_service']['port'])
1041 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
1042 if len(repostring.split("|")) > 5:
1043 service_url = repostring.split("|")[5].strip()
1044
1045 eapi3_formatcolon = service_url.rfind("#")
1046 if eapi3_formatcolon != -1:
1047 try:
1048 ports = service_url[eapi3_formatcolon+1:].split(",")
1049 eapi3_port = int(ports[0])
1050 if len(ports) > 1:
1051 eapi3_ssl_port = int(ports[1])
1052 service_url = service_url[:eapi3_formatcolon]
1053 except (ValueError, IndexError,):
1054 eapi3_port = int(etpConst['socket_service']['port'])
1055 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
1056
1057 mydata = {}
1058 mydata['repoid'] = repoid
1059 mydata['description'] = repodesc
1060 mydata['mirrors'] = []
1061 mydata['community'] = False
1062 mydata['service_url'] = service_url
1063 mydata['service_port'] = eapi3_port
1064 mydata['ssl_service_port'] = eapi3_ssl_port
1065 if repohandlers:
1066 repohandlers = os.path.join(repohandlers, product, repoid, "handlers")
1067 mydata['handler'] = repohandlers
1068 uris = repouris.split()
1069 for uri in uris:
1070 mydata['mirrors'].append(uri)
1071
1072 return repoid, mydata
1073
1075 """
1076 Setup permissions and group id (GID) to a directory, recursively.
1077
1078 @param mydir: valid file path
1079 @type mydir: string
1080 @param gid: valid group id (GID)
1081 @type gid: int
1082 @rtype: None
1083 @return: None
1084 """
1085 if gid == None:
1086 return
1087 for currentdir, subdirs, files in os.walk(mydir):
1088 try:
1089 cur_gid = os.stat(currentdir)[stat.ST_GID]
1090 if cur_gid != gid:
1091 os.chown(currentdir, -1, gid)
1092 cur_mod = const_get_chmod(currentdir)
1093 if cur_mod != oct(0775):
1094 os.chmod(currentdir, 0775)
1095 except OSError:
1096 pass
1097 for item in files:
1098 item = os.path.join(currentdir, item)
1099 try:
1100 const_setup_file(item, gid, 0664)
1101 except OSError:
1102 pass
1103
1105 """
1106 Setup file permissions and group id (GID).
1107
1108 @param myfile: valid file path
1109 @type myfile: string
1110 @param gid: valid group id (GID)
1111 @type gid: int
1112 @param chmod: permissions
1113 @type chmod: integer representing an octal
1114 @rtype: None
1115 @return: None
1116 """
1117 cur_gid = os.stat(myfile)[stat.ST_GID]
1118 if cur_gid != gid:
1119 os.chown(myfile, -1, gid)
1120 const_set_chmod(myfile, chmod)
1121
1122
1124 """
1125 This function get the current permissions of the specified
1126 file. If you want to use the returning value with const_set_chmod
1127 you need to convert it back to int.
1128
1129 @param myfile: valid file path
1130 @type myfile: string
1131 @rtype: integer(8) (octal)
1132 @return: octal representing permissions
1133 """
1134 myst = os.stat(myfile)[stat.ST_MODE]
1135 return oct(myst & 0777)
1136
1138 """
1139 This function sets specified permissions to a file.
1140 If they differ from the current ones.
1141
1142 @param myfile: valid file path
1143 @type myfile: string
1144 @param chmod: permissions
1145 @type chmod: integer representing an octal
1146 @rtype: None
1147 @return: None
1148 """
1149 cur_mod = const_get_chmod(myfile)
1150 if cur_mod != oct(chmod):
1151 os.chmod(myfile, chmod)
1152
1154 """
1155 This function tries to retrieve the "entropy" user group
1156 GID.
1157
1158 @rtype: None
1159 @return: None
1160 @raise KeyError: when "entropy" system GID is not available
1161 """
1162 group_file = etpConst['systemroot']+'/etc/group'
1163 if not os.path.isfile(group_file):
1164 raise KeyError
1165
1166 with open(group_file,"r") as group_f:
1167 for line in group_f.readlines():
1168 if line.startswith('%s:' % (etpConst['sysgroup'],)):
1169 try:
1170 gid = int(line.split(":")[2])
1171 except ValueError:
1172 raise KeyError
1173 return gid
1174 raise KeyError
1175
1177 """
1178 This function looks for an "entropy" user group.
1179 If not available, it tries to create one.
1180
1181 @rtype: None
1182 @return: None
1183 @raise KeyError: if ${ROOT}/etc/group is not found
1184 """
1185 group_file = etpConst['systemroot']+'/etc/group'
1186 if not os.path.isfile(group_file):
1187 raise KeyError
1188 ids = set()
1189
1190 with open(group_file,"r") as group_f:
1191 for line in group_f.readlines():
1192 if line and line.split(":"):
1193 try:
1194 myid = int(line.split(":")[2])
1195 except ValueError:
1196 pass
1197 ids.add(myid)
1198 if ids:
1199
1200 new_id = 1000
1201 while 1:
1202 new_id += 1
1203 if new_id not in ids:
1204 break
1205 else:
1206 new_id = 10000
1207
1208 with open(group_file,"aw") as group_fw:
1209 group_fw.seek(0, 2)
1210 app_line = "entropy:x:%s:\n" % (new_id,)
1211 group_fw.write(app_line)
1212 group_fw.flush()
1213
1215 """
1216 Live environments (Operating System running off a CD/DVD)
1217 must feature the "cdroot" parameter in kernel /proc/cmdline
1218
1219 Sample code:
1220 >>> from entropy.const import const_islive
1221 >>> const_islive()
1222 False
1223
1224 @rtype: bool
1225 @return: determine wether this is a Live system or not
1226 """
1227 if "cdroot" in etpConst['cmdline']:
1228 return True
1229 return False
1230
1232 """
1233 Entropy threads killer. Even if Python threads cannot
1234 be stopped or killed, TimeScheduled ones can, exporting
1235 the kill() method.
1236
1237 Sample code:
1238 >>> from entropy.const import const_kill_threads
1239 >>> const_kill_threads()
1240
1241 @rtype: None
1242 @return: None
1243 """
1244 import threading
1245 threads = threading.enumerate()
1246 for running_t in threads:
1247 if not hasattr(running_t,'kill'):
1248 continue
1249 running_t.kill()
1250 running_t.join()
1251
1253 """
1254 Our default Python exception handler. It kills
1255 all the threads generated by Entropy before
1256 raising exceptions. Overloads sys.excepthook,
1257 internal function !!
1258
1259 @param etype: exception type
1260 @type etype: exception type
1261 @param value: exception data
1262 @type value: string
1263 @param t_back: traceback object?
1264 @type t_back: Python traceback object
1265 @rtype: default Python exceptions hook
1266 @return: sys.__excepthook__
1267 """
1268 try:
1269 const_kill_threads()
1270 except ImportError:
1271 pass
1272 return sys.__excepthook__(etype, value, t_back)
1273
1275 """
1276 Entropy debugging output write functions.
1277
1278 @param identifier: debug identifier
1279 @type identifier: string
1280 @param msg: debugging message
1281 @type msg: string
1282 @rtype: None
1283 @return: None
1284 """
1285 if etpUi['debug']:
1286 sys.stdout.write("%s: %s" % (identifier, msg + "\n"))
1287
1288
1289 initconfig_entropy_constants(etpSys['rootdir'])
1290