Commit f3654501 authored by Christos Tranoris's avatar Christos Tranoris
Browse files

fix for new resources states

parent da274119
Loading
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -171,7 +171,12 @@ OSOM checks the presence of attribute _CR_SPEC at the RFS to make a request for
> LCM rules can be used to change attributes of this yaml/json file, before sending this for orchestration

However, the following issue needs to be solved: ** How to map the CR lifecycle that is defined in the CRD with the TMF resource Lifecycle? **
	- For this We introduced the following characteristics:  _CR_CHECK_FIELD, _CR_CHECKVAL_STANDBY, _CR_CHECKVAL_ALARM, _CR_CHECKVAL_AVAILABLE, _CR_CHECKVAL_RESERVED, _CR_CHECKVAL_UNKNOWN, _CR_CHECKVAL_SUSPENDED
	- For this we introduced `_CR_CHECK_FIELD` (the CR field to observe) plus a set of `_CR_CHECKVAL_*` characteristics that name the observed value signalling each ITU-T X.731 state / health verdict:
		- `_CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}` — the [`ResourceHealth`](https://labs.etsi.org/rep/osl/code/org.etsi.osl.model.k8s) verdict; CRIDGE folds it into `operationalState`/`administrativeState`
		- `_CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}``operationalState` directly
		- `_CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}``administrativeState` directly
		- `_CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}``usageState` directly
	- The older `_CR_CHECKVAL_{STANDBY,ALARM,AVAILABLE,RESERVED,UNKNOWN,SUSPENDED}` characteristics (which mapped to `resourceStatus`) are **no longer consumed by CRIDGE**`resourceStatus` is allocation/pool bookkeeping owned by whoever claimed the resource, never written by CRIDGE.

OSOM sends to CRIDGE a message with the following information:

@@ -182,13 +187,14 @@ OSOM sends to CRIDGE a message with the following information:
- org.etsi.osl.prefixName: we need to add a short prefix (default is cr) to various places. For example in K8s cannot start with a number 
- org.etsi.osl.serviceOrderId: the related service order id of this deployment request 
- org.etsi.osl.namespace: requested namespace name 
- org.etsi.osl.statusCheckFieldName: The name of the field that is needed to be monitored in order to monitor the status of the service and translate it to TMF resource statys (RESERVED AVAILABLE, etc) 
- org.etsi.osl.statusCheckValueStandby: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state STANDBY (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckValueAlarm: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state ALARMS (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckValueAvailable: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state AVAILABLE (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckValueReserved: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state RESERVED (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckValueUnknown: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state UNKNOWN (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckValueSuspended: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state SUSPENDED (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- org.etsi.osl.statusCheckFieldName: The name of the CR field that is observed to determine the resource's state
- org.etsi.osl.healthCheckValue{Up,Pending,Down,Held,Gone}: The CR specific value (of the CheckFieldName) that CRIDGE maps to the ITU-T X.731 `ResourceHealth` verdict (see org.etsi.osl.tmf.ri639.model.ResourceHealth)
- org.etsi.osl.operStateCheckValue{Enable,Disable}: The CR specific value that CRIDGE maps to `operationalState` (see org.etsi.osl.tmf.ri639.model.ResourceOperationalStateType)
- org.etsi.osl.adminStateCheckValue{Locked,Unlocked,Shutdown}: The CR specific value that CRIDGE maps to `administrativeState` (see org.etsi.osl.tmf.ri639.model.ResourceAdministrativeStateType)
- org.etsi.osl.usageStateCheckValue{Idle,Active,Busy}: The CR specific value that CRIDGE maps to `usageState` (see org.etsi.osl.tmf.ri639.model.ResourceUsageStateType)

**Note on what these map to.** When the observed field carries a matching value, CRIDGE records it on `KubernetesCRV1.{healthValue,operationalStateValue,administrativeStateValue,usageStateValue}` and `KubernetesCRV1.applyState()` folds it into the ITU-T X.731 pair `operationalState`/`administrativeState` (a `healthValue` verdict is authoritative; otherwise the individual attributes are used). That pair is what CRIDGE publishes and what `Resource.deriveHealth()` / `Service.findNextStateBasedOnResourceList` fold into the supported service's state. CRIDGE never writes `resourceStatus` — that is allocation/pool bookkeeping owned by whoever claimed the resource, and `CatalogClient.withoutResourceStatus()` strips it from every catalog write. The legacy `org.etsi.osl.statusCheckValue*` headers (mapping to `resourceStatus`) are still sent by OSOM for compatibility but are ignored by CRIDGE.


- Parameters:
	- aService reference to the service that the resource and the CR belongs to
+26 −32
Original line number Diff line number Diff line
@@ -73,13 +73,12 @@ All attributes of the CRD are translated into characteristics
The following specific characteristics are **added**:

		- _CR_SPEC: Used for providing the json Custom Resource description to apply
		- _CR_CHECK_FIELD: Used for providing the field that need to be checked for the resource status
		- _CR_CHECKVAL_STANDBY: Used for providing the equivalent value from resource to signal the standby status
		- _CR_CHECKVAL_ALARM: Used for providing the equivalent value from resource to signal the alarm status
		- _CR_CHECKVAL_AVAILABLE: Used for providing the equivalent value from resource to signal the available status
		- _CR_CHECKVAL_RESERVED: Used for providing the equivalent value from resource to signal the reserved status
		- _CR_CHECKVAL_UNKNOWN: Used for providing the equivalent value from resource to signal the unknown status
		- _CR_CHECKVAL_SUSPENDED: Used for providing the equivalent value from resource to signal the suspended status
		- _CR_CHECK_FIELD: The CR field that is observed to determine the resource's state
		- _CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}: The observed value signalling each ITU-T X.731 `ResourceHealth` verdict
		- _CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}: The observed value signalling `operationalState`
		- _CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}: The observed value signalling `administrativeState`
		- _CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}: The observed value signalling `usageState`
		- _CR_CHECKVAL_{STANDBY,ALARM,AVAILABLE,RESERVED,UNKNOWN,SUSPENDED}: legacy, mapped to `resourceStatus` — **no longer consumed by CRIDGE**
		
		
1. Create a new Service Specification and use this Resource Specification in Resource Specification Relationships
@@ -89,12 +88,10 @@ The following specific characteristics are **added**:
	
		- _CR_SPEC, 
		- _CR_CHECK_FIELD
		- _CR_CHECKVAL_STANDBY
		- _CR_CHECKVAL_ALARM
		- _CR_CHECKVAL_AVAILABLE
		- _CR_CHECKVAL_RESERVED
		- _CR_CHECKVAL_UNKNOWN
		- _CR_CHECKVAL_SUSPENDED
		- _CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}
		- _CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}
		- _CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}
		- _CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}
		
	1.2. You can now create LCM rules if you wish
	
