def runCommand(self): self.parseArgs(''' Marks active node idle which will cause varying actions based on the resource adapter associated with the given node. ''') # The "--node nodeName" option was implemented first # and we maintain backwards compatability for it. # The "nodeName..." arguments were added later. node_api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) try: results = node_api.idleNode(self.getArgs().nodeName) if results['NodeAlreadyIdle']: print(_('The following node(s) are already in idle state:')) print('\n'.join(results['NodeAlreadyIdle'])) if results['NodeSoftwareProfileLocked']: print( _('The following node(s) are locked and cannot be idled:')) print('\n'.join(results['NodeSoftwareProfileLocked'])) except Exception as msg: raise InvalidCliRequest(_("Can't idle node(s): {}").format(msg))
def runCommand(self): self.parseArgs() options = self.getArgs() if options.state and (options.bNotInstalled or options.bInstalled): raise InvalidCliRequest( '--state and --installed/--not-installed arguments are' ' mutually exclusive') api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) nodes: List[Dict[str, Any]] = [ dict(x) for x in api.getNodeList(nodespec=options.nodeName, tags=options.tags) ] if not nodes: if options.nodeName: print('No nodes matching nodespec [{}]\n'.format( options.nodeName)) sys.exit(1) if options.bInstalled: nodes = self.__filter_nodes(nodes, 'state', 'Installed') if options.bNotInstalled: nodes = self.__filter_nodes(nodes, 'state', 'Installed', True) if options.state: nodes = self.__filter_nodes(nodes, 'state', options.state) if options.softwareProfile: nodes = self.__filter_nodes(nodes, ['softwareprofile', 'name'], options.softwareProfile) if options.hardwareProfile: nodes = self.__filter_nodes(nodes, ['hardwareprofile', 'name'], options.hardwareProfile) if not options.showAll: nodes = self.__filter_nodes(nodes, 'state', 'Deleted', True) grouped: Dict[str, List[Dict[str, Any]]] = self.__group_nodes( nodes, options.bByHardwareProfile) if options.bShortOutput: output: Optional[str] = self.__make_short_output(grouped) elif options.bListOutput: output: Optional[str] = self.__make_list_output(nodes) else: output: Optional[str] = self.__make_full_output(grouped) if output: print(output)
def runCommand(self): self.parseArgs() node_api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) if (self.getArgs().nodeList and self.getArgs().nodeList[0] == '-') or \ (self.getArgs().nodes and self.getArgs().nodes[0] == '-'): # Perform bulk deletes, 100 nodes at a time nodes = [] for count, line in zip(itertools.count(1), sys.stdin.readlines()): nodes.append(line.rstrip()) if count % 100 == 0: node_api.deleteNode(','.join(nodes), force=self.getArgs().force) nodes = [] if nodes: node_api.deleteNode(','.join(nodes), force=self.getArgs().force) else: nodes = [] for nodespec in self.getArgs().nodes: nodes.extend(nodespec.split(',')) if self.getArgs().nodeList: nodes.append(self.getArgs().nodeList) node_api.deleteNode(','.join(nodes), force=self.getArgs().force)
def runCommand(self): self.parseArgs() self.node_wsapi = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) if self.getArgs().request_id: self._get_node_request(self.getArgs().request_id) raise SystemExit(0) for nr in self.node_wsapi.getNodeRequests(): self.__display_node_request(nr)
def __get_software_profile(self): # Determine software profile name based on command-line option(s) if self.getArgs().applyToInstaller: # Get software profile name from installer node node = NodeWsApi( username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify).getInstallerNode(optionDict={ 'softwareprofile': True, }) return node.getSoftwareProfile().getName() return self.getArgs().softwareprofile
def __get_software_profile_name(self): """ Returns software profile name based on command-line arguments or None, if not provided. """ if self.getArgs().applyToInstaller: nodeApi = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) node = nodeApi.getInstallerNode(optionDict={ 'softwareprofile': True, }) return node.getSoftwareProfile().getName() return self.getArgs().softwareProfileName
def runCommand(self): self.parseArgs() installer = self.getArgs().installer cm = ConfigManager() if ':' in installer: instHostName, instHostPort = installer.split(':') else: instHostName = installer instHostPort = cm.getAdminPort() base_url = f'https://{instHostName}:{instHostPort}' api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=base_url, verify=self._verify) fileContent = api.getProvisioningInfo( self.getArgs().nodeName).getXmlRep() # Load generated XML and update installer host name value dom = ET.fromstring(fileContent) # Override the installer host name with that provided on command-line if self.getArgs().installer: for elem in dom.findall('./globalparameter'): if elem.get('name') == 'Installer': elem.set('value', instHostName) # Generate file. rootMountPoint = self.getArgs().rootMountPoint niiProfileFile = ConfigManager().getProfileNiiFile() if rootMountPoint != '/': niiProfileFile = rootMountPoint + niiProfileFile dirPath = os.path.dirname(niiProfileFile) if not os.path.exists(dirPath): os.makedirs(dirPath) with open(niiProfileFile, 'w') as f: f.write(ET.tostring(dom, 'UTF-8').decode())
def runCommand(self): self.parseArgs(''' Transfer nodes from one software profile to another. This operation may need a reinstall of the node to apply the new software profile. ''') api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) api.transferNodes( self.getArgs().softwareProfileName, srcSoftwareProfile=self.getArgs().srcSoftwareProfileName, count=self.getArgs().count if not self.getArgs().nodespec else None, bForce=self.getArgs().force, nodespec=self.getArgs().nodespec, )
def runCommand(self): self.parseArgs(_('Shuts down the given node')) try: # Perform a "soft" shutdown NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify).shutdownNode( self.getArgs().nodeName, True) except Exception as msg: raise InvalidCliRequest(_("Can't shutdown node(s) - %s") % (msg))
def runCommand(self): self.parseArgs( _(""" Reboots specified node(s). Mark nodes for reinstallation if --reinstall flag is specified. """)) nodeApi = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) # If the node is being reinstalled as a result of the reboot, # do not use a soft shutdown. bSoftReboot = not self.getArgs().bReinstall try: nodeApi.rebootNode(self.getArgs().nodeSpec, bSoftReboot, bReinstall=self.getArgs().bReinstall) except Exception as msg: raise InvalidCliRequest(_("Can't reboot node(s) - %s") % (msg))
def runCommand(self): self.parseArgs() # Turn user input into a list destinationList = [ node.strip() for node in self.getArgs().destinationString.split(',') ] if self.getArgs().destinationString else [] try: NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify).startupNode( self.getArgs().nodeName, destinationList, self.getArgs().bootMethod) except Exception as msg: raise InvalidCliRequest(_("Unable to start node(s) - %s") % (msg))
def test_instantiation(): obj = NodeWsApi() assert obj
def runCommand(self): self.parseArgs() if not self.getArgs().name and \ not self.getArgs().hardwareProfileName: self.getParser().error( 'the following arguments are required: NAME') if self.getArgs().name and self.getArgs().hardwareProfileName: self.getParser().error( 'argument name: not allowed with argument --name') name = self.getArgs().name \ if self.getArgs().name else self.getArgs().hardwareProfileName api = HardwareProfileWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) spApi = SoftwareProfileWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) nodeApi = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) hp = api.getHardwareProfile(name, UpdateHardwareProfileCli.optionDict) if self.getArgs().newName is not None: hp.setName(self.getArgs().newName) if self.getArgs().description is not None: hp.setDescription(self.getArgs().description) if self.getArgs().nameFormat is not None: hp.setNameFormat(self.getArgs().nameFormat) if self.getArgs().kernel is not None: hp.setKernel(self.getArgs().kernel) if self.getArgs().kernelParameters is not None: hp.setKernelParams(self.getArgs().kernelParameters) if self.getArgs().initrd is not None: hp.setInitrd(self.getArgs().initrd) if self.getArgs().soAllowed is not None: if self.getArgs().soAllowed.lower() == _('true'): hp.setSoftwareOverrideAllowed(True) elif self.getArgs().soAllowed.lower() == _('false'): hp.setSoftwareOverrideAllowed(False) else: raise InvalidCliRequest( _('--software-override-allowed must be either "true" or' ' "false".')) if self.getArgs().idleProfile is not None and \ self.getArgs().bUnsetIdleProfile: raise InvalidCliRequest( _('Conflicting options --idle-software-profile and' ' --unset-idle-software-profile')) if self.getArgs().idleProfile is not None: sp = spApi.getSoftwareProfile(self.getArgs().idleProfile) hp.setIdleSoftwareProfileId(sp.getId()) if self.getArgs().bUnsetIdleProfile: hp.setIdleSoftwareProfileId(None) if self.getArgs().location is not None: hp.setLocation(self.getArgs().location) if self.getArgs().localBootParameters is not None: hp.setLocalBootParams(self.getArgs().localBootParameters) if self.getArgs().cost is not None: hp.setCost(self.getArgs().cost) if self.getArgs().resourceAdapter: resourceAdapter = ResourceAdapter( name=self.getArgs().resourceAdapter) hp.setResourceAdapter(resourceAdapter) if self.getArgs().default_adapter_config: hp.setDefaultResourceAdapterConfig( self.getArgs().default_adapter_config) if self.getArgs().deletePNic is not None: out = TortugaObjectList() for nic in hp.getProvisioningNics(): for dnic in self.getArgs().deletePNic: if dnic == nic.getIp(): # Skip over this item..its getting deleted break else: # Not a NIC we are deleting out.append(nic) hp.setProvisioningNics(out) if self.getArgs().addPNic is not None: for nicIp in self.getArgs().addPNic: nicsNode = nodeApi.getNodeByIp(nicIp) if nicsNode is not None: for nic in nicsNode.getNics(): if nic.getIp() == nicIp: hp.getProvisioningNics().append(nic) break if self.getArgs().deleteNetwork is not None: # Make sure we actually delete a network out = TortugaObjectList() out.extend(hp.getNetworks()) for netstring in self.getArgs().deleteNetwork: try: dnet, dmask, ddev = netstring.split('/') except ValueError: raise InvalidCliRequest( _('Incorrect input format for --delete-network' ' ("address/mask/device")')) for network in hp.getNetworks(): if dnet == network.getAddress() and \ dmask == network.getNetmask() and \ ddev == network.getNetworkDevice().getName(): # Skip over this item..its getting deleted for n in out: if n.getId() == network.getId(): out.remove(n) break break else: # Not a NIC we are deleting print('Ignoring deletion of non-existent network:' ' %s/%s/%s' % (dnet, dmask, ddev)) hp.setNetworks(out) if self.getArgs().addNetwork: for netstring in self.getArgs().addNetwork: try: anet, amask, adev = netstring.split('/') except ValueError: raise InvalidCliRequest( _('Incorrect input format for --add-network' ' ("address/mask/device")')) network = Network() networkDevice = NetworkDevice() networkDevice.setName(adev) network.setAddress(anet) network.setNetmask(amask) network.setNetworkDevice(networkDevice) hp.getNetworks().append(network) if self.getArgs().tags: tags = hp.getTags() tags.update(parse_tags(self.getArgs().tags)) hp.setTags(tags) if self.getArgs().remove_tags: tags = hp.getTags() for string in self.getArgs().remove_tags: for tag_name in string.split(','): if tag_name in tags.keys(): tags.pop(tag_name) hp.setTags(tags) api.updateHardwareProfile(hp)
def runCommand(self): self.parseArgs() if self.getArgs().hardwareProfile: hw_profile_api = HardwareProfileWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) hw_profile = hw_profile_api.getHardwareProfile( self.getArgs().hardwareProfile, { 'hardwareprofilenetworks': True }) if not hw_profile.getProvisioningNics(): print(yaml.dump({})) sys.exit(0) nic = hw_profile.getProvisioningNics()[0] data_dict = { 'device': nic.getNetworkDevice().getName(), 'ip': nic.getIp(), 'network': { 'address': nic.getNetwork().getAddress(), 'netmask': nic.getNetwork().getNetmask() } } if self.getArgs().bVerbose: print(yaml.safe_dump(data_dict)) else: print(yaml.safe_dump(nic.getNetworkDevice().getName())) else: # Display list of provisioning NICs on installer node_api = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) data_dict = {} for nic in node_api.getInstallerNode().getNics(): if nic.getNetwork().getType() != 'provision': continue device_name = nic.getNetworkDevice().getName() data_dict[device_name] = {} if self.getArgs().bVerbose: data_dict[device_name] = { 'ip': nic.getIp(), 'network': { 'address': nic.getNetwork().getAddress(), 'netmask': nic.getNetwork().getNetmask() } } if self.getArgs().bVerbose: print(yaml.safe_dump(data_dict)) else: print(yaml.safe_dump(list(data_dict.keys())))
class NodeManagedTags: managed_prefix = "managed:" managed_prefix_len = len(managed_prefix) node_api = NodeWsApi() env = {**os.environ, 'PATH': '/opt/tortuga/bin:' + os.environ['PATH'], 'TORTUGA_ROOT': '/opt/tortuga'} def __init__(self, script): self.script = script def update(self, update): previous_tags = update['previous_tags'] logger.warn("previous_tags={}".format(previous_tags)) previous_managed_tags = {i[self.managed_prefix_len:].replace(' ','_'):previous_tags[i].replace(' ','_') for i in previous_tags if i.startswith(self.managed_prefix)} tags = update['tags'] logger.warn("tags={}".format(tags)) managed_tags = {i[self.managed_prefix_len:].replace(' ','_'):tags[i].replace(' ','_') for i in tags if i.startswith(self.managed_prefix)} unmanaged_tags = ';'.join('{}:{}'.format(k.replace(' ','_'),v.replace(' ','_') if v is not None else 'None') for k,v in sorted({i:tags[i] for i in tags if not i.startswith(self.managed_prefix)}.items())) logger.warn('unmanaged_tags={}'.format(unmanaged_tags)) removed_tags = {k: previous_managed_tags[k] for k in set(previous_managed_tags) - set(managed_tags)} added_tags = {k: managed_tags[k] for k in set(managed_tags) - set(previous_managed_tags)} modified_tags = {k: managed_tags[k] for k in previous_managed_tags if k in managed_tags and managed_tags[k] != previous_managed_tags[k]} logger.warn('added_tags={}'.format(added_tags)) logger.warn('removed_tags={}'.format(removed_tags)) logger.warn('modified_tags={}'.format(modified_tags)) node = self.node_api.getNodeById(update['id']) software_profile = node.getSoftwareProfile() logger.warn('node={}, software_profile={}'.format(node, software_profile)) if software_profile['metadata'].get('uge'): for cluster in software_profile['metadata']['uge']['clusters']: cluster_name = cluster['name'] for setting in cluster['settings']: if setting['key'] == 'sge_root': uge_root = setting['value'] break cell_dir = os.path.join(uge_root, cluster_name) cmd = ('. {}/common/settings.sh; ' '{} ' '--software-profile {} ' '--cell-dir {} ' '{} {} {} {} {}'.format( cell_dir, self.script, software_profile['name'], cell_dir, '--added-tags ' + ','.join('{}={}'.format(k, v) for k, v in added_tags.items()) if added_tags else '', '--removed-tags ' + ','.join('{}={}'.format(k, v) for k, v in removed_tags.items()) if removed_tags else '', '--modified-tags ' + ','.join('{}={}'.format(k, v) for k, v in modified_tags.items()) if modified_tags else '', '--unmanaged-tags ' + '"' + unmanaged_tags + '"' if unmanaged_tags else '', '--node ' + node.getName())) logger.warn('Calling cmd: {}'.format(cmd)) p = tortugaSubprocess.TortugaSubprocess(cmd, env=self.env, useExceptions=False) p.run() logger.warn('stdout: {}'.format(p.getStdOut().decode().rstrip())) logger.warn('stderr: {}'.format(p.getStdErr().decode().rstrip())) es = p.getExitStatus() logger.warn('exit status: {}'.format(es)) if es != 0: raise CommandFailed(str(p.getStdErr().decode().rstrip())) else: logger.warn('Managed tagging supported only on UGE cluster, metadata: {}'.format(software_profile['metadata']))
class GetNodeRequestsCli(TortugaCli): def __init__(self): super(GetNodeRequestsCli, self).__init__() self.node_wsapi = None def parseArgs(self, usage=None): self.addOption('--request-id', '-r') super().parseArgs(usage=usage) def runCommand(self): self.parseArgs() self.node_wsapi = NodeWsApi(username=self.getUsername(), password=self.getPassword(), baseurl=self.getUrl(), verify=self._verify) if self.getArgs().request_id: self._get_node_request(self.getArgs().request_id) raise SystemExit(0) for nr in self.node_wsapi.getNodeRequests(): self.__display_node_request(nr) def __display_node_request(self, nr): \ # pylint: disable=no-self-use print(nr['addHostSession'], nr['timestamp'], nr['state'], nr['action']) if nr['state'] == 'error': print(' ' + nr['message']) else: print() def _get_node_request(self, request_id) -> None: node_requests = \ self.node_wsapi.getNodeRequests(addHostSession=request_id) if not node_requests: # Check for node nodes = self.node_wsapi.getNodeList(addHostSession=request_id) if nodes: sys.stdout.write( 'The following nodes were added successfully by' ' this request:\n%s' % ('\n'.join([node.getName() for node in nodes])) + '\n') sys.stdout.flush() sys.exit(0) else: sys.stderr.write('Error: node request [{0}] does not exist or' ' is invalid.\n'.format(request_id)) sys.exit(1) node_request = node_requests[0] request = json.loads(node_request['request']) if node_request['state'] == 'error': msg = ('Error attempting to add {} node(s) to hardware' ' profile [{}]'.format(request['count'], request['hardwareProfile'])) print(msg) print('Reported:', node_request['message']) else: self.__display_node_request(node_request)