Commit 915a5418 authored by Vladimir Vivien's avatar Vladimir Vivien

Addition of ScaleIO Kubernetes Volume Plugin

This commits implements the Kubernetes volume plugin allowing pods to seamlessly access and use data stored on ScaleIO volumes.
parent a2c7eb27
...@@ -402,6 +402,14 @@ ...@@ -402,6 +402,14 @@
"Rev": "2b8b7259d3139c96c4a6871031355808ab3fd3b3" "Rev": "2b8b7259d3139c96c4a6871031355808ab3fd3b3"
}, },
{ {
"ImportPath": "github.com/codedellemc/goscaleio",
"Rev": "8ed64a07d23f79bab973f1630651841ccc656887"
},
{
"ImportPath": "github.com/codedellemc/goscaleio/types/v1",
"Rev": "8ed64a07d23f79bab973f1630651841ccc656887"
},
{
"ImportPath": "github.com/codegangsta/negroni", "ImportPath": "github.com/codegangsta/negroni",
"Comment": "v0.1.0-62-g8d75e11", "Comment": "v0.1.0-62-g8d75e11",
"Rev": "8d75e11374a1928608c906fe745b538483e7aeb2" "Rev": "8d75e11374a1928608c906fe745b538483e7aeb2"
......
...@@ -40590,6 +40590,10 @@ ...@@ -40590,6 +40590,10 @@
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource" "$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource"
}, },
"scaleIO": {
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ScaleIOVolumeSource"
},
"storageClassName": { "storageClassName": {
"description": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.", "description": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.",
"type": "string" "type": "string"
...@@ -41567,6 +41571,56 @@ ...@@ -41567,6 +41571,56 @@
} }
} }
}, },
"io.k8s.kubernetes.pkg.api.v1.ScaleIOVolumeSource": {
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"fsType": {
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.",
"type": "string"
},
"gateway": {
"description": "The host address of the ScaleIO API Gateway.",
"type": "string"
},
"protectionDomain": {
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\").",
"type": "string"
},
"readOnly": {
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
"type": "boolean"
},
"secretRef": {
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.LocalObjectReference"
},
"sslEnabled": {
"description": "Flag to enable/disable SSL communication with Gateway, default false",
"type": "boolean"
},
"storageMode": {
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").",
"type": "string"
},
"storagePool": {
"description": "The Storage Pool associated with the protection domain (defaults to \"default\").",
"type": "string"
},
"system": {
"description": "The name of the storage system as configured in ScaleIO.",
"type": "string"
},
"volumeName": {
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source.",
"type": "string"
}
}
},
"io.k8s.kubernetes.pkg.api.v1.Secret": { "io.k8s.kubernetes.pkg.api.v1.Secret": {
"description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.",
"properties": { "properties": {
...@@ -42158,6 +42212,10 @@ ...@@ -42158,6 +42212,10 @@
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource" "$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource"
}, },
"scaleIO": {
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ScaleIOVolumeSource"
},
"secret": { "secret": {
"description": "Secret represents a secret that should populate this volume. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", "description": "Secret represents a secret that should populate this volume. More info: http://kubernetes.io/docs/user-guide/volumes#secrets",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.SecretVolumeSource" "$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.SecretVolumeSource"
...@@ -2722,6 +2722,10 @@ ...@@ -2722,6 +2722,10 @@
"portworxVolume": { "portworxVolume": {
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
},
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
} }
} }
}, },
...@@ -3502,6 +3506,57 @@ ...@@ -3502,6 +3506,57 @@
} }
} }
}, },
"v1.ScaleIOVolumeSource": {
"id": "v1.ScaleIOVolumeSource",
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"gateway": {
"type": "string",
"description": "The host address of the ScaleIO API Gateway."
},
"system": {
"type": "string",
"description": "The name of the storage system as configured in ScaleIO."
},
"secretRef": {
"$ref": "v1.LocalObjectReference",
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail."
},
"sslEnabled": {
"type": "boolean",
"description": "Flag to enable/disable SSL communication with Gateway, default false"
},
"protectionDomain": {
"type": "string",
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\")."
},
"storagePool": {
"type": "string",
"description": "The Storage Pool associated with the protection domain (defaults to \"default\")."
},
"storageMode": {
"type": "string",
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\")."
},
"volumeName": {
"type": "string",
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source."
},
"fsType": {
"type": "string",
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified."
},
"readOnly": {
"type": "boolean",
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
}
}
},
"v1.Container": { "v1.Container": {
"id": "v1.Container", "id": "v1.Container",
"description": "A single application container that you want to run within a pod.", "description": "A single application container that you want to run within a pod.",
......
...@@ -1505,6 +1505,10 @@ ...@@ -1505,6 +1505,10 @@
"portworxVolume": { "portworxVolume": {
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
},
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
} }
} }
}, },
...@@ -2285,6 +2289,57 @@ ...@@ -2285,6 +2289,57 @@
} }
} }
}, },
"v1.ScaleIOVolumeSource": {
"id": "v1.ScaleIOVolumeSource",
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"gateway": {
"type": "string",
"description": "The host address of the ScaleIO API Gateway."
},
"system": {
"type": "string",
"description": "The name of the storage system as configured in ScaleIO."
},
"secretRef": {
"$ref": "v1.LocalObjectReference",
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail."
},
"sslEnabled": {
"type": "boolean",
"description": "Flag to enable/disable SSL communication with Gateway, default false"
},
"protectionDomain": {
"type": "string",
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\")."
},
"storagePool": {
"type": "string",
"description": "The Storage Pool associated with the protection domain (defaults to \"default\")."
},
"storageMode": {
"type": "string",
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\")."
},
"volumeName": {
"type": "string",
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source."
},
"fsType": {
"type": "string",
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified."
},
"readOnly": {
"type": "boolean",
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
}
}
},
"v1.Container": { "v1.Container": {
"id": "v1.Container", "id": "v1.Container",
"description": "A single application container that you want to run within a pod.", "description": "A single application container that you want to run within a pod.",
......
...@@ -6969,6 +6969,10 @@ ...@@ -6969,6 +6969,10 @@
"portworxVolume": { "portworxVolume": {
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
},
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
} }
} }
}, },
...@@ -7749,6 +7753,57 @@ ...@@ -7749,6 +7753,57 @@
} }
} }
}, },
"v1.ScaleIOVolumeSource": {
"id": "v1.ScaleIOVolumeSource",
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"gateway": {
"type": "string",
"description": "The host address of the ScaleIO API Gateway."
},
"system": {
"type": "string",
"description": "The name of the storage system as configured in ScaleIO."
},
"secretRef": {
"$ref": "v1.LocalObjectReference",
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail."
},
"sslEnabled": {
"type": "boolean",
"description": "Flag to enable/disable SSL communication with Gateway, default false"
},
"protectionDomain": {
"type": "string",
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\")."
},
"storagePool": {
"type": "string",
"description": "The Storage Pool associated with the protection domain (defaults to \"default\")."
},
"storageMode": {
"type": "string",
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\")."
},
"volumeName": {
"type": "string",
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source."
},
"fsType": {
"type": "string",
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified."
},
"readOnly": {
"type": "boolean",
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
}
}
},
"v1.Container": { "v1.Container": {
"id": "v1.Container", "id": "v1.Container",
"description": "A single application container that you want to run within a pod.", "description": "A single application container that you want to run within a pod.",
......
...@@ -1377,6 +1377,10 @@ ...@@ -1377,6 +1377,10 @@
"portworxVolume": { "portworxVolume": {
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
},
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
} }
} }
}, },
...@@ -2119,6 +2123,57 @@ ...@@ -2119,6 +2123,57 @@
} }
} }
}, },
"v1.ScaleIOVolumeSource": {
"id": "v1.ScaleIOVolumeSource",
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"gateway": {
"type": "string",
"description": "The host address of the ScaleIO API Gateway."
},
"system": {
"type": "string",
"description": "The name of the storage system as configured in ScaleIO."
},
"secretRef": {
"$ref": "v1.LocalObjectReference",
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail."
},
"sslEnabled": {
"type": "boolean",
"description": "Flag to enable/disable SSL communication with Gateway, default false"
},
"protectionDomain": {
"type": "string",
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\")."
},
"storagePool": {
"type": "string",
"description": "The Storage Pool associated with the protection domain (defaults to \"default\")."
},
"storageMode": {
"type": "string",
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\")."
},
"volumeName": {
"type": "string",
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source."
},
"fsType": {
"type": "string",
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified."
},
"readOnly": {
"type": "boolean",
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
}
}
},
"v1.VolumeMount": { "v1.VolumeMount": {
"id": "v1.VolumeMount", "id": "v1.VolumeMount",
"description": "VolumeMount describes a mounting of a Volume within a container.", "description": "VolumeMount describes a mounting of a Volume within a container.",
......
...@@ -18013,6 +18013,10 @@ ...@@ -18013,6 +18013,10 @@
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
}, },
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
},
"accessModes": { "accessModes": {
"type": "array", "type": "array",
"items": { "items": {
...@@ -18512,6 +18516,57 @@ ...@@ -18512,6 +18516,57 @@
} }
} }
}, },
"v1.ScaleIOVolumeSource": {
"id": "v1.ScaleIOVolumeSource",
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"gateway": {
"type": "string",
"description": "The host address of the ScaleIO API Gateway."
},
"system": {
"type": "string",
"description": "The name of the storage system as configured in ScaleIO."
},
"secretRef": {
"$ref": "v1.LocalObjectReference",
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail."
},
"sslEnabled": {
"type": "boolean",
"description": "Flag to enable/disable SSL communication with Gateway, default false"
},
"protectionDomain": {
"type": "string",
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\")."
},
"storagePool": {
"type": "string",
"description": "The Storage Pool associated with the protection domain (defaults to \"default\")."
},
"storageMode": {
"type": "string",
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\")."
},
"volumeName": {
"type": "string",
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source."
},
"fsType": {
"type": "string",
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified."
},
"readOnly": {
"type": "boolean",
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
}
}
},
"v1.PersistentVolumeStatus": { "v1.PersistentVolumeStatus": {
"id": "v1.PersistentVolumeStatus", "id": "v1.PersistentVolumeStatus",
"description": "PersistentVolumeStatus is the current status of a persistent volume.", "description": "PersistentVolumeStatus is the current status of a persistent volume.",
...@@ -18808,6 +18863,10 @@ ...@@ -18808,6 +18863,10 @@
"portworxVolume": { "portworxVolume": {
"$ref": "v1.PortworxVolumeSource", "$ref": "v1.PortworxVolumeSource",
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine" "description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
},
"scaleIO": {
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
} }
} }
}, },
......
...@@ -87,6 +87,7 @@ go_library( ...@@ -87,6 +87,7 @@ go_library(
"//pkg/volume/portworx:go_default_library", "//pkg/volume/portworx:go_default_library",
"//pkg/volume/quobyte:go_default_library", "//pkg/volume/quobyte:go_default_library",
"//pkg/volume/rbd:go_default_library", "//pkg/volume/rbd:go_default_library",
"//pkg/volume/scaleio:go_default_library",
"//pkg/volume/vsphere_volume:go_default_library", "//pkg/volume/vsphere_volume:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:github.com/prometheus/client_golang/prometheus", "//vendor:github.com/prometheus/client_golang/prometheus",
......
...@@ -53,6 +53,7 @@ import ( ...@@ -53,6 +53,7 @@ import (
"k8s.io/kubernetes/pkg/volume/portworx" "k8s.io/kubernetes/pkg/volume/portworx"
"k8s.io/kubernetes/pkg/volume/quobyte" "k8s.io/kubernetes/pkg/volume/quobyte"
"k8s.io/kubernetes/pkg/volume/rbd" "k8s.io/kubernetes/pkg/volume/rbd"
"k8s.io/kubernetes/pkg/volume/scaleio"
"k8s.io/kubernetes/pkg/volume/vsphere_volume" "k8s.io/kubernetes/pkg/volume/vsphere_volume"
) )
...@@ -73,6 +74,7 @@ func ProbeAttachableVolumePlugins(config componentconfig.VolumeConfiguration) [] ...@@ -73,6 +74,7 @@ func ProbeAttachableVolumePlugins(config componentconfig.VolumeConfiguration) []
allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...) allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...) allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...) allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...)
return allPlugins return allPlugins
} }
...@@ -118,6 +120,7 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config componen ...@@ -118,6 +120,7 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config componen
allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...) allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...) allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...)
if cloud != nil { if cloud != nil {
switch { switch {
......
...@@ -94,6 +94,7 @@ go_library( ...@@ -94,6 +94,7 @@ go_library(
"//pkg/volume/projected:go_default_library", "//pkg/volume/projected:go_default_library",
"//pkg/volume/quobyte:go_default_library", "//pkg/volume/quobyte:go_default_library",
"//pkg/volume/rbd:go_default_library", "//pkg/volume/rbd:go_default_library",
"//pkg/volume/scaleio:go_default_library",
"//pkg/volume/secret:go_default_library", "//pkg/volume/secret:go_default_library",
"//pkg/volume/vsphere_volume:go_default_library", "//pkg/volume/vsphere_volume:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
......
...@@ -50,6 +50,7 @@ import ( ...@@ -50,6 +50,7 @@ import (
"k8s.io/kubernetes/pkg/volume/projected" "k8s.io/kubernetes/pkg/volume/projected"
"k8s.io/kubernetes/pkg/volume/quobyte" "k8s.io/kubernetes/pkg/volume/quobyte"
"k8s.io/kubernetes/pkg/volume/rbd" "k8s.io/kubernetes/pkg/volume/rbd"
"k8s.io/kubernetes/pkg/volume/scaleio"
"k8s.io/kubernetes/pkg/volume/secret" "k8s.io/kubernetes/pkg/volume/secret"
"k8s.io/kubernetes/pkg/volume/vsphere_volume" "k8s.io/kubernetes/pkg/volume/vsphere_volume"
// Cloud providers // Cloud providers
...@@ -92,6 +93,7 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin { ...@@ -92,6 +93,7 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin {
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...) allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...) allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...) allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...)
allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...)
return allPlugins return allPlugins
} }
......
...@@ -489,6 +489,103 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } ...@@ -489,6 +489,103 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_scaleiovolumesource">v1.ScaleIOVolumeSource</h3>
<div class="paragraph">
<p>ScaleIOVolumeSource represents a persistent ScaleIO volume</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gateway</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The host address of the ScaleIO API Gateway.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">system</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the storage system as configured in ScaleIO.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">sslEnabled</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Flag to enable/disable SSL communication with Gateway, default false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">protectionDomain</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the Protection Domain for the configured storage (defaults to "default").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">storagePool</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The Storage Pool associated with the protection domain (defaults to "default").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">storageMode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates whether the storage for a volume should be thick or thin (defaults to "thin").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeName</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of a volume already created in the ScaleIO system that is associated with this volume source.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fsType</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_photonpersistentdiskvolumesource">v1.PhotonPersistentDiskVolumeSource</h3> <h3 id="_v1_photonpersistentdiskvolumesource">v1.PhotonPersistentDiskVolumeSource</h3>
<div class="paragraph"> <div class="paragraph">
<p>Represents a Photon Controller persistent disk resource.</p> <p>Represents a Photon Controller persistent disk resource.</p>
...@@ -3202,6 +3299,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i ...@@ -3202,6 +3299,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_portworxvolumesource">v1.PortworxVolumeSource</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scaleIO</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_scaleiovolumesource">v1.ScaleIOVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
...@@ -3695,7 +3799,7 @@ Examples:<br> ...@@ -3695,7 +3799,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2017-03-01 18:58:24 UTC Last updated 2017-03-02 13:01:30 UTC
</div> </div>
</div> </div>
</body> </body>
......
...@@ -4412,6 +4412,13 @@ The resulting set of endpoints can be viewed as:<br> ...@@ -4412,6 +4412,13 @@ The resulting set of endpoints can be viewed as:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_portworxvolumesource">v1.PortworxVolumeSource</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scaleIO</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_scaleiovolumesource">v1.ScaleIOVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
...@@ -6047,6 +6054,103 @@ Examples:<br> ...@@ -6047,6 +6054,103 @@ Examples:<br>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_scaleiovolumesource">v1.ScaleIOVolumeSource</h3>
<div class="paragraph">
<p>ScaleIOVolumeSource represents a persistent ScaleIO volume</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gateway</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The host address of the ScaleIO API Gateway.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">system</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the storage system as configured in ScaleIO.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">sslEnabled</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Flag to enable/disable SSL communication with Gateway, default false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">protectionDomain</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the Protection Domain for the configured storage (defaults to "default").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">storagePool</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The Storage Pool associated with the protection domain (defaults to "default").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">storageMode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates whether the storage for a volume should be thick or thin (defaults to "thin").</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeName</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of a volume already created in the ScaleIO system that is associated with this volume source.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fsType</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_status">v1.Status</h3> <h3 id="_v1_status">v1.Status</h3>
<div class="paragraph"> <div class="paragraph">
<p>Status is a return value for calls that don&#8217;t return other objects.</p> <p>Status is a return value for calls that don&#8217;t return other objects.</p>
...@@ -7090,6 +7194,13 @@ Examples:<br> ...@@ -7090,6 +7194,13 @@ Examples:<br>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scaleIO</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_scaleiovolumesource">v1.ScaleIOVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">accessModes</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">accessModes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">AccessModes contains all ways the volume can be mounted. More info: <a href="http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes">http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">AccessModes contains all ways the volume can be mounted. More info: <a href="http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes">http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
...@@ -9732,7 +9843,7 @@ Examples:<br> ...@@ -9732,7 +9843,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2017-03-02 03:12:42 UTC Last updated 2017-03-03 18:17:39 UTC
</div> </div>
</div> </div>
</body> </body>
......
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/kubernetes/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
# Dell EMC ScaleIO Volume Plugin for Kubernetes
This document shows how to configure Kubernetes resources to consume storage from volumes hosted on ScaleIO cluster.
## Pre-Requisites
* Kubernetes ver 1.6 or later
* ScaleIO ver 2.0 or later
* A ScaleIO cluster with an API gateway
* ScaleIO SDC binary installed/configured on each Kubernetes node that will consume storage
## ScaleIO Setup
This document assumes you are familiar with ScaleIO and have a cluster ready to go. If you are *not familiar* with ScaleIO, please review *Learn how to setup a 3-node* [ScaleIO cluster on Vagrant](https://github.com/codedellemc/labs/tree/master/setup-scaleio-vagrant) and see *General instructions on* [setting up ScaleIO](https://www.emc.com/products-solutions/trial-software-download/scaleio.htm)
For this demonstration, ensure the followings:
- the ScaleIO `SDC` component is installed and properly configured on all Kubernetes nodes where deployed pods will consume ScaleIO-backed volumes.
- You have a configured ScaleIO gateway that is accessible from the Kubernetes nodes.
## Deploy Kubernetes Secret for ScaleIO
The ScaleIO plugin uses Kubernetes Secret object to store the `username` and `password` credentials used to connect to the ScaleIO gateway API server. In this step, let us create a secret object to save the data. To avoid storing secrets in as clear text, let us encode the ScaleIO credentials as `base64` using the following steps.
```
$> echo -n "siouser" | base64
c2lvdXNlcg==
$> echo -n "sc@l3I0" | base64
c2NAbDNJMA==
```
The previous will generate `base64-encoded` values for the username and password. Remember to generate the credentials for your own environment (not the username/password shown above) . Next, create a secret file, with the encoded values from above, as shown in the following.
File: [secret.yaml](secret.yaml)
```
apiVersion: v1
kind: Secret
metadata:
name: sio-secret
type: kubernetes.io/scaleio
data:
username: c2lvdXNlcg==
password: c2NAbDNJMA==
```
Notice the name of the secret specified above as `sio-secret`. It will be referred in other YAML files. Next, deploy the secret.
```
$ kubectl create -f ./examples/volumes/scaleio/secret.yaml
```
## Deploying Pods with Persistent Volumes
The following example shows how the ScaleIO volume plugin for Kubernetes automatically attach, format, and mount a volume for a deployed pod. This approach requires an existing ScaleIO volume.
### Create Volume
Static persistent volumes require that the volume, to be consumed by the pod, be already created in ScaleIO. You can use your ScaleIO tooling to create a new volume or use the name of a volume that already exists in ScaleIO. For this demo, we assume there's a volume named `vol-0`. If you want to use an existing volume, ensure its name is reflected properly in the `volumeName` attribute below.
### Deploy Pod YAML
Create a pod YAML file that declares the volume (above) to be used.
File: [pod.yaml](pod.yaml)
```
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
```
Notice the followings in the previous YAML:
- Update the `gatewway` to point to your ScaleIO gateway endpoint.
- The `volumeName` attribute refers to the name of an existing volume in ScaleIO.
- The `secretRef` attribute references the name of the secret object deployed earlier.
Next, deploy the pod.
```
$> kubectl create -f examples/volumes/scaleio/pod.yaml
```
You can verify the pod:
```
$> kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-0 1/1 Running 0 33s
```
Or for more detail, use
```
kubectl describe pod pod-0
```
You can see the attached/mapped volume on the node:
```
$> lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
...
scinia 252:0 0 8G 0 disk /var/lib/kubelet/pods/135986c7-dcb7-11e6-9fbf-080027c990a7/volumes/kubernetes.io~scaleio/vol-0
```
## StorageClass and Dynamic Provisioning
In this example, we will see how the ScaleIO volume plugin can automatically provision a new volume as described in a `StorageClass`.
### StorageClass
Define a new `StorageClass` as shown in the following YAML.
File [sc.yaml](sc.yaml)
```
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: sio-small
provisioner: kubernetes.io/scaleio
parameters:
gateway: https://localhost:443/api
system: scaleio
protectionDomain: default
secretRef: sio-secret
fsType: xfs
```
Note the followings:
- The `name` attribute is set to `sio-small` . It will be referenced later.
- The `provisioner` attribute is set to `kubernetes.io/scaleio` to trigger the ScaleIO plugin.
- The use of the `parameters:` section in the yaml for configurations.
- The `secretRef` attribute matches the name of the Secret object created earlier.
Next, deploy the storage class file.
```
$> kubectl create -f examples/volumes/scaleio/sc.yaml
$> kubectl get sc
NAME TYPE
sio-small kubernetes.io/scaleio
```
### PVC for the StorageClass
The next step is to define/deploy a `PeristentVolumeClaim` that will use the StorageClass.
File [sc-pvc.yaml](sc-pvc.yaml)
```
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-sio-small
annotations:
volume.beta.kubernetes.io/storage-class: sio-small
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
```
Note the `annotations:` entry which specifies annotation `volume.beta.kubernetes.io/storage-class: sio-small` which references the name of the storage class defined earlier.
Next, we deploy PVC file for the storage class. This step will cause the Kubernetes ScaleIO plugin to create the volume in the storage system.
```
$> kubectl create -f examples/volumes/scaleio/sc-pvc.yaml
```
You verify that a new volume created in the ScaleIO dashboard. You can also verify the newly created volume as follows.
```
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
pvc-sio-small Bound pvc-5fc78518-dcae-11e6-a263-080027c990a7 10Gi RWO 1h
```
###Pod for PVC and SC
At this point, the volume is created (by the claim) in the storage system. To use it, we must define a pod that references the volume as done in this YAML.
File [pod-sc-pvc.yaml](pod-sc-pvc.yaml)
```
kind: Pod
apiVersion: v1
metadata:
name: pod-sio-small
spec:
containers:
- name: pod-sio-small-container
image: gcr.io/google_containers/test-webserver
volumeMounts:
- mountPath: /test
name: test-data
volumes:
- name: test-data
persistentVolumeClaim:
claimName: pvc-sio-small
```
Notice that the `claimName:` attribute refers to the name of the PVC defined and deployed earlier. Next, let us deploy the file.
```
$> kubectl create -f examples/volumes/scaleio/pod-sc-pvc.yaml
```
We can now verify that the new pod is deployed OK.
```
kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-0 1/1 Running 0 23m
pod-sio-small 1/1 Running 0 5s
```
You can use the ScaleIO dashboard to verify that the new volume has one attachment. You can verify the volume information for the pod:
```
$> kubectl describe pod pod-sio-small
...
Volumes:
test-data:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-sio-small
ReadOnly: false
...
```
Lastly, you can see the volume's attachment on the Kubernetes node:
```
$> lsblk
...
scinia 252:0 0 8G 0 disk /var/lib/kubelet/pods/135986c7-dcb7-11e6-9fbf-080027c990a7/volumes/kubernetes.io~scaleio/vol-0
scinib 252:16 0 16G 0 disk /var/lib/kubelet/pods/62db442e-dcba-11e6-9fbf-080027c990a7/volumes/kubernetes.io~scaleio/sio-5fc9154ddcae11e68db708002
```
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/volumes/scaleio/README.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->
kind: Pod
apiVersion: v1
metadata:
name: pod-sio-small
spec:
containers:
- name: pod-sio-small-container
image: gcr.io/google_containers/test-webserver
volumeMounts:
- mountPath: /test
name: test-data
volumes:
- name: test-data
persistentVolumeClaim:
claimName: pvc-sio-small
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-sio-small
annotations:
volume.beta.kubernetes.io/storage-class: sio-small
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: sio-small
provisioner: kubernetes.io/scaleio
parameters:
gateway: https://localhost:443/api
system: scaleio
protectionDomain: default
secretRef: sio-secret
fsType: xfs
apiVersion: v1
kind: Secret
metadata:
name: sio-secret
type: kubernetes.io/scaleio
data:
username: YWRtaW4=
password: c0NhbGVpbzEyMw==
...@@ -12961,6 +12961,56 @@ ...@@ -12961,6 +12961,56 @@
} }
} }
}, },
"io.k8s.kubernetes.pkg.api.v1.ScaleIOVolumeSource": {
"description": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"required": [
"gateway",
"system",
"secretRef"
],
"properties": {
"fsType": {
"description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.",
"type": "string"
},
"gateway": {
"description": "The host address of the ScaleIO API Gateway.",
"type": "string"
},
"protectionDomain": {
"description": "The name of the Protection Domain for the configured storage (defaults to \"default\").",
"type": "string"
},
"readOnly": {
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
"type": "boolean"
},
"secretRef": {
"description": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.LocalObjectReference"
},
"sslEnabled": {
"description": "Flag to enable/disable SSL communication with Gateway, default false",
"type": "boolean"
},
"storageMode": {
"description": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").",
"type": "string"
},
"storagePool": {
"description": "The Storage Pool associated with the protection domain (defaults to \"default\").",
"type": "string"
},
"system": {
"description": "The name of the storage system as configured in ScaleIO.",
"type": "string"
},
"volumeName": {
"description": "The name of a volume already created in the ScaleIO system that is associated with this volume source.",
"type": "string"
}
}
},
"io.k8s.kubernetes.pkg.api.v1.Secret": { "io.k8s.kubernetes.pkg.api.v1.Secret": {
"description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "description": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.",
"properties": { "properties": {
...@@ -13451,6 +13501,10 @@ ...@@ -13451,6 +13501,10 @@
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", "description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource" "$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.RBDVolumeSource"
}, },
"scaleIO": {
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ScaleIOVolumeSource"
},
"secret": { "secret": {
"description": "Secret represents a secret that should populate this volume. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", "description": "Secret represents a secret that should populate this volume. More info: http://kubernetes.io/docs/user-guide/volumes#secrets",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.SecretVolumeSource" "$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.SecretVolumeSource"
......
...@@ -84,6 +84,10 @@ func VisitPodSecretNames(pod *api.Pod, visitor func(string) bool) bool { ...@@ -84,6 +84,10 @@ func VisitPodSecretNames(pod *api.Pod, visitor func(string) bool) bool {
if !visitor(source.Secret.SecretName) { if !visitor(source.Secret.SecretName) {
return false return false
} }
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
return false
}
} }
} }
return true return true
......
...@@ -81,7 +81,11 @@ func TestPodSecrets(t *testing.T) { ...@@ -81,7 +81,11 @@ func TestPodSecrets(t *testing.T) {
SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, { SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, {
VolumeSource: api.VolumeSource{ VolumeSource: api.VolumeSource{
Secret: &api.SecretVolumeSource{ Secret: &api.SecretVolumeSource{
SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}}, SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}, {
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
SecretRef: &api.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef"}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.NewString()
...@@ -109,6 +113,7 @@ func TestPodSecrets(t *testing.T) { ...@@ -109,6 +113,7 @@ func TestPodSecrets(t *testing.T) {
"Spec.Volumes[*].VolumeSource.RBD.SecretRef", "Spec.Volumes[*].VolumeSource.RBD.SecretRef",
"Spec.Volumes[*].VolumeSource.Secret", "Spec.Volumes[*].VolumeSource.Secret",
"Spec.Volumes[*].VolumeSource.Secret.SecretName", "Spec.Volumes[*].VolumeSource.Secret.SecretName",
"Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef",
) )
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.Pod{})) secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.Pod{}))
secretPaths = secretPaths.Difference(excludedSecretPaths) secretPaths = secretPaths.Difference(excludedSecretPaths)
......
...@@ -434,6 +434,24 @@ func coreFuncs(t apitesting.TestingCommon) []interface{} { ...@@ -434,6 +434,24 @@ func coreFuncs(t apitesting.TestingCommon) []interface{} {
*obj.ReadOnly = false *obj.ReadOnly = false
} }
}, },
func(sio *api.ScaleIOVolumeSource, c fuzz.Continue) {
sio.ProtectionDomain = c.RandString()
if sio.ProtectionDomain == "" {
sio.ProtectionDomain = "default"
}
sio.StoragePool = c.RandString()
if sio.StoragePool == "" {
sio.StoragePool = "default"
}
sio.StorageMode = c.RandString()
if sio.StorageMode == "" {
sio.StorageMode = "ThinProvisioned"
}
sio.FSType = c.RandString()
if sio.FSType == "" {
sio.FSType = "xfs"
}
},
func(s *api.NamespaceSpec, c fuzz.Continue) { func(s *api.NamespaceSpec, c fuzz.Continue) {
s.Finalizers = []api.FinalizerName{api.FinalizerKubernetes} s.Finalizers = []api.FinalizerName{api.FinalizerKubernetes}
}, },
......
...@@ -299,6 +299,9 @@ type VolumeSource struct { ...@@ -299,6 +299,9 @@ type VolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource PortworxVolume *PortworxVolumeSource
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource
} }
// Similar to VolumeSource but meant for the administrator who creates PVs. // Similar to VolumeSource but meant for the administrator who creates PVs.
...@@ -364,6 +367,9 @@ type PersistentVolumeSource struct { ...@@ -364,6 +367,9 @@ type PersistentVolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource PortworxVolume *PortworxVolumeSource
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource
} }
type PersistentVolumeClaimVolumeSource struct { type PersistentVolumeClaimVolumeSource struct {
...@@ -1056,6 +1062,41 @@ type AzureDiskVolumeSource struct { ...@@ -1056,6 +1062,41 @@ type AzureDiskVolumeSource struct {
ReadOnly *bool ReadOnly *bool
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
type ScaleIOVolumeSource struct {
// The host address of the ScaleIO API Gateway.
Gateway string
// The name of the storage system as configured in ScaleIO.
System string
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
SecretRef *LocalObjectReference
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
SSLEnabled bool
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
ProtectionDomain string
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
StoragePool string
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
StorageMode string
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
VolumeName string
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
FSType string
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
}
// Adapts a ConfigMap into a volume. // Adapts a ConfigMap into a volume.
// //
// The contents of the target ConfigMap's Data field will be presented in a // The contents of the target ConfigMap's Data field will be presented in a
......
...@@ -359,3 +359,18 @@ func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) { ...@@ -359,3 +359,18 @@ func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) {
obj.Keyring = "/etc/ceph/keyring" obj.Keyring = "/etc/ceph/keyring"
} }
} }
func SetDefaults_ScaleIOVolumeSource(obj *ScaleIOVolumeSource) {
if obj.ProtectionDomain == "" {
obj.ProtectionDomain = "default"
}
if obj.StoragePool == "" {
obj.StoragePool = "default"
}
if obj.StorageMode == "" {
obj.StorageMode = "ThinProvisioned"
}
if obj.FSType == "" {
obj.FSType = "xfs"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -2140,6 +2140,10 @@ message PersistentVolumeSource { ...@@ -2140,6 +2140,10 @@ message PersistentVolumeSource {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
optional PortworxVolumeSource portworxVolume = 18; optional PortworxVolumeSource portworxVolume = 18;
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
optional ScaleIOVolumeSource scaleIO = 19;
} }
// PersistentVolumeSpec is the specification of a persistent volume. // PersistentVolumeSpec is the specification of a persistent volume.
...@@ -3210,6 +3214,50 @@ message SELinuxOptions { ...@@ -3210,6 +3214,50 @@ message SELinuxOptions {
optional string level = 4; optional string level = 4;
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
message ScaleIOVolumeSource {
// The host address of the ScaleIO API Gateway.
optional string gateway = 1;
// The name of the storage system as configured in ScaleIO.
optional string system = 2;
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
optional LocalObjectReference secretRef = 3;
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
optional bool sslEnabled = 4;
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
optional string protectionDomain = 5;
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
optional string storagePool = 6;
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
optional string storageMode = 7;
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
optional string volumeName = 8;
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
optional string fsType = 9;
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
optional bool readOnly = 10;
}
// Secret holds secret data of a certain type. The total bytes of the values in // Secret holds secret data of a certain type. The total bytes of the values in
// the Data field must be less than MaxSecretSize bytes. // the Data field must be less than MaxSecretSize bytes.
message Secret { message Secret {
...@@ -3840,11 +3888,15 @@ message VolumeSource { ...@@ -3840,11 +3888,15 @@ message VolumeSource {
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23; optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23;
// Items for all in one resources secrets, configmaps, and downward API // Items for all in one resources secrets, configmaps, and downward API
optional ProjectedVolumeSource projected = 25; optional ProjectedVolumeSource projected = 26;
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
optional PortworxVolumeSource portworxVolume = 24; optional PortworxVolumeSource portworxVolume = 24;
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
optional ScaleIOVolumeSource scaleIO = 25;
} }
// Represents a vSphere volume resource. // Represents a vSphere volume resource.
......
...@@ -172,6 +172,11 @@ func VisitPodSecretNames(pod *v1.Pod, visitor func(string) bool) bool { ...@@ -172,6 +172,11 @@ func VisitPodSecretNames(pod *v1.Pod, visitor func(string) bool) bool {
if !visitor(source.Secret.SecretName) { if !visitor(source.Secret.SecretName) {
return false return false
} }
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
return false
}
} }
} }
return true return true
......
...@@ -249,7 +249,11 @@ func TestPodSecrets(t *testing.T) { ...@@ -249,7 +249,11 @@ func TestPodSecrets(t *testing.T) {
SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, { SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, {
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{ Secret: &v1.SecretVolumeSource{
SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}}, SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}, {
VolumeSource: v1.VolumeSource{
ScaleIO: &v1.ScaleIOVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef"}}}}},
}, },
} }
extractedNames := sets.NewString() extractedNames := sets.NewString()
...@@ -277,6 +281,7 @@ func TestPodSecrets(t *testing.T) { ...@@ -277,6 +281,7 @@ func TestPodSecrets(t *testing.T) {
"Spec.Volumes[*].VolumeSource.RBD.SecretRef", "Spec.Volumes[*].VolumeSource.RBD.SecretRef",
"Spec.Volumes[*].VolumeSource.Secret", "Spec.Volumes[*].VolumeSource.Secret",
"Spec.Volumes[*].VolumeSource.Secret.SecretName", "Spec.Volumes[*].VolumeSource.Secret.SecretName",
"Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef",
) )
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&v1.Pod{})) secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&v1.Pod{}))
secretPaths = secretPaths.Difference(excludedSecretPaths) secretPaths = secretPaths.Difference(excludedSecretPaths)
......
...@@ -331,6 +331,9 @@ type VolumeSource struct { ...@@ -331,6 +331,9 @@ type VolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"` PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource `json:"scaleIO,omitempty" protobuf:"bytes,25,opt,name=scaleIO"`
} }
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. // PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
...@@ -419,6 +422,9 @@ type PersistentVolumeSource struct { ...@@ -419,6 +422,9 @@ type PersistentVolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"` PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"`
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource `json:"scaleIO,omitempty" protobuf:"bytes,19,opt,name=scaleIO"`
} }
const ( const (
...@@ -1138,6 +1144,41 @@ type PortworxVolumeSource struct { ...@@ -1138,6 +1144,41 @@ type PortworxVolumeSource struct {
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
type ScaleIOVolumeSource struct {
// The host address of the ScaleIO API Gateway.
Gateway string `json:"gateway" protobuf:"bytes,1,opt,name=gateway"`
// The name of the storage system as configured in ScaleIO.
System string `json:"system" protobuf:"bytes,2,opt,name=system"`
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
SecretRef *LocalObjectReference `json:"secretRef" protobuf:"bytes,3,opt,name=secretRef"`
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
SSLEnabled bool `json:"sslEnabled,omitempty" protobuf:"varint,4,opt,name=sslEnabled"`
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
ProtectionDomain string `json:"protectionDomain,omitempty" protobuf:"bytes,5,opt,name=protectionDomain"`
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
StoragePool string `json:"storagePool,omitempty" protobuf:"bytes,6,opt,name=storagePool"`
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
StorageMode string `json:"storageMode,omitempty" protobuf:"bytes,7,opt,name=storageMode"`
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
VolumeName string `json:"volumeName,omitempty" protobuf:"bytes,8,opt,name=volumeName"`
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
FSType string `json:"fsType,omitempty" protobuf:"bytes,9,opt,name=fsType"`
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,10,opt,name=readOnly"`
}
// Adapts a ConfigMap into a volume. // Adapts a ConfigMap into a volume.
// //
// The contents of the target ConfigMap's Data field will be presented in a // The contents of the target ConfigMap's Data field will be presented in a
......
...@@ -1124,6 +1124,7 @@ var map_PersistentVolumeSource = map[string]string{ ...@@ -1124,6 +1124,7 @@ var map_PersistentVolumeSource = map[string]string{
"azureDisk": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", "azureDisk": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.",
"photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", "photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", "portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
"scaleIO": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
} }
func (PersistentVolumeSource) SwaggerDoc() map[string]string { func (PersistentVolumeSource) SwaggerDoc() map[string]string {
...@@ -1640,6 +1641,24 @@ func (SELinuxOptions) SwaggerDoc() map[string]string { ...@@ -1640,6 +1641,24 @@ func (SELinuxOptions) SwaggerDoc() map[string]string {
return map_SELinuxOptions return map_SELinuxOptions
} }
var map_ScaleIOVolumeSource = map[string]string{
"": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"gateway": "The host address of the ScaleIO API Gateway.",
"system": "The name of the storage system as configured in ScaleIO.",
"secretRef": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.",
"sslEnabled": "Flag to enable/disable SSL communication with Gateway, default false",
"protectionDomain": "The name of the Protection Domain for the configured storage (defaults to \"default\").",
"storagePool": "The Storage Pool associated with the protection domain (defaults to \"default\").",
"storageMode": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").",
"volumeName": "The name of a volume already created in the ScaleIO system that is associated with this volume source.",
"fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.",
"readOnly": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
}
func (ScaleIOVolumeSource) SwaggerDoc() map[string]string {
return map_ScaleIOVolumeSource
}
var map_Secret = map[string]string{ var map_Secret = map[string]string{
"": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.",
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", "metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
...@@ -1911,6 +1930,7 @@ var map_VolumeSource = map[string]string{ ...@@ -1911,6 +1930,7 @@ var map_VolumeSource = map[string]string{
"photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", "photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
"projected": "Items for all in one resources secrets, configmaps, and downward API", "projected": "Items for all in one resources secrets, configmaps, and downward API",
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", "portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
"scaleIO": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
} }
func (VolumeSource) SwaggerDoc() map[string]string { func (VolumeSource) SwaggerDoc() map[string]string {
......
...@@ -317,6 +317,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { ...@@ -317,6 +317,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_ResourceRequirements_To_v1_ResourceRequirements, Convert_api_ResourceRequirements_To_v1_ResourceRequirements,
Convert_v1_SELinuxOptions_To_api_SELinuxOptions, Convert_v1_SELinuxOptions_To_api_SELinuxOptions,
Convert_api_SELinuxOptions_To_v1_SELinuxOptions, Convert_api_SELinuxOptions_To_v1_SELinuxOptions,
Convert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource,
Convert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource,
Convert_v1_Secret_To_api_Secret, Convert_v1_Secret_To_api_Secret,
Convert_api_Secret_To_v1_Secret, Convert_api_Secret_To_v1_Secret,
Convert_v1_SecretEnvSource_To_api_SecretEnvSource, Convert_v1_SecretEnvSource_To_api_SecretEnvSource,
...@@ -2711,6 +2713,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per ...@@ -2711,6 +2713,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*api.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -2737,6 +2740,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api ...@@ -2737,6 +2740,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -3887,6 +3891,42 @@ func Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in *api.SELinuxOptions, out ...@@ -3887,6 +3891,42 @@ func Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in *api.SELinuxOptions, out
return autoConvert_api_SELinuxOptions_To_v1_SELinuxOptions(in, out, s) return autoConvert_api_SELinuxOptions_To_v1_SELinuxOptions(in, out, s)
} }
func autoConvert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in *ScaleIOVolumeSource, out *api.ScaleIOVolumeSource, s conversion.Scope) error {
out.Gateway = in.Gateway
out.System = in.System
out.SecretRef = (*api.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.SSLEnabled = in.SSLEnabled
out.ProtectionDomain = in.ProtectionDomain
out.StoragePool = in.StoragePool
out.StorageMode = in.StorageMode
out.VolumeName = in.VolumeName
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
return nil
}
func Convert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in *ScaleIOVolumeSource, out *api.ScaleIOVolumeSource, s conversion.Scope) error {
return autoConvert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in, out, s)
}
func autoConvert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *api.ScaleIOVolumeSource, out *ScaleIOVolumeSource, s conversion.Scope) error {
out.Gateway = in.Gateway
out.System = in.System
out.SecretRef = (*LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.SSLEnabled = in.SSLEnabled
out.ProtectionDomain = in.ProtectionDomain
out.StoragePool = in.StoragePool
out.StorageMode = in.StorageMode
out.VolumeName = in.VolumeName
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
return nil
}
func Convert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *api.ScaleIOVolumeSource, out *ScaleIOVolumeSource, s conversion.Scope) error {
return autoConvert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in, out, s)
}
func autoConvert_v1_Secret_To_api_Secret(in *Secret, out *api.Secret, s conversion.Scope) error { func autoConvert_v1_Secret_To_api_Secret(in *Secret, out *api.Secret, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data)) out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data))
...@@ -4487,6 +4527,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api. ...@@ -4487,6 +4527,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*api.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -4520,6 +4561,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out * ...@@ -4520,6 +4561,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
......
...@@ -176,6 +176,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { ...@@ -176,6 +176,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ScaleIOVolumeSource, InType: reflect.TypeOf(&ScaleIOVolumeSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Secret, InType: reflect.TypeOf(&Secret{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Secret, InType: reflect.TypeOf(&Secret{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})},
...@@ -2026,6 +2027,13 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv ...@@ -2026,6 +2027,13 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_v1_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
...@@ -2872,6 +2880,20 @@ func DeepCopy_v1_SELinuxOptions(in interface{}, out interface{}, c *conversion.C ...@@ -2872,6 +2880,20 @@ func DeepCopy_v1_SELinuxOptions(in interface{}, out interface{}, c *conversion.C
} }
} }
func DeepCopy_v1_ScaleIOVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ScaleIOVolumeSource)
out := out.(*ScaleIOVolumeSource)
*out = *in
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(LocalObjectReference)
**out = **in
}
return nil
}
}
func DeepCopy_v1_Secret(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_v1_Secret(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*Secret) in := in.(*Secret)
...@@ -3445,6 +3467,13 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo ...@@ -3445,6 +3467,13 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_v1_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
......
...@@ -137,6 +137,9 @@ func SetObjectDefaults_PersistentVolume(in *PersistentVolume) { ...@@ -137,6 +137,9 @@ func SetObjectDefaults_PersistentVolume(in *PersistentVolume) {
if in.Spec.PersistentVolumeSource.AzureDisk != nil { if in.Spec.PersistentVolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(in.Spec.PersistentVolumeSource.AzureDisk) SetDefaults_AzureDiskVolumeSource(in.Spec.PersistentVolumeSource.AzureDisk)
} }
if in.Spec.PersistentVolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(in.Spec.PersistentVolumeSource.ScaleIO)
}
} }
func SetObjectDefaults_PersistentVolumeClaim(in *PersistentVolumeClaim) { func SetObjectDefaults_PersistentVolumeClaim(in *PersistentVolumeClaim) {
...@@ -204,6 +207,9 @@ func SetObjectDefaults_Pod(in *Pod) { ...@@ -204,6 +207,9 @@ func SetObjectDefaults_Pod(in *Pod) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.InitContainers { for i := range in.Spec.InitContainers {
a := &in.Spec.InitContainers[i] a := &in.Spec.InitContainers[i]
...@@ -349,6 +355,9 @@ func SetObjectDefaults_PodTemplate(in *PodTemplate) { ...@@ -349,6 +355,9 @@ func SetObjectDefaults_PodTemplate(in *PodTemplate) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Template.Spec.InitContainers { for i := range in.Template.Spec.InitContainers {
a := &in.Template.Spec.InitContainers[i] a := &in.Template.Spec.InitContainers[i]
...@@ -488,6 +497,9 @@ func SetObjectDefaults_ReplicationController(in *ReplicationController) { ...@@ -488,6 +497,9 @@ func SetObjectDefaults_ReplicationController(in *ReplicationController) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -540,6 +540,14 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E ...@@ -540,6 +540,14 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
allErrs = append(allErrs, validateProjectedVolumeSource(source.Projected, fldPath.Child("projected"))...) allErrs = append(allErrs, validateProjectedVolumeSource(source.Projected, fldPath.Child("projected"))...)
} }
} }
if source.ScaleIO != nil {
if numVolumes > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("scaleIO"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateScaleIOVolumeSource(source.ScaleIO, fldPath.Child("scaleIO"))...)
}
}
if numVolumes == 0 { if numVolumes == 0 {
allErrs = append(allErrs, field.Required(fldPath, "must specify a volume type")) allErrs = append(allErrs, field.Required(fldPath, "must specify a volume type"))
...@@ -1004,6 +1012,20 @@ func validatePortworxVolumeSource(pwx *api.PortworxVolumeSource, fldPath *field. ...@@ -1004,6 +1012,20 @@ func validatePortworxVolumeSource(pwx *api.PortworxVolumeSource, fldPath *field.
return allErrs return allErrs
} }
func validateScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if sio.Gateway == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("gateway"), ""))
}
if sio.System == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("system"), ""))
}
if sio.VolumeName == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("volumeName"), ""))
}
return allErrs
}
// ValidatePersistentVolumeName checks that a name is appropriate for a // ValidatePersistentVolumeName checks that a name is appropriate for a
// PersistentVolumeName object. // PersistentVolumeName object.
var ValidatePersistentVolumeName = NameIsDNSSubdomain var ValidatePersistentVolumeName = NameIsDNSSubdomain
...@@ -1189,6 +1211,14 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList { ...@@ -1189,6 +1211,14 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateAzureDisk(pv.Spec.AzureDisk, specPath.Child("azureDisk"))...) allErrs = append(allErrs, validateAzureDisk(pv.Spec.AzureDisk, specPath.Child("azureDisk"))...)
} }
if pv.Spec.ScaleIO != nil {
if numVolumes > 0 {
allErrs = append(allErrs, field.Forbidden(specPath.Child("scaleIO"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateScaleIOVolumeSource(pv.Spec.ScaleIO, specPath.Child("scaleIO"))...)
}
}
if numVolumes == 0 { if numVolumes == 0 {
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type")) allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
......
...@@ -1968,6 +1968,65 @@ func TestValidateVolumes(t *testing.T) { ...@@ -1968,6 +1968,65 @@ func TestValidateVolumes(t *testing.T) {
errtype: field.ErrorTypeRequired, errtype: field.ErrorTypeRequired,
errfield: "azureDisk.diskURI", errfield: "azureDisk.diskURI",
}, },
// ScaleIO
{
name: "valid scaleio volume",
vol: api.Volume{
Name: "scaleio-volume",
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
Gateway: "http://abcd/efg",
System: "test-system",
VolumeName: "test-vol-1",
},
},
},
},
{
name: "ScaleIO with empty name",
vol: api.Volume{
Name: "scaleio-volume",
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
Gateway: "http://abcd/efg",
System: "test-system",
VolumeName: "",
},
},
},
errtype: field.ErrorTypeRequired,
errfield: "scaleIO.volumeName",
},
{
name: "ScaleIO with empty gateway",
vol: api.Volume{
Name: "scaleio-volume",
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
Gateway: "",
System: "test-system",
VolumeName: "test-vol-1",
},
},
},
errtype: field.ErrorTypeRequired,
errfield: "scaleIO.gateway",
},
{
name: "ScaleIO with empty system",
vol: api.Volume{
Name: "scaleio-volume",
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
Gateway: "http://agc/efg/gateway",
System: "",
VolumeName: "test-vol-1",
},
},
},
errtype: field.ErrorTypeRequired,
errfield: "scaleIO.system",
},
} }
for i, tc := range testCases { for i, tc := range testCases {
......
...@@ -179,6 +179,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { ...@@ -179,6 +179,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ScaleIOVolumeSource, InType: reflect.TypeOf(&ScaleIOVolumeSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Secret, InType: reflect.TypeOf(&Secret{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Secret, InType: reflect.TypeOf(&Secret{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})},
...@@ -2070,6 +2071,13 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con ...@@ -2070,6 +2071,13 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_api_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
...@@ -2911,6 +2919,20 @@ func DeepCopy_api_SELinuxOptions(in interface{}, out interface{}, c *conversion. ...@@ -2911,6 +2919,20 @@ func DeepCopy_api_SELinuxOptions(in interface{}, out interface{}, c *conversion.
} }
} }
func DeepCopy_api_ScaleIOVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ScaleIOVolumeSource)
out := out.(*ScaleIOVolumeSource)
*out = *in
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(LocalObjectReference)
**out = **in
}
return nil
}
}
func DeepCopy_api_Secret(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_api_Secret(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*Secret) in := in.(*Secret)
...@@ -3472,6 +3494,13 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl ...@@ -3472,6 +3494,13 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_api_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
......
...@@ -80,6 +80,9 @@ func SetObjectDefaults_Deployment(in *Deployment) { ...@@ -80,6 +80,9 @@ func SetObjectDefaults_Deployment(in *Deployment) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -218,6 +221,9 @@ func SetObjectDefaults_StatefulSet(in *StatefulSet) { ...@@ -218,6 +221,9 @@ func SetObjectDefaults_StatefulSet(in *StatefulSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -78,6 +78,9 @@ func SetObjectDefaults_Job(in *Job) { ...@@ -78,6 +78,9 @@ func SetObjectDefaults_Job(in *Job) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
api_v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *CronJob) { ...@@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *CronJob) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.JobTemplate.Spec.Template.Spec.InitContainers { for i := range in.Spec.JobTemplate.Spec.Template.Spec.InitContainers {
a := &in.Spec.JobTemplate.Spec.Template.Spec.InitContainers[i] a := &in.Spec.JobTemplate.Spec.Template.Spec.InitContainers[i]
...@@ -219,6 +222,9 @@ func SetObjectDefaults_Job(in *Job) { ...@@ -219,6 +222,9 @@ func SetObjectDefaults_Job(in *Job) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -356,6 +362,9 @@ func SetObjectDefaults_JobTemplate(in *JobTemplate) { ...@@ -356,6 +362,9 @@ func SetObjectDefaults_JobTemplate(in *JobTemplate) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Template.Spec.Template.Spec.InitContainers { for i := range in.Template.Spec.Template.Spec.InitContainers {
a := &in.Template.Spec.Template.Spec.InitContainers[i] a := &in.Template.Spec.Template.Spec.InitContainers[i]
......
...@@ -918,6 +918,7 @@ var ( ...@@ -918,6 +918,7 @@ var (
PhotonPersistentDisk FSType = "photonPersistentDisk" PhotonPersistentDisk FSType = "photonPersistentDisk"
Projected FSType = "projected" Projected FSType = "projected"
PortworxVolume FSType = "portworxVolume" PortworxVolume FSType = "portworxVolume"
ScaleIO FSType = "scaleIO"
All FSType = "*" All FSType = "*"
) )
......
...@@ -84,6 +84,9 @@ func SetObjectDefaults_DaemonSet(in *DaemonSet) { ...@@ -84,6 +84,9 @@ func SetObjectDefaults_DaemonSet(in *DaemonSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -222,6 +225,9 @@ func SetObjectDefaults_Deployment(in *Deployment) { ...@@ -222,6 +225,9 @@ func SetObjectDefaults_Deployment(in *Deployment) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -371,6 +377,9 @@ func SetObjectDefaults_ReplicaSet(in *ReplicaSet) { ...@@ -371,6 +377,9 @@ func SetObjectDefaults_ReplicaSet(in *ReplicaSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -84,6 +84,9 @@ func SetObjectDefaults_PodPreset(in *PodPreset) { ...@@ -84,6 +84,9 @@ func SetObjectDefaults_PodPreset(in *PodPreset) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
} }
......
...@@ -626,6 +626,8 @@ func describeVolumes(volumes []api.Volume, w *PrefixWriter, space string) { ...@@ -626,6 +626,8 @@ func describeVolumes(volumes []api.Volume, w *PrefixWriter, space string) {
printPhotonPersistentDiskVolumeSource(volume.VolumeSource.PhotonPersistentDisk, w) printPhotonPersistentDiskVolumeSource(volume.VolumeSource.PhotonPersistentDisk, w)
case volume.VolumeSource.PortworxVolume != nil: case volume.VolumeSource.PortworxVolume != nil:
printPortworxVolumeSource(volume.VolumeSource.PortworxVolume, w) printPortworxVolumeSource(volume.VolumeSource.PortworxVolume, w)
case volume.VolumeSource.ScaleIO != nil:
printScaleIOVolumeSource(volume.VolumeSource.ScaleIO, w)
default: default:
w.Write(LEVEL_1, "<unknown>\n") w.Write(LEVEL_1, "<unknown>\n")
} }
...@@ -788,6 +790,19 @@ func printCinderVolumeSource(cinder *api.CinderVolumeSource, w *PrefixWriter) { ...@@ -788,6 +790,19 @@ func printCinderVolumeSource(cinder *api.CinderVolumeSource, w *PrefixWriter) {
cinder.VolumeID, cinder.FSType, cinder.ReadOnly) cinder.VolumeID, cinder.FSType, cinder.ReadOnly)
} }
func printScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, w *PrefixWriter) {
w.Write(LEVEL_2, "Type:\tScaleIO (a persistent volume backed by a block device in ScaleIO)\n"+
" Gateway:\t%v\n"+
" System:\t%v\n"+
" Protection Domain:\t%v\n"+
" Storage Pool:\t%v\n"+
" Storage Mode:\t%v\n"+
" VolumeName:\t%v\n"+
" FSType:\t%v\n"+
" ReadOnly:\t%v\n",
sio.Gateway, sio.System, sio.ProtectionDomain, sio.StoragePool, sio.StorageMode, sio.VolumeName, sio.FSType, sio.ReadOnly)
}
type PersistentVolumeDescriber struct { type PersistentVolumeDescriber struct {
clientset.Interface clientset.Interface
} }
...@@ -852,6 +867,8 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe ...@@ -852,6 +867,8 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
printPhotonPersistentDiskVolumeSource(pv.Spec.PhotonPersistentDisk, w) printPhotonPersistentDiskVolumeSource(pv.Spec.PhotonPersistentDisk, w)
case pv.Spec.PortworxVolume != nil: case pv.Spec.PortworxVolume != nil:
printPortworxVolumeSource(pv.Spec.PortworxVolume, w) printPortworxVolumeSource(pv.Spec.PortworxVolume, w)
case pv.Spec.ScaleIO != nil:
printScaleIOVolumeSource(pv.Spec.ScaleIO, w)
} }
if events != nil { if events != nil {
......
...@@ -64,6 +64,7 @@ func GetAllFSTypesAsSet() sets.String { ...@@ -64,6 +64,7 @@ func GetAllFSTypesAsSet() sets.String {
string(extensions.PhotonPersistentDisk), string(extensions.PhotonPersistentDisk),
string(extensions.Projected), string(extensions.Projected),
string(extensions.PortworxVolume), string(extensions.PortworxVolume),
string(extensions.ScaleIO),
) )
return fstypes return fstypes
} }
...@@ -121,6 +122,8 @@ func GetVolumeFSType(v api.Volume) (extensions.FSType, error) { ...@@ -121,6 +122,8 @@ func GetVolumeFSType(v api.Volume) (extensions.FSType, error) {
return extensions.Projected, nil return extensions.Projected, nil
case v.PortworxVolume != nil: case v.PortworxVolume != nil:
return extensions.PortworxVolume, nil return extensions.PortworxVolume, nil
case v.ScaleIO != nil:
return extensions.ScaleIO, nil
} }
return "", fmt.Errorf("unknown volume type for volume: %#v", v) return "", fmt.Errorf("unknown volume type for volume: %#v", v)
......
...@@ -114,6 +114,7 @@ filegroup( ...@@ -114,6 +114,7 @@ filegroup(
"//pkg/volume/projected:all-srcs", "//pkg/volume/projected:all-srcs",
"//pkg/volume/quobyte:all-srcs", "//pkg/volume/quobyte:all-srcs",
"//pkg/volume/rbd:all-srcs", "//pkg/volume/rbd:all-srcs",
"//pkg/volume/scaleio:all-srcs",
"//pkg/volume/secret:all-srcs", "//pkg/volume/secret:all-srcs",
"//pkg/volume/testing:all-srcs", "//pkg/volume/testing:all-srcs",
"//pkg/volume/util:all-srcs", "//pkg/volume/util:all-srcs",
......
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"sio_mgr_test.go",
"sio_util_test.go",
"sio_volume_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api/v1:go_default_library",
"//pkg/client/clientset_generated/clientset/fake:go_default_library",
"//pkg/util/mount:go_default_library",
"//pkg/volume:go_default_library",
"//pkg/volume/testing:go_default_library",
"//vendor:github.com/codedellemc/goscaleio/types/v1",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/client-go/util/testing",
],
)
go_library(
name = "go_default_library",
srcs = [
"sio_client.go",
"sio_mgr.go",
"sio_plugin.go",
"sio_util.go",
"sio_volume.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api/v1:go_default_library",
"//pkg/util/exec:go_default_library",
"//pkg/util/keymutex:go_default_library",
"//pkg/util/mount:go_default_library",
"//pkg/util/strings:go_default_library",
"//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library",
"//vendor:github.com/codedellemc/goscaleio",
"//vendor:github.com/codedellemc/goscaleio/types/v1",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/resource",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/uuid",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
package scaleio
import (
"errors"
"strconv"
"github.com/golang/glog"
siotypes "github.com/codedellemc/goscaleio/types/v1"
)
type storageInterface interface {
CreateVolume(string, int64) (*siotypes.Volume, error)
AttachVolume(string) (string, error)
IsAttached(string) (bool, error)
DetachVolume(string) error
DeleteVolume(string) error
}
type sioMgr struct {
client sioInterface
configData map[string]string
}
func newSioMgr(configs map[string]string) (*sioMgr, error) {
if configs == nil {
return nil, errors.New("missing configuration data")
}
configs[confKey.protectionDomain] = defaultString(configs[confKey.protectionDomain], "default")
configs[confKey.storagePool] = defaultString(configs[confKey.storagePool], "default")
configs[confKey.sdcRootPath] = defaultString(configs[confKey.sdcRootPath], sdcRootPath)
configs[confKey.storageMode] = defaultString(configs[confKey.storageMode], "ThinProvisioned")
mgr := &sioMgr{configData: configs}
return mgr, nil
}
// getClient safely returns an sioInterface
func (m *sioMgr) getClient() (sioInterface, error) {
if m.client == nil {
glog.V(4).Info(log("creating scaleio client"))
configs := m.configData
username := configs[confKey.username]
password := configs[confKey.password]
gateway := configs[confKey.gateway]
b, err := strconv.ParseBool(configs[confKey.sslEnabled])
if err != nil {
glog.Error(log("failed to parse sslEnabled, must be either \"true\" or \"false\""))
return nil, err
}
certsEnabled := b
glog.V(4).Info(log("creating new client for gateway %s", gateway))
client, err := newSioClient(gateway, username, password, certsEnabled)
if err != nil {
glog.Error(log("failed to create scaleio client: %v", err))
return nil, err
}
client.sysName = configs[confKey.system]
client.pdName = configs[confKey.protectionDomain]
client.spName = configs[confKey.storagePool]
client.sdcPath = configs[confKey.sdcRootPath]
client.provisionMode = configs[confKey.storageMode]
m.client = client
glog.V(4).Info(log("client created successfully [gateway=%s]", gateway))
}
return m.client, nil
}
// CreateVolume creates a new ScaleIO volume
func (m *sioMgr) CreateVolume(volName string, sizeGB int64) (*siotypes.Volume, error) {
client, err := m.getClient()
if err != nil {
return nil, err
}
glog.V(4).Infof("scaleio: creating volume %s", volName)
vol, err := client.CreateVolume(volName, sizeGB)
if err != nil {
glog.V(4).Infof("scaleio: failed creating volume %s: %v", volName, err)
return nil, err
}
glog.V(4).Infof("scaleio: created volume %s successfully", volName)
return vol, nil
}
// AttachVolume maps a ScaleIO volume to the running node
func (m *sioMgr) AttachVolume(volName string) (string, error) {
client, err := m.getClient()
if err != nil {
glog.Error(log("attach volume failed: %v", err))
return "", err
}
glog.V(4).Infoln(log("attaching volume %s", volName))
iid, err := client.IID()
if err != nil {
glog.Error(log("failed to get instanceID"))
return "", err
}
glog.V(4).Info(log("attaching volume %s to host instance %s", volName, iid))
devs, err := client.Devs()
if err != nil {
return "", err
}
vol, err := client.FindVolume(volName)
if err != nil {
glog.Error(log("failed to find volume %s: %v", volName, err))
return "", err
}
// handle vol if already attached
if len(vol.MappedSdcInfo) > 0 {
if m.isSdcMappedToVol(iid, vol) {
glog.V(4).Info(log("skippping attachment, volume %s already attached to sdc %s", volName, iid))
return devs[vol.ID], nil
}
}
// attach volume, get deviceName
if err := client.AttachVolume(sioVolumeID(vol.ID)); err != nil {
glog.Error(log("attachment for volume %s failed :%v", volName, err))
return "", err
}
device, err := client.WaitForAttachedDevice(vol.ID)
if err != nil {
glog.Error(log("failed while waiting for device to attach: %v", err))
return "", err
}
glog.V(4).Info(log("volume %s attached succesfully as %s to instance %s", volName, device, iid))
return device, nil
}
// IsAttached verifies that the named ScaleIO volume is still attached
func (m *sioMgr) IsAttached(volName string) (bool, error) {
client, err := m.getClient()
if err != nil {
return false, err
}
iid, err := client.IID()
if err != nil {
glog.Error("scaleio: failed to get instanceID")
return false, err
}
vol, err := client.FindVolume(volName)
if err != nil {
return false, err
}
return m.isSdcMappedToVol(iid, vol), nil
}
// DetachVolume detaches the name ScaleIO volume from an instance
func (m *sioMgr) DetachVolume(volName string) error {
client, err := m.getClient()
if err != nil {
return err
}
iid, err := client.IID()
if err != nil {
glog.Error(log("failed to get instanceID: %v", err))
return err
}
vol, err := client.FindVolume(volName)
if err != nil {
return err
}
if !m.isSdcMappedToVol(iid, vol) {
glog.Warning(log(
"skipping detached, vol %s not attached to instance %s",
volName, iid,
))
return nil
}
if err := client.DetachVolume(sioVolumeID(vol.ID)); err != nil {
glog.Error(log("failed to detach vol %s: %v", volName, err))
return err
}
glog.V(4).Info(log("volume %s detached successfully", volName))
return nil
}
// DeleteVolumes removes the ScaleIO volume
func (m *sioMgr) DeleteVolume(volName string) error {
client, err := m.getClient()
if err != nil {
return err
}
iid, err := client.IID()
if err != nil {
glog.Error(log("failed to get instanceID: %v", err))
return err
}
vol, err := client.FindVolume(volName)
if err != nil {
return err
}
// if still attached, stop
if m.isSdcMappedToVol(iid, vol) {
glog.Error(log("volume %s still attached, unable to delete", volName))
return errors.New("volume still attached")
}
if err := client.DeleteVolume(sioVolumeID(vol.ID)); err != nil {
glog.Error(log("failed to delete volume %s: %v", volName, err))
return err
}
glog.V(4).Info(log("deleted volume %s successfully", volName))
return nil
}
//*****************************************************************
// Helpers
//*****************************************************************
// isSdcMappedToVol returns true if the sdc is mapped to the volume
func (m *sioMgr) isSdcMappedToVol(sdcID string, vol *siotypes.Volume) bool {
if len(vol.MappedSdcInfo) == 0 {
glog.V(4).Info(log("no attachment found"))
return false
}
for _, sdcInfo := range vol.MappedSdcInfo {
if sdcInfo.SdcID == sdcID {
return true
}
}
return false
}
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
package scaleio
import (
"errors"
"testing"
"time"
siotypes "github.com/codedellemc/goscaleio/types/v1"
)
var (
fakeSdcID = "test-sdc-123456789"
fakeVolumeName = "test-vol-0001"
fakeVolumeID = "1234567890"
fakeDev = "/dev/testABC"
fakeConfig = map[string]string{
confKey.gateway: "http://sio.gateway:1234",
confKey.sslEnabled: "false",
confKey.system: "scaleio",
confKey.volumeName: "sio-0001",
confKey.secretRef: "sio-secret",
confKey.username: "c2lvdXNlcgo=", // siouser
confKey.password: "c2lvcGFzc3dvcmQK", // siopassword
}
)
func newTestMgr(t *testing.T) *sioMgr {
mgr, err := newSioMgr(fakeConfig)
if err != nil {
t.Error(err)
}
mgr.client = newFakeSio()
return mgr
}
func TestMgrNew(t *testing.T) {
mgr, err := newSioMgr(fakeConfig)
if err != nil {
t.Fatal(err)
}
if mgr.configData == nil {
t.Fatal("configuration data not set")
}
if mgr.configData[confKey.volumeName] != "sio-0001" {
t.Errorf("expecting %s, got %s", "sio-0001", mgr.configData[confKey.volumeName])
}
// check defaults
if mgr.configData[confKey.protectionDomain] != "default" {
t.Errorf("unexpected value for confData[protectionDomain] %s", mgr.configData[confKey.protectionDomain])
}
if mgr.configData[confKey.storagePool] != "default" {
t.Errorf("unexpected value for confData[storagePool] %s", mgr.configData[confKey.storagePool])
}
if mgr.configData[confKey.storageMode] != "ThinProvisioned" {
t.Errorf("unexpected value for confData[storageMode] %s", mgr.configData[confKey.storageMode])
}
}
func TestMgrGetClient(t *testing.T) {
mgr := newTestMgr(t)
_, err := mgr.getClient()
if err != nil {
t.Fatal(err)
}
if mgr.client == nil {
t.Fatal("mgr.client not set")
}
}
func TestMgrCreateVolume(t *testing.T) {
mgr := newTestMgr(t)
vol, err := mgr.CreateVolume("test-vol-0001", 8*1024*1024)
if err != nil {
t.Fatal(err)
}
if vol.Name != "test-vol-0001" {
t.Errorf("unexpected vol.Name %s", vol.Name)
}
}
func TestMgrAttachVolume(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
device, err := mgr.AttachVolume("test-vol-0001")
if err != nil {
t.Fatal(err)
}
if device != "/dev/testABC" {
t.Errorf("unexpected value for mapped device %s", device)
}
}
func TestMgrAttachVolume_AlreadyAttached(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
mgr.AttachVolume("test-vol-0001")
dev, err := mgr.AttachVolume("test-vol-0001")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if dev != "/dev/testABC" {
t.Errorf("unexpected value for mapped device %s", dev)
}
}
func TestMgrAttachVolume_VolumeNotFoundError(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
_, err := mgr.AttachVolume("test-vol-0002")
if err == nil {
t.Error("attachVolume should fail with volume not found error")
}
}
func TestMgrAttachVolume_WaitForAttachError(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
go func() {
c := mgr.client.(*fakeSio)
close(c.waitAttachCtrl)
}()
_, err := mgr.AttachVolume("test-vol-0001")
if err == nil {
t.Error("attachVolume should fail with attach timeout error")
}
}
func TestMgrDetachVolume(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
mgr.AttachVolume("test-vol-0001")
if err := mgr.DetachVolume("test-vol-0001"); err != nil {
t.Fatal(err)
}
fakeSio := mgr.client.(*fakeSio)
if len(fakeSio.volume.MappedSdcInfo) != 0 {
t.Errorf("expecting attached sdc to 0, got %d", len(fakeSio.volume.MappedSdcInfo))
}
if len(fakeSio.devs) != 0 {
t.Errorf("expecting local devs to be 0, got %d", len(fakeSio.devs))
}
}
func TestMgrDetachVolume_VolumeNotFound(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
mgr.AttachVolume("test-vol-0001")
err := mgr.DetachVolume("test-vol-0002")
if err == nil {
t.Fatal("expected a volume not found failure")
}
}
func TestMgrDetachVolume_VolumeNotAttached(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
err := mgr.DetachVolume("test-vol-0001")
if err != nil {
t.Fatal(err)
}
}
func TestMgrDetachVolume_VolumeAlreadyDetached(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
mgr.AttachVolume("test-vol-0001")
mgr.DetachVolume("test-vol-0001")
err := mgr.DetachVolume("test-vol-0001")
if err != nil {
t.Fatal("failed detaching a volume already detached")
}
}
func TestMgrDetachVolume_WaitForDetachError(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
mgr.AttachVolume("test-vol-0001")
err := mgr.DetachVolume("test-vol-0001")
if err != nil {
t.Error("detachVolume failed")
}
}
func TestMgrDeleteVolume(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
err := mgr.DeleteVolume("test-vol-0001")
if err != nil {
t.Fatal(err)
}
sio := mgr.client.(*fakeSio)
if sio.volume != nil {
t.Errorf("volume not nil after delete operation")
}
}
func TestMgrDeleteVolume_VolumeNotFound(t *testing.T) {
mgr := newTestMgr(t)
mgr.CreateVolume("test-vol-0001", 8*1024*1024)
err := mgr.DeleteVolume("test-vol-0002")
if err == nil {
t.Fatal("expected volume not found error")
}
}
// ************************************************************
// Helper Test Types
// ************************************************************
type fakeSio struct {
volume *siotypes.Volume
waitAttachCtrl chan struct{}
waitDetachCtrl chan struct{}
devs map[string]string
}
func newFakeSio() *fakeSio {
return &fakeSio{
waitAttachCtrl: make(chan struct{}),
waitDetachCtrl: make(chan struct{}),
}
}
func (f *fakeSio) FindVolume(volumeName string) (*siotypes.Volume, error) {
if f.volume == nil || f.volume.Name != volumeName {
return nil, errors.New("volume not found")
}
return f.volume, nil
}
func (f *fakeSio) Volume(id sioVolumeID) (*siotypes.Volume, error) {
if f.volume == nil || f.volume.ID != string(id) {
return nil, errors.New("volume not found")
}
return f.volume, nil
}
func (f *fakeSio) CreateVolume(volName string, sizeGB int64) (*siotypes.Volume, error) {
f.volume = &siotypes.Volume{
ID: fakeVolumeID,
Name: volName,
SizeInKb: int(sizeGB),
VolumeType: "test",
}
return f.volume, nil
}
func (f *fakeSio) AttachVolume(id sioVolumeID) error {
_, err := f.Volume(id)
if err != nil {
return err
}
f.volume.MappedSdcInfo = []*siotypes.MappedSdcInfo{
{SdcID: fakeSdcID},
}
return nil
}
func (f *fakeSio) DetachVolume(id sioVolumeID) error {
if _, err := f.Volume(id); err != nil {
return err
}
f.volume.MappedSdcInfo = nil
delete(f.devs, f.volume.ID)
return nil
}
func (f *fakeSio) DeleteVolume(id sioVolumeID) error {
if _, err := f.Volume(id); err != nil {
return err
}
f.volume = nil
return nil
}
func (f *fakeSio) IID() (string, error) {
return fakeSdcID, nil
}
func (f *fakeSio) Devs() (map[string]string, error) {
if f.volume == nil {
return nil, errors.New("volume not found")
}
f.devs = map[string]string{
f.volume.ID: fakeDev,
}
return f.devs, nil
}
func (f *fakeSio) GetVolumeRefs(volId sioVolumeID) (int, error) {
if f.volume == nil {
return 0, nil
}
return 1, nil
}
func (f *fakeSio) WaitForAttachedDevice(token string) (string, error) {
select {
case <-time.After(500 * time.Millisecond):
return fakeDev, nil
case <-f.waitAttachCtrl:
return "", errors.New("attached device timeout")
}
}
func (f *fakeSio) WaitForDetachedDevice(token string) error {
select {
case <-time.After(500 * time.Millisecond):
delete(f.devs, f.volume.ID)
return nil
case <-f.waitDetachCtrl:
return errors.New("detach device timeout")
}
}
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
package scaleio
import (
"errors"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/types"
api "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util/keymutex"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
)
const (
sioName = "scaleio"
sioPluginName = "kubernetes.io/scaleio"
sioConfigFileName = "sioconf.dat"
)
type sioPlugin struct {
host volume.VolumeHost
mounter mount.Interface
volumeMtx keymutex.KeyMutex
}
func ProbeVolumePlugins() []volume.VolumePlugin {
p := &sioPlugin{
host: nil,
}
return []volume.VolumePlugin{p}
}
// *******************
// VolumePlugin Impl
// *******************
var _ volume.VolumePlugin = &sioPlugin{}
func (p *sioPlugin) Init(host volume.VolumeHost) error {
p.host = host
p.mounter = host.GetMounter()
p.volumeMtx = keymutex.NewKeyMutex()
return nil
}
func (p *sioPlugin) GetPluginName() string {
return sioPluginName
}
func (p *sioPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
source, err := getVolumeSourceFromSpec(spec)
if err != nil {
return "", err
}
return source.VolumeName, nil
}
func (p *sioPlugin) CanSupport(spec *volume.Spec) bool {
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.ScaleIO != nil) ||
(spec.Volume != nil && spec.Volume.ScaleIO != nil)
}
func (p *sioPlugin) RequiresRemount() bool {
return false
}
func (p *sioPlugin) NewMounter(
spec *volume.Spec,
pod *api.Pod,
_ volume.VolumeOptions) (volume.Mounter, error) {
sioSource, err := getVolumeSourceFromSpec(spec)
if err != nil {
glog.Error(log("failed to extract ScaleIOVolumeSource from spec: %v", err))
return nil, err
}
return &sioVolume{
pod: pod,
spec: spec,
source: sioSource,
namespace: pod.Namespace,
volSpecName: spec.Name(),
volName: sioSource.VolumeName,
podUID: pod.UID,
readOnly: sioSource.ReadOnly,
fsType: sioSource.FSType,
plugin: p,
}, nil
}
// NewUnmounter creates a representation of the volume to unmount
// The specName param can be used to carry the namespace value (if needed) using format:
// specName = [<namespace>nsSep]<somevalue> where the specname is pre-pended with the namespace
func (p *sioPlugin) NewUnmounter(specName string, podUID types.UID) (volume.Unmounter, error) {
glog.V(4).Info(log("Unmounter for %s", specName))
return &sioVolume{
podUID: podUID,
volSpecName: specName,
plugin: p,
}, nil
}
func (p *sioPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
sioVol := &api.Volume{
Name: volumeName,
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{},
},
}
return volume.NewSpecFromVolume(sioVol), nil
}
// SupportsMountOption returns true if volume plugins supports Mount options
// Specifying mount options in a volume plugin that doesn't support
// user specified mount options will result in error creating persistent volumes
func (p *sioPlugin) SupportsMountOption() bool {
return false
}
// SupportsBulkVolumeVerification checks if volume plugin type is capable
// of enabling bulk polling of all nodes. This can speed up verification of
// attached volumes by quite a bit, but underlying pluging must support it.
func (p *sioPlugin) SupportsBulkVolumeVerification() bool {
return false
}
//******************************
// PersistentVolumePlugin Impl
// *****************************
var _ volume.PersistentVolumePlugin = &sioPlugin{}
func (p *sioPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
return []api.PersistentVolumeAccessMode{
api.ReadWriteOnce,
}
}
// ***************************
// DeletableVolumePlugin Impl
//****************************
var _ volume.DeletableVolumePlugin = &sioPlugin{}
func (p *sioPlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
sioSource, err := getVolumeSourceFromSpec(spec)
if err != nil {
glog.Error(log("deleter failed to extract source from spec: %v", err))
return nil, err
}
namespace := spec.PersistentVolume.Spec.ClaimRef.Namespace
return &sioVolume{
spec: spec,
source: sioSource,
namespace: namespace,
volSpecName: spec.Name(),
volName: sioSource.VolumeName,
plugin: p,
readOnly: sioSource.ReadOnly,
}, nil
}
// *********************************
// ProvisionableVolumePlugin Impl
// *********************************
var _ volume.ProvisionableVolumePlugin = &sioPlugin{}
func (p *sioPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
glog.V(4).Info(log("creating Provisioner"))
configData := options.Parameters
if configData == nil {
glog.Error(log("provisioner missing parameters, unable to continue"))
return nil, errors.New("option parameters missing")
}
namespace := options.PVC.Namespace
return &sioVolume{
configData: configData,
plugin: p,
options: options,
namespace: namespace,
volSpecName: options.PVName,
}, nil
}
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
package scaleio
import (
"encoding/gob"
"errors"
"fmt"
"os"
"path"
"strconv"
"github.com/golang/glog"
api "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/volume"
volutil "k8s.io/kubernetes/pkg/volume/util"
)
var (
confKey = struct {
gateway,
sslEnabled,
secretRef,
system,
protectionDomain,
storagePool,
storageMode,
sdcRootPath,
volumeName,
volSpecName,
fsType,
readOnly,
username,
password,
namespace string
}{
gateway: "gateway",
sslEnabled: "sslEnabled",
secretRef: "secretRef",
system: "system",
protectionDomain: "protectionDomain",
storagePool: "storagePool",
storageMode: "storageMode",
sdcRootPath: "sdcRootPath",
volumeName: "volumeName",
volSpecName: "volSpecName",
fsType: "fsType",
readOnly: "readOnly",
username: "username",
password: "password",
namespace: "namespace",
}
nsSep = "%"
sdcRootPath = "/opt/emc/scaleio/sdc/bin"
secretNotFoundErr = errors.New("secret not found")
configMapNotFoundErr = errors.New("configMap not found")
gatewayNotProvidedErr = errors.New("gateway not provided")
secretRefNotProvidedErr = errors.New("secret ref not provided")
systemNotProvidedErr = errors.New("secret not provided")
)
// mapScaleIOVolumeSource maps attributes from a ScaleIOVolumeSource to config
func mapVolumeSource(config map[string]string, source *api.ScaleIOVolumeSource) {
config[confKey.gateway] = source.Gateway
config[confKey.secretRef] = func() string {
if source.SecretRef != nil {
return string(source.SecretRef.Name)
}
return ""
}()
config[confKey.system] = source.System
config[confKey.volumeName] = source.VolumeName
config[confKey.sslEnabled] = strconv.FormatBool(source.SSLEnabled)
config[confKey.protectionDomain] = source.ProtectionDomain
config[confKey.storagePool] = source.StoragePool
config[confKey.storageMode] = source.StorageMode
config[confKey.fsType] = source.FSType
config[confKey.readOnly] = strconv.FormatBool(source.ReadOnly)
//optionals
applyConfigDefaults(config)
}
func validateConfigs(config map[string]string) error {
if config[confKey.gateway] == "" {
return gatewayNotProvidedErr
}
if config[confKey.secretRef] == "" {
return secretRefNotProvidedErr
}
if config[confKey.system] == "" {
return systemNotProvidedErr
}
return nil
}
// applyConfigDefaults apply known defaults to incoming spec for dynamic PVCs.
func applyConfigDefaults(config map[string]string) {
b, err := strconv.ParseBool(config[confKey.sslEnabled])
if err != nil {
glog.Warning(log("failed to parse param sslEnabled, setting it to false"))
b = false
}
config[confKey.sslEnabled] = strconv.FormatBool(b)
config[confKey.protectionDomain] = defaultString(config[confKey.protectionDomain], "default")
config[confKey.storagePool] = defaultString(config[confKey.storagePool], "default")
config[confKey.storageMode] = defaultString(config[confKey.storageMode], "ThinProvisioned")
config[confKey.fsType] = defaultString(config[confKey.fsType], "xfs")
b, err = strconv.ParseBool(config[confKey.readOnly])
if err != nil {
glog.Warning(log("failed to parse param readOnly, setting it to true"))
b = true
}
config[confKey.readOnly] = strconv.FormatBool(b)
}
func defaultString(val, defVal string) string {
if val == "" {
return defVal
}
return val
}
// loadConfig loads configuration data from a file on disk
func loadConfig(configName string) (map[string]string, error) {
glog.V(4).Info(log("loading config file %s", configName))
file, err := os.Open(configName)
if err != nil {
glog.Error(log("failed to open config file %s: %v", configName, err))
return nil, err
}
defer file.Close()
data := map[string]string{}
if err := gob.NewDecoder(file).Decode(&data); err != nil {
glog.Error(log("failed to parse config data %s: %v", configName, err))
return nil, err
}
applyConfigDefaults(data)
if err := validateConfigs(data); err != nil {
glog.Error(log("failed to load ConfigMap %s: %v", err))
return nil, err
}
return data, nil
}
// saveConfig saves the configuration data to local disk
func saveConfig(configName string, data map[string]string) error {
glog.V(4).Info(log("saving config file %s", configName))
dir := path.Dir(configName)
if _, err := os.Stat(dir); err != nil {
if !os.IsNotExist(err) {
return err
}
glog.V(4).Info(log("creating config dir for config data: %s", dir))
if err := os.MkdirAll(dir, 0750); err != nil {
glog.Error(log("failed to create config data dir %v", err))
return err
}
}
file, err := os.Create(configName)
if err != nil {
glog.V(4).Info(log("failed to save config data file %s: %v", configName, err))
return err
}
defer file.Close()
if err := gob.NewEncoder(file).Encode(data); err != nil {
glog.Error(log("failed to save config %s: %v", configName, err))
return err
}
glog.V(4).Info(log("config data file saved successfully as %s", configName))
return nil
}
// attachSecret loads secret object and attaches to configData
func attachSecret(plug *sioPlugin, namespace string, configData map[string]string) error {
// load secret
secretRefName := configData[confKey.secretRef]
kubeClient := plug.host.GetKubeClient()
secretMap, err := volutil.GetSecretForPV(namespace, secretRefName, sioPluginName, kubeClient)
if err != nil {
glog.Error(log("failed to get secret: %v", err))
return secretNotFoundErr
}
// merge secret data
for key, val := range secretMap {
configData[key] = val
}
return nil
}
// getVolumeSourceFromSpec safely extracts ScaleIOVolumeSource from spec
func getVolumeSourceFromSpec(spec *volume.Spec) (*api.ScaleIOVolumeSource, error) {
if spec.Volume != nil && spec.Volume.ScaleIO != nil {
return spec.Volume.ScaleIO, nil
}
if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.ScaleIO != nil {
return spec.PersistentVolume.Spec.ScaleIO, nil
}
return nil, fmt.Errorf("ScaleIO not defined in spec")
}
func log(msg string, parts ...interface{}) string {
return fmt.Sprintf(fmt.Sprintf("scaleio: %s", msg), parts...)
}
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
package scaleio
import (
"encoding/gob"
"os"
"path"
"reflect"
"testing"
utiltesting "k8s.io/client-go/util/testing"
api "k8s.io/kubernetes/pkg/api/v1"
)
var (
vol = &api.Volume{
Name: testSioVolName,
VolumeSource: api.VolumeSource{
ScaleIO: &api.ScaleIOVolumeSource{
Gateway: "http://test.scaleio:1111",
System: "sio",
ProtectionDomain: "defaultPD",
StoragePool: "defaultSP",
VolumeName: "test-vol",
FSType: "ext4",
SecretRef: &api.LocalObjectReference{Name: "test-secret"},
},
},
}
config = map[string]string{
confKey.system: "sio",
confKey.gateway: "http://sio/",
confKey.volSpecName: testSioVolName,
confKey.volumeName: "sio-vol",
confKey.secretRef: "sio-secret",
confKey.protectionDomain: "defaultPD",
confKey.storagePool: "deraultSP",
confKey.fsType: "xfs",
confKey.readOnly: "true",
}
testConfigFile = "conf.dat"
)
func TestUtilMapVolumeSource(t *testing.T) {
data := make(map[string]string)
mapVolumeSource(data, vol.VolumeSource.ScaleIO)
if data[confKey.gateway] != "http://test.scaleio:1111" {
t.Error("Unexpected gateway value")
}
if data[confKey.system] != "sio" {
t.Error("Unexpected system value")
}
if data[confKey.protectionDomain] != "defaultPD" {
t.Error("Unexpected protection domain value")
}
if data[confKey.storagePool] != "defaultSP" {
t.Error("Unexpected storage pool value")
}
if data[confKey.volumeName] != "test-vol" {
t.Error("Unexpected volume name value")
}
if data[confKey.fsType] != "ext4" {
t.Error("Unexpected fstype value")
}
if data[confKey.secretRef] != "test-secret" {
t.Error("Unexpected secret ref value")
}
if data[confKey.sslEnabled] != "false" {
t.Error("Unexpected sslEnabled value")
}
if data[confKey.readOnly] != "false" {
t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
}
}
func TestUtilValidateConfigs(t *testing.T) {
data := map[string]string{
confKey.secretRef: "sio-secret",
confKey.system: "sio",
}
if err := validateConfigs(data); err != gatewayNotProvidedErr {
t.Error("Expecting error for missing gateway, but did not get it")
}
}
func TestUtilApplyConfigDefaults(t *testing.T) {
data := map[string]string{
confKey.system: "sio",
confKey.gateway: "http://sio/",
confKey.volumeName: "sio-vol",
confKey.secretRef: "test-secret",
}
applyConfigDefaults(data)
if data[confKey.gateway] != "http://sio/" {
t.Error("Unexpected gateway value")
}
if data[confKey.system] != "sio" {
t.Error("Unexpected system value")
}
if data[confKey.protectionDomain] != "default" {
t.Error("Unexpected protection domain value")
}
if data[confKey.storagePool] != "default" {
t.Error("Unexpected storage pool value")
}
if data[confKey.volumeName] != "sio-vol" {
t.Error("Unexpected volume name value")
}
if data[confKey.fsType] != "xfs" {
t.Error("Unexpected fstype value")
}
if data[confKey.storageMode] != "ThinProvisioned" {
t.Error("Unexpected storage mode value")
}
if data[confKey.secretRef] != "test-secret" {
t.Error("Unexpected secret ref value")
}
if data[confKey.sslEnabled] != "false" {
t.Error("Unexpected sslEnabled value")
}
if data[confKey.readOnly] != "true" {
t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
}
}
func TestUtilDefaultString(t *testing.T) {
if defaultString("", "foo") != "foo" {
t.Error("Unexpected value for default value")
}
}
func TestUtilSaveConfig(t *testing.T) {
tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
if err != nil {
t.Fatalf("can't make a temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
config := path.Join(tmpDir, testConfigFile)
data := map[string]string{
confKey.gateway: "https://test-gateway/",
confKey.secretRef: "sio-secret",
confKey.sslEnabled: "false",
}
if err := saveConfig(config, data); err != nil {
t.Fatal("failed while saving data", err)
}
file, err := os.Open(config)
if err != nil {
t.Fatal("failed to open conf file: ", file)
}
dataRcvd := map[string]string{}
if err := gob.NewDecoder(file).Decode(&dataRcvd); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(data, dataRcvd) {
t.Error("we got problem, config data not the same")
}
}
func TestUtilAttachSecret(t *testing.T) {
plugMgr, tmpDir := newPluginMgr(t)
defer os.RemoveAll(tmpDir)
plug, err := plugMgr.FindPluginByName(sioPluginName)
if err != nil {
t.Errorf("Can't find the plugin %v", sioPluginName)
}
sioPlug, ok := plug.(*sioPlugin)
if !ok {
t.Errorf("Cannot assert plugin to be type sioPlugin")
}
data := make(map[string]string)
for k, v := range config {
data[k] = v
}
if err := attachSecret(sioPlug, "default", data); err != nil {
t.Errorf("failed to setupConfigData %v", err)
}
if data[confKey.username] == "" {
t.Errorf("failed to merge secret")
}
}
func TestUtilLoadConfig(t *testing.T) {
tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
if err != nil {
t.Fatalf("can't make a temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
configFile := path.Join(tmpDir, sioConfigFileName)
if err := saveConfig(configFile, config); err != nil {
t.Fatal("failed while saving data", err)
}
dataRcvd, err := loadConfig(configFile)
if dataRcvd[confKey.gateway] != config[confKey.gateway] ||
dataRcvd[confKey.system] != config[confKey.system] {
t.Fatal("loaded config data not matching saved config data")
}
}
...@@ -299,6 +299,9 @@ type VolumeSource struct { ...@@ -299,6 +299,9 @@ type VolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource PortworxVolume *PortworxVolumeSource
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource
} }
// Similar to VolumeSource but meant for the administrator who creates PVs. // Similar to VolumeSource but meant for the administrator who creates PVs.
...@@ -364,6 +367,9 @@ type PersistentVolumeSource struct { ...@@ -364,6 +367,9 @@ type PersistentVolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource PortworxVolume *PortworxVolumeSource
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource
} }
type PersistentVolumeClaimVolumeSource struct { type PersistentVolumeClaimVolumeSource struct {
...@@ -1056,6 +1062,41 @@ type AzureDiskVolumeSource struct { ...@@ -1056,6 +1062,41 @@ type AzureDiskVolumeSource struct {
ReadOnly *bool ReadOnly *bool
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
type ScaleIOVolumeSource struct {
// The host address of the ScaleIO API Gateway.
Gateway string
// The name of the storage system as configured in ScaleIO.
System string
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
SecretRef *LocalObjectReference
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
SSLEnabled bool
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
ProtectionDomain string
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
StoragePool string
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
StorageMode string
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
VolumeName string
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
FSType string
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
}
// Adapts a ConfigMap into a volume. // Adapts a ConfigMap into a volume.
// //
// The contents of the target ConfigMap's Data field will be presented in a // The contents of the target ConfigMap's Data field will be presented in a
......
...@@ -359,3 +359,18 @@ func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) { ...@@ -359,3 +359,18 @@ func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) {
obj.Keyring = "/etc/ceph/keyring" obj.Keyring = "/etc/ceph/keyring"
} }
} }
func SetDefaults_ScaleIOVolumeSource(obj *ScaleIOVolumeSource) {
if obj.ProtectionDomain == "" {
obj.ProtectionDomain = "default"
}
if obj.StoragePool == "" {
obj.StoragePool = "default"
}
if obj.StorageMode == "" {
obj.StorageMode = "ThinProvisioned"
}
if obj.FSType == "" {
obj.FSType = "xfs"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -2140,6 +2140,10 @@ message PersistentVolumeSource { ...@@ -2140,6 +2140,10 @@ message PersistentVolumeSource {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
optional PortworxVolumeSource portworxVolume = 18; optional PortworxVolumeSource portworxVolume = 18;
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
optional ScaleIOVolumeSource scaleIO = 19;
} }
// PersistentVolumeSpec is the specification of a persistent volume. // PersistentVolumeSpec is the specification of a persistent volume.
...@@ -3210,6 +3214,50 @@ message SELinuxOptions { ...@@ -3210,6 +3214,50 @@ message SELinuxOptions {
optional string level = 4; optional string level = 4;
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
message ScaleIOVolumeSource {
// The host address of the ScaleIO API Gateway.
optional string gateway = 1;
// The name of the storage system as configured in ScaleIO.
optional string system = 2;
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
optional LocalObjectReference secretRef = 3;
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
optional bool sslEnabled = 4;
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
optional string protectionDomain = 5;
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
optional string storagePool = 6;
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
optional string storageMode = 7;
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
optional string volumeName = 8;
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
optional string fsType = 9;
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
optional bool readOnly = 10;
}
// Secret holds secret data of a certain type. The total bytes of the values in // Secret holds secret data of a certain type. The total bytes of the values in
// the Data field must be less than MaxSecretSize bytes. // the Data field must be less than MaxSecretSize bytes.
message Secret { message Secret {
...@@ -3840,11 +3888,15 @@ message VolumeSource { ...@@ -3840,11 +3888,15 @@ message VolumeSource {
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23; optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23;
// Items for all in one resources secrets, configmaps, and downward API // Items for all in one resources secrets, configmaps, and downward API
optional ProjectedVolumeSource projected = 25; optional ProjectedVolumeSource projected = 26;
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
optional PortworxVolumeSource portworxVolume = 24; optional PortworxVolumeSource portworxVolume = 24;
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
optional ScaleIOVolumeSource scaleIO = 25;
} }
// Represents a vSphere volume resource. // Represents a vSphere volume resource.
......
...@@ -331,6 +331,9 @@ type VolumeSource struct { ...@@ -331,6 +331,9 @@ type VolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"` PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource `json:"scaleIO,omitempty" protobuf:"bytes,25,opt,name=scaleIO"`
} }
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. // PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
...@@ -419,6 +422,9 @@ type PersistentVolumeSource struct { ...@@ -419,6 +422,9 @@ type PersistentVolumeSource struct {
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
// +optional // +optional
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"` PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"`
// ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.
// +optional
ScaleIO *ScaleIOVolumeSource `json:"scaleIO,omitempty" protobuf:"bytes,19,opt,name=scaleIO"`
} }
const ( const (
...@@ -1138,6 +1144,41 @@ type PortworxVolumeSource struct { ...@@ -1138,6 +1144,41 @@ type PortworxVolumeSource struct {
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
} }
// ScaleIOVolumeSource represents a persistent ScaleIO volume
type ScaleIOVolumeSource struct {
// The host address of the ScaleIO API Gateway.
Gateway string `json:"gateway" protobuf:"bytes,1,opt,name=gateway"`
// The name of the storage system as configured in ScaleIO.
System string `json:"system" protobuf:"bytes,2,opt,name=system"`
// SecretRef references to the secret for ScaleIO user and other
// sensitive information. If this is not provided, Login operation will fail.
SecretRef *LocalObjectReference `json:"secretRef" protobuf:"bytes,3,opt,name=secretRef"`
// Flag to enable/disable SSL communication with Gateway, default false
// +optional
SSLEnabled bool `json:"sslEnabled,omitempty" protobuf:"varint,4,opt,name=sslEnabled"`
// The name of the Protection Domain for the configured storage (defaults to "default").
// +optional
ProtectionDomain string `json:"protectionDomain,omitempty" protobuf:"bytes,5,opt,name=protectionDomain"`
// The Storage Pool associated with the protection domain (defaults to "default").
// +optional
StoragePool string `json:"storagePool,omitempty" protobuf:"bytes,6,opt,name=storagePool"`
// Indicates whether the storage for a volume should be thick or thin (defaults to "thin").
// +optional
StorageMode string `json:"storageMode,omitempty" protobuf:"bytes,7,opt,name=storageMode"`
// The name of a volume already created in the ScaleIO system
// that is associated with this volume source.
VolumeName string `json:"volumeName,omitempty" protobuf:"bytes,8,opt,name=volumeName"`
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// +optional
FSType string `json:"fsType,omitempty" protobuf:"bytes,9,opt,name=fsType"`
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,10,opt,name=readOnly"`
}
// Adapts a ConfigMap into a volume. // Adapts a ConfigMap into a volume.
// //
// The contents of the target ConfigMap's Data field will be presented in a // The contents of the target ConfigMap's Data field will be presented in a
......
...@@ -1124,6 +1124,7 @@ var map_PersistentVolumeSource = map[string]string{ ...@@ -1124,6 +1124,7 @@ var map_PersistentVolumeSource = map[string]string{
"azureDisk": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.", "azureDisk": "AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod.",
"photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", "photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", "portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
"scaleIO": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
} }
func (PersistentVolumeSource) SwaggerDoc() map[string]string { func (PersistentVolumeSource) SwaggerDoc() map[string]string {
...@@ -1640,6 +1641,24 @@ func (SELinuxOptions) SwaggerDoc() map[string]string { ...@@ -1640,6 +1641,24 @@ func (SELinuxOptions) SwaggerDoc() map[string]string {
return map_SELinuxOptions return map_SELinuxOptions
} }
var map_ScaleIOVolumeSource = map[string]string{
"": "ScaleIOVolumeSource represents a persistent ScaleIO volume",
"gateway": "The host address of the ScaleIO API Gateway.",
"system": "The name of the storage system as configured in ScaleIO.",
"secretRef": "SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail.",
"sslEnabled": "Flag to enable/disable SSL communication with Gateway, default false",
"protectionDomain": "The name of the Protection Domain for the configured storage (defaults to \"default\").",
"storagePool": "The Storage Pool associated with the protection domain (defaults to \"default\").",
"storageMode": "Indicates whether the storage for a volume should be thick or thin (defaults to \"thin\").",
"volumeName": "The name of a volume already created in the ScaleIO system that is associated with this volume source.",
"fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.",
"readOnly": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
}
func (ScaleIOVolumeSource) SwaggerDoc() map[string]string {
return map_ScaleIOVolumeSource
}
var map_Secret = map[string]string{ var map_Secret = map[string]string{
"": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.", "": "Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.",
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", "metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
...@@ -1911,6 +1930,7 @@ var map_VolumeSource = map[string]string{ ...@@ -1911,6 +1930,7 @@ var map_VolumeSource = map[string]string{
"photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine", "photonPersistentDisk": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
"projected": "Items for all in one resources secrets, configmaps, and downward API", "projected": "Items for all in one resources secrets, configmaps, and downward API",
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine", "portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
"scaleIO": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
} }
func (VolumeSource) SwaggerDoc() map[string]string { func (VolumeSource) SwaggerDoc() map[string]string {
......
...@@ -317,6 +317,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { ...@@ -317,6 +317,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_ResourceRequirements_To_v1_ResourceRequirements, Convert_api_ResourceRequirements_To_v1_ResourceRequirements,
Convert_v1_SELinuxOptions_To_api_SELinuxOptions, Convert_v1_SELinuxOptions_To_api_SELinuxOptions,
Convert_api_SELinuxOptions_To_v1_SELinuxOptions, Convert_api_SELinuxOptions_To_v1_SELinuxOptions,
Convert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource,
Convert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource,
Convert_v1_Secret_To_api_Secret, Convert_v1_Secret_To_api_Secret,
Convert_api_Secret_To_v1_Secret, Convert_api_Secret_To_v1_Secret,
Convert_v1_SecretEnvSource_To_api_SecretEnvSource, Convert_v1_SecretEnvSource_To_api_SecretEnvSource,
...@@ -2711,6 +2713,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per ...@@ -2711,6 +2713,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*api.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -2737,6 +2740,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api ...@@ -2737,6 +2740,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk)) out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -3887,6 +3891,42 @@ func Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in *api.SELinuxOptions, out ...@@ -3887,6 +3891,42 @@ func Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in *api.SELinuxOptions, out
return autoConvert_api_SELinuxOptions_To_v1_SELinuxOptions(in, out, s) return autoConvert_api_SELinuxOptions_To_v1_SELinuxOptions(in, out, s)
} }
func autoConvert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in *ScaleIOVolumeSource, out *api.ScaleIOVolumeSource, s conversion.Scope) error {
out.Gateway = in.Gateway
out.System = in.System
out.SecretRef = (*api.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.SSLEnabled = in.SSLEnabled
out.ProtectionDomain = in.ProtectionDomain
out.StoragePool = in.StoragePool
out.StorageMode = in.StorageMode
out.VolumeName = in.VolumeName
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
return nil
}
func Convert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in *ScaleIOVolumeSource, out *api.ScaleIOVolumeSource, s conversion.Scope) error {
return autoConvert_v1_ScaleIOVolumeSource_To_api_ScaleIOVolumeSource(in, out, s)
}
func autoConvert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *api.ScaleIOVolumeSource, out *ScaleIOVolumeSource, s conversion.Scope) error {
out.Gateway = in.Gateway
out.System = in.System
out.SecretRef = (*LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.SSLEnabled = in.SSLEnabled
out.ProtectionDomain = in.ProtectionDomain
out.StoragePool = in.StoragePool
out.StorageMode = in.StorageMode
out.VolumeName = in.VolumeName
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
return nil
}
func Convert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in *api.ScaleIOVolumeSource, out *ScaleIOVolumeSource, s conversion.Scope) error {
return autoConvert_api_ScaleIOVolumeSource_To_v1_ScaleIOVolumeSource(in, out, s)
}
func autoConvert_v1_Secret_To_api_Secret(in *Secret, out *api.Secret, s conversion.Scope) error { func autoConvert_v1_Secret_To_api_Secret(in *Secret, out *api.Secret, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data)) out.Data = *(*map[string][]byte)(unsafe.Pointer(&in.Data))
...@@ -4487,6 +4527,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api. ...@@ -4487,6 +4527,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*api.ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
...@@ -4520,6 +4561,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out * ...@@ -4520,6 +4561,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk)) out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected)) out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume)) out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
out.ScaleIO = (*ScaleIOVolumeSource)(unsafe.Pointer(in.ScaleIO))
return nil return nil
} }
......
...@@ -176,6 +176,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { ...@@ -176,6 +176,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ScaleIOVolumeSource, InType: reflect.TypeOf(&ScaleIOVolumeSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Secret, InType: reflect.TypeOf(&Secret{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Secret, InType: reflect.TypeOf(&Secret{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})},
...@@ -2026,6 +2027,13 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv ...@@ -2026,6 +2027,13 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_v1_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
...@@ -2872,6 +2880,20 @@ func DeepCopy_v1_SELinuxOptions(in interface{}, out interface{}, c *conversion.C ...@@ -2872,6 +2880,20 @@ func DeepCopy_v1_SELinuxOptions(in interface{}, out interface{}, c *conversion.C
} }
} }
func DeepCopy_v1_ScaleIOVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ScaleIOVolumeSource)
out := out.(*ScaleIOVolumeSource)
*out = *in
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(LocalObjectReference)
**out = **in
}
return nil
}
}
func DeepCopy_v1_Secret(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_v1_Secret(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*Secret) in := in.(*Secret)
...@@ -3445,6 +3467,13 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo ...@@ -3445,6 +3467,13 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_v1_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
......
...@@ -137,6 +137,9 @@ func SetObjectDefaults_PersistentVolume(in *PersistentVolume) { ...@@ -137,6 +137,9 @@ func SetObjectDefaults_PersistentVolume(in *PersistentVolume) {
if in.Spec.PersistentVolumeSource.AzureDisk != nil { if in.Spec.PersistentVolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(in.Spec.PersistentVolumeSource.AzureDisk) SetDefaults_AzureDiskVolumeSource(in.Spec.PersistentVolumeSource.AzureDisk)
} }
if in.Spec.PersistentVolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(in.Spec.PersistentVolumeSource.ScaleIO)
}
} }
func SetObjectDefaults_PersistentVolumeClaim(in *PersistentVolumeClaim) { func SetObjectDefaults_PersistentVolumeClaim(in *PersistentVolumeClaim) {
...@@ -204,6 +207,9 @@ func SetObjectDefaults_Pod(in *Pod) { ...@@ -204,6 +207,9 @@ func SetObjectDefaults_Pod(in *Pod) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.InitContainers { for i := range in.Spec.InitContainers {
a := &in.Spec.InitContainers[i] a := &in.Spec.InitContainers[i]
...@@ -349,6 +355,9 @@ func SetObjectDefaults_PodTemplate(in *PodTemplate) { ...@@ -349,6 +355,9 @@ func SetObjectDefaults_PodTemplate(in *PodTemplate) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Template.Spec.InitContainers { for i := range in.Template.Spec.InitContainers {
a := &in.Template.Spec.InitContainers[i] a := &in.Template.Spec.InitContainers[i]
...@@ -488,6 +497,9 @@ func SetObjectDefaults_ReplicationController(in *ReplicationController) { ...@@ -488,6 +497,9 @@ func SetObjectDefaults_ReplicationController(in *ReplicationController) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -179,6 +179,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { ...@@ -179,6 +179,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceQuotaStatus, InType: reflect.TypeOf(&ResourceQuotaStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ScaleIOVolumeSource, InType: reflect.TypeOf(&ScaleIOVolumeSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Secret, InType: reflect.TypeOf(&Secret{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Secret, InType: reflect.TypeOf(&Secret{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})},
...@@ -2070,6 +2071,13 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con ...@@ -2070,6 +2071,13 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_api_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
...@@ -2911,6 +2919,20 @@ func DeepCopy_api_SELinuxOptions(in interface{}, out interface{}, c *conversion. ...@@ -2911,6 +2919,20 @@ func DeepCopy_api_SELinuxOptions(in interface{}, out interface{}, c *conversion.
} }
} }
func DeepCopy_api_ScaleIOVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ScaleIOVolumeSource)
out := out.(*ScaleIOVolumeSource)
*out = *in
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(LocalObjectReference)
**out = **in
}
return nil
}
}
func DeepCopy_api_Secret(in interface{}, out interface{}, c *conversion.Cloner) error { func DeepCopy_api_Secret(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*Secret) in := in.(*Secret)
...@@ -3472,6 +3494,13 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl ...@@ -3472,6 +3494,13 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl
*out = new(PortworxVolumeSource) *out = new(PortworxVolumeSource)
**out = **in **out = **in
} }
if in.ScaleIO != nil {
in, out := &in.ScaleIO, &out.ScaleIO
*out = new(ScaleIOVolumeSource)
if err := DeepCopy_api_ScaleIOVolumeSource(*in, *out, c); err != nil {
return err
}
}
return nil return nil
} }
} }
......
...@@ -80,6 +80,9 @@ func SetObjectDefaults_Deployment(in *Deployment) { ...@@ -80,6 +80,9 @@ func SetObjectDefaults_Deployment(in *Deployment) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -218,6 +221,9 @@ func SetObjectDefaults_StatefulSet(in *StatefulSet) { ...@@ -218,6 +221,9 @@ func SetObjectDefaults_StatefulSet(in *StatefulSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -78,6 +78,9 @@ func SetObjectDefaults_Job(in *Job) { ...@@ -78,6 +78,9 @@ func SetObjectDefaults_Job(in *Job) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
api_v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *CronJob) { ...@@ -81,6 +81,9 @@ func SetObjectDefaults_CronJob(in *CronJob) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.JobTemplate.Spec.Template.Spec.InitContainers { for i := range in.Spec.JobTemplate.Spec.Template.Spec.InitContainers {
a := &in.Spec.JobTemplate.Spec.Template.Spec.InitContainers[i] a := &in.Spec.JobTemplate.Spec.Template.Spec.InitContainers[i]
...@@ -219,6 +222,9 @@ func SetObjectDefaults_Job(in *Job) { ...@@ -219,6 +222,9 @@ func SetObjectDefaults_Job(in *Job) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -356,6 +362,9 @@ func SetObjectDefaults_JobTemplate(in *JobTemplate) { ...@@ -356,6 +362,9 @@ func SetObjectDefaults_JobTemplate(in *JobTemplate) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Template.Spec.Template.Spec.InitContainers { for i := range in.Template.Spec.Template.Spec.InitContainers {
a := &in.Template.Spec.Template.Spec.InitContainers[i] a := &in.Template.Spec.Template.Spec.InitContainers[i]
......
...@@ -918,6 +918,7 @@ var ( ...@@ -918,6 +918,7 @@ var (
PhotonPersistentDisk FSType = "photonPersistentDisk" PhotonPersistentDisk FSType = "photonPersistentDisk"
Projected FSType = "projected" Projected FSType = "projected"
PortworxVolume FSType = "portworxVolume" PortworxVolume FSType = "portworxVolume"
ScaleIO FSType = "scaleIO"
All FSType = "*" All FSType = "*"
) )
......
...@@ -84,6 +84,9 @@ func SetObjectDefaults_DaemonSet(in *DaemonSet) { ...@@ -84,6 +84,9 @@ func SetObjectDefaults_DaemonSet(in *DaemonSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -222,6 +225,9 @@ func SetObjectDefaults_Deployment(in *Deployment) { ...@@ -222,6 +225,9 @@ func SetObjectDefaults_Deployment(in *Deployment) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
...@@ -371,6 +377,9 @@ func SetObjectDefaults_ReplicaSet(in *ReplicaSet) { ...@@ -371,6 +377,9 @@ func SetObjectDefaults_ReplicaSet(in *ReplicaSet) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
for i := range in.Spec.Template.Spec.InitContainers { for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i] a := &in.Spec.Template.Spec.InitContainers[i]
......
...@@ -84,6 +84,9 @@ func SetObjectDefaults_PodPreset(in *PodPreset) { ...@@ -84,6 +84,9 @@ func SetObjectDefaults_PodPreset(in *PodPreset) {
} }
} }
} }
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
} }
} }
......
...@@ -16262,3 +16262,32 @@ filegroup( ...@@ -16262,3 +16262,32 @@ filegroup(
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
) )
go_library(
name = "github.com/codedellemc/goscaleio",
srcs = [
"github.com/codedellemc/goscaleio/api.go",
"github.com/codedellemc/goscaleio/certs.go",
"github.com/codedellemc/goscaleio/device.go",
"github.com/codedellemc/goscaleio/instance.go",
"github.com/codedellemc/goscaleio/protectiondomain.go",
"github.com/codedellemc/goscaleio/scsiinitiator.go",
"github.com/codedellemc/goscaleio/sdc.go",
"github.com/codedellemc/goscaleio/sds.go",
"github.com/codedellemc/goscaleio/storagepool.go",
"github.com/codedellemc/goscaleio/system.go",
"github.com/codedellemc/goscaleio/user.go",
"github.com/codedellemc/goscaleio/volume.go",
],
tags = ["automanaged"],
deps = [
"//vendor:github.com/Sirupsen/logrus",
"//vendor:github.com/codedellemc/goscaleio/types/v1",
],
)
go_library(
name = "github.com/codedellemc/goscaleio/types/v1",
srcs = ["github.com/codedellemc/goscaleio/types/v1/types.go"],
tags = ["automanaged"],
)
*.*-e
.*-e
*-e
vendor/
.build/
.rpmbuild/
example
release/*
golang-crosscompile/
.project
*.d
*.out
.gaesdk/
# Created by https://www.gitignore.io
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Go ###
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studo 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.[Cc]ache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
language: go
install:
- go get -t ./...
- go get code.google.com/p/go.tools/cmd/cover
- go get github.com/mattn/goveralls
script:
- PATH="$HOME/gopath/bin:$PATH"
- script/coverage --coveralls
# Goscaleio
The *Goscaleio* project represents API bindings that can be used to provide ScaleIO functionality into other Go applications.
- [Current State](#state)
- [Usage](#usage)
- [Licensing](#licensing)
- [Support](#support)
## Use Cases
Any application written in Go can take advantage of these bindings. Specifically, things that are involved in monitoring, management, and more specifically infrastructrue as code would find these bindings relevant.
## <a id="state">Current State</a>
Early build-out and pre-documentation stages. The basics around authentication and object models are there.
## <a id="usage">Usage</a>
### Logging in
client, err := goscaleio.NewClient()
if err != nil {
log.Fatalf("err: %v", err)
}
_, err = client.Authenticate(&goscaleio.ConfigConnect{endpoint, username, password})
if err != nil {
log.Fatalf("error authenticating: %v", err)
}
fmt.Println("Successfuly logged in to ScaleIO Gateway at", client.SIOEndpoint.String())
### Reusing the authentication token
Once a client struct is created via the ```NewClient()``` function, you can replace the ```Token``` with the saved token.
client, err := goscaleio.NewClient()
if err != nil {
log.Fatalf("error with NewClient: %s", err)
}
client.Token = oldToken
### Get Systems
Retrieving systems is the first step after authentication which enables you to work with other necessary methods.
#### All Systems
systems, err := client.GetInstance()
if err != nil {
log.Fatalf("err: problem getting instance %v", err)
}
#### Find a System
system, err := client.FindSystem(systemid,"","")
if err != nil {
log.Fatalf("err: problem getting instance %v", err)
}
### Get Protection Domains
Once you have a ```System``` struct you can then get other things like ```Protection Domains```.
protectiondomains, err := system.GetProtectionDomain()
if err != nil {
log.Fatalf("error getting protection domains: %v", err)
}
<a id="licensing">Licensing</a>
---------
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.
<a id="support">Support</a>
-------
Please file bugs and issues at the Github issues page. For more general discussions you can contact the EMC Code team at <a href="https://groups.google.com/forum/#!forum/emccode-users">Google Groups</a> or tagged with **EMC** on <a href="https://stackoverflow.com">Stackoverflow.com</a>. The code and documentation are released with no warranties or SLAs and are intended to be supported through a community driven process.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment