Statistics
| Branch: | Revision:

root / shared-filer / attach @ master

History | View | Annotate | Download (5.2 kB)

1 bd924ffd Dimitris Aragiorgis
#!/usr/bin/env python
2 bd924ffd Dimitris Aragiorgis
#
3 bd924ffd Dimitris Aragiorgis
# Copyright (C) 2012 Greek Research and Technology Network
4 bd924ffd Dimitris Aragiorgis
#
5 bd924ffd Dimitris Aragiorgis
# This program is free software; you can redistribute it and/or modify
6 bd924ffd Dimitris Aragiorgis
# it under the terms of the GNU General Public License as published by
7 bd924ffd Dimitris Aragiorgis
# the Free Software Foundation; either version 2 of the License, or
8 bd924ffd Dimitris Aragiorgis
# (at your option) any later version.
9 bd924ffd Dimitris Aragiorgis
#
10 bd924ffd Dimitris Aragiorgis
# This program is distributed in the hope that it will be useful, but
11 bd924ffd Dimitris Aragiorgis
# WITHOUT ANY WARRANTY; without even the implied warranty of
12 bd924ffd Dimitris Aragiorgis
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 bd924ffd Dimitris Aragiorgis
# General Public License for more details.
14 bd924ffd Dimitris Aragiorgis
#
15 bd924ffd Dimitris Aragiorgis
# You should have received a copy of the GNU General Public License
16 bd924ffd Dimitris Aragiorgis
# along with this program; if not, write to the Free Software
17 bd924ffd Dimitris Aragiorgis
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 bd924ffd Dimitris Aragiorgis
# 02110-1301, USA.
19 bd924ffd Dimitris Aragiorgis
20 bd924ffd Dimitris Aragiorgis
"""Map an existing file Image to a loop device
21 bd924ffd Dimitris Aragiorgis
22 bd924ffd Dimitris Aragiorgis
This program maps an existing file Image to a block device
23 bd924ffd Dimitris Aragiorgis
e.g. /dev/loop{X} and returns the device path. If the mapping
24 bd924ffd Dimitris Aragiorgis
already exists, it returns the corresponding device path.
25 bd924ffd Dimitris Aragiorgis
26 bd924ffd Dimitris Aragiorgis
It takes it's input from environment variables. Specifically the
27 bd924ffd Dimitris Aragiorgis
following variables should be present:
28 bd924ffd Dimitris Aragiorgis
29 bd924ffd Dimitris Aragiorgis
 - VOL_NAME: The name of the Image to map
30 bd924ffd Dimitris Aragiorgis
31 bd924ffd Dimitris Aragiorgis
Returns the block device path (which maps the Image) as a string
32 bd924ffd Dimitris Aragiorgis
upon success, or 1 upon failure
33 bd924ffd Dimitris Aragiorgis
34 bd924ffd Dimitris Aragiorgis
"""
35 bd924ffd Dimitris Aragiorgis
36 bd924ffd Dimitris Aragiorgis
import os
37 bd924ffd Dimitris Aragiorgis
import sys
38 bd924ffd Dimitris Aragiorgis
39 68abdf0d Dimitris Aragiorgis
sys.path.insert(0, "/etc/ganeti/share")
40 bd924ffd Dimitris Aragiorgis
41 bd924ffd Dimitris Aragiorgis
from ganeti import utils
42 bd924ffd Dimitris Aragiorgis
43 bd924ffd Dimitris Aragiorgis
44 bd924ffd Dimitris Aragiorgis
# Default shared directory
45 bd924ffd Dimitris Aragiorgis
SHARED_DIR = "/srv/ganeti/shared-file-storage"
46 bd924ffd Dimitris Aragiorgis
#SHARED_DIR = "/mnt/okeanos/shared_dir"
47 bd924ffd Dimitris Aragiorgis
48 bd924ffd Dimitris Aragiorgis
49 bd924ffd Dimitris Aragiorgis
def ReadEnv():
50 bd924ffd Dimitris Aragiorgis
  """Read the mandatory enviromental variables
51 bd924ffd Dimitris Aragiorgis
52 bd924ffd Dimitris Aragiorgis
  """
53 bd924ffd Dimitris Aragiorgis
  name = os.getenv("VOL_NAME")
54 bd924ffd Dimitris Aragiorgis
  if name is None:
55 bd924ffd Dimitris Aragiorgis
    sys.stderr.write('The environment variable VOL_NAME is missing.\n')
56 bd924ffd Dimitris Aragiorgis
    return None
57 bd924ffd Dimitris Aragiorgis
  shared_dir_param = os.getenv("EXTP_SHARED_DIR")
58 bd924ffd Dimitris Aragiorgis
  if shared_dir_param is not None:
