Beispiel #1
0
    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))
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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)
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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())
Beispiel #8
0
    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,
        )
Beispiel #9
0
    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))
Beispiel #10
0
    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))
Beispiel #11
0
    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))
Beispiel #12
0
def test_instantiation():
    obj = NodeWsApi()

    assert obj
Beispiel #13
0
    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())))
Beispiel #15
0
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']))
Beispiel #16
0
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)