Statistics
| Branch: | Tag: | Revision:

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