def __enter__(self): self.directory = tempfile.mkdtemp() self.subdirectory = io.PathJoin(self.directory, "pinky") os.mkdir(self.subdirectory) self.path = io.PathJoin(self.subdirectory, "bunny") self.volume = TestFileDeviceHelper._Make(self.path) if self.create_file: open(self.path, mode="w").close() return self
def Create(cls, unique_id, children, size, spindles, params, excl_stor, dyn_params, *args): """Create a new file. @param size: the size of file in MiB @rtype: L{bdev.FileStorage} @return: an instance of FileStorage """ if excl_stor: raise errors.ProgrammerError("FileStorage device requested with" " exclusive_storage") if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: raise ValueError("Invalid configuration data %s" % str(unique_id)) full_path = unique_id[1] server_addr = params[constants.GLUSTER_HOST] port = params[constants.GLUSTER_PORT] volume = params[constants.GLUSTER_VOLUME] volume_obj = GlusterVolume(server_addr, port, volume) full_path = io.PathJoin(volume_obj.mount_point, full_path) # Possible optimization: defer actual creation to first Attach, rather # than mounting and unmounting here, then remounting immediately after. with volume_obj.Mount(): FileDeviceHelper.CreateFile(full_path, size, create_folders=True) return GlusterStorage(unique_id, children, size, params, dyn_params, *args)
def __init__(self, unique_id, children, size, params, dyn_params, *args): """Initalizes a file device backend. """ if children: base.ThrowError("Invalid setup for file device") try: driver, path = unique_id except ValueError: # wrong number of arguments raise ValueError("Invalid configuration data %s" % repr(unique_id)) server_addr = params[constants.GLUSTER_HOST] port = params[constants.GLUSTER_PORT] volume = params[constants.GLUSTER_VOLUME] self.volume = GlusterVolume(server_addr, port, volume) self.path = path self.driver = driver self.full_path = io.PathJoin(self.volume.mount_point, self.path) self.file = None super(GlusterStorage, self).__init__(unique_id, children, size, params, dyn_params, *args) self.Attach()
def RunParts(dir_name, env=None, reset_env=False): """Run Scripts or programs in a directory @type dir_name: string @param dir_name: absolute path to a directory @type env: dict @param env: The environment to use @type reset_env: boolean @param reset_env: whether to reset or keep the default os environment @rtype: list of tuples @return: list of (name, (one of RUNDIR_STATUS), RunResult) """ rr = [] try: dir_contents = utils_io.ListVisibleFiles(dir_name) except OSError as err: logging.warning("RunParts: skipping %s (cannot list: %s)", dir_name, err) return rr for relname in sorted(dir_contents): fname = utils_io.PathJoin(dir_name, relname) if not (constants.EXT_PLUGIN_MASK.match(relname) is not None and utils_wrapper.IsExecutable(fname)): rr.append((relname, constants.RUNPARTS_SKIP, None)) else: try: result = RunCmd([fname], env=env, reset_env=reset_env) except Exception as err: # pylint: disable=W0703 rr.append((relname, constants.RUNPARTS_ERR, str(err))) else: rr.append((relname, constants.RUNPARTS_RUN, result)) return rr
def CreateBdevPartitionMapping(image_path): """Create dm device for each partition of disk image. This operation will allocate a loopback and a device-mapper device to map partitions. You must call L{ReleaseBdevPartitionMapping} to clean up resources allocated by this function call. @type image_path: string @param image_path: path of multi-partition disk image @rtype: tuple(string, list(string)) or NoneType @return: returns the tuple(loopback_device, list(device_mapper_files)) if image_path is a multi-partition disk image. otherwise, returns None. """ # Unfortunately, there are two different losetup commands in this world. # One has the '-s' switch and the other has the '--show' switch to provide the # same functionality. result = utils_process.RunCmd(["losetup", "-f", "-s", image_path]) if result.failed and "invalid option -- 's'" in result.stderr: result = utils_process.RunCmd(["losetup", "-f", "--show", image_path]) if result.failed: raise errors.CommandError("Failed to setup loop device for %s: %s" % (image_path, result.output)) loop_dev_path = result.stdout.strip() logging.debug("Loop dev %s allocated for %s", loop_dev_path, image_path) result = utils_process.RunCmd(["kpartx", "-a", "-v", loop_dev_path]) if result.failed: # Just try to cleanup allocated loop device utils_process.RunCmd(["losetup", "-d", loop_dev_path]) raise errors.CommandError( "Failed to add partition mapping for %s: %s" % (image_path, result.output)) dm_devs = [x.split(" ") for x in result.stdout.split("\n") if x] if dm_devs: dm_dev_paths = [ utils_io.PathJoin("/dev/mapper", x[2]) for x in dm_devs ] return (loop_dev_path, dm_dev_paths) else: # image_path is not a multi partition disk image, no need to use # device-mapper. logging.debug("Release loop dev %s allocated for %s", loop_dev_path, image_path) ReleaseBdevPartitionMapping(loop_dev_path) return None
@type reset_env: boolean @param reset_env: whether to reset or keep the default os environment @rtype: list of tuples @return: list of (name, (one of RUNDIR_STATUS), RunResult) """ rr = [] try: dir_contents = utils_io.ListVisibleFiles(dir_name) except OSError, err: logging.warning("RunParts: skipping %s (cannot list: %s)", dir_name, err) return rr for relname in sorted(dir_contents): fname = utils_io.PathJoin(dir_name, relname) if not (constants.EXT_PLUGIN_MASK.match(relname) is not None and utils_wrapper.IsExecutable(fname)): rr.append((relname, constants.RUNPARTS_SKIP, None)) else: try: result = RunCmd([fname], env=env, reset_env=reset_env) except Exception, err: # pylint: disable=W0703 rr.append((relname, constants.RUNPARTS_ERR, str(err))) else: rr.append((relname, constants.RUNPARTS_RUN, result)) return rr def _GetProcStatusPath(pid):
def _GuessMountFailReasons(self): """Try and give reasons why the mount might've failed. @rtype: str @return: A semicolon-separated list of problems found with the current setup suitable for display to the user. """ reasons = [] # Does the mount point exist? if not os.path.exists(self.mount_point): reasons.append("%r: does not exist" % self.mount_point) # Okay, it exists, but is it a directory? elif not os.path.isdir(self.mount_point): reasons.append("%r: not a directory" % self.mount_point) # If, for some unfortunate reason, this folder exists before mounting: # # /var/run/ganeti/gluster/gv0/10.0.0.1:30000:gv0/ # '--------- cwd ------------' # # and you _are_ trying to mount the gluster volume gv0 on 10.0.0.1:30000, # then the mount.glusterfs command parser gets confused and this command: # # mount -t glusterfs 10.0.0.1:30000:gv0 /var/run/ganeti/gluster/gv0 # '-- remote end --' '------ mountpoint -------' # # gets parsed instead like this: # # mount -t glusterfs 10.0.0.1:30000:gv0 /var/run/ganeti/gluster/gv0 # '-- mountpoint --' '----- syntax error ------' # # and if there _is_ a gluster server running locally at the default remote # end, localhost:24007, then this is not a network error and therefore... no # usage message gets printed out. All you get is a Byson parser error in the # gluster log files about an unexpected token in line 1, "". (That's stdin.) # # Not that we rely on that output in any way whatsoever... parser_confusing = io.PathJoin(self.mount_point, self._GetFUSEMountString()) if os.path.exists(parser_confusing): reasons.append("%r: please delete, rename or move." % parser_confusing) # Let's try something else: can we connect to the server? sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((self.server_ip, self.port)) sock.close() except socket.error as err: reasons.append("%s:%d: %s" % (self.server_ip, self.port, err.strerror)) reasons.append("try running 'gluster volume info %s' on %s to ensure" " it exists, it is started and it is using the tcp" " transport" % (self.volume, self.server_ip)) return "; ".join(reasons)