def mount_dynamic(self, windows_volumes): try: for volume in windows_volumes: mount_func = self._fetch_mount_func(volume) if not mount_func: continue # 已经挂载不再挂载 if volume['VolumeName'] in [ mount[2] for mount in self.successful_mount_info ]: continue label = self.get_name(volume) mount_point = os.path.join(self.mount_dir, label) duuid = hex(int(volume['VolumeSerialNumber']))[2:].upper() _logger.info('start get {} {} device path'.format( label, duuid)) devices = self._fetch_device(duuid) # 会匹配多个 for device in devices: rev = mount_func(device, mount_point) if not rev: execute_cmd('rm -rf "{}"'.format(mount_point)) self.fail_mount_info.add( (device, mount_point, volume['VolumeName'])) else: self.successful_mount_info.append( (device, mount_point, volume['VolumeName'])) break except Exception as e: _logger.error('mount_dynamic error:{}'.format(e), exc_info=True)
def umount_smb(args_dict, raw_input): """ 卸载在smb中的挂载aio备份镜像数据的盘符,将连接aio数据备份点的账号登出 :param args_dict: {'root_url':r'\\172.16.1.3\share\aio','username':'******','password':'******', 'drive_letter_and_sub_url_list':[['X', r'\\172.16.1.3\share\aio\X'],['Y ', r'\\172.16.1.3\share\aio\Y'],...],} :param raw_input: :return: """ root_url = args_dict['root_url'] drive_letter_and_sub_url_list = args_dict['drive_letter_and_sub_url_list'] reval_list = list() outs_list = list() errs_list = list() for drive_letter_and_sub_url in drive_letter_and_sub_url_list: drive_letter = drive_letter_and_sub_url[0] umount_disk_cmd = 'subst {}: /d'.format(drive_letter) retval, outs, errs = funcs.execute_cmd(umount_disk_cmd) reval_list.append(retval) outs_list.append(outs) errs_list.append(errs) aio_data_disk_login_out_cmd = 'net use "{}" /delete'.format(root_url) funcs.execute_cmd(aio_data_disk_login_out_cmd) return json.dumps({'retval': reval_list, 'outs': outs_list, 'errs': errs_list}), b''
def smb_add_userpath(username, userpwd, read_only): userpath = smb_get_userpath(username) if not os.path.isdir(userpath): cmd_line = 'useradd {};mkdir -p "{}"'.format(username, userpath) retval = funcs.execute_cmd(cmd_line) if retval[0] != 0: smb_del_userpath(username) return -1, 'create sys user {} failed'.format(username) # samba config cmd_line = '(echo "{}";echo "{}")|smbpasswd -a "{}"'.format( userpwd, userpwd, username) retval = funcs.execute_cmd(cmd_line) if retval[0] != 0: _logger.error("add smb user {} failed,ret str\n{}".format( username, retval[1])) smb_del_userpath(username) return -1, 'create smb user {} failed'.format(username) else: _logger.error("add smb user {} success,ret str\n{}".format( username, retval[1])) retval = smb_add_cfg(username, read_only) if retval != 0: _logger.error( "smb user {} create cfg file failed".format(username)) smb_del_userpath(username) return -1, 'create smb cfg file failed,user {}'.format( username) else: _logger.debug('smb susr path already have {}'.format(userpath)) _logger.debug('smb_create_smbuser user {} pwd {} success'.format( username, userpwd)) return 0, 'success'
def mount(self, dev_path, partition_info): try: cmd_line = "partx -d {};partx -a {}".format(dev_path, dev_path) execute_cmd(cmd_line) dev_partition2offset_dict = self.get_dev_detail(dev_path) _logger.debug('dev:{} partition info:{}'.format( dev_path, dev_partition2offset_dict)) for partition in partition_info: mount_func = self._fetch_mount_func(partition) if not mount_func: continue dev_str = dev_partition2offset_dict.get( str(partition['PartitionOffset']), None) vol_name = self.get_name(partition) if not dev_str: _logger.warning('get vol:[{},offset:{}] dev fail'.format( vol_name, partition['PartitionOffset'])) continue des_path = os.path.join(self.mount_dir, '{}'.format(vol_name)) rev = mount_func(dev_str, des_path) if not rev: execute_cmd('rm -rf "{}"'.format(des_path)) self.fail_mount_info.add( (dev_str, des_path, partition['VolumeName'])) else: self.successful_mount_info.append( (dev_str, des_path, partition['VolumeName'])) except Exception as e: _logger.error('mount error:{}'.format(e), exc_info=True)
def _mount_clw_lvm(): try: funcs.execute_cmd('mount {device} {path}'.format( path=db_backup_logic.MOUNT_PATH, device='/dev/mapper/{}-{}'.format(db_backup_logic.VG_NAME, db_backup_logic.LV_NAME))) except Exception as e: _logger.warning('_mount_clw_lvm error:{}'.format(e))
def _create_lvm(self): disks = self._args_dict['lvm_config']['disks'] code, stdout, stderr = funcs.execute_cmd('pvscan') if code != 0: xlogging.raise_system_error( '初始化数据缓存区域失败', 'execute_cmd pvscan:{}{}{}'.format(code, stdout, stderr), 1161) pvs = list() for disk in disks: for dev_path, size in self._all_blocks_size.items(): if int(disk['disk_bytes']) == int(size): disk['dev_path'] = dev_path break else: xlogging.raise_system_error( '初始化数据缓存区域失败', 'not found disk {} dev_path {}'.format( disk, self._all_blocks_size), 1162) funcs.execute_cmd('pvcreate {}'.format(disk['dev_path'])) pvs.append(disk['dev_path']) cmd = 'vgcreate {} '.format(VG_NAME) cmd += ' '.join(pvs) funcs.execute_cmd(cmd) funcs.execute_cmd('lvcreate -l 100%VG -n {} {}'.format( LV_NAME, VG_NAME)) funcs.execute_cmd( 'mkfs.ext4 /dev/mapper/{}-{}'.format(VG_NAME, LV_NAME), 60 * 30)
def _init_network(self): for net_info in funcs.get_net_dev_info(): if net_info.get( 'Mac', '-2').upper() == self._args_dict['kvm_ip_info'].get( 'mac', '-1').upper(): break else: _logger.warning('not found net info {} {}'.format( self._args_dict['kvm_ip_info'], funcs.get_net_dev_info())) return funcs.execute_cmd('ip addr add {}/{} dev {}'.format( self._args_dict['kvm_ip_info']['ip'], self._args_dict['kvm_ip_info']['mask'], net_info['Name'])) funcs.execute_cmd('ip link set {} up'.format(net_info['Name']))
def _scan_windows_volume(self): execute_cmd('/usr/local/bin/ldmtool create all') # 加载动态卷 rev = execute_cmd('blkid |egrep "ntfs|vfat"') if rev[0] != 0: return for line in rev[1].strip().splitlines(): uuid, device = '', '' uuid_match = UUID.search(line) if uuid_match: uuid = uuid_match.groups()[0] else: pass device = line.split(':')[0] self._windows_volumes.append((device, uuid.replace('-', ''))) _logger.info('_windows_volumes:{}'.format(self._windows_volumes))
def restart_samba(args_dict, raw_input): ret = funcs.execute_cmd('systemctl restart smb;systemctl restart nmb') if ret[0] != 0: _logger.info('reset_samba,fail') else: _logger.info('reset_samba,successful') return '', b''
def mount_smb(args_dict, raw_input): """ 通过验证账号密码登录到aio的备份点的位置,将备份点的镜像挂载到一个新的空的盘符上 :param args_dict:{'root_url':r'\\172.16.1.3\share\aio','username':'******','password':'******', 'drive_letter_and_sub_url_list':[['X', r'\\172.16.1.3\share\aio\X'],['Y ', r'\\172.16.1.3\share\aio\Y'],...],} :param raw_input: :return: """ # root_url = args_dict['root_url'] # username = args_dict['username'] # password = args_dict['password'] drive_letter_and_sub_url_list = args_dict['drive_letter_and_sub_url_list'] # # aio_data_disk_login_cmd = 'net use "{}" /user:{} {}'.format(root_url, username, password) # funcs.execute_cmd(aio_data_disk_login_cmd) reval_list = list() outs_list = list() errs_list = list() for drive_letter_and_sub_url in drive_letter_and_sub_url_list: mount_drive_cmd = 'subst {}: "{}"'.format(drive_letter_and_sub_url[0], drive_letter_and_sub_url[1]) retval, outs, errs = funcs.execute_cmd(mount_drive_cmd) reval_list.append(retval) outs_list.append(outs) errs_list.append(errs) return json.dumps({'retval': reval_list, 'outs': outs_list, 'errs': errs_list}), b''
def mount_disk(args_dict, raw_input): """ 将vhd格式的镜像数据通过diskpart重新以文件格式挂载到新盘符上 :param args_dict:{'file_vhd':r'Y:\vhd2\w10vhd.vhd','part_num_and_drive_letter_list':[[1,'K'],[2,'J'],...],} :param raw_input: :return: """ file_vhd = args_dict['file_vhd'] part_num_and_drive_letter_list = args_dict['part_num_and_drive_letter_list'] mount_disk_script_name = 'mount_disk_script.txt' mount_disk_script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), mount_disk_script_name) with open(mount_disk_script_path, 'w') as f: f.write('select vdisk file="{}" \r\n'.format(file_vhd)) f.write('attach vdisk \r\n') f.write('rescan \r\n') for part_num_and_drive_letter in part_num_and_drive_letter_list: # 如果select不到volume号则会直接退出本脚本也不再执行,因此暂取消本卸载功能 # f.write('select volume {} \r\n'.format(part_num_and_drive_letter[1])) # f.write('remove letter={} \r\n'.format(part_num_and_drive_letter[1])) f.write('select part {} \r\n'.format(part_num_and_drive_letter[0])) f.write('assign letter={} \r\n'.format(part_num_and_drive_letter[1])) f.write('exit \r\n') mount_disk_cmd = 'DiskPart /s "{}"'.format(mount_disk_script_path) retval, outs, errs = funcs.execute_cmd(mount_disk_cmd) # retval=-1 操作也是成功的 return json.dumps({'retval': retval, 'outs': outs, 'errs': errs}), b''
def get_all_mounted_vdisk(args_dict, raw_input): _vdisk_list = list() get_all_mounted_vdisk_script_name = 'get_all_mounted_vdisk.txt' get_all_mounted_vdisk_script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), get_all_mounted_vdisk_script_name) with open(get_all_mounted_vdisk_script_path, 'w') as f: f.write('list vdisk \r\n') f.write('exit \r\n') get_all_mounted_vdisk_cmd = 'DiskPart /s "{}"'.format(get_all_mounted_vdisk_script_path) retval, outs, errs = funcs.execute_cmd(get_all_mounted_vdisk_cmd) strio = StringIO(outs) while True: _line = strio.readline() if not _line: break print(_line) if '------' in _line: break while True: _line = strio.readline() if not _line: break _line_data_list = _line.split() if len(_line_data_list) < 4: break _vdisk_list.append(_line_data_list[len(_line_data_list) - 1]) return json.dumps(_vdisk_list), b''
def connect_smb(args_dict, raw_input): root_url = args_dict['root_url'] username = args_dict['username'] password = args_dict['password'] aio_data_disk_login_cmd = 'net use "{}" /user:{} {}'.format(root_url, username, password) retval, outs, errs = funcs.execute_cmd(aio_data_disk_login_cmd) return json.dumps({'retval': retval, 'outs': outs, 'errs': errs}), b''
def smb_del_hostpath(username, hostname): hostpath = smb_get_hostpath(username, hostname) _logger.debug('del host path: user {} host {} host path {}'.format( username, hostname, hostpath)) if os.path.isdir(hostpath): smb_umount_path(hostpath) cmdline = 'fuser -k "{hostpath}";fuser -k "{hostpath}";fuser -k "{hostpath}";rm -rf "{hostpath}"'.format( hostpath=hostpath) funcs.execute_cmd(cmdline) time.sleep(0.1) while is_one_mount(hostpath): r = funcs.execute_cmd(r'umount "{}"'.format(hostpath)) if r[0] != 0: funcs.execute_cmd(r'fuser -k "{}"'.format(hostpath)) time.sleep(0.1) smb_del_userpath(username) return 0, 'success'
def shutdown(args_dict, raw_input): if args_dict['logic'] == 'windows': cmd = 'start wpeutil shutdown' else: # shutdown之前的命令是用来清除缓存的 cmd = 'sync && echo 3 > /proc/sys/vm/drop_caches;shutdown -h now' code, stdout, stderr = execute_cmd(cmd) return json.dumps({'code': code, 'stdout': stdout, 'stderr': stderr}), b''
def _mount_ntfs(self, vol, point): xlogging.makedirs(point, exist_ok=True) if self._read_only: cmd_line = 'mount -t ntfs-3g "{}" "{}" -o ro'.format(vol, point) else: cmd_line = 'mount -t ntfs-3g "{}" "{}";mount -no remount rw "{}"'.format( vol, point, point) ret = execute_cmd(cmd_line) return ret[0] == 0
def smb_umount_path(hostpath): if not os.path.isdir(hostpath): _logger.error('umount host path not exist {}'.format(hostpath)) return 0, 'success' mountlist = psutil.disk_partitions() umountlist = list() for diskpart in mountlist: mountpoint = diskpart.mountpoint if mountpoint.startswith(hostpath): umountlist.append(mountpoint) if len(umountlist) > 0: sortlist = sorted(umountlist, key=(lambda x: len(x)), reverse=True) _logger.debug('umount sort list {}'.format(sortlist)) for mountpoint in sortlist: _logger.debug('umount path {}'.format(mountpoint)) cmdline = 'fuser -k "{mountpoint}";fuser -k "{mountpoint}";fuser -k "{mountpoint}";umount "{mountpoint}"'.format( mountpoint=mountpoint) funcs.execute_cmd(cmdline)
def _mount_vfat(self, vol, point): xlogging.makedirs(point, exist_ok=True) if self._read_only: cmd_line = 'mount -o ro,iocharset=utf8,codepage=936 "{}" "{}"'.format( vol, point) else: cmd_line = 'mount -o rw,iocharset=utf8,codepage=936 "{}" "{}"'.format( vol, point) ret = execute_cmd(cmd_line) return ret[0] == 0
def startup_data_agent(self): vmagent = VMAGENT_PATH cmd = "nohup ./clwobkapp > clwobkapp.log 2>&1 &" retval, stdout, stderr = funcs.execute_cmd(cmd, cwd=vmagent) if retval != 0: _logger.error( '[startup_data_agent] execute_cmd failed, cmd={} out={} err={}' .format(cmd, stdout, stderr)) return False return True
def smb_add_hostpath(user_name, hostname): hostpath = smb_get_hostpath(user_name, hostname) if os.path.exists(hostpath): _logger.error( 'smb_add_hostpath host {} already exist'.format(hostpath)) return -1, '' cmdline = 'mkdir -p "{}"'.format(hostpath) ret = funcs.execute_cmd(cmdline) if ret[0] != 0: _logger.debug('add hostpath failed {}'.format(ret)) return -1, 'failed' return 0, 'success'
def smb_del_userpath(user_name): # del sys usr userpath = smb_get_userpath(user_name) have_host = 0 if os.path.isdir(userpath): for hostname in os.listdir(userpath): hostpath = os.path.join(userpath, hostname) if os.path.isdir(hostpath): have_host += 1 break if have_host == 0: # del sys user cmd_line = 'userdel -r -f "{}"'.format(user_name) _logger.debug("start del sys user {},cmd {}".format( user_name, cmd_line)) funcs.execute_cmd(cmd_line) # del smb user smb_del_cfg(user_name) cmd_line = 'pdbedit -x {}'.format(user_name) _logger.debug("start del smb user {},cmd {}".format( user_name, cmd_line)) funcs.execute_cmd(cmd_line) cmdline = 'fuser -k "{userpath}";fuser -k "{userpath}";fuser -k "{userpath}";rm -rf "{userpath}"'.format( userpath=userpath) _logger.debug("start user path,cmd {}".format(cmd_line)) funcs.execute_cmd(cmdline) else: _logger.error('already have {} host,can not del userpath {}'.format( have_host, userpath)) return -1, "failed" return 0, 'success'
def _scan_device(self): rev = funcs.execute_cmd('blkid') if rev[0] != 0: return for line in rev[1].strip().splitlines(): uuid, device = '', '' uuid_match = UUID.search(line) if uuid_match: uuid = uuid_match.groups()[0] else: pass device = line.split(':')[0] self._uuid2device[uuid] = device _logger.info('_scan_device _uuid2device {}'.format(self._uuid2device))
def smb_get_user_list(): userlist = list() cmd_line = 'pdbedit -L' retval = funcs.execute_cmd(cmd_line) if retval[0] != 0: _logger.error("get info from cmd {} failed".format(cmd_line)) else: mlist = retval[1].strip().split('\n') for i in range(len(mlist)): mstr = mlist[i] mindex = mstr.find(':') if mindex > 0: muser_name = mstr[:mindex] userlist.append(muser_name) return userlist
def chattr_clerwaremeta_del_i(clerware_meta_path): """ 从一下目录找到clerware_meta, 并取消掉 -i 属性 /bin/目录下 /opt/ :param clerware_meta_path: :return: """ cmd = 'chattr -i {}'.format(clerware_meta_path) code, stdout, stderr = funcs.execute_cmd(cmd) if code != 0: # xlogging.raise_system_error('更改属性失败', 'change meta failed', 532) _logger.info('ClerWareMeta del i Failed.ignore.') else: _logger.info('ClerWareMeta del i successful!')
def _init_data_area(self): if 'lvm_config' not in self._args_dict: return lvm_path = '/dev/mapper/{}-{}'.format(VG_NAME, LV_NAME) if not os.path.exists(lvm_path): self._status = ('初始化数据缓存区域', 'init_data_area') _logger.warning('not found lvm {}, start create'.format(lvm_path)) self._pause_in_debug_mod('开始创建lvm') self._create_lvm() xlogging.makedirs(MOUNT_PATH, exist_ok=True) code, stdout, stderr = funcs.execute_cmd('mount {} {}'.format( lvm_path, MOUNT_PATH)) if code != 0: xlogging.raise_system_error( '初始化数据缓存区域失败', 'execute_cmd mount:{}{}{}'.format(code, stdout, stderr), 1162)
def get_dev_detail(dev_path): rs = dict() if not os.path.exists(dev_path): _logger.warning( 'DevDetail get_dict fail, dev:{} is not found'.format( dev_path)) return rs cmd = r"partx -o NR,START {} |grep -v NR".format(dev_path) ret = execute_cmd(cmd) if ret[0] == 0: for line in ret[1].splitlines(): item_list = line.strip().split() if len(item_list) == 2: offset = str(int(item_list[1]) * 512) rs[offset] = "{}{}".format(dev_path, item_list[0]) else: _logger.error('get DevDetail fail:{}'.format(ret[2])) return rs
def umount_disk(args_dict, raw_input): """ 清除挂载的vhd文件格式的分区 :param args_dict:{'file_vhd':r'Y:\vhd2\w10vhd.vhd','part_num_and_drive_letter_list':[[1,'K'],[2,'J'],...],} :param raw_input: :return: """ umount_disk_script_name = 'umount_disk_script.txt' umount_disk_script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), umount_disk_script_name) file_vhd = args_dict['file_vhd'] part_num_and_drive_letter_list = args_dict['part_num_and_drive_letter_list'] with open(umount_disk_script_path, 'w') as f: for part_num_and_drive_letter in part_num_and_drive_letter_list: f.write('select volume={} \r\n'.format(part_num_and_drive_letter[1])) f.write('remove \r\n') f.write('select vdisk file="{}" \r\n'.format(file_vhd)) f.write('detach vdisk \r\n') f.write('rescan \r\n') f.write('exit \r\n') umount_disk_cmd = 'DiskPart /s "{}"'.format(umount_disk_script_path) retval, outs, errs = funcs.execute_cmd(umount_disk_cmd) # reval = -1,实际操作也是正常的。 return json.dumps({'retval': retval, 'outs': outs, 'errs': errs}), b''
def _read_key_files_in_system(root_path): # 预读单个文件 single_files = get_path_from_key_files(root_path, file_type='file') for file in single_files: cmd = r'cat {0} > /dev/null'.format(file) funcs.execute_cmd(cmd, 60 * 5) # 预读目录当层文件 folders = get_path_from_key_files(root_path, file_type='dir_cur') for folder in folders: cmd = r'find {0} -maxdepth 1 -type f | tar -cf - -T - | cat > /dev/null'.format( folder) funcs.execute_cmd(cmd, 60 * 5) # 预读文件夹内所有(子)文件(<5MB) folders = get_path_from_key_files(root_path, file_type='dir_all') for folder in folders: cmd = r'find {0} -type f -size -5M | tar -cf - -T - | cat > /dev/null'.format( folder) funcs.execute_cmd(cmd, 60 * 5)
def _get_info_from_syscmd_timeout_long(cmd): return funcs.execute_cmd(cmd, timeout=60 * 30)
def _get_info_from_syscmd_timeout_middle(cmd): return funcs.execute_cmd(cmd, timeout=60 * 15)