def check_root_dir(self): """ Do the necessary checks for the destination directory depending on the type of the transfer. Raises: IOError: Root dir state inconsistent. """ root_str = self.header['dst' if self.d2t else 'src'] fs = self.get_fs(root_str) url = client.URL(root_str.encode("utf-8")) arg = url.path + "?eos.ruid=0&eos.rgid=0" st, __ = fs.stat(arg.encode("utf-8")) if self.d2t: if st.ok: # For PUT destination dir must NOT exist err_msg = "Root PUT dir={0} exists".format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: # Make sure the rest of the path exists as for the moment CASTOR # mkdir -p /path/to/file does not work properly pos = url.path.find('/', 1) while pos != -1: dpath = url.path[:pos] pos = url.path.find('/', pos + 1) st, __ = fs.stat(dpath.encode("utf-8")) if not st.ok: st, __ = fs.mkdir(dpath.encode("utf-8")) if not st.ok: err_msg = ("Dir={0} failed mkdir errmsg={1}" "").format(dpath, st.message.decode("utf-8")) self.logger.error(err_msg) raise IOError(err_msg) elif not self.d2t: # For GET destination must exist and contain just the archive file if not st.ok: err_msg = "Root GET dir={0} does NOT exist".format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: ffindcount = ''.join([ url.protocol, "://", url.hostid, "//proc/user/?mgm.cmd=find&mgm.path=", seal_path(url.path), "&mgm.option=Z" ]) (status, stdout, stderr) = exec_cmd(ffindcount) if status: for entry in stdout.split(): tag, num = entry.split('=') if ((tag == 'nfiles' and num not in ['1', '2']) or (tag == 'ndirectories' and num != '1')): err_msg = ( "Root GET dir={0} should contain at least " "one file and at most two - clean up and " "try again").format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: err_msg = ("Error doing find count on GET destination={0}" ", msg={1}").format(root_str, stderr) self.logger.error(err_msg) raise IOError(err_msg)
def check_root_dir(self): """ Do the necessary checks for the destination directory depending on the type of the transfer. Raises: IOError: Root dir state inconsistent. """ root_str = self.header['dst' if self.d2t else 'src'] fs = self.get_fs(root_str) url = client.URL(root_str.encode("utf-8")) arg = url.path + "?eos.ruid=0&eos.rgid=0" st, __ = fs.stat(arg.encode("utf-8")) if self.d2t: if st.ok: # For PUT destination dir must NOT exist err_msg = "Root PUT dir={0} exists".format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: # Make sure the rest of the path exists as for the moment CASTOR # mkdir -p /path/to/file does not work properly pos = url.path.find('/', 1) while pos != -1: dpath = url.path[: pos] pos = url.path.find('/', pos + 1) st, __ = fs.stat(dpath.encode("utf-8")) if not st.ok: st, __ = fs.mkdir(dpath.encode("utf-8")) if not st.ok: err_msg = ("Dir={0} failed mkdir errmsg={1}" "").format(dpath, st.message.decode("utf-8")) self.logger.error(err_msg) raise IOError(err_msg) elif not self.d2t: # For GET destination must exist and contain just the archive file if not st.ok: err_msg = "Root GET dir={0} does NOT exist".format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: ffindcount = ''.join([url.protocol, "://", url.hostid, "//proc/user/?mgm.cmd=find&mgm.path=", seal_path(url.path), "&mgm.option=Z"]) (status, stdout, stderr) = exec_cmd(ffindcount) if status: for entry in stdout.split(): tag, num = entry.split('=') if ((tag == 'nfiles' and num not in ['1', '2']) or (tag == 'ndirectories' and num != '1')): err_msg = ("Root GET dir={0} should contain at least " "one file and at most two - clean up and " "try again").format(root_str) self.logger.error(err_msg) raise IOError(err_msg) else: err_msg = ("Error doing find count on GET destination={0}" ", msg={1}").format(root_str, stderr) self.logger.error(err_msg) raise IOError(err_msg)
def make_mutable(self): """ Make the EOS sub-tree pointed by header['src'] mutable. Raises: IOError when operation fails. """ url = client.URL(self.header['src'].encode("utf-8")) for dentry in self.dirs(): dir_path = url.path + dentry[1] fgetattr = ''.join([ url.protocol, "://", url.hostid, "//proc/user/", "?mgm.cmd=attr&mgm.subcmd=get&mgm.attr.key=sys.acl", "&mgm.path=", seal_path(dir_path) ]) (status, stdout, __) = exec_cmd(fgetattr) if not status: warn_msg = "No xattr sys.acl found for dir={0}".format( dir_path) self.logger.warning(warn_msg) else: # Remove the 'z:i' rule from the acl list stdout = stdout.replace('"', '') acl_val = stdout[stdout.find('=') + 1:] rules = acl_val.split(',') new_rules = [] for rule in rules: if rule.startswith("z:"): tag, definition = rule.split(':') pos = definition.find('i') if pos != -1: definition = definition[:pos] + definition[pos + 1:] if definition: new_rules.append(':'.join([tag, definition])) continue new_rules.append(rule) acl_val = ','.join(new_rules) self.logger.error("new acl: {0}".format(acl_val)) if acl_val: # Set the new sys.acl xattr fmutable = ''.join([ url.protocol, "://", url.hostid, "//proc/user/?", "mgm.cmd=attr&mgm.subcmd=set&mgm.attr.key=sys.acl", "&mgm.attr.value=", acl_val, "&mgm.path=", dir_path ]) (status, __, stderr) = exec_cmd(fmutable) if not status: err_msg = "Error making dir={0} mutable, msg={1}".format( dir_path, stderr) self.logger.error(err_msg) raise IOError(err_msg) else: # sys.acl empty, remove it from the xattrs frmattr = ''.join([ url.protocol, "://", url.hostid, "//proc/user/?", "mgm.cmd=attr&mgm.subcmd=rm&mgm.attr.key=sys.acl", "&mgm.path=", dir_path ]) (status, __, stderr) = exec_cmd(frmattr) if not status: err_msg = ( "Error removing xattr=sys.acl for dir={0}, msg={1}" "").format(dir_path, stderr) self.logger.error(err_msg) raise IOError(err_msg)
def make_mutable(self): """ Make the EOS sub-tree pointed by header['src'] mutable. Raises: IOError when operation fails. """ url = client.URL(self.header['src'].encode("utf-8")) for dentry in self.dirs(): dir_path = url.path + dentry[1] fgetattr = ''.join([url.protocol, "://", url.hostid, "//proc/user/", "?mgm.cmd=attr&mgm.subcmd=get&mgm.attr.key=sys.acl", "&mgm.path=", seal_path(dir_path)]) (status, stdout, __) = exec_cmd(fgetattr) if not status: warn_msg = "No xattr sys.acl found for dir={0}".format(dir_path) self.logger.warning(warn_msg) else: # Remove the 'z:i' rule from the acl list stdout = stdout.replace('"', '') acl_val = stdout[stdout.find('=') + 1:] rules = acl_val.split(',') new_rules = [] for rule in rules: if rule.startswith("z:"): tag, definition = rule.split(':') pos = definition.find('i') if pos != -1: definition = definition[:pos] + definition[pos + 1:] if definition: new_rules.append(':'.join([tag, definition])) continue new_rules.append(rule) acl_val = ','.join(new_rules) self.logger.error("new acl: {0}".format(acl_val)) if acl_val: # Set the new sys.acl xattr fmutable = ''.join([url.protocol, "://", url.hostid, "//proc/user/?", "mgm.cmd=attr&mgm.subcmd=set&mgm.attr.key=sys.acl", "&mgm.attr.value=", acl_val, "&mgm.path=", dir_path]) (status, __, stderr) = exec_cmd(fmutable) if not status: err_msg = "Error making dir={0} mutable, msg={1}".format( dir_path, stderr) self.logger.error(err_msg) raise IOError(err_msg) else: # sys.acl empty, remove it from the xattrs frmattr = ''.join([url.protocol, "://", url.hostid, "//proc/user/?", "mgm.cmd=attr&mgm.subcmd=rm&mgm.attr.key=sys.acl", "&mgm.path=", dir_path]) (status, __, stderr) = exec_cmd(frmattr) if not status: err_msg = ("Error removing xattr=sys.acl for dir={0}, msg={1}" "").format(dir_path, stderr) self.logger.error(err_msg) raise IOError(err_msg)