]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | import os |
2 | import errno | |
3 | import logging | |
9f95a23c | 4 | import sys |
92f5a8d4 | 5 | |
9f95a23c | 6 | if sys.version_info >= (3, 2): |
92f5a8d4 | 7 | import configparser |
9f95a23c | 8 | else: |
92f5a8d4 TL |
9 | import ConfigParser as configparser |
10 | ||
11 | try: | |
12 | from StringIO import StringIO | |
13 | except ImportError: | |
14 | from io import StringIO | |
15 | ||
16 | import cephfs | |
17 | ||
18 | from ...exception import MetadataMgrException | |
19 | ||
20 | log = logging.getLogger(__name__) | |
21 | ||
22 | class MetadataManager(object): | |
23 | GLOBAL_SECTION = "GLOBAL" | |
24 | GLOBAL_META_KEY_VERSION = "version" | |
25 | GLOBAL_META_KEY_TYPE = "type" | |
26 | GLOBAL_META_KEY_PATH = "path" | |
27 | GLOBAL_META_KEY_STATE = "state" | |
28 | ||
29 | MAX_IO_BYTES = 8 * 1024 | |
30 | ||
31 | def __init__(self, fs, config_path, mode): | |
32 | self.fs = fs | |
33 | self.mode = mode | |
34 | self.config_path = config_path | |
9f95a23c TL |
35 | if sys.version_info >= (3, 2): |
36 | self.config = configparser.ConfigParser() | |
37 | else: | |
38 | self.config = configparser.SafeConfigParser() | |
92f5a8d4 TL |
39 | |
40 | def refresh(self): | |
41 | fd = None | |
42 | conf_data = StringIO() | |
43 | try: | |
44 | log.debug("opening config {0}".format(self.config_path)) | |
45 | fd = self.fs.open(self.config_path, os.O_RDONLY) | |
46 | while True: | |
47 | data = self.fs.read(fd, -1, MetadataManager.MAX_IO_BYTES) | |
48 | if not len(data): | |
49 | break | |
50 | conf_data.write(data.decode('utf-8')) | |
51 | conf_data.seek(0) | |
52 | self.config.readfp(conf_data) | |
53 | except cephfs.ObjectNotFound: | |
54 | raise MetadataMgrException(-errno.ENOENT, "metadata config '{0}' not found".format(self.config_path)) | |
55 | except cephfs.Error as e: | |
56 | raise MetadataMgrException(-e.args[0], e.args[1]) | |
57 | finally: | |
58 | if fd is not None: | |
59 | self.fs.close(fd) | |
60 | ||
61 | def flush(self): | |
62 | # cull empty sections | |
63 | for section in list(self.config.sections()): | |
64 | if len(self.config.items(section)) == 0: | |
65 | self.config.remove_section(section) | |
66 | ||
67 | conf_data = StringIO() | |
68 | self.config.write(conf_data) | |
69 | conf_data.seek(0) | |
70 | ||
71 | fd = None | |
72 | try: | |
73 | fd = self.fs.open(self.config_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, self.mode) | |
74 | wrote = 0 | |
75 | while True: | |
76 | data = conf_data.read() | |
77 | if not len(data): | |
78 | break | |
79 | wrote += self.fs.write(fd, data.encode('utf-8'), -1) | |
80 | self.fs.fsync(fd, 0) | |
81 | log.info("wrote {0} bytes to config {1}".format(wrote, self.config_path)) | |
82 | except cephfs.Error as e: | |
83 | raise MetadataMgrException(-e.args[0], e.args[1]) | |
84 | finally: | |
85 | if fd is not None: | |
86 | self.fs.close(fd) | |
87 | ||
88 | def init(self, version, typ, path, state): | |
89 | # you may init just once before refresh (helps to overwrite conf) | |
90 | if self.config.has_section(MetadataManager.GLOBAL_SECTION): | |
91 | raise MetadataMgrException(-errno.EINVAL, "init called on an existing config") | |
92 | ||
93 | self.add_section(MetadataManager.GLOBAL_SECTION) | |
94 | self.update_section_multi( | |
95 | MetadataManager.GLOBAL_SECTION, {MetadataManager.GLOBAL_META_KEY_VERSION : str(version), | |
96 | MetadataManager.GLOBAL_META_KEY_TYPE : str(typ), | |
97 | MetadataManager.GLOBAL_META_KEY_PATH : str(path), | |
98 | MetadataManager.GLOBAL_META_KEY_STATE : str(state) | |
99 | }) | |
100 | ||
101 | def add_section(self, section): | |
102 | try: | |
103 | self.config.add_section(section) | |
104 | except configparser.DuplicateSectionError: | |
105 | return | |
106 | except: | |
107 | raise MetadataMgrException(-errno.EINVAL, "error adding section to config") | |
108 | ||
109 | def remove_option(self, section, key): | |
110 | if not self.config.has_section(section): | |
111 | raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) | |
112 | self.config.remove_option(section, key) | |
113 | ||
114 | def remove_section(self, section): | |
115 | self.config.remove_section(section) | |
116 | ||
117 | def update_section(self, section, key, value): | |
118 | if not self.config.has_section(section): | |
119 | raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) | |
120 | self.config.set(section, key, str(value)) | |
121 | ||
122 | def update_section_multi(self, section, dct): | |
123 | if not self.config.has_section(section): | |
124 | raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) | |
125 | for key,value in dct.items(): | |
126 | self.config.set(section, key, str(value)) | |
127 | ||
128 | def update_global_section(self, key, value): | |
129 | self.update_section(MetadataManager.GLOBAL_SECTION, key, str(value)) | |
130 | ||
131 | def get_option(self, section, key): | |
132 | if not self.config.has_section(section): | |
133 | raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) | |
134 | if not self.config.has_option(section, key): | |
135 | raise MetadataMgrException(-errno.ENOENT, "no config '{0}' in section '{1}'".format(key, section)) | |
136 | return self.config.get(section, key) | |
137 | ||
138 | def get_global_option(self, key): | |
139 | return self.get_option(MetadataManager.GLOBAL_SECTION, key) | |
140 | ||
141 | def section_has_item(self, section, item): | |
142 | if not self.config.has_section(section): | |
143 | raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) | |
144 | return item in [v[1] for v in self.config.items(section)] |