From 27d54b3c460d303b802a68ec60b6661a719dd39b Mon Sep 17 00:00:00 2001 From: Scott Hussey Date: Wed, 18 Oct 2017 13:59:37 -0500 Subject: [PATCH] Add client access to enquiry API Add drydock client access to the enquiry API endpoint and CLI commands to access this endpoit. Use PrettyTable to output the data. Add a tox job for creating the frozen dependency list Change-Id: Ie1724052eb9ae9500e6b0df8f0c78e25ae0617f4 --- drydock_provisioner/cli/commands.py | 6 +- drydock_provisioner/cli/node/.actions.py.swp | Bin 0 -> 12288 bytes drydock_provisioner/cli/node/__init__.py | 0 drydock_provisioner/cli/node/actions.py | 32 +++++++++++ drydock_provisioner/cli/node/commands.py | 47 ++++++++++++++++ drydock_provisioner/drydock_client/client.py | 10 ++++ requirements-direct.txt | 1 + requirements-lock.txt | 56 ++++++++++--------- setup.py | 14 +---- tox.ini | 8 +++ 10 files changed, 134 insertions(+), 40 deletions(-) create mode 100644 drydock_provisioner/cli/node/.actions.py.swp create mode 100644 drydock_provisioner/cli/node/__init__.py create mode 100644 drydock_provisioner/cli/node/actions.py create mode 100644 drydock_provisioner/cli/node/commands.py diff --git a/drydock_provisioner/cli/commands.py b/drydock_provisioner/cli/commands.py index eb9bc155..75825a58 100644 --- a/drydock_provisioner/cli/commands.py +++ b/drydock_provisioner/cli/commands.py @@ -11,8 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" The entry point for the cli commands -""" +"""The entry point for the cli commands.""" import os import logging from urllib.parse import urlparse @@ -23,7 +22,7 @@ from drydock_provisioner.drydock_client.client import DrydockClient from .design import commands as design from .part import commands as part from .task import commands as task - +from .node import commands as node @click.group() @click.option( @@ -82,3 +81,4 @@ def drydock(ctx, debug, token, url): drydock.add_command(design.design) drydock.add_command(part.part) drydock.add_command(task.task) +drydock.add_command(node.node) diff --git a/drydock_provisioner/cli/node/.actions.py.swp b/drydock_provisioner/cli/node/.actions.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..0ddf5376c3a92f776acca4b3b0fe3a12c1c4d7c1 GIT binary patch literal 12288 zcmeHNOKclO7@pD>ukt7$#6#l8QE(zTb`tuMX@uOQP>bTAI7tZzS)29P9%a3|-C4&C zs30M6Lcoawk1MJ~%LxH@E(mVGffI-dREZN8P6#2snSBP^k!Z^Sv?G1?&dxvo{PX?) z{4-8weR{R}G#xD-Vkmbo_S{ET);dS_v)>OgCOgMwW@l8x&LxnWS{0t(GprNNxe?+o z2ZE(0-z@c9>3iJhmYUvH(=j)uWUt#5epGF^p0g>WaBS|COiPq(r^!o(>En$ox?3Yg z$X;g*WDE>tpy#)yjvZKebarN1wU6ZD2@W(;HuWDH~sWDH~sWDH~sWDH~s z{687+-CgVzOznnndS>{&>u=v-HT%jK$QZ~N$QZ~N$QZ~N$QZ~N$QZ~N$QZ~N$Qbw! zGGH_rTZ7%Z)E@xw|NrRs|7W)|_6Zd$fOmjXz;WPS;D=in`yTiLcprEVco(PxW55Hz{lISE%FWOP zTmW7JOrQcB27bPYu{VGj;JX_cI}eNl_W{4{hwZ?JfB_r__5xS-K_74tcndfStO6^* zgTPOF8M_2r1l|NXzzN_X;2z*^;LkmnBX9|L6?hgn1FQmf0>A8L>@x5p@G)=!SOpFO z`+&>f|8rmqSOr#q#{umZeE(~O!s2ni=h-B=)hZgUXyDQXxBX(9`wica8x!iIA)0eq zAgoL>)w#)ABAcWeU{U1bFbLs>%I0wei=j6J5Ha1`yNm( zd|_DPMc$;A<56VFxGdxgEE*$i7|lgONpsKT-o#|F(NO9djfrHE!8DYfTrL-PQ1!BF zct)3SRYlnCNM)J)4yTos>H;|}{j3Zk-yv}53BJjP=~xKvxy)-?DH*&>%g}~81&mWq zhSOA>nufaZQj8Tw1}e_unW&i;QYs6PrI9P5UihYpzC)v|m6~ELo0ssS;<(66%aD>H z7fit3pvPpHXpGz~OW1yynnD`u7N7GSXR5{fQ*LkF66REw`yHn#5v(9DF6!=1qa`e# zdqMc5UL@QraqZc_>w#qO+^~%BQc0{*f`KA6r&yD&BvLw-Q!F8#UrIO~Tr#;D zCmWnZlhGx+yT2aal%rI5kE*9GXq4+rwxrUT@T1Y=}V35Qt^$saf zQ5*!L&WS2}ntn7z!*!7t#@O!&v!habkmSf1 zsrLHrM#_J2(G;uoKBty6wxGBrdPv->MUv2t1cJcQ?ieMJB72lb%-N6ulKnSm9NbTX zBsP5K4Cz%qlVr3FVI%O3aD}CI&|q<2^By{4CyS0|aw5nwJDkIYB%c}9qX5;c+$wJ*sqk-z}F){eB-mXAHB$i;mYWVe3&0%F^lT{K;DVf>G9K@L1_3?8>c@kzD zw#lgv($bz%T!s45L{+qnQA>eVxu+aOu#YB`qjO=W+~i~0;Ca~RiFU`Q+3A_1R9Svx mnX0zWEsLA#8a_SaIoN0Xts+syvdGcC(>)Z!l6#xVaeo1Ta;zc% literal 0 HcmV?d00001 diff --git a/drydock_provisioner/cli/node/__init__.py b/drydock_provisioner/cli/node/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drydock_provisioner/cli/node/actions.py b/drydock_provisioner/cli/node/actions.py new file mode 100644 index 00000000..eadb797b --- /dev/null +++ b/drydock_provisioner/cli/node/actions.py @@ -0,0 +1,32 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" Actions related to task commands +""" + +from drydock_provisioner.cli.action import CliAction + + +class NodeList(CliAction): # pylint: disable=too-few-public-methods + """ Action to list tasks + """ + + def __init__(self, api_client): + """ + :param DrydockClient api_client: The api client used for invocation. + """ + super().__init__(api_client) + self.logger.debug('NodeList action initialized') + + def invoke(self): + return self.api_client.get_nodes() diff --git a/drydock_provisioner/cli/node/commands.py b/drydock_provisioner/cli/node/commands.py new file mode 100644 index 00000000..b8e9242c --- /dev/null +++ b/drydock_provisioner/cli/node/commands.py @@ -0,0 +1,47 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" cli.task.commands + Contains commands related to tasks against designs +""" +import click +import json + +from prettytable import PrettyTable + +from drydock_provisioner.cli.node.actions import NodeList + + +@click.group() +def node(): + """ Drydock node commands + """ + +@node.command(name='list') +@click.option('--output', '-o', help='Output format: table|json', default='table') +@click.pass_context +def node_list(ctx, output='table'): + """List nodes.""" + nodelist = NodeList(ctx.obj['CLIENT']).invoke() + + if output == 'table': + pt = PrettyTable() + + pt.field_names = ['Node Name', 'Status', 'CPUs', 'Memory', 'PXE MAC'] + + for n in nodelist: + pt.add_row([n['hostname'], n['status_name'], n['cpu_count'], n['memory'], n['boot_mac']]) + + click.echo(pt) + elif output == 'json': + click.echo(json.dumps(nodelist)) diff --git a/drydock_provisioner/drydock_client/client.py b/drydock_provisioner/drydock_client/client.py index 760e8f33..4ac34ee2 100644 --- a/drydock_provisioner/drydock_client/client.py +++ b/drydock_provisioner/drydock_client/client.py @@ -29,6 +29,16 @@ class DrydockClient(object): self.session = session self.logger = logging.getLogger(__name__) + def get_nodes(self): + """Get list of nodes in MaaS and their status.""" + endpoint = 'v1.0/nodes' + + resp = self.session.get(endpoint) + + self._check_response(resp) + + return resp.json() + def get_design_ids(self): """ Get list of Drydock design_ids diff --git a/requirements-direct.txt b/requirements-direct.txt index f56c82a0..844801ef 100644 --- a/requirements-direct.txt +++ b/requirements-direct.txt @@ -14,3 +14,4 @@ keystonemiddleware===4.9.1 oslo.policy===1.22.1 iso8601===0.1.11 keystoneauth1===2.13.0 +PTable==0.9.2 diff --git a/requirements-lock.txt b/requirements-lock.txt index c76954ce..28d09dfa 100644 --- a/requirements-lock.txt +++ b/requirements-lock.txt @@ -1,22 +1,22 @@ -amqp==2.2.1 -Babel==2.3.4 +amqp==2.2.2 +Babel==2.5.1 bson==0.4.7 -cachetools==2.0.0 +cachetools==2.0.1 certifi==2017.7.27.1 chardet==3.0.4 click==6.7 contextlib2==0.5.5 -debtcollector==1.17.0 +debtcollector==1.18.0 enum-compat==0.0.2 eventlet==0.20.0 -falcon==1.2.0 +falcon==1.3.0 fasteners==0.14.1 -futurist==1.3.0 +futurist==1.4.0 greenlet==0.4.12 -idna==2.5 +idna==2.6 iso8601==0.1.11 Jinja2==2.9.6 -keystoneauth1===2.13.0 +keystoneauth1==2.13.0 keystonemiddleware==4.9.1 kombu==4.1.0 MarkupSafe==1.0 @@ -24,26 +24,28 @@ monotonic==1.3 msgpack-python==0.4.8 netaddr==0.7.19 netifaces==0.10.6 -oauthlib==2.0.2 -oslo.concurrency==3.21.0 -oslo.config==4.11.0 -oslo.context==2.17.0 -oslo.i18n==3.17.0 -oslo.log==3.30.0 -oslo.messaging==5.30.0 -oslo.middleware==3.30.0 +oauthlib==2.0.4 +oslo.concurrency==3.23.0 +oslo.config==3.16.0 +oslo.context==2.19.1 +oslo.i18n==3.18.0 +oslo.log==3.31.0 +oslo.messaging==5.33.0 +oslo.middleware==3.32.1 oslo.policy==1.22.1 -oslo.serialization==2.20.0 -oslo.service==1.25.0 -oslo.utils==3.28.0 +oslo.serialization==2.21.1 +oslo.service==1.26.0 +oslo.utils==3.30.0 oslo.versionedobjects==1.23.0 Paste==2.0.3 PasteDeploy==1.5.2 pbr==3.1.1 -pika==0.10.0 +pika==0.11.0 pika-pool==0.1.3 -positional==1.1.2 +pip==9.0.1 +positional==1.2.1 prettytable==0.7.2 +PTable==0.9.2 pycadf==2.6.0 pycrypto==2.6.1 pyghmi==1.0.18 @@ -54,16 +56,18 @@ python-keystoneclient==3.13.0 python-mimeparse==1.6.0 pytz==2017.2 PyYAML==3.12 -repoze.lru==0.6 -requests==2.18.2 +repoze.lru==0.7 +requests==2.18.4 rfc3986==1.1.0 Routes==2.4.1 -six==1.10.0 +setuptools==36.6.0 +six==1.11.0 statsd==3.2.1 -stevedore==1.25.0 +stevedore==1.27.1 tenacity==4.4.0 urllib3==1.22 uWSGI==2.0.15 vine==1.1.4 WebOb==1.7.3 -wrapt==1.10.10 +wheel==0.30.0 +wrapt==1.10.11 diff --git a/setup.py b/setup.py index 9629e6f4..842939ab 100644 --- a/setup.py +++ b/setup.py @@ -17,9 +17,7 @@ # scripts from setuptools import setup -from sphinx.setup_command import BuildDoc -cmdclass = {'build_sphinx': BuildDoc} setup( @@ -43,7 +41,8 @@ setup( 'drydock_provisioner.drivers.node.maasdriver.models', 'drydock_provisioner.control', 'drydock_provisioner.cli', 'drydock_provisioner.cli.design', 'drydock_provisioner.cli.part', - 'drydock_provisioner.cli.task', 'drydock_provisioner.drydock_client' + 'drydock_provisioner.cli.task', 'drydock_provisioner.cli.node', + 'drydock_provisioner.drydock_client' ], entry_points={ 'oslo.config.opts': @@ -53,11 +52,4 @@ setup( 'console_scripts': 'drydock = drydock_provisioner.cli.commands:drydock' }, - cmdclass=cmdclass, - command_options={ - 'build_sphinx': { - 'source_dir': ('setup.py', 'docs/source'), - 'build_dir': ('setup.py', 'docs/build'), - 'all_files': ('setup.py', 1), - } - }) + ) diff --git a/tox.ini b/tox.ini index f791da4a..415e38c8 100644 --- a/tox.ini +++ b/tox.ini @@ -7,6 +7,14 @@ deps= -rrequirements-direct.txt -rrequirements-test.txt +[testenv:freeze] +whitelist_externals=rm +deps= + -rrequirements-direct.txt +commands= + rm requirements-lock.txt + sh -c "pip freeze --all | grep -v 'drydock-provisioner' > requirements-lock.txt" + [testenv:yapf] whitelist_externals=find commands=