root / lib / vcluster.py @ 05e733b4
History | View | Annotate | Download (6.2 kB)
1 | 05e733b4 | Michael Hanselmann | #
|
---|---|---|---|
2 | 05e733b4 | Michael Hanselmann | #
|
3 | 05e733b4 | Michael Hanselmann | |
4 | 05e733b4 | Michael Hanselmann | # Copyright (C) 2012 Google Inc.
|
5 | 05e733b4 | Michael Hanselmann | #
|
6 | 05e733b4 | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify
|
7 | 05e733b4 | Michael Hanselmann | # it under the terms of the GNU General Public License as published by
|
8 | 05e733b4 | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or
|
9 | 05e733b4 | Michael Hanselmann | # (at your option) any later version.
|
10 | 05e733b4 | Michael Hanselmann | #
|
11 | 05e733b4 | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but
|
12 | 05e733b4 | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 05e733b4 | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 05e733b4 | Michael Hanselmann | # General Public License for more details.
|
15 | 05e733b4 | Michael Hanselmann | #
|
16 | 05e733b4 | Michael Hanselmann | # You should have received a copy of the GNU General Public License
|
17 | 05e733b4 | Michael Hanselmann | # along with this program; if not, write to the Free Software
|
18 | 05e733b4 | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | 05e733b4 | Michael Hanselmann | # 02110-1301, USA.
|
20 | 05e733b4 | Michael Hanselmann | |
21 | 05e733b4 | Michael Hanselmann | |
22 | 05e733b4 | Michael Hanselmann | """Module containing utilities for virtual clusters.
|
23 | 05e733b4 | Michael Hanselmann |
|
24 | 05e733b4 | Michael Hanselmann |
|
25 | 05e733b4 | Michael Hanselmann | """
|
26 | 05e733b4 | Michael Hanselmann | |
27 | 05e733b4 | Michael Hanselmann | import os |
28 | 05e733b4 | Michael Hanselmann | |
29 | 05e733b4 | Michael Hanselmann | from ganeti import compat |
30 | 05e733b4 | Michael Hanselmann | |
31 | 05e733b4 | Michael Hanselmann | |
32 | 05e733b4 | Michael Hanselmann | _VIRT_PATH_PREFIX = "/###-VIRTUAL-PATH-###,"
|
33 | 05e733b4 | Michael Hanselmann | _ROOTDIR_ENVNAME = "GANETI_ROOTDIR"
|
34 | 05e733b4 | Michael Hanselmann | _HOSTNAME_ENVNAME = "GANETI_HOSTNAME"
|
35 | 05e733b4 | Michael Hanselmann | |
36 | 05e733b4 | Michael Hanselmann | |
37 | 05e733b4 | Michael Hanselmann | def _GetRootDirectory(envname): |
38 | 05e733b4 | Michael Hanselmann | """Retrieves root directory from an environment variable.
|
39 | 05e733b4 | Michael Hanselmann |
|
40 | 05e733b4 | Michael Hanselmann | @type envname: string
|
41 | 05e733b4 | Michael Hanselmann | @param envname: Environment variable name
|
42 | 05e733b4 | Michael Hanselmann | @rtype: string
|
43 | 05e733b4 | Michael Hanselmann | @return: Root directory (can be empty)
|
44 | 05e733b4 | Michael Hanselmann |
|
45 | 05e733b4 | Michael Hanselmann | """
|
46 | 05e733b4 | Michael Hanselmann | path = os.getenv(envname) |
47 | 05e733b4 | Michael Hanselmann | |
48 | 05e733b4 | Michael Hanselmann | if path:
|
49 | 05e733b4 | Michael Hanselmann | if not os.path.isabs(path): |
50 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Root directory in '%s' must be absolute: %s" % |
51 | 05e733b4 | Michael Hanselmann | (envname, path)) |
52 | 05e733b4 | Michael Hanselmann | return os.path.normpath(path)
|
53 | 05e733b4 | Michael Hanselmann | |
54 | 05e733b4 | Michael Hanselmann | return "" |
55 | 05e733b4 | Michael Hanselmann | |
56 | 05e733b4 | Michael Hanselmann | |
57 | 05e733b4 | Michael Hanselmann | def _GetHostname(envname): |
58 | 05e733b4 | Michael Hanselmann | """Retrieves virtual hostname from an environment variable.
|
59 | 05e733b4 | Michael Hanselmann |
|
60 | 05e733b4 | Michael Hanselmann | @type envname: string
|
61 | 05e733b4 | Michael Hanselmann | @param envname: Environment variable name
|
62 | 05e733b4 | Michael Hanselmann | @rtype: string
|
63 | 05e733b4 | Michael Hanselmann | @return: Host name (can be empty)
|
64 | 05e733b4 | Michael Hanselmann |
|
65 | 05e733b4 | Michael Hanselmann | """
|
66 | 05e733b4 | Michael Hanselmann | return os.getenv(envname, default="") |
67 | 05e733b4 | Michael Hanselmann | |
68 | 05e733b4 | Michael Hanselmann | |
69 | 05e733b4 | Michael Hanselmann | def _CheckHostname(hostname): |
70 | 05e733b4 | Michael Hanselmann | """Very basic check for hostnames.
|
71 | 05e733b4 | Michael Hanselmann |
|
72 | 05e733b4 | Michael Hanselmann | @type hostname: string
|
73 | 05e733b4 | Michael Hanselmann | @param hostname: Hostname
|
74 | 05e733b4 | Michael Hanselmann |
|
75 | 05e733b4 | Michael Hanselmann | """
|
76 | 05e733b4 | Michael Hanselmann | if os.path.basename(hostname) != hostname:
|
77 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Hostname '%s' can not be used for a file system" |
78 | 05e733b4 | Michael Hanselmann | " path" % hostname)
|
79 | 05e733b4 | Michael Hanselmann | |
80 | 05e733b4 | Michael Hanselmann | |
81 | 05e733b4 | Michael Hanselmann | def _PreparePaths(rootdir, hostname): |
82 | 05e733b4 | Michael Hanselmann | """Checks if the root directory and hostname are acceptable.
|
83 | 05e733b4 | Michael Hanselmann |
|
84 | 05e733b4 | Michael Hanselmann | @type rootdir: string
|
85 | 05e733b4 | Michael Hanselmann | @param rootdir: Root directory (from environment)
|
86 | 05e733b4 | Michael Hanselmann | @type hostname: string
|
87 | 05e733b4 | Michael Hanselmann | @param hostname: Hostname (from environment)
|
88 | 05e733b4 | Michael Hanselmann | @rtype: tuple; (string, string, string or None)
|
89 | 05e733b4 | Michael Hanselmann | @return: Tuple containing cluster-global root directory, node root directory
|
90 | 05e733b4 | Michael Hanselmann | and virtual hostname
|
91 | 05e733b4 | Michael Hanselmann |
|
92 | 05e733b4 | Michael Hanselmann | """
|
93 | 05e733b4 | Michael Hanselmann | if bool(rootdir) ^ bool(hostname): |
94 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Both root directory and hostname must be specified" |
95 | 05e733b4 | Michael Hanselmann | " using the environment variables %s and %s" %
|
96 | 05e733b4 | Michael Hanselmann | (_ROOTDIR_ENVNAME, _HOSTNAME_ENVNAME)) |
97 | 05e733b4 | Michael Hanselmann | |
98 | 05e733b4 | Michael Hanselmann | if rootdir:
|
99 | 05e733b4 | Michael Hanselmann | assert rootdir == os.path.normpath(rootdir)
|
100 | 05e733b4 | Michael Hanselmann | |
101 | 05e733b4 | Michael Hanselmann | _CheckHostname(hostname) |
102 | 05e733b4 | Michael Hanselmann | |
103 | 05e733b4 | Michael Hanselmann | if os.path.basename(rootdir) != hostname:
|
104 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Last component of root directory ('%s') must match" |
105 | 05e733b4 | Michael Hanselmann | " hostname ('%s')" % (rootdir, hostname))
|
106 | 05e733b4 | Michael Hanselmann | |
107 | 05e733b4 | Michael Hanselmann | return (os.path.dirname(rootdir), rootdir, hostname)
|
108 | 05e733b4 | Michael Hanselmann | else:
|
109 | 05e733b4 | Michael Hanselmann | return ("", "", None) |
110 | 05e733b4 | Michael Hanselmann | |
111 | 05e733b4 | Michael Hanselmann | |
112 | 05e733b4 | Michael Hanselmann | (_VIRT_BASEDIR, _VIRT_NODEROOT, _VIRT_HOSTNAME) = \ |
113 | 05e733b4 | Michael Hanselmann | _PreparePaths(_GetRootDirectory(_ROOTDIR_ENVNAME), |
114 | 05e733b4 | Michael Hanselmann | _GetHostname(_HOSTNAME_ENVNAME)) |
115 | 05e733b4 | Michael Hanselmann | |
116 | 05e733b4 | Michael Hanselmann | |
117 | 05e733b4 | Michael Hanselmann | assert (compat.all([_VIRT_BASEDIR, _VIRT_NODEROOT, _VIRT_HOSTNAME]) or |
118 | 05e733b4 | Michael Hanselmann | not compat.any([_VIRT_BASEDIR, _VIRT_NODEROOT, _VIRT_HOSTNAME]))
|
119 | 05e733b4 | Michael Hanselmann | |
120 | 05e733b4 | Michael Hanselmann | |
121 | 05e733b4 | Michael Hanselmann | def GetVirtualHostname(): |
122 | 05e733b4 | Michael Hanselmann | """Returns the virtual hostname.
|
123 | 05e733b4 | Michael Hanselmann |
|
124 | 05e733b4 | Michael Hanselmann | @rtype: string or L{None}
|
125 | 05e733b4 | Michael Hanselmann |
|
126 | 05e733b4 | Michael Hanselmann | """
|
127 | 05e733b4 | Michael Hanselmann | return _VIRT_HOSTNAME
|
128 | 05e733b4 | Michael Hanselmann | |
129 | 05e733b4 | Michael Hanselmann | |
130 | 05e733b4 | Michael Hanselmann | def _MakeNodeRoot(base, node_name): |
131 | 05e733b4 | Michael Hanselmann | """Appends a node name to the base directory.
|
132 | 05e733b4 | Michael Hanselmann |
|
133 | 05e733b4 | Michael Hanselmann | """
|
134 | 05e733b4 | Michael Hanselmann | _CheckHostname(node_name) |
135 | 05e733b4 | Michael Hanselmann | return os.path.normpath("%s/%s" % (base, node_name)) |
136 | 05e733b4 | Michael Hanselmann | |
137 | 05e733b4 | Michael Hanselmann | |
138 | 05e733b4 | Michael Hanselmann | def ExchangeNodeRoot(node_name, filename, |
139 | 05e733b4 | Michael Hanselmann | _basedir=_VIRT_BASEDIR, _noderoot=_VIRT_NODEROOT): |
140 | 05e733b4 | Michael Hanselmann | """Replaces the node-specific root directory in a path.
|
141 | 05e733b4 | Michael Hanselmann |
|
142 | 05e733b4 | Michael Hanselmann | Replaces it with the root directory for another node.
|
143 | 05e733b4 | Michael Hanselmann |
|
144 | 05e733b4 | Michael Hanselmann | """
|
145 | 05e733b4 | Michael Hanselmann | if _basedir:
|
146 | 05e733b4 | Michael Hanselmann | pure = _RemoveNodePrefix(filename, _noderoot=_noderoot) |
147 | 05e733b4 | Michael Hanselmann | result = "%s/%s" % (_MakeNodeRoot(_basedir, node_name), pure)
|
148 | 05e733b4 | Michael Hanselmann | else:
|
149 | 05e733b4 | Michael Hanselmann | result = filename |
150 | 05e733b4 | Michael Hanselmann | |
151 | 05e733b4 | Michael Hanselmann | return os.path.normpath(result)
|
152 | 05e733b4 | Michael Hanselmann | |
153 | 05e733b4 | Michael Hanselmann | |
154 | 05e733b4 | Michael Hanselmann | def EnvironmentForHost(hostname, _basedir=_VIRT_BASEDIR): |
155 | 05e733b4 | Michael Hanselmann | """Returns the environment variables for a host.
|
156 | 05e733b4 | Michael Hanselmann |
|
157 | 05e733b4 | Michael Hanselmann | """
|
158 | 05e733b4 | Michael Hanselmann | if _basedir:
|
159 | 05e733b4 | Michael Hanselmann | return {
|
160 | 05e733b4 | Michael Hanselmann | _ROOTDIR_ENVNAME: _MakeNodeRoot(_basedir, hostname), |
161 | 05e733b4 | Michael Hanselmann | _HOSTNAME_ENVNAME: hostname, |
162 | 05e733b4 | Michael Hanselmann | } |
163 | 05e733b4 | Michael Hanselmann | else:
|
164 | 05e733b4 | Michael Hanselmann | return {}
|
165 | 05e733b4 | Michael Hanselmann | |
166 | 05e733b4 | Michael Hanselmann | |
167 | 05e733b4 | Michael Hanselmann | def AddNodePrefix(path, _noderoot=_VIRT_NODEROOT): |
168 | 05e733b4 | Michael Hanselmann | """Adds a node-specific prefix to a path in a virtual cluster.
|
169 | 05e733b4 | Michael Hanselmann |
|
170 | 05e733b4 | Michael Hanselmann | Returned path includes user-specified root directory if specified in
|
171 | 05e733b4 | Michael Hanselmann | environment.
|
172 | 05e733b4 | Michael Hanselmann |
|
173 | 05e733b4 | Michael Hanselmann | """
|
174 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(path)
|
175 | 05e733b4 | Michael Hanselmann | |
176 | 05e733b4 | Michael Hanselmann | if _noderoot:
|
177 | 05e733b4 | Michael Hanselmann | result = "%s/%s" % (_noderoot, path)
|
178 | 05e733b4 | Michael Hanselmann | else:
|
179 | 05e733b4 | Michael Hanselmann | result = path |
180 | 05e733b4 | Michael Hanselmann | |
181 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(result)
|
182 | 05e733b4 | Michael Hanselmann | |
183 | 05e733b4 | Michael Hanselmann | return os.path.normpath(result)
|
184 | 05e733b4 | Michael Hanselmann | |
185 | 05e733b4 | Michael Hanselmann | |
186 | 05e733b4 | Michael Hanselmann | def _RemoveNodePrefix(path, _noderoot=_VIRT_NODEROOT): |
187 | 05e733b4 | Michael Hanselmann | """Removes the node-specific prefix from a path.
|
188 | 05e733b4 | Michael Hanselmann |
|
189 | 05e733b4 | Michael Hanselmann | """
|
190 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(path)
|
191 | 05e733b4 | Michael Hanselmann | |
192 | 05e733b4 | Michael Hanselmann | norm_path = os.path.normpath(path) |
193 | 05e733b4 | Michael Hanselmann | |
194 | 05e733b4 | Michael Hanselmann | if _noderoot:
|
195 | 05e733b4 | Michael Hanselmann | # Make sure path is actually below node root
|
196 | 05e733b4 | Michael Hanselmann | norm_root = os.path.normpath(_noderoot) |
197 | 05e733b4 | Michael Hanselmann | root_with_sep = "%s%s" % (norm_root, os.sep)
|
198 | 05e733b4 | Michael Hanselmann | prefix = os.path.commonprefix([root_with_sep, norm_path]) |
199 | 05e733b4 | Michael Hanselmann | |
200 | 05e733b4 | Michael Hanselmann | if prefix == root_with_sep:
|
201 | 05e733b4 | Michael Hanselmann | result = norm_path[len(norm_root):]
|
202 | 05e733b4 | Michael Hanselmann | else:
|
203 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Path '%s' is not below node root '%s'" % |
204 | 05e733b4 | Michael Hanselmann | (path, _noderoot)) |
205 | 05e733b4 | Michael Hanselmann | else:
|
206 | 05e733b4 | Michael Hanselmann | result = norm_path |
207 | 05e733b4 | Michael Hanselmann | |
208 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(result)
|
209 | 05e733b4 | Michael Hanselmann | |
210 | 05e733b4 | Michael Hanselmann | return result
|
211 | 05e733b4 | Michael Hanselmann | |
212 | 05e733b4 | Michael Hanselmann | |
213 | 05e733b4 | Michael Hanselmann | def MakeVirtualPath(path, _noderoot=_VIRT_NODEROOT): |
214 | 05e733b4 | Michael Hanselmann | """Virtualizes a path.
|
215 | 05e733b4 | Michael Hanselmann |
|
216 | 05e733b4 | Michael Hanselmann | A path is "virtualized" by stripping it of its node-specific directory and
|
217 | 05e733b4 | Michael Hanselmann | prepending a prefix (L{_VIRT_PATH_PREFIX}). Use L{LocalizeVirtualPath} to
|
218 | 05e733b4 | Michael Hanselmann | undo the process.
|
219 | 05e733b4 | Michael Hanselmann |
|
220 | 05e733b4 | Michael Hanselmann | """
|
221 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(path)
|
222 | 05e733b4 | Michael Hanselmann | |
223 | 05e733b4 | Michael Hanselmann | if _noderoot:
|
224 | 05e733b4 | Michael Hanselmann | return _VIRT_PATH_PREFIX + _RemoveNodePrefix(path, _noderoot=_noderoot)
|
225 | 05e733b4 | Michael Hanselmann | else:
|
226 | 05e733b4 | Michael Hanselmann | return path
|
227 | 05e733b4 | Michael Hanselmann | |
228 | 05e733b4 | Michael Hanselmann | |
229 | 05e733b4 | Michael Hanselmann | def LocalizeVirtualPath(path, _noderoot=_VIRT_NODEROOT): |
230 | 05e733b4 | Michael Hanselmann | """Localizes a virtual path.
|
231 | 05e733b4 | Michael Hanselmann |
|
232 | 05e733b4 | Michael Hanselmann | A "virtualized" path consists of a prefix (L{LocalizeVirtualPath}) and a
|
233 | 05e733b4 | Michael Hanselmann | local path. This function adds the node-specific directory to the local path.
|
234 | 05e733b4 | Michael Hanselmann |
|
235 | 05e733b4 | Michael Hanselmann | """
|
236 | 05e733b4 | Michael Hanselmann | assert os.path.isabs(path)
|
237 | 05e733b4 | Michael Hanselmann | |
238 | 05e733b4 | Michael Hanselmann | if _noderoot:
|
239 | 05e733b4 | Michael Hanselmann | if path.startswith(_VIRT_PATH_PREFIX):
|
240 | 05e733b4 | Michael Hanselmann | return AddNodePrefix(path[len(_VIRT_PATH_PREFIX):], _noderoot=_noderoot) |
241 | 05e733b4 | Michael Hanselmann | else:
|
242 | 05e733b4 | Michael Hanselmann | raise RuntimeError("Path '%s' is not a virtual path" % path) |
243 | 05e733b4 | Michael Hanselmann | else:
|
244 | 05e733b4 | Michael Hanselmann | return path |