59 bd924ffd Dimitris Aragiorgis
    sys.stderr.write('Found shared dir param, value: %s\n' % shared_dir_param)
60 bd924ffd Dimitris Aragiorgis
61 bd924ffd Dimitris Aragiorgis
  return (name, shared_dir_param)
62 bd924ffd Dimitris Aragiorgis
63 bd924ffd Dimitris Aragiorgis
64 bd924ffd Dimitris Aragiorgis
def _ParseLosetupOutput(output, filename):
65 bd924ffd Dimitris Aragiorgis
  """Parse the output of `losetup -j <filename>`
66 bd924ffd Dimitris Aragiorgis
67 bd924ffd Dimitris Aragiorgis
  This method parses the output of `losetup -j <filename>` and returns
68 bd924ffd Dimitris Aragiorgis
  the corresponding loop device path for this filename
69 bd924ffd Dimitris Aragiorgis
  (e.g. /dev/loop0)
70 bd924ffd Dimitris Aragiorgis
71 bd924ffd Dimitris Aragiorgis
  @type output: string
72 bd924ffd Dimitris Aragiorgis
  @param output: the whole output of `losetup -j filename`
73 bd924ffd Dimitris Aragiorgis
  @type filename: string
74 bd924ffd Dimitris Aragiorgis
  @param filename: the complete file path to the file we search for
75 bd924ffd Dimitris Aragiorgis
  @rtype: string or None
76 bd924ffd Dimitris Aragiorgis
  @return: loop device path if the file is losetup, else None
77 bd924ffd Dimitris Aragiorgis
78 bd924ffd Dimitris Aragiorgis
  """
79 bd924ffd Dimitris Aragiorgis
  # `losetup -j file1` output looks like this
80 bd924ffd Dimitris Aragiorgis
  #   /dev/loop0: [X]:Y (/path/to/file1)
81 bd924ffd Dimitris Aragiorgis
  # if the file has been losetup. If not there is no output.
82 bd924ffd Dimitris Aragiorgis
  # If the file has been losetup more than once, then there will be
83 bd924ffd Dimitris Aragiorgis
  # multiple lines like the one above.
84 bd924ffd Dimitris Aragiorgis
  #
85 bd924ffd Dimitris Aragiorgis
  # We assume the following format (space is the seperator):
86 bd924ffd Dimitris Aragiorgis
  # field0: field1 (field2)
87 bd924ffd Dimitris Aragiorgis
88 bd924ffd Dimitris Aragiorgis
  field0 = 0
89 bd924ffd Dimitris Aragiorgis
  field_sep = " "
90 bd924ffd Dimitris Aragiorgis
  
91 bd924ffd Dimitris Aragiorgis
  lines = output.splitlines()
92 bd924ffd Dimitris Aragiorgis
  splitted_lines = map(lambda l: l.split(field_sep), lines)
93 bd924ffd Dimitris Aragiorgis
94 bd924ffd Dimitris Aragiorgis
  # Check empty output. If empty, the file is not losetup
95 bd924ffd Dimitris Aragiorgis
  if not splitted_lines:
96 bd924ffd Dimitris Aragiorgis
    return None
97 bd924ffd Dimitris Aragiorgis
98 bd924ffd Dimitris Aragiorgis
  # Check if we have more than one lines in the output
99 bd924ffd Dimitris Aragiorgis
  if len(splitted_lines) > 1:
100 bd924ffd Dimitris Aragiorgis
    sys.stderr.write("The file %s is losetup more than once" % filename)
101 bd924ffd Dimitris Aragiorgis
    sys.exit(1)
102 bd924ffd Dimitris Aragiorgis
103 bd924ffd Dimitris Aragiorgis
  # The file is losetup only once
104 bd924ffd Dimitris Aragiorgis
  # Take field0, remove the ":" at the end and we have our path
105 bd924ffd Dimitris Aragiorgis
  dev_path = splitted_lines[0][field0].split(":")[0]
106 bd924ffd Dimitris Aragiorgis
107 bd924ffd Dimitris Aragiorgis
  return dev_path
108 bd924ffd Dimitris Aragiorgis
109 bd924ffd Dimitris Aragiorgis
110 bd924ffd Dimitris Aragiorgis
def main():
111 bd924ffd Dimitris Aragiorgis
  sys.stderr.write('Attaching started: reading environment...\n')
112 bd924ffd Dimitris Aragiorgis
113 bd924ffd Dimitris Aragiorgis
  # Read environment
114 bd924ffd Dimitris Aragiorgis
  env = ReadEnv()
115 bd924ffd Dimitris Aragiorgis
  if env is None:
116 bd924ffd Dimitris Aragiorgis
    sys.stderr.write('Wrong environment. Aborting\n')
