Merge "Convert dib-request-list to image-status command"
This commit is contained in:
commit
b4e9e4a52c
@ -149,9 +149,9 @@ dib-image-list
|
|||||||
.. program-output:: nodepool dib-image-list --help
|
.. program-output:: nodepool dib-image-list --help
|
||||||
:nostderr:
|
:nostderr:
|
||||||
|
|
||||||
dib-request-list
|
image-status
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
.. program-output:: nodepool dib-request-list --help
|
.. program-output:: nodepool image-status --help
|
||||||
:nostderr:
|
:nostderr:
|
||||||
|
|
||||||
image-list
|
image-list
|
||||||
@ -396,9 +396,9 @@ launchers, all will provide the same information.
|
|||||||
:resheader Content-Type: ``application/json`` or ``text/plain``
|
:resheader Content-Type: ``application/json`` or ``text/plain``
|
||||||
depending on the :http:header:`Accept` header
|
depending on the :http:header:`Accept` header
|
||||||
|
|
||||||
.. http:get:: /dib-request-list
|
.. http:get:: /image-status
|
||||||
|
|
||||||
The status of manual build requests
|
The paused and manual build status of images
|
||||||
|
|
||||||
:query fields: comma-separated list of fields to display
|
:query fields: comma-separated list of fields to display
|
||||||
:reqheader Accept: ``application/json`` or ``text/*``
|
:reqheader Accept: ``application/json`` or ``text/*``
|
||||||
|
@ -61,10 +61,10 @@ class NodePoolCmd(NodepoolApp):
|
|||||||
help='list images built with diskimage-builder')
|
help='list images built with diskimage-builder')
|
||||||
cmd_dib_image_list.set_defaults(func=self.dib_image_list)
|
cmd_dib_image_list.set_defaults(func=self.dib_image_list)
|
||||||
|
|
||||||
cmd_dib_request_list = subparsers.add_parser(
|
cmd_image_status = subparsers.add_parser(
|
||||||
'dib-request-list',
|
'image-status',
|
||||||
help='list image build requests')
|
help='list image status')
|
||||||
cmd_dib_request_list.set_defaults(func=self.dib_request_list)
|
cmd_image_status.set_defaults(func=self.image_status)
|
||||||
|
|
||||||
cmd_image_build = subparsers.add_parser(
|
cmd_image_build = subparsers.add_parser(
|
||||||
'image-build',
|
'image-build',
|
||||||
@ -208,8 +208,8 @@ class NodePoolCmd(NodepoolApp):
|
|||||||
results = status.dib_image_list(self.zk)
|
results = status.dib_image_list(self.zk)
|
||||||
print(status.output(results, 'pretty'))
|
print(status.output(results, 'pretty'))
|
||||||
|
|
||||||
def dib_request_list(self):
|
def image_status(self):
|
||||||
results = status.dib_request_list(self.zk)
|
results = status.image_status(self.zk)
|
||||||
print(status.output(results, 'pretty'))
|
print(status.output(results, 'pretty'))
|
||||||
|
|
||||||
def image_list(self):
|
def image_list(self):
|
||||||
@ -431,7 +431,7 @@ class NodePoolCmd(NodepoolApp):
|
|||||||
|
|
||||||
# commands needing ZooKeeper
|
# commands needing ZooKeeper
|
||||||
if self.args.command in ('image-build', 'dib-image-list',
|
if self.args.command in ('image-build', 'dib-image-list',
|
||||||
'dib-request-list',
|
'image-status',
|
||||||
'image-list', 'dib-image-delete',
|
'image-list', 'dib-image-delete',
|
||||||
'image-delete', 'alien-image-list',
|
'image-delete', 'alien-image-list',
|
||||||
'list', 'delete',
|
'list', 'delete',
|
||||||
|
@ -71,7 +71,7 @@ def _to_pretty_table(objs, headers_table, fields):
|
|||||||
for k in headers_table:
|
for k in headers_table:
|
||||||
if fields and k not in fields:
|
if fields and k not in fields:
|
||||||
continue
|
continue
|
||||||
if k == 'age':
|
if k == 'age' or k.endswith('_age') and obj[k] is not None:
|
||||||
try:
|
try:
|
||||||
obj_age = age(int(obj[k]))
|
obj_age = age(int(obj[k]))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -81,6 +81,8 @@ def _to_pretty_table(objs, headers_table, fields):
|
|||||||
else:
|
else:
|
||||||
if isinstance(obj[k], list):
|
if isinstance(obj[k], list):
|
||||||
values.append(','.join(obj[k]))
|
values.append(','.join(obj[k]))
|
||||||
|
elif obj[k] is None:
|
||||||
|
values.append('')
|
||||||
else:
|
else:
|
||||||
values.append(obj[k])
|
values.append(obj[k])
|
||||||
t.add_row(values)
|
t.add_row(values)
|
||||||
@ -202,21 +204,28 @@ def dib_image_list(zk):
|
|||||||
return (objs, headers_table)
|
return (objs, headers_table)
|
||||||
|
|
||||||
|
|
||||||
def dib_request_list(zk):
|
def image_status(zk):
|
||||||
headers_table = OrderedDict([
|
headers_table = OrderedDict([
|
||||||
("image", "Image"),
|
("image", "Image"),
|
||||||
("state", "State"),
|
("paused", "Paused"),
|
||||||
("age", "Age")
|
("build_request", "Build Request"),
|
||||||
|
("build_request_age", "Build Request Age")
|
||||||
])
|
])
|
||||||
objs = []
|
objs = []
|
||||||
for image_name in zk.getImageNames():
|
for image_name in zk.getImageNames():
|
||||||
request = zk.getBuildRequest(image_name)
|
request = zk.getBuildRequest(image_name)
|
||||||
if request is None:
|
paused = zk.getImagePaused(image_name)
|
||||||
continue
|
if request:
|
||||||
|
age = int(request.state_time)
|
||||||
|
req = 'pending' if request.pending else 'building'
|
||||||
|
else:
|
||||||
|
age = None
|
||||||
|
req = None
|
||||||
objs.append({
|
objs.append({
|
||||||
"image": request.image_name,
|
"image": image_name,
|
||||||
"state": "pending" if request.pending else "building",
|
"paused": bool(paused),
|
||||||
"age": int(request.state_time)
|
"build_request": req,
|
||||||
|
"build_request_age": age,
|
||||||
})
|
})
|
||||||
return (objs, headers_table)
|
return (objs, headers_table)
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ class TestNodepoolCMD(tests.DBTestCase):
|
|||||||
nodepoolcmd.main()
|
nodepoolcmd.main()
|
||||||
self.assert_listed(configfile, ['dib-image-list'], 4, zk.READY, 1)
|
self.assert_listed(configfile, ['dib-image-list'], 4, zk.READY, 1)
|
||||||
|
|
||||||
def test_dib_request_list(self):
|
def test_image_status(self):
|
||||||
configfile = self.setup_config('node.yaml')
|
configfile = self.setup_config('node.yaml')
|
||||||
builder = self.useBuilder(configfile)
|
builder = self.useBuilder(configfile)
|
||||||
# Make sure we have enough time to test for the build request
|
# Make sure we have enough time to test for the build request
|
||||||
@ -202,7 +202,7 @@ class TestNodepoolCMD(tests.DBTestCase):
|
|||||||
worker._interval = 60
|
worker._interval = 60
|
||||||
self.waitForImage('fake-provider', 'fake-image')
|
self.waitForImage('fake-provider', 'fake-image')
|
||||||
self.zk.submitBuildRequest("fake-image")
|
self.zk.submitBuildRequest("fake-image")
|
||||||
self.assert_listed(configfile, ['dib-request-list'],
|
self.assert_listed(configfile, ['image-status'],
|
||||||
0, 'fake-image', 1)
|
0, 'fake-image', 1)
|
||||||
|
|
||||||
def test_dib_image_build_pause(self):
|
def test_dib_image_build_pause(self):
|
||||||
|
@ -138,7 +138,7 @@ class TestWebApp(tests.DBTestCase):
|
|||||||
'formats': ['qcow2'],
|
'formats': ['qcow2'],
|
||||||
'state': 'ready'}, objs[0])
|
'state': 'ready'}, objs[0])
|
||||||
|
|
||||||
def test_dib_request_list_json(self):
|
def test_image_status_json(self):
|
||||||
configfile = self.setup_config("node.yaml")
|
configfile = self.setup_config("node.yaml")
|
||||||
pool = self.useNodepool(configfile, watermark_sleep=1)
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
builder = self.useBuilder(configfile)
|
builder = self.useBuilder(configfile)
|
||||||
@ -155,10 +155,8 @@ class TestWebApp(tests.DBTestCase):
|
|||||||
self.waitForImage("fake-provider", "fake-image")
|
self.waitForImage("fake-provider", "fake-image")
|
||||||
self.waitForNodes('fake-label')
|
self.waitForNodes('fake-label')
|
||||||
|
|
||||||
self.zk.submitBuildRequest("fake-image")
|
|
||||||
|
|
||||||
req = request.Request(
|
req = request.Request(
|
||||||
"http://localhost:{}/dib-request-list".format(port))
|
"http://localhost:{}/image-status".format(port))
|
||||||
req.add_header("Accept", "application/json")
|
req.add_header("Accept", "application/json")
|
||||||
|
|
||||||
f = request.urlopen(req)
|
f = request.urlopen(req)
|
||||||
@ -168,7 +166,18 @@ class TestWebApp(tests.DBTestCase):
|
|||||||
data = f.read()
|
data = f.read()
|
||||||
objs = json.loads(data.decode("utf8"))
|
objs = json.loads(data.decode("utf8"))
|
||||||
self.assertDictContainsSubset({"image": "fake-image",
|
self.assertDictContainsSubset({"image": "fake-image",
|
||||||
"state": "pending"}, objs[0])
|
"paused": False,
|
||||||
|
"build_request": None}, objs[0])
|
||||||
|
|
||||||
|
self.zk.submitBuildRequest("fake-image")
|
||||||
|
|
||||||
|
webapp.cache.cache.clear()
|
||||||
|
f = request.urlopen(req)
|
||||||
|
data = f.read()
|
||||||
|
objs = json.loads(data.decode("utf8"))
|
||||||
|
self.assertDictContainsSubset({"image": "fake-image",
|
||||||
|
"paused": False,
|
||||||
|
"build_request": "pending"}, objs[0])
|
||||||
|
|
||||||
webapp.cache.cache.clear()
|
webapp.cache.cache.clear()
|
||||||
with self.zk.imageBuildLock('fake-image', blocking=True, timeout=1):
|
with self.zk.imageBuildLock('fake-image', blocking=True, timeout=1):
|
||||||
@ -177,7 +186,8 @@ class TestWebApp(tests.DBTestCase):
|
|||||||
|
|
||||||
objs = json.loads(data.decode("utf8"))
|
objs = json.loads(data.decode("utf8"))
|
||||||
self.assertDictContainsSubset({"image": "fake-image",
|
self.assertDictContainsSubset({"image": "fake-image",
|
||||||
"state": "building"}, objs[0])
|
"paused": False,
|
||||||
|
"build_request": "building"}, objs[0])
|
||||||
|
|
||||||
def test_node_list_json(self):
|
def test_node_list_json(self):
|
||||||
configfile = self.setup_config('node.yaml')
|
configfile = self.setup_config('node.yaml')
|
||||||
|
@ -101,8 +101,8 @@ class WebApp(threading.Thread):
|
|||||||
results = status.image_list(zk)
|
results = status.image_list(zk)
|
||||||
elif path == '/dib-image-list':
|
elif path == '/dib-image-list':
|
||||||
results = status.dib_image_list(zk)
|
results = status.dib_image_list(zk)
|
||||||
elif path == '/dib-request-list':
|
elif path == '/image-status':
|
||||||
results = status.dib_request_list(zk)
|
results = status.image_status(zk)
|
||||||
elif path == '/node-list':
|
elif path == '/node-list':
|
||||||
results = status.node_list(zk,
|
results = status.node_list(zk,
|
||||||
node_id=params.get('node_id'))
|
node_id=params.get('node_id'))
|
||||||
|
7
releasenotes/notes/image-status-bedca1dd0184c14b.yaml
Normal file
7
releasenotes/notes/image-status-bedca1dd0184c14b.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
A new `image-status` command and accompanying web endpoint are
|
||||||
|
available to easily see what images have been paused via the
|
||||||
|
`image-pause` command and have pending manual build requests via
|
||||||
|
the `build-image` command.
|
Loading…
Reference in New Issue
Block a user