From d5fa0606fc7f486a07484fe013077da28895a47f Mon Sep 17 00:00:00 2001 From: Komal Thareja <36123970+kthare10@users.noreply.github.com> Date: Mon, 10 Aug 2020 21:09:10 +0000 Subject: [PATCH] changes to handle geni-api w.r.t ticketreview and comet cert validation for enumerate --- .../xmlrpc/geni/GeniAmV2Handler.java | 9 ++- .../resources/scripts/comet_common_iface.py | 12 +-- .../resources/scripts/nova_essex_common.py | 56 +++++++++++-- .../resources/scripts/nova_essex_common.py | 81 ++++++++++++++----- 4 files changed, 124 insertions(+), 34 deletions(-) diff --git a/controllers/xmlrpc/src/main/java/orca/controllers/xmlrpc/geni/GeniAmV2Handler.java b/controllers/xmlrpc/src/main/java/orca/controllers/xmlrpc/geni/GeniAmV2Handler.java index 1d195a50f..284d2a579 100644 --- a/controllers/xmlrpc/src/main/java/orca/controllers/xmlrpc/geni/GeniAmV2Handler.java +++ b/controllers/xmlrpc/src/main/java/orca/controllers/xmlrpc/geni/GeniAmV2Handler.java @@ -807,7 +807,14 @@ public Map SliverStatus(String slice_urn, Object[] credentials, if (r.getState() == OrcaConstants.ReservationStateFailed) { en.put(ApiReturnFields.GENI_ERROR.name, (r.getNotices() != null ? r.getNotices() : "ERROR: no detailed error message available")); - } else { + } + else if (r.getState() == OrcaConstants.ReservationStateClosed && r.getNotices() != null && + r.getNotices().toLowerCase().contains("insufficient")) { + en.put(ApiReturnFields.GENI_ERROR.name, (r.getNotices() != null ? r.getNotices() + : "ERROR: no detailed error message available")); + en.put(ApiReturnFields.GENI_STATUS.name, GeniStates.FAILED.name); + } + else { en.put(ApiReturnFields.GENI_ERROR.name, ""); } // en.put(ApiReturnFields.ORCA_EXPIRES.name, (new Date(r.getEnd())).toString()); //ORCA reservation diff --git a/handlers/ec2/resources/scripts/comet_common_iface.py b/handlers/ec2/resources/scripts/comet_common_iface.py index f3177734c..7457a1960 100755 --- a/handlers/ec2/resources/scripts/comet_common_iface.py +++ b/handlers/ec2/resources/scripts/comet_common_iface.py @@ -62,10 +62,7 @@ def get_family(self, host, sliceId, rId, readToken, family): 'Key':rId, 'readToken':readToken } - if self._verify == False: - response = requests.get((host + '/readScope'), headers=self._headers(), params=params, verify=False) - else: - response = requests.get((host + '/readScope'), headers=self._headers(), params=params, cert= self._cert, verify=False) + response = requests.get((host + '/readScope'), headers=self._headers(), params=params, verify=False) self._log.debug ("get_family: Received Response Status Code: " + str(response.status_code)) if response.status_code == 200 : self._log.debug ("get_family: Received Response Message: " + response.json()["message"]) @@ -105,7 +102,7 @@ def delete_family(self, host, sliceId, rId, readToken, writeToken, family): if self._verify == False: response = requests.delete((host +'/deleteScope'), headers=self._headers(), params=params, verify=False) else: - response = requests.delete((host +'/deleteScope'), headers=self._headers(), params=params, cert= self._cert, verify=False) + response = requests.delete((host +'/deleteScope'), headers=self._headers(), params=params, cert= self._cert, verify=self._verify) self._log.debug ("delete_family: Received Response Status Code: " + str(response.status_code)) if response.status_code == 200 : self._log.debug ("delete_family: Received Response Message: " + response.json()["message"]) @@ -128,10 +125,7 @@ def enumerate_families(self, host, sliceId, readToken, family=None): 'family':family, } - if self._verify == False: - response = requests.get((host +'/enumerateScope'), headers=self._headers(), params=params, verify=False) - else: - response = requests.get((host +'/enumerateScope'), headers=self._headers(), params=params, cert= self._cert, verify=False) + response = requests.get((host +'/enumerateScope'), headers=self._headers(), params=params, verify=False) self._log.debug ("enumerate_families: Received Response Status Code: " + str(response.status_code)) if response.status_code == 200 : self._log.debug ("enumerate_families: Received Response Message: " + response.json()["message"]) diff --git a/handlers/ec2/resources/scripts/nova_essex_common.py b/handlers/ec2/resources/scripts/nova_essex_common.py index 7383bd1e6..935943ee3 100755 --- a/handlers/ec2/resources/scripts/nova_essex_common.py +++ b/handlers/ec2/resources/scripts/nova_essex_common.py @@ -6,6 +6,8 @@ import signal import time import traceback +import stat +import tempfile from os import kill from signal import alarm, signal, SIGALRM, SIGKILL from subprocess import * @@ -290,6 +292,53 @@ def create_project(self, project_name): return new_project_id + @classmethod + def atomic_output(self, file_contents, output_fname): + """ + Take a Python object and attempt to serialize it to JSON and write + the resulting bytes to an output file atomically. + + This function does not return a value and throws an exception on failure. + + :param output_object: A Python object to be serialized into JSON. + :param output_fname: A filename to write the object into. + :type output_fname: string + """ + + dir_name, file_name = os.path.split(output_fname) + + tmp_fd, tmp_file_name = tempfile.mkstemp(dir = dir_name, prefix=file_name) + try: + with os.fdopen(tmp_fd, 'w') as fp: + fp.write(file_contents) + + # atomically move new tokens in place + self.atomic_rename(tmp_file_name, output_fname) + + finally: + try: + os.unlink(tmp_file_name) + except OSError: + pass + + + @classmethod + def atomic_rename(self, tmp_file, target_file, mode=stat.S_IRUSR): + """ + If successful Credmgr will only be dealing with fully prepared and + usable credential cache files. + + :param tmp_file: The temp file path containing + the TGT acquired from the ngbauth service. + :type tmp_file: string + :param target_file: The target file. + :return: Whether the chmod/rename was successful. + :rtype: bool + """ + + os.chmod(tmp_file, mode) + os.rename(tmp_file, target_file) + @classmethod def generate_user_keystone_file(self, project_name, user_name, user_pwd, ec2_auth_url): @@ -569,13 +618,8 @@ def generate_key_file(self, user_name, ssh_key): time.sleep(4) return key_file - fd = None try: - fd = open(key_file, 'a+') - fd.seek(0) - fd.truncate() - fd.write(ssh_key) - fd.close + self.atomic_output(ssh_key, key_file) except Exception as e: LOG.error("Exception occured e=" + str(e)) raise Openstack_Command_Fail('failed to write to key file ' + key_file) diff --git a/handlers/providers/resources/scripts/nova_essex_common.py b/handlers/providers/resources/scripts/nova_essex_common.py index 228ceef11..935943ee3 100755 --- a/handlers/providers/resources/scripts/nova_essex_common.py +++ b/handlers/providers/resources/scripts/nova_essex_common.py @@ -6,6 +6,8 @@ import signal import time import traceback +import stat +import tempfile from os import kill from signal import alarm, signal, SIGALRM, SIGKILL from subprocess import * @@ -290,6 +292,53 @@ def create_project(self, project_name): return new_project_id + @classmethod + def atomic_output(self, file_contents, output_fname): + """ + Take a Python object and attempt to serialize it to JSON and write + the resulting bytes to an output file atomically. + + This function does not return a value and throws an exception on failure. + + :param output_object: A Python object to be serialized into JSON. + :param output_fname: A filename to write the object into. + :type output_fname: string + """ + + dir_name, file_name = os.path.split(output_fname) + + tmp_fd, tmp_file_name = tempfile.mkstemp(dir = dir_name, prefix=file_name) + try: + with os.fdopen(tmp_fd, 'w') as fp: + fp.write(file_contents) + + # atomically move new tokens in place + self.atomic_rename(tmp_file_name, output_fname) + + finally: + try: + os.unlink(tmp_file_name) + except OSError: + pass + + + @classmethod + def atomic_rename(self, tmp_file, target_file, mode=stat.S_IRUSR): + """ + If successful Credmgr will only be dealing with fully prepared and + usable credential cache files. + + :param tmp_file: The temp file path containing + the TGT acquired from the ngbauth service. + :type tmp_file: string + :param target_file: The target file. + :return: Whether the chmod/rename was successful. + :rtype: bool + """ + + os.chmod(tmp_file, mode) + os.rename(tmp_file, target_file) + @classmethod def generate_user_keystone_file(self, project_name, user_name, user_pwd, ec2_auth_url): @@ -569,13 +618,8 @@ def generate_key_file(self, user_name, ssh_key): time.sleep(4) return key_file - fd = None try: - fd = open(key_file, 'a+') - fd.seek(0) - fd.truncate() - fd.write(ssh_key) - fd.close + self.atomic_output(ssh_key, key_file) except Exception as e: LOG.error("Exception occured e=" + str(e)) raise Openstack_Command_Fail('failed to write to key file ' + key_file) @@ -783,20 +827,21 @@ def _has_resources(self, project_name): @classmethod def _has_resources_poll(self, project_name, timeout): + retry = 3 - begin = time.time() - while True: - time_passed = time.time() - begin - res = self._has_resources(project_name) - - if res == False: - LOG.warning("openstack project " + str(project_name) + " has no resources") - return False + res = True + for i in range(retry): + begin = time.time() + while True: + time_passed = time.time() - begin + res = self._has_resources(project_name) - if time_passed > timeout: - break - time.sleep(10) - return True + if time_passed > timeout: + break + time.sleep(10) + if res == False: + LOG.warning("openstack project " + str(project_name) + " has no resources") + return res @classmethod def cleanup(self, project_name, user_name):