1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Framework SystemSettings module}.
10
11 SystemSettings is a singleton, pluggable interface which contains
12 all the runtime settings (mostly parsed from configuration files
13 and inherited from entropy.const -- which contains almost all the
14 default values).
15 SystemSettings works as a I{dict} object. Due to limitations of
16 multiple inherittance when using the Singleton class, SystemSettings
17 ONLY mimics a I{dict} AND it's not a subclass of it.
18
19 """
20 import os
21 import sys
22 from threading import RLock
23
24 from entropy.const import etpConst, etpUi, etpSys, const_setup_perms, \
25 const_secure_config_file, const_set_nice_level, \
26 const_extract_cli_repo_params, etpCache, const_isunicode, \
27 const_convert_to_unicode, const_convert_to_rawstring
28 from entropy.core import Singleton, EntropyPluginStore
29 from entropy.core.settings.plugins.skel import SystemSettingsPlugin
30
32
33 """
34 This is the place where all the Entropy settings are stored if
35 they are not considered instance constants (etpConst).
36 For example, here we store package masking cache information and
37 settings, client-side, server-side and services settings.
38 Also, this class mimics a dictionary (even if not inheriting it
39 due to development choices).
40
41 Sample code:
42
43 >>> from entropy.core.settings.base import SystemSettings
44 >>> system_settings = SystemSettings()
45 >>> system_settings.clear()
46 >>> system_settings.destroy()
47
48 """
49
50 import entropy.tools as entropyTools
52
53 """
54 Replaces __init__ because SystemSettings is a Singleton.
55 see Singleton API reference for more information.
56
57 """
58 EntropyPluginStore.__init__(self)
59
60 from entropy.core.settings.plugins.factory import get_available_plugins
61 self.__get_external_plugins = get_available_plugins
62
63 from entropy.cache import EntropyCacher
64 self.__cacher = EntropyCacher()
65 self.__data = {}
66 self.__is_destroyed = False
67 self.__mutex = RLock()
68
69 self.__external_plugins = {}
70 self.__setting_files_order = []
71 self.__setting_files_pre_run = []
72 self.__setting_files = {}
73 self.__mtime_files = {}
74 self.__persistent_settings = {
75 'pkg_masking_reasons': etpConst['pkg_masking_reasons'].copy(),
76 'pkg_masking_reference': etpConst['pkg_masking_reference'].copy(),
77 'backed_up': {},
78
79 'live_packagemasking': {
80 'unmask_matches': set(),
81 'mask_matches': set(),
82 },
83 }
84
85 self.__setup_const()
86 self.__scan()
87
89 """
90 Overloaded method from Singleton.
91 "Destroys" the instance.
92
93 @return: None
94 @rtype: None
95 """
96 with self.__mutex:
97 self.__is_destroyed = True
98
99 - def add_plugin(self, system_settings_plugin_instance):
100 """
101 This method lets you add custom parsers to SystemSettings.
102 Mind that you are responsible of handling your plugin instance
103 and remove it before it is destroyed. You can remove the plugin
104 instance at any time by issuing remove_plugin.
105 Every add_plugin or remove_plugin method will also issue clear()
106 for you. This could be bad and it might be removed in future.
107
108 @param system_settings_plugin_instance: valid SystemSettingsPlugin
109 instance
110 @type system_settings_plugin_instance: SystemSettingsPlugin instance
111 @return: None
112 @rtype: None
113 """
114 inst = system_settings_plugin_instance
115 if not isinstance(inst, SystemSettingsPlugin):
116 raise AttributeError("SystemSettings: expected valid " + \
117 "SystemSettingsPlugin instance")
118 with self.__mutex:
119 EntropyPluginStore.add_plugin(self, inst.get_id(), inst)
120 self.clear()
121
123 """
124 This method lets you remove previously added custom parsers from
125 SystemSettings through its plugin identifier. If plugin_id is not
126 available, KeyError exception will be raised.
127 Every add_plugin or remove_plugin method will also issue clear()
128 for you. This could be bad and it might be removed in future.
129
130 @param plugin_id: plugin identifier
131 @type plugin_id: basestring
132 @return: None
133 @rtype: None
134 """
135 with self.__mutex:
136 EntropyPluginStore.remove_plugin(self, plugin_id)
137 self.clear()
138
140
141 """
142 Internal method. Does constants initialization.
143
144 @return: None
145 @rtype: None
146 """
147
148 del self.__setting_files_order[:]
149 del self.__setting_files_pre_run[:]
150 self.__setting_files.clear()
151 self.__mtime_files.clear()
152
153 self.__setting_files.update({
154
155 'keywords': etpConst['confpackagesdir']+"/package.keywords",
156
157 'unmask': etpConst['confpackagesdir']+"/package.unmask",
158
159 'mask': etpConst['confpackagesdir']+"/package.mask",
160
161 'satisfied': etpConst['confpackagesdir']+"/package.satisfied",
162
163 'license_mask': etpConst['confpackagesdir']+"/license.mask",
164 'system_mask': etpConst['confpackagesdir']+"/system.mask",
165 'system_dirs': etpConst['confdir']+"/fsdirs.conf",
166 'system_dirs_mask': etpConst['confdir']+"/fsdirsmask.conf",
167 'system_rev_symlinks': etpConst['confdir']+"/fssymlinks.conf",
168 'broken_syms': etpConst['confdir']+"/brokensyms.conf",
169 'broken_libs_mask': etpConst['confdir']+"/brokenlibsmask.conf",
170 'hw_hash': etpConst['confdir']+"/.hw.hash",
171 'socket_service': etpConst['socketconf'],
172 'system': etpConst['entropyconf'],
173 'repositories': etpConst['repositoriesconf'],
174 'system_package_sets': {},
175 })
176 self.__setting_files_order.extend([
177 'keywords', 'unmask', 'mask', 'satisfied', 'license_mask',
178 'system_mask', 'system_package_sets', 'system_dirs',
179 'system_dirs_mask', 'socket_service', 'system',
180 'system_rev_symlinks', 'hw_hash', 'broken_syms', 'broken_libs_mask'
181 ])
182 self.__setting_files_pre_run.extend(['repositories'])
183
184 dmp_dir = etpConst['dumpstoragedir']
185 self.__mtime_files.update({
186 'keywords_mtime': dmp_dir+"/keywords.mtime",
187 'unmask_mtime': dmp_dir+"/unmask.mtime",
188 'mask_mtime': dmp_dir+"/mask.mtime",
189 'satisfied_mtime': dmp_dir+"/satisfied.mtime",
190 'license_mask_mtime': dmp_dir+"/license_mask.mtime",
191 'system_mask_mtime': dmp_dir+"/system_mask.mtime",
192 })
193
194
196
197 """
198 Internal method. Scan settings and fill variables.
199
200 @return: None
201 @rtype: None
202 """
203
204 def enforce_persistent():
205
206 self.__data.update(self.__persistent_settings)
207
208 self.__data.update(self.__persistent_settings['backed_up'].copy())
209
210 self.__parse()
211 enforce_persistent()
212
213
214 local_plugins = self.get_plugins()
215 for plugin_id in sorted(local_plugins):
216 local_plugins[plugin_id].parse(self)
217
218
219 external_plugins = self.__get_external_plugins()
220 for external_plugin_id in sorted(external_plugins):
221 external_plugin = external_plugins[external_plugin_id]()
222 external_plugin.parse(self)
223 self.__external_plugins[external_plugin_id] = external_plugin
224
225 enforce_persistent()
226
227
228 for plugin_id in sorted(local_plugins):
229 local_plugins[plugin_id].post_setup(self)
230
231
232 for external_plugin_id in sorted(self.__external_plugins):
233 self.__external_plugins[external_plugin_id].post_setup(self)
234
236 """
237 dict method. See Python dict API reference.
238 """
239 with self.__mutex:
240
241 if mykey in self.__persistent_settings:
242 self.__persistent_settings[mykey] = myvalue
243 self.__data[mykey] = myvalue
244
246 """
247 dict method. See Python dict API reference.
248 """
249 with self.__mutex:
250 return self.__data[mykey]
251
253 """
254 dict method. See Python dict API reference.
255 """
256 with self.__mutex:
257 del self.__data[mykey]
258
260 """
261 dict method. See Python dict API reference.
262 """
263 with self.__mutex:
264 return iter(self.__data)
265
267 """
268 dict method. See Python dict API reference.
269 """
270 with self.__mutex:
271 return item in self.__data
272
274 """
275 dict method. See Python dict API reference.
276 """
277 with self.__mutex:
278 return hash(self.__data)
279
281 """
282 dict method. See Python dict API reference.
283 """
284 with self.__mutex:
285 return len(self.__data)
286
287 - def get(self, mykey, alt_obj = None):
288 """
289 dict method. See Python dict API reference.
290 """
291 with self.__mutex:
292 return self.__data.get(mykey, alt_obj)
293
295 """
296 dict method. See Python dict API reference.
297 """
298 with self.__mutex:
299 return self.__data.copy()
300
302 """
303 dict method. See Python dict API reference.
304 """
305 with self.__mutex:
306 return self.__data.fromkeys(seq, val)
307
309 """
310 dict method. See Python dict API reference.
311 """
312 with self.__mutex:
313 return self.__data.items()
314
316 """
317 dict method. See Python dict API reference.
318 """
319 with self.__mutex:
320 return self.__data.iteritems()
321
323 """
324 dict method. See Python dict API reference.
325 """
326 with self.__mutex:
327 return self.__data.iterkeys()
328
330 """
331 dict method. See Python dict API reference.
332 """
333 with self.__mutex:
334 return self.__data.keys()
335
336 - def pop(self, mykey, default = None):
337 """
338 dict method. See Python dict API reference.
339 """
340 with self.__mutex:
341 return self.__data.pop(mykey, default)
342
344 """
345 dict method. See Python dict API reference.
346 """
347 with self.__mutex:
348 return self.__data.popitem()
349
351 """
352 dict method. See Python dict API reference.
353 """
354 with self.__mutex:
355 return self.__data.setdefault(mykey, default)
356
358 """
359 dict method. See Python dict API reference.
360 """
361 with self.__mutex:
362 return self.__data.update(kwargs)
363
365 """
366 dict method. See Python dict API reference.
367 """
368 with self.__mutex:
369 return self.__data.values()
370
372 """
373 dict method. See Python dict API reference.
374 Settings are also re-initialized here.
375
376 @return None
377 """
378 with self.__mutex:
379 self.__data.clear()
380 self.__setup_const()
381 self.__scan()
382
384 """
385 Make metadata persistent, the input dict will be merged
386 with the base one at every reset call (clear()).
387
388 @param persistent_dict: dictionary to merge
389 @type persistent_dict: dict
390
391 @return: None
392 @rtype: None
393 """
394 with self.__mutex:
395 self.__persistent_settings.update(persistent_dict)
396
398 """
399 Remove dict key from persistent dictionary
400
401 @param persistent_key: key to remove
402 @type persistent_dict: dict
403
404 @return: None
405 @rtype: None
406 """
407 with self.__mutex:
408 del self.__persistent_settings[persistent_key]
409 del self.__data[persistent_key]
410
412
413 """
414 This function setups the *files* dictionary about package sets
415 that will be read and parsed afterwards by the respective
416 internal parser.
417
418 @return: None
419 @rtype: None
420 """
421
422
423 sets_dir = etpConst['confsetsdir']
424 pkg_set_data = {}
425 if (os.path.isdir(sets_dir) and os.access(sets_dir, os.R_OK)):
426 set_files = [x for x in os.listdir(sets_dir) if \
427 (os.path.isfile(os.path.join(sets_dir, x)) and \
428 os.access(os.path.join(sets_dir, x), os.R_OK))]
429 for set_file in set_files:
430 try:
431 set_file = const_convert_to_unicode(set_file, 'utf-8')
432 except UnicodeDecodeError:
433 set_file = const_convert_to_unicode(set_file,
434 sys.getfilesystemencoding())
435
436 path = os.path.join(sets_dir, set_file)
437 if sys.hexversion < 0x3000000:
438 if const_isunicode(path):
439 path = const_convert_to_rawstring(path, 'utf-8')
440 pkg_set_data[set_file] = path
441
442 self.__setting_files['system_package_sets'].update(pkg_set_data)
443
445 """
446 This is the main internal parsing method.
447 *files* and *mtimes* dictionaries are prepared and
448 parsed just a few lines later.
449
450 @return: None
451 @rtype: None
452 """
453
454 for item in self.__setting_files_pre_run:
455 myattr = '_%s_parser' % (item,)
456 if not hasattr(self, myattr):
457 continue
458 func = getattr(self, myattr)
459 self.__data[item] = func()
460
461
462 self.__setup_package_sets_vars()
463
464 for item in self.__setting_files_order:
465 myattr = '_%s_parser' % (item,)
466 if not hasattr(self, myattr):
467 continue
468 func = getattr(self, myattr)
469 self.__data[item] = func()
470
472 """
473 Return a copy of the internal *files* dictionary.
474 This dict contains config file paths and their identifiers.
475
476 @return: dict __setting_files
477 @rtype: dict
478 """
479 with self.__mutex:
480 return self.__setting_files.copy()
481
483 """
484 Parser returning package keyword masking metadata
485 read from package.keywords file.
486 This file contains package mask or unmask directives
487 based on package keywords.
488
489 @return: parsed metadata
490 @rtype: dict
491 """
492
493 data = {
494 'universal': set(),
495 'packages': {},
496 'repositories': {},
497 }
498
499 self.validate_entropy_cache(self.__setting_files['keywords'],
500 self.__mtime_files['keywords_mtime'])
501 content = [x.split() for x in \
502 self.__generic_parser(self.__setting_files['keywords']) \
503 if len(x.split()) < 4]
504 for keywordinfo in content:
505
506 if len(keywordinfo) > 3:
507 continue
508
509 if len(keywordinfo) == 1:
510 if keywordinfo[0].startswith("repo="):
511 continue
512
513 if keywordinfo[0] == "**":
514 keywordinfo[0] = ""
515 data['universal'].add(keywordinfo[0])
516 continue
517
518 if len(keywordinfo) in (2, 3,):
519
520 if keywordinfo[0].startswith("repo="):
521 continue
522
523 items = keywordinfo[1:]
524
525 if keywordinfo[0] == "**":
526 keywordinfo[0] = ""
527 reponame = [x for x in items if x.startswith("repo=") \
528 and (len(x.split("=")) == 2)]
529 if reponame:
530 reponame = reponame[0].split("=")[1]
531 if reponame not in data['repositories']:
532 data['repositories'][reponame] = {}
533
534 if keywordinfo[0] not in data['repositories'][reponame]:
535 data['repositories'][reponame][keywordinfo[0]] = set()
536 if len(items) == 1:
537
538 data['repositories'][reponame][keywordinfo[0]].add('*')
539 elif "*" not in \
540 data['repositories'][reponame][keywordinfo[0]]:
541
542 item = [x for x in items if not x.startswith("repo=")]
543 data['repositories'][reponame][keywordinfo[0]].add(
544 item[0])
545 elif len(items) == 2:
546
547
548 continue
549 else:
550
551 if keywordinfo[0] not in data['packages']:
552 data['packages'][keywordinfo[0]] = set()
553 data['packages'][keywordinfo[0]].add(items[0])
554
555
556 etpConst['keywords'].clear()
557 etpConst['keywords'].update(etpSys['keywords'])
558 for keyword in data['universal']:
559 etpConst['keywords'].add(keyword)
560
561 return data
562
563
565 """
566 Parser returning package unmasking metadata read from
567 package.unmask file.
568 This file contains package unmask directives, allowing
569 to enable experimental or *secret* packages.
570
571 @return: parsed metadata
572 @rtype: dict
573 """
574 self.validate_entropy_cache(self.__setting_files['unmask'],
575 self.__mtime_files['unmask_mtime'])
576 return self.__generic_parser(self.__setting_files['unmask'])
577
579 """
580 Parser returning package masking metadata read from
581 package.mask file.
582 This file contains package mask directives, allowing
583 to disable experimental or *secret* packages.
584
585 @return: parsed metadata
586 @rtype: dict
587 """
588 self.validate_entropy_cache(self.__setting_files['mask'],
589 self.__mtime_files['mask_mtime'])
590 return self.__generic_parser(self.__setting_files['mask'])
591
593 """
594 Parser returning package forced satisfaction metadata
595 read from package.satisfied file.
596 This file contains packages which updates as dependency are
597 filtered out.
598
599 @return: parsed metadata
600 @rtype: dict
601 """
602 self.validate_entropy_cache(self.__setting_files['satisfied'],
603 self.__mtime_files['satisfied_mtime'])
604 return self.__generic_parser(self.__setting_files['satisfied'])
605
607 """
608 Parser returning system packages mask metadata read from
609 package.system_mask file.
610 This file contains packages that should be always kept
611 installed, extending the already defined (in repository database)
612 set of atoms.
613
614 @return: parsed metadata
615 @rtype: dict
616 """
617 self.validate_entropy_cache(self.__setting_files['system_mask'],
618 self.__mtime_files['system_mask_mtime'])
619 return self.__generic_parser(self.__setting_files['system_mask'])
620
622 """
623 Parser returning packages masked by license metadata read from
624 license.mask file.
625 Packages shipped with licenses listed there will be masked.
626
627 @return: parsed metadata
628 @rtype: dict
629 """
630 self.validate_entropy_cache(self.__setting_files['license_mask'],
631 self.__mtime_files['license_mask_mtime'])
632 return self.__generic_parser(self.__setting_files['license_mask'])
633
635 """
636 Parser returning system defined package sets read from
637 /etc/entropy/packages/sets.
638
639 @return: parsed metadata
640 @rtype: dict
641 """
642 data = {}
643 for set_name in self.__setting_files['system_package_sets']:
644 set_filepath = self.__setting_files['system_package_sets'][set_name]
645 set_elements = self.entropyTools.extract_packages_from_set_file(
646 set_filepath)
647 if set_elements:
648 data[set_name] = set_elements.copy()
649 return data
650
652 """
653 Parser returning directories considered part of the base system.
654
655 @return: parsed metadata
656 @rtype: dict
657 """
658 return self.__generic_parser(self.__setting_files['system_dirs'])
659
661 """
662 Parser returning directories NOT considered part of the base system.
663 Settings here overlay system_dirs_parser.
664
665 @return: parsed metadata
666 @rtype: dict
667 """
668 return self.__generic_parser(self.__setting_files['system_dirs_mask'])
669
671 """
672 Parser returning a list of shared objects symbols that can be used by
673 QA tools to scan the filesystem or a subset of it.
674
675 @return: parsed metadata
676 @rtype: dict
677 """
678 return self.__generic_parser(self.__setting_files['broken_syms'])
679
681 """
682 Parser returning a list of broken shared libraries which are
683 always considered sane.
684
685 @return: parsed metadata
686 @rtype: dict
687 """
688 return self.__generic_parser(self.__setting_files['broken_libs_mask'])
689
691 """
692 Hardware hash metadata parser and generator. It returns a theorically
693 unique SHA256 hash bound to the computer running this Framework.
694
695 @return: string containing SHA256 hexdigest
696 @rtype: string
697 """
698 hw_hash_file = self.__setting_files['hw_hash']
699 if os.access(hw_hash_file, os.R_OK) and os.path.isfile(hw_hash_file):
700 hash_f = open(hw_hash_file, "r")
701 hash_data = hash_f.readline().strip()
702 hash_f.close()
703 return hash_data
704
705 hash_file_dir = os.path.dirname(hw_hash_file)
706 hw_hash_exec = etpConst['etp_hw_hash_gen']
707 if os.access(hash_file_dir, os.W_OK) and \
708 os.access(hw_hash_exec, os.X_OK | os.R_OK) and \
709 os.path.isfile(hw_hash_exec):
710
711 pipe = os.popen('{ ' + hw_hash_exec + '; } 2>&1', 'r')
712 hash_data = pipe.read().strip()
713 sts = pipe.close()
714 if sts != None:
715 return None
716 hash_f = open(hw_hash_file, "w")
717 hash_f.write(hash_data)
718 hash_f.flush()
719 hash_f.close()
720 return hash_data
721
723 """
724 Parser returning important system symlinks mapping. For example:
725 {'/usr/lib': ['/usr/lib64']}
726 Useful for reverse matching files belonging to packages.
727
728 @return: dict containing the mapping
729 @rtype: dict
730 """
731 setting_file = self.__setting_files['system_rev_symlinks']
732 raw_data = self.__generic_parser(setting_file)
733 data = {}
734 for line in raw_data:
735 line = line.split()
736 if len(line) < 2:
737 continue
738 data[line[0]] = frozenset(line[1:])
739 return data
740
742 """
743 Parses socket service configuration file.
744 This file contains information about Entropy remote service ports
745 and SSL.
746
747 @return: parsed metadata
748 @rtype: dict
749 """
750
751 data = etpConst['socket_service'].copy()
752
753 sock_conf = self.__setting_files['socket_service']
754 if not (os.path.isfile(sock_conf) and \
755 os.access(sock_conf, os.R_OK)):
756 return data
757
758 socket_f = open(sock_conf, "r")
759 socketconf = [x.strip() for x in socket_f.readlines() if \
760 x.strip() and not x.strip().startswith("#")]
761 socket_f.close()
762
763 for line in socketconf:
764
765 split_line = line.split("|")
766 split_line_len = len(split_line)
767
768 if line.startswith("listen|") and (split_line_len > 1):
769
770 item = split_line[1].strip()
771 if item:
772 data['hostname'] = item
773
774 elif line.startswith("listen-port|") and \
775 (split_line_len > 1):
776
777 item = split_line[1].strip()
778 try:
779 item = int(item)
780 data['port'] = item
781 except ValueError:
782 continue
783
784 elif line.startswith("listen-timeout|") and \
785 (split_line_len > 1):
786
787 item = split_line[1].strip()
788 try:
789 item = int(item)
790 data['timeout'] = item
791 except ValueError:
792 continue
793
794 elif line.startswith("listen-threads|") and \
795 (split_line_len > 1):
796
797 item = split_line[1].strip()
798 try:
799 item = int(item)
800 data['threads'] = item
801 except ValueError:
802 continue
803
804 elif line.startswith("session-ttl|") and \
805 (split_line_len > 1):
806
807 item = split_line[1].strip()
808 try:
809 item = int(item)
810 data['session_ttl'] = item
811 except ValueError:
812 continue
813
814 elif line.startswith("max-connections|") and \
815 (split_line_len > 1):
816
817 item = split_line[1].strip()
818 try:
819 item = int(item)
820 data['max_connections'] = item
821 except ValueError:
822 continue
823
824 elif line.startswith("ssl-port|") and \
825 (split_line_len > 1):
826
827 item = split_line[1].strip()
828 try:
829 item = int(item)
830 data['ssl_port'] = item
831 except ValueError:
832 continue
833
834 elif line.startswith("disabled-commands|") and \
835 (split_line_len > 1):
836
837 disabled_cmds = split_line[1].strip().split()
838 for disabled_cmd in disabled_cmds:
839 data['disabled_cmds'].add(disabled_cmd)
840
841 elif line.startswith("ip-blacklist|") and \
842 (split_line_len > 1):
843
844 ips_blacklist = split_line[1].strip().split()
845 for ip_blacklist in ips_blacklist:
846 data['ip_blacklist'].add(ip_blacklist)
847
848 return data
849
851
852 """
853 Parses Entropy system configuration file.
854
855 @return: parsed metadata
856 @rtype: dict
857 """
858
859 data = {
860 'proxy': etpConst['proxy'].copy(),
861 'name': etpConst['systemname'],
862 'log_level': etpConst['entropyloglevel'],
863 'spm_backend': None,
864 }
865
866 etp_conf = self.__setting_files['system']
867 if not (os.path.isfile(etp_conf) and \
868 os.access(etp_conf, os.R_OK)):
869 return data
870
871 const_secure_config_file(etp_conf)
872 entropy_f = open(etp_conf, "r")
873 entropyconf = [x.strip() for x in entropy_f.readlines() if \
874 x.strip() and not x.strip().startswith("#")]
875 entropy_f.close()
876
877 for line in entropyconf:
878
879 split_line = line.split("|")
880 split_line_len = len(split_line)
881
882 if line.startswith("loglevel|") and \
883 (len(line.split("loglevel|")) == 2):
884
885 loglevel = line.split("loglevel|")[1]
886 try:
887 loglevel = int(loglevel)
888 except ValueError:
889 pass
890 if (loglevel > -1) and (loglevel < 3):
891 data['log_level'] = loglevel
892
893 elif line.startswith("ftp-proxy|") and \
894 (split_line_len == 2):
895
896 ftpproxy = split_line[1].strip().split()
897 if ftpproxy:
898 data['proxy']['ftp'] = ftpproxy[-1]
899
900 elif line.startswith("http-proxy|") and \
901 (split_line_len == 2):
902
903 httpproxy = split_line[1].strip().split()
904 if httpproxy:
905 data['proxy']['http'] = httpproxy[-1]
906
907 elif line.startswith("proxy-username|") and \
908 (split_line_len == 2):
909
910 httpproxy = split_line[1].strip().split()
911 if httpproxy:
912 data['proxy']['username'] = httpproxy[-1]
913
914 elif line.startswith("proxy-password|") and \
915 (split_line_len == 2):
916
917 httpproxy = split_line[1].strip().split()
918 if httpproxy:
919 data['proxy']['password'] = httpproxy[-1]
920
921 elif line.startswith("system-name|") and \
922 (split_line_len == 2):
923
924 data['name'] = split_line[1].strip()
925
926 elif line.startswith("spm-backend|") and \
927 (split_line_len == 2):
928
929 data['spm_backend'] = split_line[1].strip()
930
931 elif line.startswith("nice-level|") and \
932 (split_line_len == 2):
933
934 mylevel = split_line[1].strip()
935 try:
936 mylevel = int(mylevel)
937 if (mylevel >= -19) and (mylevel <= 19):
938 const_set_nice_level(mylevel)
939 except (ValueError,):
940 continue
941
942 return data
943
945
946 """
947 Setup Entropy Client repository settings reading them from
948 the relative config file specified in etpConst['repositoriesconf']
949
950 @return: parsed metadata
951 @rtype: dict
952 """
953
954 data = {
955 'available': {},
956 'excluded': {},
957 'order': [],
958 'product': etpConst['product'],
959 'branch': etpConst['branch'],
960 'default_repository': etpConst['officialrepositoryid'],
961 'transfer_limit': etpConst['downloadspeedlimit'],
962 'timeout': etpConst['default_download_timeout'],
963 'security_advisories_url': etpConst['securityurl'],
964 }
965
966 repo_conf = etpConst['repositoriesconf']
967 if not (os.path.isfile(repo_conf) and os.access(repo_conf, os.R_OK)):
968 return data
969
970 repo_f = open(repo_conf, "r")
971 repositoriesconf = [x.strip() for x in repo_f.readlines() if x.strip()]
972 repo_f.close()
973
974
975 for line in repositoriesconf:
976
977 split_line = line.split("|")
978 split_line_len = len(split_line)
979
980 if (line.find("product|") != -1) and \
981 (not line.startswith("#")) and (split_line_len == 2):
982
983 data['product'] = split_line[1]
984
985 elif (line.find("branch|") != -1) and \
986 (not line.startswith("#")) and (split_line_len == 2):
987
988 branch = split_line[1].strip()
989 data['branch'] = branch
990 if not os.path.isdir(etpConst['packagesbindir']+"/"+branch) \
991 and (etpConst['uid'] == 0):
992
993 try:
994 os.makedirs(etpConst['packagesbindir']+"/"+branch)
995 except (OSError, IOError,):
996 continue
997
998 for line in repositoriesconf:
999
1000 split_line = line.split("|")
1001 split_line_len = len(split_line)
1002
1003
1004 if (line.find("repository|") != -1) and (split_line_len == 5):
1005
1006 excluded = False
1007 my_repodata = data['available']
1008 if line.startswith("##"):
1009 continue
1010 elif line.startswith("#"):
1011 excluded = True
1012 my_repodata = data['excluded']
1013 line = line[1:]
1014
1015 reponame, repodata = const_extract_cli_repo_params(line,
1016 data['branch'], data['product'])
1017 if reponame in my_repodata:
1018
1019 my_repodata[reponame]['plain_packages'].extend(
1020 repodata['plain_packages'])
1021 my_repodata[reponame]['packages'].extend(
1022 repodata['packages'])
1023
1024 if (not my_repodata[reponame]['plain_database']) and \
1025 repodata['plain_database']:
1026
1027 my_repodata[reponame]['plain_database'] = \
1028 repodata['plain_database']
1029 my_repodata[reponame]['database'] = \
1030 repodata['database']
1031 my_repodata[reponame]['dbrevision'] = \
1032 repodata['dbrevision']
1033 my_repodata[reponame]['dbcformat'] = \
1034 repodata['dbcformat']
1035 else:
1036
1037 my_repodata[reponame] = repodata.copy()
1038 if not excluded:
1039 data['order'].append(reponame)
1040
1041 elif (line.find("officialrepositoryid|") != -1) and \
1042 (not line.startswith("#")) and (split_line_len == 2):
1043
1044 officialreponame = split_line[1]
1045 data['default_repository'] = officialreponame
1046
1047 elif (line.find("downloadspeedlimit|") != -1) and \
1048 (not line.startswith("#")) and (split_line_len == 2):
1049
1050 try:
1051 myval = int(split_line[1])
1052 if myval > 0:
1053 data['transfer_limit'] = myval
1054 else:
1055 data['transfer_limit'] = None
1056 except (ValueError, IndexError,):
1057 data['transfer_limit'] = None
1058
1059 elif (line.find("downloadtimeout|") != -1) and \
1060 (not line.startswith("#")) and (split_line_len == 2):
1061
1062 try:
1063 myval = int(split_line[1])
1064 data['timeout'] = myval
1065 except (ValueError, IndexError,):
1066 continue
1067
1068 elif (line.find("securityurl|") != -1) and \
1069 (not line.startswith("#")) and (split_line_len == 2):
1070
1071 try:
1072 data['security_advisories_url'] = split_line[1]
1073 except (IndexError, ValueError, TypeError,):
1074 continue
1075
1076 try:
1077 tx_limit = int(os.getenv("ETP_DOWNLOAD_KB"))
1078 except (ValueError, TypeError,):
1079 tx_limit = None
1080 if tx_limit is not None:
1081 data['transfer_limit'] = tx_limit
1082
1083 return data
1084
1086 """
1087 Internal method, go away!
1088 """
1089 self.__cacher.discard()
1090 self._clear_dump_cache(etpCache['world_available'])
1091 self._clear_dump_cache(etpCache['world_update'])
1092 self._clear_dump_cache(etpCache['critical_update'])
1093 self._clear_dump_cache(etpCache['check_package_update'])
1094 self._clear_dump_cache(etpCache['filter_satisfied_deps'])
1095 self._clear_dump_cache(etpCache['atomMatch'])
1096 self._clear_dump_cache(etpCache['dep_tree'])
1097 if repoid != None:
1098 self._clear_dump_cache("%s/%s%s/" % (
1099 etpCache['dbMatch'], etpConst['dbnamerepoprefix'], repoid,))
1100 self._clear_dump_cache("%s/%s%s/" % (
1101 etpCache['dbSearch'], etpConst['dbnamerepoprefix'], repoid,))
1102
1104 """
1105 Internal method, go away!
1106 """
1107 dump_path = os.path.join(etpConst['dumpstoragedir'], dump_name)
1108 dump_dir = os.path.dirname(dump_path)
1109
1110 for currentdir, subdirs, files in os.walk(dump_dir):
1111 path = os.path.join(dump_dir, currentdir)
1112 if skip:
1113 found = False
1114 for myskip in skip:
1115 if path.find(myskip) != -1:
1116 found = True
1117 break
1118 if found: continue
1119 for item in files:
1120 if item.endswith(etpConst['cachedumpext']):
1121 item = os.path.join(path, item)
1122 try:
1123 os.remove(item)
1124 except (OSError, IOError,):
1125 pass
1126 try:
1127 if not os.listdir(path):
1128 os.rmdir(path)
1129 except (OSError, IOError,):
1130 pass
1131
1133 """
1134 Internal method. This is the generic file parser here.
1135
1136 @param filepath: valid path
1137 @type filepath: string
1138 @return: raw text extracted from file
1139 @rtype: list
1140 """
1141 return self.entropyTools.generic_file_content_parser(filepath)
1142
1144 """
1145 Internal method. Remove repository cache, because not valid anymore.
1146
1147 @keyword repoid: repository identifier or None
1148 @type repoid: string or None
1149 @return: None
1150 @rtype: None
1151 """
1152 if os.path.isdir(etpConst['dumpstoragedir']):
1153 if repoid:
1154 self._clear_repository_cache(repoid = repoid)
1155 return
1156 for repoid in self['repositories']['order']:
1157 self._clear_repository_cache(repoid = repoid)
1158 else:
1159 try:
1160 os.makedirs(etpConst['dumpstoragedir'])
1161 except IOError as e:
1162 if e.errno == 30:
1163 etpUi['pretend'] = True
1164 return
1165 except OSError:
1166 return
1167
1169 """
1170 Internal method. Save mtime of a file to another file.
1171
1172 @param toread: file path to read
1173 @type toread: string
1174 @param tosaveinto: path where to save retrieved mtime information
1175 @type tosaveinto: string
1176 @return: None
1177 @rtype: None
1178 """
1179 if not os.path.isfile(toread):
1180 currmtime = 0.0
1181 else:
1182 currmtime = os.path.getmtime(toread)
1183
1184 if not os.path.isdir(etpConst['dumpstoragedir']):
1185 try:
1186 os.makedirs(etpConst['dumpstoragedir'], 0o775)
1187 const_setup_perms(etpConst['dumpstoragedir'],
1188 etpConst['entropygid'])
1189 except IOError as e:
1190 if e.errno == 30:
1191 etpUi['pretend'] = True
1192 return
1193 except (OSError,) as e:
1194
1195
1196 return
1197
1198 try:
1199 mtime_f = open(tosaveinto, "w")
1200 except IOError as e:
1201 if e.errno == 30:
1202 etpUi['pretend'] = True
1203 return
1204 else:
1205 mtime_f.write(str(currmtime))
1206 mtime_f.flush()
1207 mtime_f.close()
1208 os.chmod(tosaveinto, 0o664)
1209 if etpConst['entropygid'] != None:
1210 os.chown(tosaveinto, 0, etpConst['entropygid'])
1211
1212
1214 """
1215 Internal method. Validates Entropy Cache based on a setting file
1216 and its stored (cache bound) mtime.
1217
1218 @param settingfile: path of the setting file
1219 @type settingfile: string
1220 @param mtimefile: path where to save retrieved mtime information
1221 @type mtimefile: string
1222 @keyword repoid: repository identifier or None
1223 @type repoid: string or None
1224 @return: None
1225 @rtype: None
1226 """
1227
1228
1229
1230 if os.getuid() != 0:
1231 return
1232
1233
1234
1235
1236 if not os.path.isfile(mtimefile):
1237
1238
1239 self.__remove_repo_cache(repoid = repoid)
1240 self.__save_file_mtime(settingfile, mtimefile)
1241 else:
1242
1243 try:
1244 mtime_f = open(mtimefile, "r")
1245 mtime = mtime_f.readline().strip()
1246 mtime_f.close()
1247
1248 try:
1249 currmtime = str(os.path.getmtime(settingfile))
1250 except OSError:
1251 currmtime = "0.0"
1252 if mtime != currmtime:
1253 self.__remove_repo_cache(repoid = repoid)
1254 self.__save_file_mtime(settingfile, mtimefile)
1255 except (OSError, IOError,):
1256 self.__remove_repo_cache(repoid = repoid)
1257 self.__save_file_mtime(settingfile, mtimefile)
1258