def validate_save_dir(dest_dir, force): try: dest_dir = os.path.abspath(dest_dir) if dest_dir[-1] == '/': dest_dir = dest_dir[:-1] if os.path.isfile(dest_dir): raise click.UsageError('destination cannot be an existing file') if os.path.exists(dest_dir): if force: return dest_dir else: raise click.UsageError('destination directory already exists') if not os.path.exists(os.path.dirname(dest_dir)): raise click.UsageError('base directory %s does not exist' % (os.path.dirname(dest_dir))) if not os.path.isdir(os.path.dirname(dest_dir)): raise click.UsageError('base directory %s is not a direcotry' % (os.path.dirname(dest_dir))) else: os.mkdir(dest_dir) except OSError as err: raise click.UsageError('invalid destination directory: ' + err.strerror) return dest_dir
def pcocc_display(jobid, jobname, print_opts, vm): """Display the graphical output of a VM This requires the VM to have a remote display method defined in it's template. \b Example usage: pcocc display vm0 """ try: config = load_config(jobid, jobname, default_batchname='pcocc') cluster = load_batch_cluster() index = vm_name_to_index(vm) vm = cluster.vms[index] if vm.remote_display == 'spice': opts_file = os.path.join(config.batch.cluster_state_dir, 'spice_vm{0}/console.vv'.format(index)) if print_opts: with open(opts_file, 'r') as f: print f.read() else: s_ctl = subprocess.Popen(['remote-viewer', opts_file]) ret = s_ctl.wait() sys.exit(ret) else: raise click.UsageError('VM has no valid remote display') except PcoccError as err: handle_error(err)
def pcocc_setup(action, jobid, nolock, force): # Dont load user config, we run as a privileged user config = Config() if not nolock: config.lock_node() # Always raise verbosity for setup processes config.verbose = max(config.verbose, 1) if (action != 'delete' and (jobid or force)): raise click.UsageError('this option can only be used with delete') if action == 'init': config.load(process_type=ProcessType.OTHER) config.batch.init_node() config.config_node() elif action == 'cleanup': config.load(process_type=ProcessType.OTHER) config.cleanup_node() elif action == 'create': config.load(process_type=ProcessType.SETUP) config.tracker.reclaim(config.batch.list_all_jobs()) config.batch.create_resources() cluster = Cluster(config.batch.cluster_definition, resource_only=True) cluster.alloc_node_resources() elif action == 'delete': config.load(jobid=jobid, process_type=ProcessType.SETUP) config.tracker.cleanup_ref(config.batch.batchid) config.batch.delete_resources(force) cluster = Cluster(config.batch.cluster_definition, resource_only=True) cluster.free_node_resources() if not nolock: config.release_node()
def pcocc_nc(jobid, jobname, user, nc_opts): """Connect to a VM via nc This requires the VM to have the selected port reverse NAT'ed to the host in its NAT network configuration. \b Example usage: pcocc nc vm1 80 """ try: load_config(jobid, jobname, default_batchname='pcocc', batchuser=user) cluster = load_batch_cluster() nc_opts = list(nc_opts) rgxp = r'^vm(\d+)$' if len(nc_opts) > 0 and re.match(rgxp, nc_opts[-1]): host_opts = [nc_opts[-1]] vm_index = int(re.match(rgxp, host_opts[-1]).group(1)) vm_port = 31337 last_opt = max(0, len(nc_opts) - 1) elif len(nc_opts) > 1 and re.match(rgxp, nc_opts[-2]): vm_index = int(re.match(rgxp, nc_opts[-2]).group(1)) try: vm_port = int(nc_opts[-1]) except ValueError: raise click.UsageError('Invalid port number {0}.'.format( nc_opts[-1])) last_opt = max(0, len(nc_opts) - 2) else: raise click.UsageError("Unable to parse vm name") remote_host = cluster.vms[vm_index].get_host() nc_port = find_vm_rnat_port(cluster, vm_index, vm_port) s_ctl = subprocess.Popen(['nc'] + nc_opts[0:last_opt] + [remote_host, nc_port]) ret = s_ctl.wait() sys.exit(ret) except PcoccError as err: handle_error(err)
def find_vm_ssh_opt(opts, regex, s_opts, v_opts, first_arg_only=True): """Parse ssh/scp arguments to find the remote vm hostname""" skip = False i = 0 for i, opt in enumerate(opts): if skip: skip = False continue if re.match(r'-[{0}]+$'.format(s_opts), opt): continue if opt in ["-" + o for o in v_opts]: skip = True continue match = re.search(regex, opt) if match: break if first_arg_only: raise click.UsageError("Unable to parse vm name") else: raise click.UsageError("Unable to parse vm name") return i, match
def display_manpage(page): try: if page == 'pcocc': p = subprocess.Popen(['man', page]) else: p = subprocess.Popen(['man', 'pcocc-' + page]) except: raise click.UsageError("No such help topic '" + page + "'\n" " use 'pcocc help' to list topics") signal.signal(signal.SIGINT, signal.SIG_IGN) p.communicate() signal.signal(signal.SIGINT, signal.SIG_DFL)
def load_config(batchid=None, batchname=None, batchuser=None, default_batchname=None, process_type=ProcessType.USER): if batchuser and (batchid is None) and (batchname is None): raise click.UsageError('the target job must be explicitely set ' 'when specifying a user') config = Config() config.load(jobid=batchid, jobname=batchname, batchuser=batchuser, default_jobname=default_batchname, process_type=process_type) config.load_user() return config
def vm_name_to_index(name): match = re.match(r'vm(\d+)$', name) if not match: raise click.UsageError("invalid vm name " + name) return int(match.group(1))