Revision 47f8a2d2 lib/backend.py
b/lib/backend.py | ||
---|---|---|
2016 | 2016 |
disk.unique_id, disk.dev_type) |
2017 | 2017 |
|
2018 | 2018 |
|
2019 |
def ExportSnapshot(disk, dest_node, instance, cluster_name, idx, debug): |
|
2020 |
"""Export a block device snapshot to a remote node. |
|
2021 |
|
|
2022 |
@type disk: L{objects.Disk} |
|
2023 |
@param disk: the description of the disk to export |
|
2024 |
@type dest_node: str |
|
2025 |
@param dest_node: the destination node to export to |
|
2026 |
@type instance: L{objects.Instance} |
|
2027 |
@param instance: the instance object to whom the disk belongs |
|
2028 |
@type cluster_name: str |
|
2029 |
@param cluster_name: the cluster name, needed for SSH hostalias |
|
2030 |
@type idx: int |
|
2031 |
@param idx: the index of the disk in the instance's disk list, |
|
2032 |
used to export to the OS scripts environment |
|
2033 |
@type debug: integer |
|
2034 |
@param debug: debug level, passed to the OS scripts |
|
2035 |
@rtype: None |
|
2036 |
|
|
2037 |
""" |
|
2038 |
inst_os = OSFromDisk(instance.os) |
|
2039 |
export_env = OSEnvironment(instance, inst_os, debug) |
|
2040 |
|
|
2041 |
export_script = inst_os.export_script |
|
2042 |
|
|
2043 |
logfile = _InstanceLogName("export", inst_os.name, instance.name) |
|
2044 |
if not os.path.exists(constants.LOG_OS_DIR): |
|
2045 |
os.mkdir(constants.LOG_OS_DIR, 0750) |
|
2046 |
|
|
2047 |
real_disk = _OpenRealBD(disk) |
|
2048 |
|
|
2049 |
export_env['EXPORT_DEVICE'] = real_disk.dev_path |
|
2050 |
export_env['EXPORT_INDEX'] = str(idx) |
|
2051 |
|
|
2052 |
destdir = utils.PathJoin(constants.EXPORT_DIR, instance.name + ".new") |
|
2053 |
destfile = disk.physical_id[1] |
|
2054 |
|
|
2055 |
# the target command is built out of three individual commands, |
|
2056 |
# which are joined by pipes; we check each individual command for |
|
2057 |
# valid parameters |
|
2058 |
expcmd = utils.BuildShellCmd("set -e; set -o pipefail; cd %s; %s 2>%s", |
|
2059 |
inst_os.path, export_script, logfile) |
|
2060 |
|
|
2061 |
comprcmd = "gzip" |
|
2062 |
|
|
2063 |
destcmd = utils.BuildShellCmd("mkdir -p %s && cat > %s", |
|
2064 |
destdir, utils.PathJoin(destdir, destfile)) |
|
2065 |
remotecmd = _GetSshRunner(cluster_name).BuildCmd(dest_node, |
|
2066 |
constants.GANETI_RUNAS, |
|
2067 |
destcmd) |
|
2068 |
|
|
2069 |
# all commands have been checked, so we're safe to combine them |
|
2070 |
command = '|'.join([expcmd, comprcmd, utils.ShellQuoteArgs(remotecmd)]) |
|
2071 |
|
|
2072 |
result = utils.RunCmd(["bash", "-c", command], env=export_env) |
|
2073 |
|
|
2074 |
if result.failed: |
|
2075 |
_Fail("OS snapshot export command '%s' returned error: %s" |
|
2076 |
" output: %s", command, result.fail_reason, result.output) |
|
2077 |
|
|
2078 |
|
|
2079 | 2019 |
def FinalizeExport(instance, snap_disks): |
2080 | 2020 |
"""Write out the export configuration information. |
2081 | 2021 |
|
... | ... | |
2175 | 2115 |
return config.Dumps() |
2176 | 2116 |
|
2177 | 2117 |
|
2178 |
def ImportOSIntoInstance(instance, src_node, src_images, cluster_name, debug): |
|
2179 |
"""Import an os image into an instance. |
|
2180 |
|
|
2181 |
@type instance: L{objects.Instance} |
|
2182 |
@param instance: instance to import the disks into |
|
2183 |
@type src_node: string |
|
2184 |
@param src_node: source node for the disk images |
|
2185 |
@type src_images: list of string |
|
2186 |
@param src_images: absolute paths of the disk images |
|
2187 |
@type debug: integer |
|
2188 |
@param debug: debug level, passed to the OS scripts |
|
2189 |
@rtype: list of boolean |
|
2190 |
@return: each boolean represent the success of importing the n-th disk |
|
2191 |
|
|
2192 |
""" |
|
2193 |
inst_os = OSFromDisk(instance.os) |
|
2194 |
import_env = OSEnvironment(instance, inst_os, debug) |
|
2195 |
import_script = inst_os.import_script |
|
2196 |
|
|
2197 |
logfile = _InstanceLogName("import", instance.os, instance.name) |
|
2198 |
if not os.path.exists(constants.LOG_OS_DIR): |
|
2199 |
os.mkdir(constants.LOG_OS_DIR, 0750) |
|
2200 |
|
|
2201 |
comprcmd = "gunzip" |
|
2202 |
impcmd = utils.BuildShellCmd("(cd %s; %s >%s 2>&1)", inst_os.path, |
|
2203 |
import_script, logfile) |
|
2204 |
|
|
2205 |
final_result = [] |
|
2206 |
for idx, image in enumerate(src_images): |
|
2207 |
if image: |
|
2208 |
destcmd = utils.BuildShellCmd('cat %s', image) |
|
2209 |
remotecmd = _GetSshRunner(cluster_name).BuildCmd(src_node, |
|
2210 |
constants.GANETI_RUNAS, |
|
2211 |
destcmd) |
|
2212 |
command = '|'.join([utils.ShellQuoteArgs(remotecmd), comprcmd, impcmd]) |
|
2213 |
import_env['IMPORT_DEVICE'] = import_env['DISK_%d_PATH' % idx] |
|
2214 |
import_env['IMPORT_INDEX'] = str(idx) |
|
2215 |
result = utils.RunCmd(command, env=import_env) |
|
2216 |
if result.failed: |
|
2217 |
logging.error("Disk import command '%s' returned error: %s" |
|
2218 |
" output: %s", command, result.fail_reason, |
|
2219 |
result.output) |
|
2220 |
final_result.append("error importing disk %d: %s, %s" % |
|
2221 |
(idx, result.fail_reason, result.output[-100])) |
|
2222 |
|
|
2223 |
if final_result: |
|
2224 |
_Fail("; ".join(final_result), log=False) |
|
2225 |
|
|
2226 |
|
|
2227 | 2118 |
def ListExports(): |
2228 | 2119 |
"""Return a list of exports currently available on this machine. |
2229 | 2120 |
|
Also available in: Unified diff