alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 1 | # ================================================================================ |
Alex Shatov | ebc1a06 | 2019-01-31 16:07:48 -0500 | [diff] [blame] | 2 | # Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved. |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 3 | # ================================================================================ |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | # ============LICENSE_END========================================================= |
| 16 | # |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 17 | |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 18 | """web-server for policy_handler""" |
Alex Shatov | f53e5e7 | 2018-01-11 11:15:56 -0500 | [diff] [blame] | 19 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 20 | import json |
| 21 | from datetime import datetime |
Schmalzried, Terry (ts862m) | 05f475f | 2019-11-13 16:47:45 -0500 | [diff] [blame] | 22 | import os |
| 23 | import time |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 24 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 25 | import cherrypy |
| 26 | |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 27 | from . import pdp_client |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 28 | from .config import Config |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 29 | from .deploy_handler import PolicyUpdateMessage |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 30 | from .onap.audit import Audit, AuditHttpCode |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 31 | from .policy_receiver import PolicyReceiver |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 32 | from .utils import Utils |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 33 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 34 | |
| 35 | class PolicyWeb(object): |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 36 | """run http API of policy-handler on 0.0.0.0:wservice_port - any incoming address""" |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 37 | DATA_NOT_FOUND_ERROR = 404 |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 38 | HOST_INADDR_ANY = ".".join("0"*4) |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 39 | logger = Utils.get_logger(__file__) |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 40 | |
| 41 | @staticmethod |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 42 | def run_forever(audit): |
| 43 | """run the web-server of the policy-handler forever""" |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 44 | cherrypy.config.update({"server.socket_host": PolicyWeb.HOST_INADDR_ANY, |
| 45 | "server.socket_port": Config.wservice_port}) |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 46 | |
| 47 | protocol = "http" |
| 48 | tls_info = "" |
Schmalzried, Terry (ts862m) | 05f475f | 2019-11-13 16:47:45 -0500 | [diff] [blame] | 49 | if Config.tls_server_cert_file and Config.tls_private_key_file: |
| 50 | tm_cert = os.path.getmtime(Config.tls_server_cert_file) |
| 51 | tm_key = os.path.getmtime(Config.tls_private_key_file) |
| 52 | cherrypy.server.ssl_module = 'builtin' |
| 53 | cherrypy.server.ssl_certificate = Config.tls_server_cert_file |
| 54 | cherrypy.server.ssl_private_key = Config.tls_private_key_file |
| 55 | if Config.tls_server_ca_chain_file: |
| 56 | cherrypy.server.ssl_certificate_chain = Config.tls_server_ca_chain_file |
| 57 | protocol = "https" |
| 58 | tls_info = "cert: {} {} {}".format(Config.tls_server_cert_file, |
| 59 | Config.tls_private_key_file, |
| 60 | Config.tls_server_ca_chain_file) |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 61 | |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 62 | cherrypy.tree.mount(_PolicyWeb(), '/') |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 63 | |
| 64 | PolicyWeb.logger.info( |
| 65 | "%s with config: %s", audit.info("running policy_handler as {}://{}:{} {}".format( |
| 66 | protocol, cherrypy.server.socket_host, cherrypy.server.socket_port, tls_info)), |
| 67 | json.dumps(cherrypy.config)) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 68 | cherrypy.engine.start() |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 69 | |
Schmalzried, Terry (ts862m) | 05f475f | 2019-11-13 16:47:45 -0500 | [diff] [blame] | 70 | # If HTTPS server certificate changes, exit to let kubernetes restart us |
| 71 | if Config.tls_server_cert_file and Config.tls_private_key_file: |
| 72 | while True: |
| 73 | time.sleep(600) |
| 74 | c_tm_cert = os.path.getmtime(Config.tls_server_cert_file) |
| 75 | c_tm_key = os.path.getmtime(Config.tls_private_key_file) |
| 76 | if c_tm_cert > tm_cert or c_tm_key > tm_key: |
| 77 | PolicyWeb.logger.info("cert or key file updated") |
| 78 | cherrypy.engine.stop() |
| 79 | cherrypy.engine.exit() |
| 80 | break |
| 81 | |
| 82 | |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 83 | class _PolicyWeb(object): |
| 84 | """REST API of policy-handler""" |
| 85 | |
| 86 | @staticmethod |
| 87 | def _get_request_info(request): |
| 88 | """returns info about the http request""" |
| 89 | return "{0} {1}{2}".format(request.method, request.script_name, request.path_info) |
| 90 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 91 | @cherrypy.expose |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 92 | @cherrypy.popargs('policy_id') |
| 93 | @cherrypy.tools.json_out() |
| 94 | def policy_latest(self, policy_id): |
| 95 | """retireves the latest policy identified by policy_id""" |
| 96 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 97 | audit = Audit(job_name="get_latest_policy", |
| 98 | req_message=req_info, headers=cherrypy.request.headers) |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 99 | PolicyWeb.logger.info("%s policy_id=%s headers=%s", |
| 100 | req_info, policy_id, json.dumps(cherrypy.request.headers)) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 101 | |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 102 | latest_policy = pdp_client.PolicyRest.get_latest_policy( |
| 103 | (audit, policy_id, None, None)) or {} |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 104 | |
Alex Shatov | 2322ef8 | 2018-01-25 17:40:39 -0500 | [diff] [blame] | 105 | PolicyWeb.logger.info("res %s policy_id=%s latest_policy=%s", |
| 106 | req_info, policy_id, json.dumps(latest_policy)) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 107 | |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 108 | _, http_status_code, _ = audit.audit_done(result=json.dumps(latest_policy)) |
| 109 | if http_status_code == AuditHttpCode.DATA_NOT_FOUND_OK.value: |
| 110 | http_status_code = PolicyWeb.DATA_NOT_FOUND_ERROR |
| 111 | cherrypy.response.status = http_status_code |
Alex Shatov | 2322ef8 | 2018-01-25 17:40:39 -0500 | [diff] [blame] | 112 | |
| 113 | return latest_policy |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 114 | |
| 115 | def _get_all_policies_latest(self): |
| 116 | """retireves all the latest policies on GET /policies_latest""" |
| 117 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 118 | audit = Audit(job_name="get_all_policies_latest", |
| 119 | req_message=req_info, headers=cherrypy.request.headers) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 120 | |
| 121 | PolicyWeb.logger.info("%s", req_info) |
| 122 | |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 123 | result, policies, policy_filters = pdp_client.PolicyMatcher.get_deployed_policies(audit) |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 124 | if not result: |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 125 | result, policy_update = pdp_client.PolicyMatcher.build_catch_up_message( |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 126 | audit, policies, policy_filters) |
| 127 | if policy_update and isinstance(policy_update, PolicyUpdateMessage): |
| 128 | result["policy_update"] = policy_update.get_message() |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 129 | |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 130 | result_str = json.dumps(result, sort_keys=True) |
| 131 | PolicyWeb.logger.info("result %s: %s", req_info, result_str) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 132 | |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 133 | _, http_status_code, _ = audit.audit_done(result=result_str) |
| 134 | if http_status_code == AuditHttpCode.DATA_NOT_FOUND_OK.value: |
| 135 | http_status_code = PolicyWeb.DATA_NOT_FOUND_ERROR |
| 136 | cherrypy.response.status = http_status_code |
Alex Shatov | 2322ef8 | 2018-01-25 17:40:39 -0500 | [diff] [blame] | 137 | |
Alex Shatov | ac779d3 | 2018-02-01 14:16:56 -0500 | [diff] [blame] | 138 | return result |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 139 | |
| 140 | @cherrypy.expose |
| 141 | @cherrypy.tools.json_out() |
| 142 | @cherrypy.tools.json_in() |
| 143 | def policies_latest(self): |
| 144 | """ |
Alex Shatov | d7f34d4 | 2018-08-07 12:11:35 -0400 | [diff] [blame] | 145 | on :GET: retrieves all the latest policies from policy-engine that are deployed |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 146 | |
| 147 | on :POST: expects to receive the params that mimic the /getConfig of policy-engine |
| 148 | and retrieves the matching policies from policy-engine and picks the latest on each policy. |
| 149 | |
| 150 | sample request - policies filter |
| 151 | |
| 152 | { |
| 153 | "configAttributes": { "key1":"value1" }, |
| 154 | "configName": "alex_config_name", |
Alex Shatov | b9b955c | 2018-03-08 13:12:23 -0500 | [diff] [blame] | 155 | "onapName": "DCAE", |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 156 | "policyName": "DCAE_alex.Config_alex_.*", |
| 157 | "unique": false |
| 158 | } |
| 159 | |
| 160 | sample response |
| 161 | |
| 162 | { |
| 163 | "DCAE_alex.Config_alex_priority": { |
| 164 | "policy_body": { |
| 165 | "policyName": "DCAE_alex.Config_alex_priority.3.xml", |
| 166 | "policyConfigMessage": "Config Retrieved! ", |
| 167 | "responseAttributes": {}, |
| 168 | "policyConfigStatus": "CONFIG_RETRIEVED", |
| 169 | "type": "JSON", |
| 170 | "matchingConditions": { |
| 171 | "priority": "10", |
| 172 | "key1": "value1", |
Alex Shatov | b9b955c | 2018-03-08 13:12:23 -0500 | [diff] [blame] | 173 | "ONAPName": "DCAE", |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 174 | "ConfigName": "alex_config_name" |
| 175 | }, |
| 176 | "property": null, |
| 177 | "config": { |
| 178 | "foo": "bar", |
Alex Shatov | 2322ef8 | 2018-01-25 17:40:39 -0500 | [diff] [blame] | 179 | "foo_updated": "2018-10-06T16:54:31.696Z" |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 180 | }, |
| 181 | "policyVersion": "3" |
| 182 | }, |
| 183 | "policy_id": "DCAE_alex.Config_alex_priority" |
| 184 | } |
| 185 | } |
| 186 | """ |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 187 | if Config.is_pdp_api_default(): |
| 188 | raise cherrypy.HTTPError(404, "temporarily unsupported due to the new pdp API") |
| 189 | |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 190 | if cherrypy.request.method == "GET": |
| 191 | return self._get_all_policies_latest() |
| 192 | |
| 193 | if cherrypy.request.method != "POST": |
| 194 | raise cherrypy.HTTPError(404, "unexpected method {0}".format(cherrypy.request.method)) |
| 195 | |
| 196 | policy_filter = cherrypy.request.json or {} |
| 197 | str_policy_filter = json.dumps(policy_filter) |
| 198 | |
| 199 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 200 | audit = Audit(job_name="get_latest_policies", |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 201 | req_message="{0}: {1}".format(req_info, str_policy_filter), |
| 202 | headers=cherrypy.request.headers) |
| 203 | PolicyWeb.logger.info("%s: policy_filter=%s headers=%s", |
| 204 | req_info, str_policy_filter, json.dumps(cherrypy.request.headers)) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 205 | |
Alex Shatov | 9a4d3c5 | 2019-04-01 11:32:06 -0400 | [diff] [blame] | 206 | result = pdp_client.PolicyRest.get_latest_policies(audit, policy_filter=policy_filter) or {} |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 207 | result_str = json.dumps(result, sort_keys=True) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 208 | |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 209 | PolicyWeb.logger.info("result %s: policy_filter=%s result=%s", |
| 210 | req_info, str_policy_filter, result_str) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 211 | |
Alex Shatov | a39f4e8 | 2018-12-05 15:23:50 -0500 | [diff] [blame] | 212 | _, http_status_code, _ = audit.audit_done(result=result_str) |
| 213 | if http_status_code == AuditHttpCode.DATA_NOT_FOUND_OK.value: |
| 214 | http_status_code = PolicyWeb.DATA_NOT_FOUND_ERROR |
| 215 | cherrypy.response.status = http_status_code |
Alex Shatov | 2322ef8 | 2018-01-25 17:40:39 -0500 | [diff] [blame] | 216 | |
Alex Shatov | ac779d3 | 2018-02-01 14:16:56 -0500 | [diff] [blame] | 217 | return result |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 218 | |
| 219 | @cherrypy.expose |
| 220 | @cherrypy.tools.json_out() |
| 221 | def catch_up(self): |
| 222 | """catch up with all DCAE policies""" |
Alex Shatov | f2d7bef | 2018-05-10 09:23:16 -0400 | [diff] [blame] | 223 | started = str(datetime.utcnow()) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 224 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 225 | audit = Audit(job_name="catch_up", req_message=req_info, headers=cherrypy.request.headers) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 226 | |
| 227 | PolicyWeb.logger.info("%s", req_info) |
| 228 | PolicyReceiver.catch_up(audit) |
| 229 | |
Alex Shatov | ebc1a06 | 2019-01-31 16:07:48 -0500 | [diff] [blame] | 230 | res = {"catch-up requested": started, "request_id": audit.request_id} |
| 231 | PolicyWeb.logger.info("requested %s: %s", req_info, json.dumps(res)) |
| 232 | audit.info_requested(started) |
| 233 | return res |
| 234 | |
| 235 | @cherrypy.expose |
| 236 | @cherrypy.tools.json_out() |
| 237 | def reconfigure(self): |
| 238 | """schedule reconfigure""" |
| 239 | started = str(datetime.utcnow()) |
| 240 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
| 241 | audit = Audit(job_name="reconfigure", req_message=req_info, |
| 242 | headers=cherrypy.request.headers) |
| 243 | |
| 244 | PolicyWeb.logger.info("%s", req_info) |
| 245 | PolicyReceiver.reconfigure(audit) |
| 246 | |
| 247 | res = {"reconfigure requested": started, "request_id": audit.request_id} |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 248 | PolicyWeb.logger.info("requested %s: %s", req_info, json.dumps(res)) |
| 249 | audit.info_requested(started) |
| 250 | return res |
| 251 | |
| 252 | @cherrypy.expose |
| 253 | def shutdown(self): |
| 254 | """Shutdown the policy-handler""" |
| 255 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 256 | audit = Audit(job_name="shutdown", req_message=req_info, headers=cherrypy.request.headers) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 257 | |
| 258 | PolicyWeb.logger.info("%s: --- stopping REST API of policy-handler ---", req_info) |
| 259 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 260 | cherrypy.engine.exit() |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 261 | |
| 262 | PolicyReceiver.shutdown(audit) |
| 263 | |
Alex Shatov | f2d7bef | 2018-05-10 09:23:16 -0400 | [diff] [blame] | 264 | PolicyWeb.logger.info("policy_handler health: {0}" |
| 265 | .format(json.dumps(audit.health(full=True)))) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 266 | PolicyWeb.logger.info("%s: --------- the end -----------", req_info) |
Alex Shatov | f2d7bef | 2018-05-10 09:23:16 -0400 | [diff] [blame] | 267 | res = str(datetime.utcnow()) |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 268 | audit.info_requested(res) |
Alex Shatov | 5105258 | 2018-05-18 15:13:40 -0400 | [diff] [blame] | 269 | PolicyWeb.logger.info("process_info: %s", json.dumps(audit.process_info())) |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 270 | return "goodbye! shutdown requested {0}".format(res) |
| 271 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 272 | @cherrypy.expose |
| 273 | @cherrypy.tools.json_out() |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 274 | def healthcheck(self): |
| 275 | """returns the healthcheck results""" |
| 276 | req_info = _PolicyWeb._get_request_info(cherrypy.request) |
Alex Shatov | 50bed53 | 2018-04-27 11:53:55 -0400 | [diff] [blame] | 277 | audit = Audit(job_name="healthcheck", |
| 278 | req_message=req_info, headers=cherrypy.request.headers) |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 279 | |
| 280 | PolicyWeb.logger.info("%s", req_info) |
| 281 | |
Alex Shatov | f2d7bef | 2018-05-10 09:23:16 -0400 | [diff] [blame] | 282 | res = audit.health() |
Alex Shatov | 1369bea | 2018-01-10 11:00:50 -0500 | [diff] [blame] | 283 | |
| 284 | PolicyWeb.logger.info("healthcheck %s: res=%s", req_info, json.dumps(res)) |
| 285 | |
alex_sh | 9d980ce | 2017-08-23 17:30:56 -0400 | [diff] [blame] | 286 | audit.audit_done(result=json.dumps(res)) |
| 287 | return res |