diff --git a/devnest/lib/cli.py b/devnest/lib/cli.py index b36a0ff..4bc2b76 100755 --- a/devnest/lib/cli.py +++ b/devnest/lib/cli.py @@ -45,7 +45,7 @@ class Action(object): """Enumeration for the CLI Action.""" - (LIST, RELEASE, RESERVE, GROUP, CAPABILITIES, SETUP, EXTEND, DUMP) = range(8) + (DISCONNECT, LIST, RELEASE, RESERVE, GROUP, CAPABILITIES, SETUP, EXTEND, DUMP) = range(9) class Columns(object): @@ -139,7 +139,7 @@ def get_base_parser(self): parser = argparse.ArgumentParser(prog='devnest', parents=[config_group], description='CLI to reserve, release' - ' or manage hardware in DevNest.', + ' or manage nodes in DevNest.', formatter_class=formatter, add_help=False) @@ -175,6 +175,12 @@ def get_base_parser(self): action='store_true', help=argparse.SUPPRESS) + disconnect_parser = subparsers.add_parser('disconnect', + parents=[node_parser, nest_parser], + formatter_class=formatter, + help='disconnect node(s) from Jenkins master') + disconnect_parser.set_defaults(action=Action.DISCONNECT) + list_parser = subparsers.add_parser('list', parents=[node_parser, nest_parser], formatter_class=formatter, @@ -379,6 +385,17 @@ def main(self, argv): jenkins_obj = JenkinsInstance(parser_args.url, parser_args.user, parser_args.password, parser_args.conf) + # disconnect nodes from Jenkins master + if parser_args.action is Action.DISCONNECT: + group = parser_args.group + if parser_args.all: + group = None + + jenkins_nodes = jenkins_obj.get_nodes(parser_args.node_regex, group) + + for jenkins_node in jenkins_nodes: + jenkins_node = jenkins_node.disconnect() + # List nodes if parser_args.action is Action.LIST: group = parser_args.group @@ -450,10 +467,11 @@ def main(self, argv): if reserve_node.get_node_status() == NodeStatus.JOB_RUNNING and \ not parser_args.force: - err_msg = "Node %s is currently running CI job. Use --force flag " \ - "to reserve the node.\n\tAfter doing so, use:\n\t" \ - " $ devnest list -g %s %s\n\tTo check if " \ - "CI job is finished and you can use it - node "\ + err_msg = "A CI job is is currently running on %s node. Use --force flag " \ + "to reserve the node.\n\tIt will be reserved and available once the currently \ " \ + "running CI job finishes\n\tUse:\n\t" \ + " $ devnest list -g %s %s\n\tto check if " \ + "CI job has finished and you can use it, if so the node "\ "status will become reserved.\n\tThis may take even few hours!" \ "\n\tMore details about current node usage is available at:" \ "\n\t %s" \ @@ -467,7 +485,7 @@ def main(self, argv): not parser_args.force: err_msg = "Node %s is not online and can not be reserved. " \ % reserve_node.get_name() - err_msg += "Node status: %s. Try release the node." \ + err_msg += "Node status: %s. Try releasing the node." \ % reserve_node.get_node_status_str() raise CommandError(err_msg) diff --git a/devnest/lib/node.py b/devnest/lib/node.py index c42d59d..d5f075c 100755 --- a/devnest/lib/node.py +++ b/devnest/lib/node.py @@ -770,6 +770,15 @@ def get_node_config_xml(self): self._set_node_config() return self._config + def disconnect(self, msg='disconnected_by_devnest'): + """Disconnect the node from Jenkins master + """ + node_url = self.get_node_url() + + LOG.info('Disconnecting %s from Jenkins master' % self.node_name) + + self.jenkins.requester.post_and_confirm_status("%s/doDisconnect?offlineMessage=%s" % (node_url, msg), data={} ) + def _update_node_with_node_details(self, node_details): """Update node with NodeDetails data.