117 bd924ffd Dimitris Aragiorgis
    return 1
118 bd924ffd Dimitris Aragiorgis
119 bd924ffd Dimitris Aragiorgis
  file_name, shared_dir_param = env
120 bd924ffd Dimitris Aragiorgis
121 bd924ffd Dimitris Aragiorgis
  if shared_dir_param is None:
122 bd924ffd Dimitris Aragiorgis
    shared_dir_param = SHARED_DIR
123 bd924ffd Dimitris Aragiorgis
124 bd924ffd Dimitris Aragiorgis
  file_path = utils.PathJoin(shared_dir_param, file_name)
125 bd924ffd Dimitris Aragiorgis
126 bd924ffd Dimitris Aragiorgis
  sys.stderr.write('Read environment successfully: file name: %s\n' % file_path)
127 bd924ffd Dimitris Aragiorgis
128 bd924ffd Dimitris Aragiorgis
  # Check if the file exists
129 bd924ffd Dimitris Aragiorgis
  if not os.path.exists(file_path):
130 bd924ffd Dimitris Aragiorgis
    sys.stderr.write("File %s does not exist. Aborting\n" % file_path)
131 bd924ffd Dimitris Aragiorgis
    return 1
132 bd924ffd Dimitris Aragiorgis
133 bd924ffd Dimitris Aragiorgis
  # Check if the file is already losetup
134 bd924ffd Dimitris Aragiorgis
  cmd1 = ["losetup", "-j", "%s" % file_path]
135 bd924ffd Dimitris Aragiorgis
  result = utils.RunCmd(cmd1)
136 bd924ffd Dimitris Aragiorgis
  if result.failed:
137 bd924ffd Dimitris Aragiorgis
    sys.stderr.write("losetup -j %s failed (%s): %s" %
138 bd924ffd Dimitris Aragiorgis
                     (file_path, result.fail_reason, result.output))
139 bd924ffd Dimitris Aragiorgis
    return 1
140 bd924ffd Dimitris Aragiorgis
  else:
141 bd924ffd Dimitris Aragiorgis
    # Parse the result's output
142 bd924ffd Dimitris Aragiorgis
    dev_path = _ParseLosetupOutput(result.output, file_path)
143 bd924ffd Dimitris Aragiorgis
144 bd924ffd Dimitris Aragiorgis
    if dev_path is None:
145 bd924ffd Dimitris Aragiorgis
      # The file is not attached. Attach it
146 bd924ffd Dimitris Aragiorgis
      cmd2 = ["losetup", "-f", "--show", "%s" % file_path]
147 bd924ffd Dimitris Aragiorgis
      result = utils.RunCmd(cmd2)
148 bd924ffd Dimitris Aragiorgis
      if result.failed:
149 bd924ffd Dimitris Aragiorgis
        sys.stderr.write('Cannot losetup file %s, attachment failed (%s): %s' %
150 bd924ffd Dimitris Aragiorgis
                         file_path, result.fail_reason, result.output)
151 bd924ffd Dimitris Aragiorgis
        return 1
152 bd924ffd Dimitris Aragiorgis
153 bd924ffd Dimitris Aragiorgis
      # The '--show' option returns an EOL at the end. Remove it.
154 bd924ffd Dimitris Aragiorgis
      dev_path = result.output.split("\n")[0]
155 bd924ffd Dimitris Aragiorgis
156 bd924ffd Dimitris Aragiorgis
      # The file was losetup successfully. Return the loop device.
157 bd924ffd Dimitris Aragiorgis
      sys.stderr.write('File %s successfully attached at %s\n' %
158 bd924ffd Dimitris Aragiorgis
                       (file_path, dev_path))
159 bd924ffd Dimitris Aragiorgis
      sys.stdout.write("%s" % str(dev_path))
160 bd924ffd Dimitris Aragiorgis
      return 0
161 bd924ffd Dimitris Aragiorgis
162 bd924ffd Dimitris Aragiorgis
    else:
163 bd924ffd Dimitris Aragiorgis
      # The file is already losetup. Return the loop device path
164 bd924ffd Dimitris Aragiorgis
      sys.stderr.write('File %s successfully attached at %s\n' %
165 bd924ffd Dimitris Aragiorgis
                       (file_path, dev_path))
166 bd924ffd Dimitris Aragiorgis
      sys.stdout.write("%s" % str(dev_path))
167 bd924ffd Dimitris Aragiorgis
      return 0
168 bd924ffd Dimitris Aragiorgis
169 bd924ffd Dimitris Aragiorgis
170 bd924ffd Dimitris Aragiorgis
if __name__ == "__main__":
171 bd924ffd Dimitris Aragiorgis
    sys.exit(main())