diff --git a/confluent_client/bin/nodedeploy b/confluent_client/bin/nodedeploy index 79afa33f..477063d4 100755 --- a/confluent_client/bin/nodedeploy +++ b/confluent_client/bin/nodedeploy @@ -52,7 +52,7 @@ def setpending(nr, profile, profilebynodes, cli): if profilebynodes: for node in sortutil.natural_sort(profilebynodes): prof = profilebynodes[node] - args = {'deployment.pendingprofile': prof, 'deployment.state': '', 'deployment.state_detail': ''} + args = {'deployment.pendingprofile': prof, 'deployment.state': '', 'deployment.state_detail': '', 'deployment.state_last_updated': ''} if not prof.startswith('genesis-'): args['deployment.stagedprofile'] = '' args['deployment.profile'] = '' @@ -60,7 +60,7 @@ def setpending(nr, profile, profilebynodes, cli): args): pass return - args = {'deployment.pendingprofile': profile, 'deployment.state': '', 'deployment.state_detail': ''} + args = {'deployment.pendingprofile': profile, 'deployment.state': '', 'deployment.state_detail': '', 'deployment.state_last_updated': ''} if not profile.startswith('genesis-'): args['deployment.stagedprofile'] = '' args['deployment.profile'] = '' @@ -179,7 +179,7 @@ def main(args): if node not in databynode: databynode[node] = {} for attr in dbn[node]: - if attr in ('deployment.pendingprofile', 'deployment.apiarmed', 'deployment.stagedprofile', 'deployment.profile', 'deployment.state', 'deployment.state_detail'): + if attr in ('deployment.pendingprofile', 'deployment.apiarmed', 'deployment.stagedprofile', 'deployment.profile', 'deployment.state', 'deployment.state_detail', 'deployment.state_last_updated'): databynode[node][attr] = dbn[node][attr].get('value', '') for node in sortutil.natural_sort(databynode): profile = databynode[node].get('deployment.pendingprofile', '') @@ -203,11 +203,14 @@ def main(args): stateinfo = '' deploymentstate = databynode[node].get('deployment.state', '') if deploymentstate: + deploymentdate = databynode[node].get('deployment.state_last_updated', '') statedetails = databynode[node].get('deployment.state_detail', '') if statedetails: stateinfo = '{}: {}'.format(deploymentstate, statedetails) else: stateinfo = deploymentstate + if deploymentdate: + stateinfo += ' (last updated: {})'.format(deploymentdate) if stateinfo: print('{0}: {1} ({2})'.format(node, profile, stateinfo)) else: diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index 06f430ed..75999910 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -252,6 +252,9 @@ node = { 'deployment.state_detail': { 'description': ('Detailed state information as reported by an OS profile, when available'), }, + 'deployment.state_last_updated': { + 'description': ('Timestamp of last state change, as reported by an OS profile, when available'), + }, 'deployment.useinsecureprotocols': { 'description': ('What phase(s) of boot are permitted to use insecure protocols ' '(TFTP and HTTP without TLS. By default, only HTTPS is used. However ' diff --git a/confluent_server/confluent/selfservice.py b/confluent_server/confluent/selfservice.py index 2d20586c..bb2fa14f 100644 --- a/confluent_server/confluent/selfservice.py +++ b/confluent_server/confluent/selfservice.py @@ -466,17 +466,18 @@ async def handle_request(req, make_response, mimetype): update = yamlload(reqbody) statusstr = update.get('state', None) statusdetail = update.get('state_detail', None) - didstateupdate = False if statusstr or 'status' in update: await cfg.set_node_attributes({nodename: { 'deployment.client_ip': {'value': clientip}}}) + stateupdate = {} if statusstr: - await cfg.set_node_attributes({nodename: {'deployment.state': statusstr}}) - didstateupdate = True + stateupdate['deployment.state'] = statusstr if statusdetail: - await cfg.set_node_attributes({nodename: {'deployment.state_detail': statusdetail}}) - didstateupdate = True - if 'status' not in update and didstateupdate: + stateupdate['deployment.state_detail'] = statusdetail + if stateupdate: + stateupdate['deployment.state_last_updated'] = time.strftime('%Y-%m-%dT%H:%M:%S%z', time.localtime()) + await cfg.set_node_attributes({nodename: stateupdate}) + if 'status' not in update and stateupdate: mrsp = await make_response(mimetype, 200, 'Ok') await mrsp.write(b'Accepted') return