def in_cli(argv=sys.argv[1:]): try: arguments = commandline_to_docopt(argv) return arguments_to_functions(arguments) except KeyboardInterrupt: log(logger, "Keyboard break received, exiting") return 1
def prechecks(): from smb.cli.ibox_connect import InfiSdkObjects log(logger, "Running Prechecks...", level=INFO) sdk = InfiSdkObjects() sdk.get_ibox() is_cluster_online() am_I_master() return sdk
def run_fs_attach(arguments, sdk): from smb.cli.fs import fs_attach config = config_get(silent=True) lib.approve_danger_op( "Adding volume {} to Cluster {}".format(arguments['--name'], config['Cluster']), arguments) log(logger, "calling {}") fs_attach(arguments['--name'], sdk, arguments['--force'])
def delete_volume_on_infinibox(volume_name, sdk): ibox = sdk.get_ibox() volume = ibox.volumes.choose(name=volume_name) volume.delete() log(logger, "Volume {} was deleted".format(volume_name), level=INFO, color="yellow")
def unmap_vol_from_cluster_infinibox(volume_name, sdk): ibox = sdk.get_ibox() cluster = sdk.get_cluster() volume = ibox.volumes.choose(name=volume_name) cluster.unmap_volume(volume) log(logger, "Volume {} was unmapped".format(volume.get_name()), color="yellow", level=INFO)
def map_vol_to_cluster_infinibox(volume, sdk): cluster = sdk.get_cluster() try: mapping = cluster.map_volume(volume) except: error = sys.exc_info()[1] log_n_raise( logger, "Couldn't Map Volume {} to {}! {!r}".format( volume.get_name(), cluster.get_name(), str(error.message))) log(logger, "Mapping {} to {}".format(volume.get_name(), cluster.get_name()), level=INFO)
def unmap_volume(volume_name, mountpoint, sdk): import os unmap_vol_from_cluster_infinibox(volume_name, sdk) try: if os.listdir(mountpoint) == []: os.rmdir(mountpoint) else: log(logger, "Not Deleting {} Because it's Not Empty".format(mountpoint), color="yellow", level=INFO) except Exception as e: log(logger, "{}".format(e))
def read_config(filename): if path.exists(filename): config = powershell_config_to_dict(filename) if config is None: log( logger, "config file {} was empty!".format(filename, level=WARNING, color="yellow")) generate_config() return config else: log(logger, "Config file did not exist on {}. Generating it".format(filename), level=INFO) generate_config()
def _winid_serial_table_to_dict(): import re disk_list = [] cmd_output = execute([ 'powershell', '-c', 'Get-Disk', '|', 'Select-Object', 'Number,SerialNumber' ]).get_stdout() cmd_output = cmd_output.replace("Number SerialNumber", "").replace("-", "") regex = re.compile(r'(?P<winid>\d+)\ (?P<serial>\w+)') for line in cmd_output.splitlines(): result = re.search(regex, line) if result: disk_list.append(result.groupdict()) log(logger, "winid serial dict: {}".format(disk_list)) return disk_list
def change_powershell_config(key, value): import fileinput config = read_config(conf_file) if not config: log_n_raise(logger, "Problem reading config file") log(logger, "Changing {} = {}".format(key, value), level=INFO) for line in fileinput.input(conf_file, inplace=True): if "=" not in line: print line, continue line_key, line_val = line.split("=") if line_key.strip() == key: print ' {} = "{}"'.format(key, value) else: print line, fileinput.close()
def generate_config(): default_conf_content = '''@{ TempDriveLetter = "Z:\" MountRoot = "G:\" PoolName = "<infinibox_pool>" Cluster = "<infinibox_cluster>" IboxAddress = "<infinibox_address>" FSRoleName = "<ms_role_name>" } ''' with open(conf_file, 'w') as fd: fd.write(default_conf_content) log(logger, "Vanilla config file was generated at {}".format(conf_file), level=INFO, color="green") raise SmbCliExited()
def tearDownClass(cls): log(logger, "Starting Teardown") sdk = InfiSdkObjects() for fs in fs_names + ['fs_test_for_shares']: try: cmd = [ 'smbmgr', 'fs', 'delete', '--name={}'.format(fs), '--yes' ] execute(cmd) except: pass try: for fs in fs_names + ['fs_test_for_shares']: vol = sdk.volumes.choose(name=fs) vol.delete except: pass
def config_get(silent=False, skip_validation=False): if not path.exists(conf_dir): mkdir(conf_dir) generate_config() config = read_config(conf_file) if silent or not config: return config log(logger, "Current Config:", level=INFO, raw=True) for key, val in config.items(): message = " {}: {}".format(key, val) log(logger, message, level=INFO, raw=True) if not skip_validation: validate_config(config) if not path.exists(infinihost_bin): log_n_raise( logger, 'smb.cli depends on "Host Power Tools" and can NOT find it!') return config
def get_path_free_size(full_path): ''' inspired by: http://code.activestate.com/recipes/577972-disk-usage/ ''' import ctypes from capacity import byte size = {} _, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), ctypes.c_ulonglong() space = ctypes.windll.kernel32.GetDiskFreeSpaceExA result = space(str(full_path), ctypes.byref(_), ctypes.byref(total), ctypes.byref(free)) if result == 0: return used = total.value - free.value size['size'] = total.value * byte size['used'] = used * byte size['avail'] = free.value * byte log(logger, "sizes are {}".format(size)) return size
def fs_create(volume_name, volume_pool, volume_size, sdk): _validate_max_amount_of_volumes(sdk) _validate_vol_name(volume_name) ibox = sdk.get_ibox() volume = create_volume_on_infinibox(volume_name, volume_pool, volume_size, sdk) try: map_vol_to_cluster_infinibox(volume, sdk) lib.exit_if_vol_not_mapped(volume) except: log(logger, "Something went wrong. Rolling back operations...", level=ERROR, color="red") unmap_volume(volume_name, _get_default_mountpoint(volume_name), sdk) delete_volume_on_infinibox(volume_name, sdk) raise SmbCliExited fs = Fs(volume, sdk) log(logger, "Preparing Filesystem for {}. This might take a while. \nDO NOT EXIT!". format(volume_name), level=INFO, color="yellow") if fs.get_winid() is None: fs = Fs(volume, sdk) try: ps_cmd._run_prep_vol_to_cluster_script(fs) except: log(logger, "Something went wrong. Rolling back operations...", level=ERROR, color="red") unmap_volume(volume_name, _get_default_mountpoint(volume_name), sdk) delete_volume_on_infinibox(volume_name, sdk) raise SmbCliExited try: fs_attach(volume_name, sdk, force=True) except: log(logger, "Something went wrong. Rolling back operations...", level=ERROR, color="red") try: ps_cmd._run_move_cluster_volume_offline(volume_name) except: pass try: lib.cluster_remove_ms_volume_and_wait(volume_name) except: pass unmap_volume(volume_name, _get_default_mountpoint(volume_name), sdk) delete_volume_on_infinibox(volume_name, sdk) raise SmbCliExited
def create_volume_on_infinibox(volume_name, pool_name, size, sdk): ibox = sdk.get_ibox() pool = _validate_pool(pool_name, ibox, size) try: log(logger, "Creating Volume {} at {}".format(volume_name, pool_name), level=INFO) volume = ibox.volumes.create(name=volume_name, pool=pool, size=size, provtype='THIN') volume.set_metadata('volume.provisionedby', 'smb.cli-{}'.format(__version__)) return volume except: error = sys.exc_info()[1] log_n_raise( logger, "Volume {} couldn't be created. {!r}".format( volume_name, str(error.message)))
def fs_attach(volume_name, sdk, force=False): ibox = sdk.get_ibox() _validate_max_amount_of_volumes(sdk) _validate_vol_name(volume_name) volume = _validate_vol(ibox, volume_name) if force and lib.is_volume_mapped_to_cluster(volume, sdk): pass else: map_vol_to_cluster_infinibox(volume, sdk) lib.exit_if_vol_not_mapped(volume) fs = Fs(volume, sdk) _mountpoint_exist(fs.get_mountpoint()) try: ps_cmd._run_attach_vol_to_cluster_script(fs) except: log_n_raise(logger, "Couldn't add {} to SMB Cluster".format(volume_name)) log(logger, "Volume {} Attached to Cluster Successfully.".format(volume_name), level=INFO, color="green")
def arguments_to_functions(arguments): log(logger, "Arguments received from user:{}".format(arguments)) try: if arguments['config']: if arguments['get']: run_config_get() return if arguments['set']: run_config_set(arguments) return try: config = config_get(silent=True) except SmbCliExited: return sdk = lib.prechecks() if arguments['fs']: arguments = _use_default_config_if_needed(arguments) if arguments['create']: run_fs_create(arguments, sdk) if arguments['delete']: run_fs_delete(arguments, sdk) if arguments['attach']: run_fs_attach(arguments, sdk) if arguments['detach']: run_fs_detach(arguments, sdk) if arguments['query']: run_fs_query(arguments, sdk) if arguments['share']: if arguments['create']: run_share_create(arguments, sdk) if arguments['query']: run_share_query(arguments, sdk) if arguments['resize']: run_share_resize(arguments, sdk) if arguments['delete']: run_share_delete(arguments) except KeyboardInterrupt: log(logger, "Keyboard break received, exiting") return except SmbCliExited: return 1 except Exception as e: log(logger, traceback.format_exc()) message = '''{} \n(This is Unusual) Please collect the Logs from "{}" and open a ticket on github''' log(logger, message.format(e, logger.handlers[0].baseFilename), level=ERROR, color="red") return 1
def run_config_set(arguments): from smb.cli.config import config_set, config_get config = config_get(silent=True) log(logger, "Current Config:", raw=True) if config is None: return key, value = arguments.get('<key=value>', "").split("=") config_case_sensitive = {item.lower(): item for item in config.keys()} if key.lower() not in config_case_sensitive.keys(): log(logger, "{} is not valid for your config".format(key), color="red", raw=True) return config_set(config_case_sensitive[key.lower()], value) log(logger, "New Config:", level=INFO) config_get(skip_validation=True)
def commandline_to_docopt(argv): import docopt global output_stream lib._init_colorama() output_stream = sys.stdout doc = __doc__ try: return docopt.docopt( doc.format(version=__version__, privileges_text=lib.get_privileges_text()).strip(), version=__version__, help=True, argv=argv) except docopt.DocoptExit as e: log(logger, e, level=INFO, raw=True) log(logger, "Invalid Arguments", level=ERROR, color="red") log(logger, argv) exit(1)
def _mountpoint_exist(mountpoint): '''Check if mount point exist otherwise create it ''' if not path.exists(mountpoint): log(logger, "Creating mount path {}".format(mountpoint), level=DEBUG) mkdir(mountpoint)
def print_fs_query(mapped_vols, print_units, serial_list, sdk, detailed=False): from smb.cli.share import _share_query_to_share_instance shares = _share_query_to_share_instance() shares_paths = [share.get_path() for share in shares] if len(mapped_vols) <= 2: log(logger, "No InfiniBox Volumes are Mapped to the Cluster", level=INFO) return ibox = mapped_vols[0].get_system() vols_in_cluster = ps_cmd._get_cluster_vols().splitlines() print_output = "" for volume in mapped_vols: volume_name = volume.get_name() # Hide irrelevant stuff if volume_name in ["mountpoint", "witness"]: continue if volume_name not in vols_in_cluster: continue if not path.exists(_get_default_mountpoint(volume_name)): continue volume_serial = volume.get_serial() win_id = None for disk in serial_list: if disk['serial'] == volume_serial: win_id = disk['winid'] break fs = Fs(volume, sdk, win_id) num_of_shares = lib.count_shares_on_fs(fs.get_mountpoint(), shares_paths) if print_units: fs_size = "{:.2f}".format( float( str( float(fs.get_fs_size().roundup(MiB) / MiB) * MiB / print_units))) fs_size = fs_size + " " + str(print_units)[2:] used_size = "{:.2f}".format( float( str( float(fs.get_used_size().roundup(MiB) / MiB) * MiB / print_units))) used_size = used_size + " " + str(print_units)[2:] else: fs_size = fs.get_fs_size( ) if Capacity(0) != fs.get_fs_size() else 0 used_size = fs.get_used_size( ) if Capacity(0) != fs.get_used_size() else 0 if detailed: line = [ "{}: {}".format("name", fs.get_name()), "{}: {}".format("mount", fs.get_mountpoint()), "{}: {}".format("size", str(fs_size)), "{}: {}".format("used_size", str(used_size)), "{}: {}".format("snaps", str(fs.get_num_snaps())), "{}: {}".format("shares", str(num_of_shares)) ] else: line = [ _print_format(fs.get_name(), "name"), _print_format(fs.get_mountpoint(), "mount"), _print_format( str(fs_size), "size", ), _print_format(str(used_size), "used_size"), _print_format(str(fs.get_num_snaps()), "snaps"), _print_format(str(num_of_shares), "shares") ] log(logger, line) print_output = print_output + " ".join(line) + '\n' if print_output.splitlines() == []: log(logger, "No InfiniBox Volumes are Mapped to the Cluster", level=INFO) return header = 'Name Mount Size Used Size Snaps Shares' log(logger, header, level=INFO, raw=True) print print_output
def approve_danger_op(message, arguments): if arguments['--yes'] is False: full_massage = "This Operations is considered dangerous!\nPlease Confirm: {}".format(message) log(logger, full_massage, level=WARNING, color="yellow") approve_operation()