# coding: utf-8

"""
    Kubernetes

    No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)

    The version of the OpenAPI document: release-1.37
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from collections.abc import Mapping as _Mapping
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, cast as _cast
from kubernetes.client.models.v1_aws_elastic_block_store_volume_source import V1AWSElasticBlockStoreVolumeSource
from kubernetes.client.models.v1_azure_disk_volume_source import V1AzureDiskVolumeSource
from kubernetes.client.models.v1_azure_file_persistent_volume_source import V1AzureFilePersistentVolumeSource
from kubernetes.client.models.v1_ceph_fs_persistent_volume_source import V1CephFSPersistentVolumeSource
from kubernetes.client.models.v1_cinder_persistent_volume_source import V1CinderPersistentVolumeSource
from kubernetes.client.models.v1_csi_persistent_volume_source import V1CSIPersistentVolumeSource
from kubernetes.client.models.v1_fc_volume_source import V1FCVolumeSource
from kubernetes.client.models.v1_flex_persistent_volume_source import V1FlexPersistentVolumeSource
from kubernetes.client.models.v1_flocker_volume_source import V1FlockerVolumeSource
from kubernetes.client.models.v1_gce_persistent_disk_volume_source import V1GCEPersistentDiskVolumeSource
from kubernetes.client.models.v1_glusterfs_persistent_volume_source import V1GlusterfsPersistentVolumeSource
from kubernetes.client.models.v1_host_path_volume_source import V1HostPathVolumeSource
from kubernetes.client.models.v1_iscsi_persistent_volume_source import V1ISCSIPersistentVolumeSource
from kubernetes.client.models.v1_local_volume_source import V1LocalVolumeSource
from kubernetes.client.models.v1_nfs_volume_source import V1NFSVolumeSource
from kubernetes.client.models.v1_object_reference import V1ObjectReference
from kubernetes.client.models.v1_photon_persistent_disk_volume_source import V1PhotonPersistentDiskVolumeSource
from kubernetes.client.models.v1_portworx_volume_source import V1PortworxVolumeSource
from kubernetes.client.models.v1_quobyte_volume_source import V1QuobyteVolumeSource
from kubernetes.client.models.v1_rbd_persistent_volume_source import V1RBDPersistentVolumeSource
from kubernetes.client.models.v1_scale_io_persistent_volume_source import V1ScaleIOPersistentVolumeSource
from kubernetes.client.models.v1_storage_os_persistent_volume_source import V1StorageOSPersistentVolumeSource
from kubernetes.client.models.v1_volume_node_affinity import V1VolumeNodeAffinity
from kubernetes.client.models.v1_vsphere_virtual_disk_volume_source import V1VsphereVirtualDiskVolumeSource
from typing import Optional, Set
from typing_extensions import Self
from pydantic_core import to_jsonable_python


_OPENAPI_GENERATOR_TO_DICT = "_openapi_generator_to_dict"


def _get_openapi_to_dict(value: Any) -> Any:
    # Reciprocal function references preserve inherited generated methods
    # without reserving model member names. Checking both directions also
    # rejects overrides whose decorators copy function attributes.
    to_dict = getattr(value, "to_dict", None)
    type_to_dict = getattr(type(value), "to_dict", None)
    if (
        not callable(to_dict)
        or getattr(to_dict, "__func__", None) is not type_to_dict
    ):
        return None

    openapi_to_dict = getattr(
        type_to_dict, _OPENAPI_GENERATOR_TO_DICT, None
    )
    if (
        not callable(openapi_to_dict)
        or getattr(
            openapi_to_dict,
            _OPENAPI_GENERATOR_TO_DICT,
            None,
        ) is not type_to_dict
    ):
        return None
    return openapi_to_dict


def _to_legacy_item(value: Any, serialize: bool) -> Any:
    to_dict = getattr(value, "to_dict", None)
    if _get_openapi_to_dict(value) is not None and callable(to_dict):
        return to_dict(serialize=serialize)
    if callable(to_dict):
        return to_dict()
    return value


def _to_legacy_value(value: Any, serialize: bool) -> Any:
    # python-legacy converted only immediate list elements or dictionary values:
    # https://github.com/OpenAPITools/openapi-generator/blob/c84b949df1a9ec04ba75989cb49b45c940c2f694/modules/openapi-generator/src/main/resources/python-legacy/model.mustache#L203-L231
    if isinstance(value, list):
        return [_to_legacy_item(item, serialize) for item in value]
    if isinstance(value, dict):
        return {
            key: _to_legacy_item(item, serialize)
            for key, item in value.items()
        }
    return _to_legacy_item(value, serialize)


def _to_openapi_value(value: Any) -> Any:
    if isinstance(value, list):
        return [_to_openapi_value(item) for item in value]
    if isinstance(value, dict):
        return {key: _to_openapi_value(item) for key, item in value.items()}

    to_openapi_dict = _get_openapi_to_dict(value)
    if to_openapi_dict is not None:
        return to_openapi_dict(value)

    to_dict = getattr(value, "to_dict", None)
    if callable(to_dict):
        return to_dict()
    return value


class V1PersistentVolumeSpec(BaseModel):
    """
    PersistentVolumeSpec is the specification of a persistent volume.

    Attributes:
      openapi_types (dict): The key is attribute name
                            and the value is attribute type.
      attribute_map (dict): The key is attribute name
                            and the value is json key in definition.
    """ # noqa: E501
    access_modes: Optional[List[StrictStr]] = Field(default=None, validation_alias=AliasChoices("accessModes", "access_modes"), serialization_alias="accessModes", description="accessModes contains all ways the volume can be mounted. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes")
    aws_elastic_block_store: Optional[V1AWSElasticBlockStoreVolumeSource] = Field(default=None, validation_alias=AliasChoices("awsElasticBlockStore", "aws_elastic_block_store"), serialization_alias="awsElasticBlockStore")
    azure_disk: Optional[V1AzureDiskVolumeSource] = Field(default=None, validation_alias=AliasChoices("azureDisk", "azure_disk"), serialization_alias="azureDisk")
    azure_file: Optional[V1AzureFilePersistentVolumeSource] = Field(default=None, validation_alias=AliasChoices("azureFile", "azure_file"), serialization_alias="azureFile")
    capacity: Optional[Dict[str, StrictStr]] = Field(default=None, description="capacity is the description of the persistent volume's resources and capacity. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity")
    cephfs: Optional[V1CephFSPersistentVolumeSource] = None
    cinder: Optional[V1CinderPersistentVolumeSource] = None
    claim_ref: Optional[V1ObjectReference] = Field(default=None, validation_alias=AliasChoices("claimRef", "claim_ref"), serialization_alias="claimRef")
    csi: Optional[V1CSIPersistentVolumeSource] = None
    fc: Optional[V1FCVolumeSource] = None
    flex_volume: Optional[V1FlexPersistentVolumeSource] = Field(default=None, validation_alias=AliasChoices("flexVolume", "flex_volume"), serialization_alias="flexVolume")
    flocker: Optional[V1FlockerVolumeSource] = None
    gce_persistent_disk: Optional[V1GCEPersistentDiskVolumeSource] = Field(default=None, validation_alias=AliasChoices("gcePersistentDisk", "gce_persistent_disk"), serialization_alias="gcePersistentDisk")
    glusterfs: Optional[V1GlusterfsPersistentVolumeSource] = None
    host_path: Optional[V1HostPathVolumeSource] = Field(default=None, validation_alias=AliasChoices("hostPath", "host_path"), serialization_alias="hostPath")
    iscsi: Optional[V1ISCSIPersistentVolumeSource] = None
    local: Optional[V1LocalVolumeSource] = None
    mount_options: Optional[List[StrictStr]] = Field(default=None, validation_alias=AliasChoices("mountOptions", "mount_options"), serialization_alias="mountOptions", description="mountOptions is the list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options")
    nfs: Optional[V1NFSVolumeSource] = None
    node_affinity: Optional[V1VolumeNodeAffinity] = Field(default=None, validation_alias=AliasChoices("nodeAffinity", "node_affinity"), serialization_alias="nodeAffinity")
    persistent_volume_reclaim_policy: Optional[StrictStr] = Field(default=None, validation_alias=AliasChoices("persistentVolumeReclaimPolicy", "persistent_volume_reclaim_policy"), serialization_alias="persistentVolumeReclaimPolicy", description="persistentVolumeReclaimPolicy defines what happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming")
    photon_persistent_disk: Optional[V1PhotonPersistentDiskVolumeSource] = Field(default=None, validation_alias=AliasChoices("photonPersistentDisk", "photon_persistent_disk"), serialization_alias="photonPersistentDisk")
    portworx_volume: Optional[V1PortworxVolumeSource] = Field(default=None, validation_alias=AliasChoices("portworxVolume", "portworx_volume"), serialization_alias="portworxVolume")
    quobyte: Optional[V1QuobyteVolumeSource] = None
    rbd: Optional[V1RBDPersistentVolumeSource] = None
    scale_io: Optional[V1ScaleIOPersistentVolumeSource] = Field(default=None, validation_alias=AliasChoices("scaleIO", "scale_io"), serialization_alias="scaleIO")
    storage_class_name: Optional[StrictStr] = Field(default=None, validation_alias=AliasChoices("storageClassName", "storage_class_name"), serialization_alias="storageClassName", description="storageClassName is the name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.")
    storageos: Optional[V1StorageOSPersistentVolumeSource] = None
    volume_attributes_class_name: Optional[StrictStr] = Field(default=None, validation_alias=AliasChoices("volumeAttributesClassName", "volume_attributes_class_name"), serialization_alias="volumeAttributesClassName", description="Name of VolumeAttributesClass to which this persistent volume belongs. Empty value is not allowed. When this field is not set, it indicates that this volume does not belong to any VolumeAttributesClass. This field is mutable and can be changed by the CSI driver after a volume has been updated successfully to a new class. For an unbound PersistentVolume, the volumeAttributesClassName will be matched with unbound PersistentVolumeClaims during the binding process.")
    volume_mode: Optional[StrictStr] = Field(default=None, validation_alias=AliasChoices("volumeMode", "volume_mode"), serialization_alias="volumeMode", description="volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec.")
    vsphere_volume: Optional[V1VsphereVirtualDiskVolumeSource] = Field(default=None, validation_alias=AliasChoices("vsphereVolume", "vsphere_volume"), serialization_alias="vsphereVolume")
    openapi_types: ClassVar[Dict[str, str]] = {
        "access_modes": "List[str]",
        "aws_elastic_block_store": "V1AWSElasticBlockStoreVolumeSource",
        "azure_disk": "V1AzureDiskVolumeSource",
        "azure_file": "V1AzureFilePersistentVolumeSource",
        "capacity": "Dict[str, str]",
        "cephfs": "V1CephFSPersistentVolumeSource",
        "cinder": "V1CinderPersistentVolumeSource",
        "claim_ref": "V1ObjectReference",
        "csi": "V1CSIPersistentVolumeSource",
        "fc": "V1FCVolumeSource",
        "flex_volume": "V1FlexPersistentVolumeSource",
        "flocker": "V1FlockerVolumeSource",
        "gce_persistent_disk": "V1GCEPersistentDiskVolumeSource",
        "glusterfs": "V1GlusterfsPersistentVolumeSource",
        "host_path": "V1HostPathVolumeSource",
        "iscsi": "V1ISCSIPersistentVolumeSource",
        "local": "V1LocalVolumeSource",
        "mount_options": "List[str]",
        "nfs": "V1NFSVolumeSource",
        "node_affinity": "V1VolumeNodeAffinity",
        "persistent_volume_reclaim_policy": "str",
        "photon_persistent_disk": "V1PhotonPersistentDiskVolumeSource",
        "portworx_volume": "V1PortworxVolumeSource",
        "quobyte": "V1QuobyteVolumeSource",
        "rbd": "V1RBDPersistentVolumeSource",
        "scale_io": "V1ScaleIOPersistentVolumeSource",
        "storage_class_name": "str",
        "storageos": "V1StorageOSPersistentVolumeSource",
        "volume_attributes_class_name": "str",
        "volume_mode": "str",
        "vsphere_volume": "V1VsphereVirtualDiskVolumeSource"
    }

    attribute_map: ClassVar[Dict[str, str]] = {
        "access_modes": "accessModes",
        "aws_elastic_block_store": "awsElasticBlockStore",
        "azure_disk": "azureDisk",
        "azure_file": "azureFile",
        "capacity": "capacity",
        "cephfs": "cephfs",
        "cinder": "cinder",
        "claim_ref": "claimRef",
        "csi": "csi",
        "fc": "fc",
        "flex_volume": "flexVolume",
        "flocker": "flocker",
        "gce_persistent_disk": "gcePersistentDisk",
        "glusterfs": "glusterfs",
        "host_path": "hostPath",
        "iscsi": "iscsi",
        "local": "local",
        "mount_options": "mountOptions",
        "nfs": "nfs",
        "node_affinity": "nodeAffinity",
        "persistent_volume_reclaim_policy": "persistentVolumeReclaimPolicy",
        "photon_persistent_disk": "photonPersistentDisk",
        "portworx_volume": "portworxVolume",
        "quobyte": "quobyte",
        "rbd": "rbd",
        "scale_io": "scaleIO",
        "storage_class_name": "storageClassName",
        "storageos": "storageos",
        "volume_attributes_class_name": "volumeAttributesClassName",
        "volume_mode": "volumeMode",
        "vsphere_volume": "vsphereVolume"
    }
    __properties: ClassVar[List[str]] = ["accessModes", "awsElasticBlockStore", "azureDisk", "azureFile", "capacity", "cephfs", "cinder", "claimRef", "csi", "fc", "flexVolume", "flocker", "gcePersistentDisk", "glusterfs", "hostPath", "iscsi", "local", "mountOptions", "nfs", "nodeAffinity", "persistentVolumeReclaimPolicy", "photonPersistentDisk", "portworxVolume", "quobyte", "rbd", "scaleIO", "storageClassName", "storageos", "volumeAttributesClassName", "volumeMode", "vsphereVolume"]

    @classmethod
    def __preprocess_input_names(
        cls,
        obj: Any,
        remove_hidden_storage_names: bool = True,
    ) -> Any:
        if not isinstance(obj, _Mapping):
            return obj
        obj = dict(obj)
        if "accessModes" not in obj and "access_modes" in obj:
            obj["accessModes"] = obj["access_modes"]
        obj.pop("access_modes", None)
        if "awsElasticBlockStore" not in obj and "aws_elastic_block_store" in obj:
            obj["awsElasticBlockStore"] = obj["aws_elastic_block_store"]
        obj.pop("aws_elastic_block_store", None)
        if "azureDisk" not in obj and "azure_disk" in obj:
            obj["azureDisk"] = obj["azure_disk"]
        obj.pop("azure_disk", None)
        if "azureFile" not in obj and "azure_file" in obj:
            obj["azureFile"] = obj["azure_file"]
        obj.pop("azure_file", None)
        if "claimRef" not in obj and "claim_ref" in obj:
            obj["claimRef"] = obj["claim_ref"]
        obj.pop("claim_ref", None)
        if "flexVolume" not in obj and "flex_volume" in obj:
            obj["flexVolume"] = obj["flex_volume"]
        obj.pop("flex_volume", None)
        if "gcePersistentDisk" not in obj and "gce_persistent_disk" in obj:
            obj["gcePersistentDisk"] = obj["gce_persistent_disk"]
        obj.pop("gce_persistent_disk", None)
        if "hostPath" not in obj and "host_path" in obj:
            obj["hostPath"] = obj["host_path"]
        obj.pop("host_path", None)
        if "mountOptions" not in obj and "mount_options" in obj:
            obj["mountOptions"] = obj["mount_options"]
        obj.pop("mount_options", None)
        if "nodeAffinity" not in obj and "node_affinity" in obj:
            obj["nodeAffinity"] = obj["node_affinity"]
        obj.pop("node_affinity", None)
        if "persistentVolumeReclaimPolicy" not in obj and "persistent_volume_reclaim_policy" in obj:
            obj["persistentVolumeReclaimPolicy"] = obj["persistent_volume_reclaim_policy"]
        obj.pop("persistent_volume_reclaim_policy", None)
        if "photonPersistentDisk" not in obj and "photon_persistent_disk" in obj:
            obj["photonPersistentDisk"] = obj["photon_persistent_disk"]
        obj.pop("photon_persistent_disk", None)
        if "portworxVolume" not in obj and "portworx_volume" in obj:
            obj["portworxVolume"] = obj["portworx_volume"]
        obj.pop("portworx_volume", None)
        if "scaleIO" not in obj and "scale_io" in obj:
            obj["scaleIO"] = obj["scale_io"]
        obj.pop("scale_io", None)
        if "storageClassName" not in obj and "storage_class_name" in obj:
            obj["storageClassName"] = obj["storage_class_name"]
        obj.pop("storage_class_name", None)
        if "volumeAttributesClassName" not in obj and "volume_attributes_class_name" in obj:
            obj["volumeAttributesClassName"] = obj["volume_attributes_class_name"]
        obj.pop("volume_attributes_class_name", None)
        if "volumeMode" not in obj and "volume_mode" in obj:
            obj["volumeMode"] = obj["volume_mode"]
        obj.pop("volume_mode", None)
        if "vsphereVolume" not in obj and "vsphere_volume" in obj:
            obj["vsphereVolume"] = obj["vsphere_volume"]
        obj.pop("vsphere_volume", None)
        return obj

    model_config = ConfigDict(
        validate_by_name=True,
        validate_by_alias=True,
        validate_assignment=True,
        extra="forbid",
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model"""
        return pprint.pformat(self.to_dict())

    def __repr__(self) -> str:
        """For print and pprint"""
        return self.to_str()

    def __eq__(self, other: object) -> bool:
        """Returns true if both objects are equal"""
        if not isinstance(other, V1PersistentVolumeSpec):
            return False

        return self.to_dict() == other.to_dict()

    def __ne__(self, other: object) -> bool:
        """Returns true if both objects are not equal"""
        if not isinstance(other, V1PersistentVolumeSpec):
            return True

        return not (self == other)


    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        to_openapi_dict = _get_openapi_to_dict(self)
        if to_openapi_dict is not None:
            return json.dumps(to_jsonable_python(to_openapi_dict(self)))
        return json.dumps(to_jsonable_python(self.to_dict()))

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of V1PersistentVolumeSpec from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self, serialize: bool = False) -> Dict[str, Any]:
        """Return all declared model fields using public or wire names."""
        return {
            ("accessModes" if serialize else "access_modes"): _to_legacy_value(getattr(self, "access_modes", None), serialize),
            ("awsElasticBlockStore" if serialize else "aws_elastic_block_store"): _to_legacy_value(getattr(self, "aws_elastic_block_store", None), serialize),
            ("azureDisk" if serialize else "azure_disk"): _to_legacy_value(getattr(self, "azure_disk", None), serialize),
            ("azureFile" if serialize else "azure_file"): _to_legacy_value(getattr(self, "azure_file", None), serialize),
            ("capacity" if serialize else "capacity"): _to_legacy_value(getattr(self, "capacity", None), serialize),
            ("cephfs" if serialize else "cephfs"): _to_legacy_value(getattr(self, "cephfs", None), serialize),
            ("cinder" if serialize else "cinder"): _to_legacy_value(getattr(self, "cinder", None), serialize),
            ("claimRef" if serialize else "claim_ref"): _to_legacy_value(getattr(self, "claim_ref", None), serialize),
            ("csi" if serialize else "csi"): _to_legacy_value(getattr(self, "csi", None), serialize),
            ("fc" if serialize else "fc"): _to_legacy_value(getattr(self, "fc", None), serialize),
            ("flexVolume" if serialize else "flex_volume"): _to_legacy_value(getattr(self, "flex_volume", None), serialize),
            ("flocker" if serialize else "flocker"): _to_legacy_value(getattr(self, "flocker", None), serialize),
            ("gcePersistentDisk" if serialize else "gce_persistent_disk"): _to_legacy_value(getattr(self, "gce_persistent_disk", None), serialize),
            ("glusterfs" if serialize else "glusterfs"): _to_legacy_value(getattr(self, "glusterfs", None), serialize),
            ("hostPath" if serialize else "host_path"): _to_legacy_value(getattr(self, "host_path", None), serialize),
            ("iscsi" if serialize else "iscsi"): _to_legacy_value(getattr(self, "iscsi", None), serialize),
            ("local" if serialize else "local"): _to_legacy_value(getattr(self, "local", None), serialize),
            ("mountOptions" if serialize else "mount_options"): _to_legacy_value(getattr(self, "mount_options", None), serialize),
            ("nfs" if serialize else "nfs"): _to_legacy_value(getattr(self, "nfs", None), serialize),
            ("nodeAffinity" if serialize else "node_affinity"): _to_legacy_value(getattr(self, "node_affinity", None), serialize),
            ("persistentVolumeReclaimPolicy" if serialize else "persistent_volume_reclaim_policy"): _to_legacy_value(getattr(self, "persistent_volume_reclaim_policy", None), serialize),
            ("photonPersistentDisk" if serialize else "photon_persistent_disk"): _to_legacy_value(getattr(self, "photon_persistent_disk", None), serialize),
            ("portworxVolume" if serialize else "portworx_volume"): _to_legacy_value(getattr(self, "portworx_volume", None), serialize),
            ("quobyte" if serialize else "quobyte"): _to_legacy_value(getattr(self, "quobyte", None), serialize),
            ("rbd" if serialize else "rbd"): _to_legacy_value(getattr(self, "rbd", None), serialize),
            ("scaleIO" if serialize else "scale_io"): _to_legacy_value(getattr(self, "scale_io", None), serialize),
            ("storageClassName" if serialize else "storage_class_name"): _to_legacy_value(getattr(self, "storage_class_name", None), serialize),
            ("storageos" if serialize else "storageos"): _to_legacy_value(getattr(self, "storageos", None), serialize),
            ("volumeAttributesClassName" if serialize else "volume_attributes_class_name"): _to_legacy_value(getattr(self, "volume_attributes_class_name", None), serialize),
            ("volumeMode" if serialize else "volume_mode"): _to_legacy_value(getattr(self, "volume_mode", None), serialize),
            ("vsphereVolume" if serialize else "vsphere_volume"): _to_legacy_value(getattr(self, "vsphere_volume", None), serialize),
        }

    def __openapi_generator_modern_projection(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of aws_elastic_block_store
        if self.aws_elastic_block_store:
            _dict['awsElasticBlockStore'] = _to_openapi_value(self.aws_elastic_block_store)
        # override the default output from pydantic by calling `to_dict()` of azure_disk
        if self.azure_disk:
            _dict['azureDisk'] = _to_openapi_value(self.azure_disk)
        # override the default output from pydantic by calling `to_dict()` of azure_file
        if self.azure_file:
            _dict['azureFile'] = _to_openapi_value(self.azure_file)
        # override the default output from pydantic by calling `to_dict()` of cephfs
        if self.cephfs:
            _dict['cephfs'] = _to_openapi_value(self.cephfs)
        # override the default output from pydantic by calling `to_dict()` of cinder
        if self.cinder:
            _dict['cinder'] = _to_openapi_value(self.cinder)
        # override the default output from pydantic by calling `to_dict()` of claim_ref
        if self.claim_ref:
            _dict['claimRef'] = _to_openapi_value(self.claim_ref)
        # override the default output from pydantic by calling `to_dict()` of csi
        if self.csi:
            _dict['csi'] = _to_openapi_value(self.csi)
        # override the default output from pydantic by calling `to_dict()` of fc
        if self.fc:
            _dict['fc'] = _to_openapi_value(self.fc)
        # override the default output from pydantic by calling `to_dict()` of flex_volume
        if self.flex_volume:
            _dict['flexVolume'] = _to_openapi_value(self.flex_volume)
        # override the default output from pydantic by calling `to_dict()` of flocker
        if self.flocker:
            _dict['flocker'] = _to_openapi_value(self.flocker)
        # override the default output from pydantic by calling `to_dict()` of gce_persistent_disk
        if self.gce_persistent_disk:
            _dict['gcePersistentDisk'] = _to_openapi_value(self.gce_persistent_disk)
        # override the default output from pydantic by calling `to_dict()` of glusterfs
        if self.glusterfs:
            _dict['glusterfs'] = _to_openapi_value(self.glusterfs)
        # override the default output from pydantic by calling `to_dict()` of host_path
        if self.host_path:
            _dict['hostPath'] = _to_openapi_value(self.host_path)
        # override the default output from pydantic by calling `to_dict()` of iscsi
        if self.iscsi:
            _dict['iscsi'] = _to_openapi_value(self.iscsi)
        # override the default output from pydantic by calling `to_dict()` of local
        if self.local:
            _dict['local'] = _to_openapi_value(self.local)
        # override the default output from pydantic by calling `to_dict()` of nfs
        if self.nfs:
            _dict['nfs'] = _to_openapi_value(self.nfs)
        # override the default output from pydantic by calling `to_dict()` of node_affinity
        if self.node_affinity:
            _dict['nodeAffinity'] = _to_openapi_value(self.node_affinity)
        # override the default output from pydantic by calling `to_dict()` of photon_persistent_disk
        if self.photon_persistent_disk:
            _dict['photonPersistentDisk'] = _to_openapi_value(self.photon_persistent_disk)
        # override the default output from pydantic by calling `to_dict()` of portworx_volume
        if self.portworx_volume:
            _dict['portworxVolume'] = _to_openapi_value(self.portworx_volume)
        # override the default output from pydantic by calling `to_dict()` of quobyte
        if self.quobyte:
            _dict['quobyte'] = _to_openapi_value(self.quobyte)
        # override the default output from pydantic by calling `to_dict()` of rbd
        if self.rbd:
            _dict['rbd'] = _to_openapi_value(self.rbd)
        # override the default output from pydantic by calling `to_dict()` of scale_io
        if self.scale_io:
            _dict['scaleIO'] = _to_openapi_value(self.scale_io)
        # override the default output from pydantic by calling `to_dict()` of storageos
        if self.storageos:
            _dict['storageos'] = _to_openapi_value(self.storageos)
        # override the default output from pydantic by calling `to_dict()` of vsphere_volume
        if self.vsphere_volume:
            _dict['vsphereVolume'] = _to_openapi_value(self.vsphere_volume)
        return _dict

    setattr(
        to_dict,
        _OPENAPI_GENERATOR_TO_DICT,
        __openapi_generator_modern_projection,
    )
    setattr(
        __openapi_generator_modern_projection,
        _OPENAPI_GENERATOR_TO_DICT,
        to_dict,
    )
    del __openapi_generator_modern_projection

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of V1PersistentVolumeSpec from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        obj = _cast(
            Dict[str, Any],
            cls.__preprocess_input_names(
                obj,
                remove_hidden_storage_names=True,
            ),
        )

        _obj = cls.model_validate({
            "accessModes": obj.get("accessModes"),
            "awsElasticBlockStore": V1AWSElasticBlockStoreVolumeSource.from_dict(obj["awsElasticBlockStore"]) if obj.get("awsElasticBlockStore") is not None else None,
            "azureDisk": V1AzureDiskVolumeSource.from_dict(obj["azureDisk"]) if obj.get("azureDisk") is not None else None,
            "azureFile": V1AzureFilePersistentVolumeSource.from_dict(obj["azureFile"]) if obj.get("azureFile") is not None else None,
            "capacity": obj.get("capacity"),
            "cephfs": V1CephFSPersistentVolumeSource.from_dict(obj["cephfs"]) if obj.get("cephfs") is not None else None,
            "cinder": V1CinderPersistentVolumeSource.from_dict(obj["cinder"]) if obj.get("cinder") is not None else None,
            "claimRef": V1ObjectReference.from_dict(obj["claimRef"]) if obj.get("claimRef") is not None else None,
            "csi": V1CSIPersistentVolumeSource.from_dict(obj["csi"]) if obj.get("csi") is not None else None,
            "fc": V1FCVolumeSource.from_dict(obj["fc"]) if obj.get("fc") is not None else None,
            "flexVolume": V1FlexPersistentVolumeSource.from_dict(obj["flexVolume"]) if obj.get("flexVolume") is not None else None,
            "flocker": V1FlockerVolumeSource.from_dict(obj["flocker"]) if obj.get("flocker") is not None else None,
            "gcePersistentDisk": V1GCEPersistentDiskVolumeSource.from_dict(obj["gcePersistentDisk"]) if obj.get("gcePersistentDisk") is not None else None,
            "glusterfs": V1GlusterfsPersistentVolumeSource.from_dict(obj["glusterfs"]) if obj.get("glusterfs") is not None else None,
            "hostPath": V1HostPathVolumeSource.from_dict(obj["hostPath"]) if obj.get("hostPath") is not None else None,
            "iscsi": V1ISCSIPersistentVolumeSource.from_dict(obj["iscsi"]) if obj.get("iscsi") is not None else None,
            "local": V1LocalVolumeSource.from_dict(obj["local"]) if obj.get("local") is not None else None,
            "mountOptions": obj.get("mountOptions"),
            "nfs": V1NFSVolumeSource.from_dict(obj["nfs"]) if obj.get("nfs") is not None else None,
            "nodeAffinity": V1VolumeNodeAffinity.from_dict(obj["nodeAffinity"]) if obj.get("nodeAffinity") is not None else None,
            "persistentVolumeReclaimPolicy": obj.get("persistentVolumeReclaimPolicy"),
            "photonPersistentDisk": V1PhotonPersistentDiskVolumeSource.from_dict(obj["photonPersistentDisk"]) if obj.get("photonPersistentDisk") is not None else None,
            "portworxVolume": V1PortworxVolumeSource.from_dict(obj["portworxVolume"]) if obj.get("portworxVolume") is not None else None,
            "quobyte": V1QuobyteVolumeSource.from_dict(obj["quobyte"]) if obj.get("quobyte") is not None else None,
            "rbd": V1RBDPersistentVolumeSource.from_dict(obj["rbd"]) if obj.get("rbd") is not None else None,
            "scaleIO": V1ScaleIOPersistentVolumeSource.from_dict(obj["scaleIO"]) if obj.get("scaleIO") is not None else None,
            "storageClassName": obj.get("storageClassName"),
            "storageos": V1StorageOSPersistentVolumeSource.from_dict(obj["storageos"]) if obj.get("storageos") is not None else None,
            "volumeAttributesClassName": obj.get("volumeAttributesClassName"),
            "volumeMode": obj.get("volumeMode"),
            "vsphereVolume": V1VsphereVirtualDiskVolumeSource.from_dict(obj["vsphereVolume"]) if obj.get("vsphereVolume") is not None else None
        })
        return _obj