@@ -105,12 +102,10 @@ The following specific characteristics are **added**:
	
		- _CR_SPEC, 
		- _CR_CHECK_FIELD
		- _CR_CHECKVAL_STANDBY
		- _CR_CHECKVAL_ALARM
		- _CR_CHECKVAL_AVAILABLE
		- _CR_CHECKVAL_RESERVED
		- _CR_CHECKVAL_UNKNOWN
		- _CR_CHECKVAL_SUSPENDED
		- _CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}
		- _CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}
		- _CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}
		- _CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}
		
	2.2. You We can create LCM rules for this new Service Specification
	
@@ -135,23 +130,22 @@ OSOM - OpenSlice Service Orchestrator, checks the presence of attribute _CR_SPEC
OpenSlice adds automatically as we see the following characteristics: 

		- _CR_CHECK_FIELD
		- _CR_CHECKVAL_STANDBY
		- _CR_CHECKVAL_ALARM
		- _CR_CHECKVAL_AVAILABLE
		- _CR_CHECKVAL_RESERVED
		- _CR_CHECKVAL_UNKNOWN
		- _CR_CHECKVAL_SUSPENDED
		- _CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}
		- _CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}
		- _CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}
		- _CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}
		
**These characteristics instrument OpenSlice services to manage and reflect the lifecycle of a kubernetes resource to OpenSlice's (TMF based) lifecycle**


