From 546a7c251f6e0ad57f28f78939c349d7a0722c8f Mon Sep 17 00:00:00 2001 From: Bart Wensley Date: Tue, 5 Nov 2019 14:26:34 -0600 Subject: [PATCH] Add patch API to determine if patches are available Adding a new patch API to determine if a patch (or list of patches) is in the available state. This is necessary to support kubernetes upgrades, which will require certain patches to be available before a kubernetes upgrade is started. Change-Id: I13de8385c59dd15550cee646b3ed9b90d2a7e379 Story: 2006590 Task: 37370 Signed-off-by: Bart Wensley --- cgcs-patch/bin/sw-patch.completion | 3 +- .../cgcs_patch/api/controllers/root.py | 4 +++ .../cgcs-patch/cgcs_patch/patch_client.py | 31 +++++++++++++++++++ .../cgcs-patch/cgcs_patch/patch_controller.py | 19 ++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/cgcs-patch/bin/sw-patch.completion b/cgcs-patch/bin/sw-patch.completion index 59c55297..c4b1ec33 100644 --- a/cgcs-patch/bin/sw-patch.completion +++ b/cgcs-patch/bin/sw-patch.completion @@ -32,6 +32,7 @@ function _swpatch() what-requires drop-host is-applied + is-available report-app-dependencies query-app-dependencies " @@ -51,7 +52,7 @@ function _swpatch() # Complete the arguments to the subcommands. # case "$subcommand" in - apply|delete|show|what-requires|is-applied) + apply|delete|show|what-requires|is-applied|is-available) # Query the list of known patches local patches=$(sw-patch completion patches 2>/dev/null) COMPREPLY=( $(compgen -W "${patches}" -- ${cur}) ) diff --git a/cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py b/cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py index 6ed28c3b..f1e0262d 100644 --- a/cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py +++ b/cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py @@ -262,6 +262,10 @@ class PatchAPIController(object): def is_applied(self, *args): return pc.is_applied(list(args)) + @expose('json') + def is_available(self, *args): + return pc.is_available(list(args)) + @expose('json') def report_app_dependencies(self, *args, **kwargs): try: diff --git a/cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py b/cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py index 20ab3890..ace24ad9 100644 --- a/cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py +++ b/cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py @@ -62,6 +62,8 @@ help_query_dependencies = "List dependencies for specified patch. Use " + \ constants.CLI_OPT_RECURSIVE + " for recursive query." help_is_applied = "Query Applied state for list of patches. " + \ "Returns True if all are Applied, False otherwise." +help_is_available = "Query Available state for list of patches. " + \ + "Returns True if all are Available, False otherwise." help_report_app_dependencies = "Report application patch dependencies, " + \ "specifying application name with --app option, plus a list of patches. " + \ "Reported dependencies can be dropped by specifying app with no patch list." @@ -142,6 +144,9 @@ def print_help(): print(textwrap.fill(" {0:<15} ".format("is-applied:") + help_is_applied, width=TERM_WIDTH, subsequent_indent=' ' * 20)) print("") + print(textwrap.fill(" {0:<15} ".format("is-available:") + help_is_available, + width=TERM_WIDTH, subsequent_indent=' ' * 20)) + print("") print(textwrap.fill(" {0:<15} ".format("report-app-dependencies:") + help_report_app_dependencies, width=TERM_WIDTH, subsequent_indent=' ' * 20)) print("") @@ -1176,6 +1181,30 @@ def patch_is_applied_req(args): return rc +def patch_is_available_req(args): + if len(args) == 0: + print_help() + + patches = "/".join(args) + url = "http://%s/patch/is_available/%s" % (api_addr, patches) + + headers = {} + append_auth_token_if_required(headers) + req = requests.post(url, headers=headers) + + rc = 1 + + if req.status_code == 200: + result = json.loads(req.text) + print(result) + if result is True: + rc = 0 + elif req.status_code == 500: + print("An internal error has occurred. Please check /var/log/patching.log for details") + + return rc + + def patch_report_app_dependencies_req(debug, args): if len(args) < 2: print_help() @@ -1460,6 +1489,8 @@ def main(): rc = patch_del_release(debug, sys.argv[2:]) elif action == "is-applied": rc = patch_is_applied_req(sys.argv[2:]) + elif action == "is-available": + rc = patch_is_available_req(sys.argv[2:]) elif action == "report-app-dependencies": rc = patch_report_app_dependencies_req(debug, sys.argv[2:]) elif action == "query-app-dependencies": diff --git a/cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py b/cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py index 4cbdef09..1ba8f5e0 100644 --- a/cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py +++ b/cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py @@ -2244,6 +2244,25 @@ class PatchController(PatchService): return all_applied + def is_available(self, patch_ids): + all_available = True + + self.patch_data_lock.acquire() + + for patch_id in patch_ids: + if patch_id not in self.patch_data.metadata: + all_available = False + break + + if self.patch_data.metadata[patch_id]["patchstate"] != \ + constants.AVAILABLE: + all_available = False + break + + self.patch_data_lock.release() + + return all_available + def report_app_dependencies(self, patch_ids, **kwargs): """ Handle report of application dependencies