]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
import 15.2.0 Octopus source
[ceph.git] / ceph / src / pybind / mgr / volumes / fs / operations / versions / metadata_manager.py
CommitLineData
92f5a8d4
TL
1import os
2import errno
3import logging
9f95a23c 4import sys
92f5a8d4 5
9f95a23c 6if sys.version_info >= (3, 2):
92f5a8d4 7 import configparser
9f95a23c 8else:
92f5a8d4
TL
9 import ConfigParser as configparser
10
11try:
12 from StringIO import StringIO
13except ImportError:
14 from io import StringIO
15
16import cephfs
17
18from ...exception import MetadataMgrException
19
20log = logging.getLogger(__name__)
21
22class 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)]