- _CR_CHECK_FIELD: The name of the field that is needed to be monitored in order to monitor the status of the service and translate it to TMF resource statys (RESERVED AVAILABLE, etc) 
- _CR_CHECKVAL_STANDBY: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state STANDBY (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECKVAL_ALARM: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state ALARMS (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECKVAL_AVAILABLE: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state AVAILABLE (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECKVAL_RESERVED: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state RESERVED (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECKVAL_UNKNOWN: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state UNKNOWN (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECKVAL_SUSPENDED: The CR specific value (of the CheckFieldName) that needs to me mapped to the TMF resource state SUSPENDED (see org.etsi.osl.tmf.ri639.model.ResourceStatusType) 
- _CR_CHECK_FIELD: The name of the CR field that is observed to determine the resource's state
- _CR_CHECKVAL_HEALTH_{UP,PENDING,DOWN,HELD,GONE}: The CR specific value (of the CheckField) that CRIDGE maps to the ITU-T X.731 `ResourceHealth` verdict (see org.etsi.osl.tmf.ri639.model.ResourceHealth). A verdict is authoritative and CRIDGE folds it into `operationalState`/`administrativeState`.
- _CR_CHECKVAL_OPERSTATE_{ENABLE,DISABLE}: The CR specific value that CRIDGE maps to `operationalState` (see org.etsi.osl.tmf.ri639.model.ResourceOperationalStateType)
- _CR_CHECKVAL_ADMINSTATE_{LOCKED,UNLOCKED,SHUTDOWN}: The CR specific value that CRIDGE maps to `administrativeState` (see org.etsi.osl.tmf.ri639.model.ResourceAdministrativeStateType)
- _CR_CHECKVAL_USAGESTATE_{IDLE,ACTIVE,BUSY}: The CR specific value that CRIDGE maps to `usageState` (see org.etsi.osl.tmf.ri639.model.ResourceUsageStateType)

**Note on what these map to.** When the observed field carries a matching value, `KubernetesCRV1.applyState()` folds it into the ITU-T X.731 pair `operationalState`/`administrativeState` (a health verdict is authoritative; otherwise the individual attributes are used). That pair is what CRIDGE publishes and what `Resource.deriveHealth()` / `Service.findNextStateBasedOnResourceList` fold into the supported service's state. CRIDGE never writes `resourceStatus` — that is allocation/pool bookkeeping owned by whoever claimed the resource, and `CatalogClient.withoutResourceStatus()` strips it from every catalog write. The legacy `_CR_CHECKVAL_{STANDBY,ALARM,AVAILABLE,RESERVED,UNKNOWN,SUSPENDED}` characteristics (mapping to `resourceStatus`) are still emitted for compatibility but ignored by CRIDGE.



---
+31 −0
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ public class CatalogClient extends RouteBuilder{
	
	public Resource createOrUpdateResourceByNameCategoryVersion( ResourceCreate s) {
		logger.info("will createOrUpdateResourceByNameVersion a Resource "  );
		withoutResourceStatus( s );
		try {
			Map<String, Object> map = new HashMap<>();
			map.put("aname", s.getName());
@@ -199,6 +200,35 @@ public class CatalogClient extends RouteBuilder{
	

	
	/**
	 * Strips {@code resourceStatus} from anything CRIDGE sends to the catalog.
	 *
	 * <p>CRIDGE observes condition, never allocation. {@code resourceStatus} is inventory/pool
	 * bookkeeping - {@code RESERVED}/{@code STANDBY} record a claim someone else made (see
	 * {@code ResourceStatusType.isAllocation()}), and CRIDGE has no way to know about it: it is driven
	 * by cluster informers, not by the order that reserved the resource. Writing the field on every
	 * event - and CRIDGE writes on every CR event, every 30s namespace resync and every CRD replay at
	 * startup - would hand an in-use resource back to the free pool.
	 *
	 * <p>What CRIDGE does declare, unconditionally, is health: the ITU-T X.731 pair
	 * {@code operationalState}/{@code administrativeState}. That is its own observation, nobody else
	 * has a claim on it, and it is what {@code Resource.deriveHealth()} turns into the supported
	 * service's state. Those are set by the {@code org.etsi.osl.model.k8s} domain classes
	 * ({@code KubernetesCRV1.applyState} and friends) and are passed through untouched.
	 *
	 * <p>A null is a "leave unchanged", not a wipe: this class serializes with
	 * {@code JsonInclude.NON_NULL} so the field never reaches the wire, and
	 * {@code ResourceRepoService.updateResource} only assigns it when the incoming value is non-null.
	 * On the create branch the row is simply created without one, and seeding an initial allocation
	 * status is the allocating party's job (OSOM), not the controller's.
	 */
	private static <T extends ResourceUpdate> T withoutResourceStatus( T rs ) {
	  if ( rs != null ) {
	    rs.setResourceStatus( null );
	  }
	  return rs;
	}

	private <T> T toJsonObj(String content, Class<T> valueType)  throws IOException {
	  ObjectMapper mapper = new ObjectMapper();
	  mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
@@ -217,6 +247,7 @@ public class CatalogClient extends RouteBuilder{


	  logger.info("will update Resource : " + oslResourceId );
	  withoutResourceStatus( rs );
	  try {
	    Map<String, Object> map = new HashMap<>();
	    map.put("resourceId", oslResourceId );
+0 −19
Original line number Diff line number Diff line
/*-
 * ========================LICENSE_START=================================
 * org.etsi.osl.cridge
 * %%
 * Copyright (C) 2019 openslice.io
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */
package org.etsi.osl.cridge;

import org.slf4j.Logger;
+88 −32
Original line number Diff line number Diff line
@@ -14,8 +14,10 @@ import org.etsi.osl.domain.model.kubernetes.KubernetesContextDefinition;
import org.etsi.osl.domain.model.kubernetes.KubernetesSecret;
import org.etsi.osl.tmf.common.model.EValueType;
import org.etsi.osl.tmf.rcm634.model.ResourceSpecification;
import org.etsi.osl.tmf.ri639.model.ResourceCreate;
import org.etsi.osl.tmf.ri639.model.ResourceStatusType;
import org.etsi.osl.tmf.ri639.model.ResourceAdministrativeStateType;
import org.etsi.osl.tmf.ri639.model.ResourceHealth;
import org.etsi.osl.tmf.ri639.model.ResourceOperationalStateType;
import org.etsi.osl.tmf.ri639.model.ResourceUsageStateType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -250,14 +252,29 @@ public class KubernetesClientResource {

    });

    kcrv.setStatusCheckFieldName( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckFieldName"));
    kcrv.setStatusCheckValueStandby( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueStandby"));
    kcrv.setStatusCheckValueAlarm( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueAlarm"));
    kcrv.setStatusCheckValueAvailable( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueAvailable"));
    kcrv.setStatusCheckValueReserved( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueReserved"));
    kcrv.setStatusCheckValueUnknown( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueUnknown"));
    kcrv.setStatusCheckValueSuspended( gkr.getMetadata().getLabels().get("org.etsi.osl.statusCheckValueSuspended"));
    kcrv.setStatusValue(    ResourceStatusType.UNKNOWN );
    // The observed field selector is unchanged; its value is matched against the check values below.
    Map<String, String> labels = gkr.getMetadata().getLabels();
    kcrv.setStatusCheckFieldName( labels.get("org.etsi.osl.statusCheckFieldName"));

    // The CR-specific value of the observed field that signals each ITU-T X.731 state / health
    // verdict. applyObservedState() maps the observed value to
    // KubernetesCRV1.{healthValue,operationalStateValue,administrativeStateValue,usageStateValue},
    // which KubernetesCRV1.applyState() folds into the operationalState/administrativeState pair -
    // the only status attributes CRIDGE publishes. resourceStatus is never written (see
    // CatalogClient.withoutResourceStatus).
    kcrv.setHealthCheckValueUp(       labels.get("org.etsi.osl.healthCheckValueUp"));
    kcrv.setHealthCheckValuePending(  labels.get("org.etsi.osl.healthCheckValuePending"));
    kcrv.setHealthCheckValueDown(     labels.get("org.etsi.osl.healthCheckValueDown"));
    kcrv.setHealthCheckValueHeld(     labels.get("org.etsi.osl.healthCheckValueHeld"));
    kcrv.setHealthCheckValueGone(     labels.get("org.etsi.osl.healthCheckValueGone"));
    kcrv.setOperStateCheckValueEnable(  labels.get("org.etsi.osl.operStateCheckValueEnable"));
    kcrv.setOperStateCheckValueDisable( labels.get("org.etsi.osl.operStateCheckValueDisable"));
    kcrv.setAdminStateCheckValueLocked(   labels.get("org.etsi.osl.adminStateCheckValueLocked"));
    kcrv.setAdminStateCheckValueUnlocked( labels.get("org.etsi.osl.adminStateCheckValueUnlocked"));
    kcrv.setAdminStateCheckValueShutdown( labels.get("org.etsi.osl.adminStateCheckValueShutdown"));
    kcrv.setUsageStateCheckValueIdle(   labels.get("org.etsi.osl.usageStateCheckValueIdle"));
    kcrv.setUsageStateCheckValueActive( labels.get("org.etsi.osl.usageStateCheckValueActive"));
    kcrv.setUsageStateCheckValueBusy(   labels.get("org.etsi.osl.usageStateCheckValueBusy"));

    gkr.getAdditionalProperties().forEach((pk, pv) -> {
      logger.debug("\t {} {} ", pk, pv);
@@ -271,9 +288,9 @@ public class KubernetesClientResource {
          String propertyValue = specv.toString();
          kcrv.getProperties().put( propertyName , propertyValue);

          //check resource status
          if ( kcrv.getStatusCheckFieldName().equals(propertyName) ){
            kcrv.setStatusValue(  checKCRVResourceStatus(kcrv, propertyValue) );            
          //map the observed field value to the CR's ITU-T X.731 state / health verdict
          if ( kcrv.getStatusCheckFieldName()!=null && kcrv.getStatusCheckFieldName().equals(propertyName) ){
            applyObservedState( kcrv, propertyValue );
          }
        });					
      }
@@ -291,22 +308,61 @@ public class KubernetesClientResource {
  }


  private ResourceStatusType checKCRVResourceStatus(KubernetesCRV1 kcrv, String propertyValue) {
  /**
   * Maps the observed value of the CR's {@code org.etsi.osl.statusCheckFieldName} field to the CR's
   * ITU-T X.731 state, using the {@code org.etsi.osl.{health,operState,adminState,usageState}CheckValue*}
   * labels the operator put on the resource (fed from the CRD's {@code _CR_CHECKVAL_*} characteristics
   * by OSOM).
   *
   * <p>This is CRIDGE's own <em>health observation</em> of the CR - not the catalog's
   * {@code resourceStatus}, which is allocation/pool bookkeeping owned by whoever claimed the resource
   * and is stripped on the way out ({@code CatalogClient.withoutResourceStatus}). The values set here
   * are consumed by {@code KubernetesCRV1.applyState()}, which folds them into the
   * {@code operationalState}/{@code administrativeState} pair CRIDGE publishes: a {@code healthValue}
   * verdict is authoritative, otherwise the individual operational/administrative/usage attributes are
   * used. A value matching no label leaves everything unset, which {@code Resource.deriveHealth()}
   * reads as {@code PENDING} - it neither promotes nor demotes the supported service.
   */
  private void applyObservedState(KubernetesCRV1 kcrv, String observedValue) {

    if (observedValue == null || observedValue.isEmpty()) {
      return;
    }

    if (propertyValue.equals(kcrv.getStatusCheckValueAlarm())) {
      return ResourceStatusType.ALARM;
    } else if (propertyValue.equals(kcrv.getStatusCheckValueAvailable())) {
      return ResourceStatusType.AVAILABLE;
    } else if (propertyValue.equals(kcrv.getStatusCheckValueReserved())) {
      return ResourceStatusType.RESERVED;
    } else if (propertyValue.equals(kcrv.getStatusCheckValueStandby())) {
      return ResourceStatusType.STANDBY;
    } else if (propertyValue.equals(kcrv.getStatusCheckValueSuspended())) {
      return ResourceStatusType.SUSPENDED;
    } else if (propertyValue.equals(kcrv.getStatusCheckValueUnknown())) {
      return ResourceStatusType.UNKNOWN;
    } else {
      return ResourceStatusType.UNKNOWN;
    // Health verdict - authoritative in KubernetesCRV1.applyState().
    if (observedValue.equals(kcrv.getHealthCheckValueUp())) {
      kcrv.setHealthValue(ResourceHealth.UP);
    } else if (observedValue.equals(kcrv.getHealthCheckValuePending())) {
      kcrv.setHealthValue(ResourceHealth.PENDING);
    } else if (observedValue.equals(kcrv.getHealthCheckValueDown())) {
      kcrv.setHealthValue(ResourceHealth.DOWN);
    } else if (observedValue.equals(kcrv.getHealthCheckValueHeld())) {
      kcrv.setHealthValue(ResourceHealth.HELD);
    } else if (observedValue.equals(kcrv.getHealthCheckValueGone())) {
      kcrv.setHealthValue(ResourceHealth.GONE);
    }

    // Individual X.731 attributes - consulted only when no health verdict was given.
    if (observedValue.equals(kcrv.getOperStateCheckValueEnable())) {
      kcrv.setOperationalStateValue(ResourceOperationalStateType.ENABLE);
    } else if (observedValue.equals(kcrv.getOperStateCheckValueDisable())) {
      kcrv.setOperationalStateValue(ResourceOperationalStateType.DISABLE);
    }

    if (observedValue.equals(kcrv.getAdminStateCheckValueLocked())) {
      kcrv.setAdministrativeStateValue(ResourceAdministrativeStateType.LOCKED);
    } else if (observedValue.equals(kcrv.getAdminStateCheckValueUnlocked())) {
      kcrv.setAdministrativeStateValue(ResourceAdministrativeStateType.UNLOCKED);
    } else if (observedValue.equals(kcrv.getAdminStateCheckValueShutdown())) {
      kcrv.setAdministrativeStateValue(ResourceAdministrativeStateType.SHUTDOWN);
    }

    if (observedValue.equals(kcrv.getUsageStateCheckValueIdle())) {
      kcrv.setUsageStateValue(ResourceUsageStateType.IDLE);
    } else if (observedValue.equals(kcrv.getUsageStateCheckValueActive())) {
      kcrv.setUsageStateValue(ResourceUsageStateType.ACTIVE);
    } else if (observedValue.equals(kcrv.getUsageStateCheckValueBusy())) {
      kcrv.setUsageStateValue(ResourceUsageStateType.BUSY);
    }

  }
@@ -327,7 +383,7 @@ public class KubernetesClientResource {
        String propertyName = propertyToAdd;
        String propertyValue = specv.toString();
        if ( kcrv.getStatusCheckFieldName()!=null && kcrv.getStatusCheckFieldName().equals(propertyName) ){
          kcrv.setStatusValue(  checKCRVResourceStatus(kcrv, propertyValue) );            
          applyObservedState( kcrv, propertyValue );
        }
      }

Loading