def create_oc_resource( template_name, cluster_path, _templating, template_data=None, template_dir="ocs-deployment", ): """ Create an oc resource after rendering the specified template with the rook data from cluster_conf. Args: template_name (str): Name of the ocs-deployment config template cluster_path (str): Path to cluster directory, where files will be written _templating (Templating): Object of Templating class used for templating template_data (dict): Data for render template (default: {}) template_dir (str): Directory under templates dir where template exists (default: ocs-deployment) """ if template_data is None: template_data = {} template_path = os.path.join(template_dir, template_name) template = _templating.render_template(template_path, template_data) cfg_file = os.path.join(cluster_path, template_name) with open(cfg_file, "w") as f: f.write(template) log.info(f"Creating rook resource from {template_name}") occli = OCP() occli.create(cfg_file)
def create_dummy_osd(deployment): """ Replace one of OSD pods with pod that contains all data from original OSD but doesn't run osd daemon. This can be used e.g. for direct acccess to Ceph Placement Groups. Args: deployment (str): Name of deployment to use Returns: list: first item is dummy deployment object, second item is dummy pod object """ oc = OCP(kind=constants.DEPLOYMENT, namespace=config.ENV_DATA.get('cluster_namespace')) osd_data = oc.get(deployment) dummy_deployment = create_unique_resource_name('dummy', 'osd') osd_data['metadata']['name'] = dummy_deployment osd_containers = osd_data.get('spec').get('template').get('spec').get( 'containers') # get osd container spec original_osd_args = osd_containers[0].get('args') osd_data['spec']['template']['spec']['containers'][0]['args'] = [] osd_data['spec']['template']['spec']['containers'][0]['command'] = [ '/bin/bash', '-c', 'sleep infinity' ] osd_file = tempfile.NamedTemporaryFile(mode='w+', prefix=dummy_deployment, delete=False) with open(osd_file.name, "w") as temp: yaml.dump(osd_data, temp) oc.create(osd_file.name) # downscale the original deployment and start dummy deployment instead oc.exec_oc_cmd(f"scale --replicas=0 deployment/{deployment}") oc.exec_oc_cmd(f"scale --replicas=1 deployment/{dummy_deployment}") osd_list = pod.get_osd_pods() dummy_pod = [pod for pod in osd_list if dummy_deployment in pod.name][0] wait_for_resource_state(resource=dummy_pod, state=constants.STATUS_RUNNING, timeout=60) ceph_init_cmd = '/rook/tini' + ' ' + ' '.join(original_osd_args) try: logger.info('Following command should expire after 7 seconds') dummy_pod.exec_cmd_on_pod(ceph_init_cmd, timeout=7) except TimeoutExpired: logger.info('Killing /rook/tini process') try: dummy_pod.exec_bash_cmd_on_pod( "kill $(ps aux | grep '[/]rook/tini' | awk '{print $2}')") except CommandFailed: pass return dummy_deployment, dummy_pod
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)
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_to_dict( 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) @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 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 create(self): log.info(f"Adding {self.kind} with name {self.name}") templating.dump_dict_to_temp_yaml(self.data, self.temp_yaml.name) status = self.ocp.create(yaml_file=self.temp_yaml.name) self.reload() return status def delete(self, wait=True): return self.ocp.delete(resource_name=self.name, wait=wait) 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)