def verify_health(self, timeout=60, interval=5): """ Health verification function that tries to verify the a bucket's health by using its appropriate internal_verify_health function until a given time limit is reached Args: timeout (int): Timeout for the check, in seconds interval (int): Interval to wait between checks, in seconds """ logger.info(f"Waiting for {self.name} to be healthy") try: for health_check in TimeoutSampler(timeout, interval, self.internal_verify_health): if health_check: logger.info(f"{self.name} is healthy") break else: logger.info(f"{self.name} is unhealthy. Rechecking.") except TimeoutExpiredError: logger.error( f"{self.name} did not reach a healthy state within {timeout} seconds." ) obc_obj = OCP(kind="obc", namespace=self.namespace, resource_name=self.name) obc_yaml = obc_obj.get() obc_description = obc_obj.describe(resource_name=self.name) raise UnhealthyBucket( f"{self.name} did not reach a healthy state within {timeout} seconds.\n" f"OBC YAML:\n{json.dumps(obc_yaml, indent=2)}\n\n" f"OBC description:\n{obc_description}")
def wait_for_build_to_complete(self, timeout=900): """ Wait for build status to reach complete state Args: timeout (int): Time in seconds to wait """ log.info(f"Waiting for the build to reach {JENKINS_BUILD_COMPLETE} state") for project in self.projects: jenkins_builds = self.get_builds_obj(namespace=project) for jenkins_build in jenkins_builds: if (jenkins_build.name, project) not in self.build_completed: try: wait_for_resource_state( resource=jenkins_build, state=JENKINS_BUILD_COMPLETE, timeout=timeout ) self.get_build_duration_time( namespace=project, build_name=jenkins_build.name ) except ResourceWrongStatusException: ocp_obj = OCP(namespace=project, kind='build') output = ocp_obj.describe(resource_name=jenkins_build.name) error_msg = ( f'{jenkins_build.name} did not reach to ' f'{JENKINS_BUILD_COMPLETE} state after {timeout} sec\n' f'oc describe output of {jenkins_build.name} \n:{output}' ) log.error(error_msg) self.print_completed_builds_results() raise UnexpectedBehaviour(error_msg)
def wait_for_build_status(self, status, timeout=900): """ Wait for build status to reach running/completed Args: status (str): status to reach Running or Completed timeout (int): Time in seconds to wait """ log.info(f"Waiting for the build to reach {status} state") for project in self.projects: jenkins_builds = self.get_builds_obj(namespace=project) for jenkins_build in jenkins_builds: if (jenkins_build.name, project) not in self.build_completed: try: wait_for_resource_state(resource=jenkins_build, state=status, timeout=timeout) self.build_completed.append( (jenkins_build.name, project)) except ResourceWrongStatusException: ocp_obj = OCP(namespace=project, kind='build') output = ocp_obj.describe( resource_name=jenkins_build.name) error_msg = ( f'{jenkins_build.name} did not reach to ' f'{status} state after {timeout} sec\n' f'oc describe output of {jenkins_build.name} \n:{output}' ) log.error(error_msg) self.get_builds_logs() raise UnexpectedBehaviour(error_msg)
def get_build_duration_time(self, namespace, build_name): """ get build duration time Args: namespace (str): get build in namespace build_name (str): the name of the jenkins build """ ocp_obj = OCP(namespace=namespace, kind='build') output_build = ocp_obj.describe(resource_name=build_name) list_build = output_build.split() index = list_build.index('Duration:') self.build_completed[(build_name, namespace)] = list_build[index + 1]
def get_builds_logs(self): """ Get builds logs and print them on table """ log.info('Print builds results') build_table = PrettyTable() build_table.field_names = ["Project", "Build", "Duration"] for build in self.build_completed: ocp_obj = OCP(namespace=build[1], kind='build') output_build = ocp_obj.describe(resource_name=build[0]) list_build = output_build.split() index = list_build.index('Duration:') build_table.add_row([build[1], build[0], list_build[index + 1]]) log.info(f'\n{build_table}\n')
class OCS(object): """ Base OCSClass """ def __init__(self, **kwargs): """ Initializer function Args: kwargs (dict): 1) For existing resource, use OCP.reload() to get the resource's dictionary and use it to pass as **kwargs 2) For new resource, use yaml files templates under /templates/CSI like: obj_dict = load_yaml( os.path.join( TEMPLATE_DIR, "some_resource.yaml" ) ) """ self.data = kwargs self._api_version = self.data.get('api_version') self._kind = self.data.get('kind') self._namespace = None if 'metadata' in self.data: self._namespace = self.data.get('metadata').get('namespace') self._name = self.data.get('metadata').get('name') self.ocp = OCP(api_version=self._api_version, kind=self.kind, namespace=self._namespace) self.temp_yaml = tempfile.NamedTemporaryFile(mode='w+', prefix=self._kind, delete=False) # This _is_delete flag is set to True if the delete method was called # on object of this class and was successfull. self._is_deleted = False @property def api_version(self): return self._api_version @property def kind(self): return self._kind @property def namespace(self): return self._namespace @property def name(self): return self._name @property def is_deleted(self): return self._is_deleted def reload(self): """ Reloading the OCS instance with the new information from its actual data. After creating a resource from a yaml file, the actual yaml file is being changed and more information about the resource is added. """ self.data = self.get() self.__init__(**self.data) def get(self, out_yaml_format=True): return self.ocp.get(resource_name=self.name, out_yaml_format=out_yaml_format) def describe(self): return self.ocp.describe(resource_name=self.name) def create(self, do_reload=True): log.info(f"Adding {self.kind} with name {self.name}") templating.dump_data_to_temp_yaml(self.data, self.temp_yaml.name) status = self.ocp.create(yaml_file=self.temp_yaml.name) if do_reload: self.reload() return status def delete(self, wait=True, force=False): """ Delete the OCS object if its not already deleted (using the internal is_deleted flag) Args: wait (bool): Wait for object to be deleted force (bool): Force delete object Returns: bool: True if deleted, False otherwise """ # Avoid accidental delete of default storageclass and secret if (self.name == constants.DEFAULT_STORAGECLASS_CEPHFS or self.name == constants.DEFAULT_STORAGECLASS_RBD): log.info(f"Attempt to delete default Secret or StorageClass") return if self._is_deleted: log.info(f"Attempt to remove resource: {self.name} which is" f"already deleted! Skipping delete of this resource!") result = True else: result = self.ocp.delete(resource_name=self.name, wait=wait, force=force) self._is_deleted = True return result def apply(self, **data): with open(self.temp_yaml.name, 'w') as yaml_file: yaml.dump(data, yaml_file) assert self.ocp.apply( yaml_file=self.temp_yaml.name), (f"Failed to apply changes {data}") self.reload() def add_label(self, label): """ Addss a new label Args: label (str): New label to be assigned for this pod E.g: "label=app='rook-ceph-mds'" """ status = self.ocp.add_label(resource_name=self.name, label=label) self.reload() return status def delete_temp_yaml_file(self): utils.delete_file(self.temp_yaml.name)