mirror of https://github.com/k3s-io/k3s
Portworx Volume Driver in Kubernetes
- Add a new type PortworxVolumeSource - Implement the kubernetes volume plugin for Portworx Volumes under pkg/volume/portworx - The Portworx Volume Driver uses the libopenstorage/openstorage specifications and apis for volume operations. Changes for k8s configuration and examples for portworx volumes. - Add PortworxVolume hooks in kubectl, kube-controller-manager and validation. - Add a README for PortworxVolume usage as PVs, PVCs and StorageClass. - Add example spec files Handle code review comments. - Modified READMEs to incorporate to suggestions. - Add a test for ReadWriteMany access mode. - Use util.UnmountPath in TearDown. - Add ReadOnly flag to PortworxVolumeSource - Use hostname:port instead of unix sockets - Delete the mount dir in TearDown. - Fix link issue in persistentvolumes README - In unit test check for mountpath after Setup is done. - Add PVC Claim Name as a Portworx Volume Label Generated code and documentation. - Updated swagger spec - Updated api-reference docs - Updated generated code under pkg/api/v1 Godeps update for Portworx Volume Driver - Adds github.com/libopenstorage/openstorage - Adds go.pedge.io/pb/go/google/protobuf - Updates Godep Licensespull/6/head
parent
dba0af3675
commit
28df55fc31
|
@ -1663,6 +1663,30 @@
|
|||
"Comment": "release.r56-29-gf7ee69f",
|
||||
"Rev": "f7ee69f31298ecbe5d2b349c711e2547a617d398"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/api",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/api/client",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/api/client/volume",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/api/spec",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/pkg/units",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/libopenstorage/openstorage/volume",
|
||||
"Rev": "6e787003b91ddba85f108b8aede075b1af0d3606"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/lpabon/godbc",
|
||||
"Comment": "v1.0-1-g9577782",
|
||||
|
@ -2393,6 +2417,10 @@
|
|||
"Comment": "v1.0-13-g5292687",
|
||||
"Rev": "5292687f5379e01054407da44d7c4590a61fd3de"
|
||||
},
|
||||
{
|
||||
"ImportPath": "go.pedge.io/pb/go/google/protobuf",
|
||||
"Rev": "f3c84f58974dc53d460d0855337cad85843bf0df"
|
||||
},
|
||||
{
|
||||
"ImportPath": "go4.org/errorutil",
|
||||
"Rev": "03efcb870d84809319ea509714dd6d19a1498483"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37838,6 +37838,10 @@
|
|||
"description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PhotonPersistentDiskVolumeSource"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PortworxVolumeSource"
|
||||
},
|
||||
"quobyte": {
|
||||
"description": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.QuobyteVolumeSource"
|
||||
|
@ -38325,6 +38329,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.kubernetes.pkg.api.v1.PortworxVolumeSource": {
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"fsType": {
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.",
|
||||
"type": "string"
|
||||
},
|
||||
"readOnly": {
|
||||
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"volumeID": {
|
||||
"description": "VolumeID uniquely identifies a Portworx volume",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.kubernetes.pkg.api.v1.PreferredSchedulingTerm": {
|
||||
"description": "An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).",
|
||||
"required": [
|
||||
|
@ -39378,6 +39402,10 @@
|
|||
"description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PhotonPersistentDiskVolumeSource"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PortworxVolumeSource"
|
||||
},
|
||||
"projected": {
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ProjectedVolumeSource"
|
||||
|
|
|
@ -1484,6 +1484,10 @@
|
|||
"projected": {
|
||||
"$ref": "v1.ProjectedVolumeSource",
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"$ref": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2243,6 +2247,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.PortworxVolumeSource": {
|
||||
"id": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"volumeID": {
|
||||
"type": "string",
|
||||
"description": "VolumeID uniquely identifies a Portworx volume"
|
||||
},
|
||||
"fsType": {
|
||||
"type": "string",
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". 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": {
|
||||
"id": "v1.Container",
|
||||
"description": "A single application container that you want to run within a pod.",
|
||||
|
|
|
@ -1489,6 +1489,10 @@
|
|||
"projected": {
|
||||
"$ref": "v1.ProjectedVolumeSource",
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"$ref": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2248,6 +2252,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.PortworxVolumeSource": {
|
||||
"id": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"volumeID": {
|
||||
"type": "string",
|
||||
"description": "VolumeID uniquely identifies a Portworx volume"
|
||||
},
|
||||
"fsType": {
|
||||
"type": "string",
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". 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": {
|
||||
"id": "v1.Container",
|
||||
"description": "A single application container that you want to run within a pod.",
|
||||
|
|
|
@ -6905,6 +6905,10 @@
|
|||
"projected": {
|
||||
"$ref": "v1.ProjectedVolumeSource",
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"$ref": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -7664,6 +7668,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.PortworxVolumeSource": {
|
||||
"id": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"volumeID": {
|
||||
"type": "string",
|
||||
"description": "VolumeID uniquely identifies a Portworx volume"
|
||||
},
|
||||
"fsType": {
|
||||
"type": "string",
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". 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": {
|
||||
"id": "v1.Container",
|
||||
"description": "A single application container that you want to run within a pod.",
|
||||
|
|
|
@ -17885,6 +17885,10 @@
|
|||
"$ref": "v1.PhotonPersistentDiskVolumeSource",
|
||||
"description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"$ref": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
|
||||
},
|
||||
"accessModes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -18363,6 +18367,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"v1.PortworxVolumeSource": {
|
||||
"id": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"volumeID": {
|
||||
"type": "string",
|
||||
"description": "VolumeID uniquely identifies a Portworx volume"
|
||||
},
|
||||
"fsType": {
|
||||
"type": "string",
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". 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": {
|
||||
"id": "v1.PersistentVolumeStatus",
|
||||
"description": "PersistentVolumeStatus is the current status of a persistent volume.",
|
||||
|
@ -18655,6 +18680,10 @@
|
|||
"projected": {
|
||||
"$ref": "v1.ProjectedVolumeSource",
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"$ref": "v1.PortworxVolumeSource",
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -84,6 +84,7 @@ go_library(
|
|||
"//pkg/volume/host_path:go_default_library",
|
||||
"//pkg/volume/nfs:go_default_library",
|
||||
"//pkg/volume/photon_pd:go_default_library",
|
||||
"//pkg/volume/portworx:go_default_library",
|
||||
"//pkg/volume/quobyte:go_default_library",
|
||||
"//pkg/volume/rbd:go_default_library",
|
||||
"//pkg/volume/vsphere_volume:go_default_library",
|
||||
|
|
|
@ -50,6 +50,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/volume/host_path"
|
||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||
"k8s.io/kubernetes/pkg/volume/photon_pd"
|
||||
"k8s.io/kubernetes/pkg/volume/portworx"
|
||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
||||
"k8s.io/kubernetes/pkg/volume/rbd"
|
||||
"k8s.io/kubernetes/pkg/volume/vsphere_volume"
|
||||
|
@ -68,6 +69,7 @@ func ProbeAttachableVolumePlugins(config componentconfig.VolumeConfiguration) []
|
|||
allPlugins = append(allPlugins, gce_pd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, cinder.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, flexvolume.ProbeVolumePlugins(config.FlexVolumePluginDir)...)
|
||||
allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
|
||||
|
@ -115,6 +117,7 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config componen
|
|||
allPlugins = append(allPlugins, quobyte.ProbeVolumePlugins()...)
|
||||
|
||||
allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...)
|
||||
|
||||
if cloud != nil {
|
||||
switch {
|
||||
|
|
|
@ -90,6 +90,7 @@ go_library(
|
|||
"//pkg/volume/iscsi:go_default_library",
|
||||
"//pkg/volume/nfs:go_default_library",
|
||||
"//pkg/volume/photon_pd:go_default_library",
|
||||
"//pkg/volume/portworx:go_default_library",
|
||||
"//pkg/volume/projected:go_default_library",
|
||||
"//pkg/volume/quobyte:go_default_library",
|
||||
"//pkg/volume/rbd:go_default_library",
|
||||
|
|
|
@ -46,6 +46,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/volume/iscsi"
|
||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||
"k8s.io/kubernetes/pkg/volume/photon_pd"
|
||||
"k8s.io/kubernetes/pkg/volume/portworx"
|
||||
"k8s.io/kubernetes/pkg/volume/projected"
|
||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
||||
"k8s.io/kubernetes/pkg/volume/rbd"
|
||||
|
@ -90,6 +91,7 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin {
|
|||
allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...)
|
||||
return allPlugins
|
||||
}
|
||||
|
||||
|
|
|
@ -1758,6 +1758,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_v1_portworxvolumesource">v1.PortworxVolumeSource</h3>
|
||||
<div class="paragraph">
|
||||
<p>PortworxVolumeSource represents a Portworx volume resource.</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">volumeID</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">VolumeID uniquely identifies a Portworx volume</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">fsType</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". 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_localobjectreference">v1.LocalObjectReference</h3>
|
||||
|
@ -4244,6 +4292,13 @@ The StatefulSet guarantees that a given network identity will always map to the
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_projectedvolumesource">v1.ProjectedVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">portworxVolume</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">PortworxVolume represents a portworx volume attached and mounted on kubelets host machine</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_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -5396,7 +5451,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-23 20:32:09 UTC
|
||||
Last updated 2017-02-27 07:15:52 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -1655,6 +1655,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_v1_portworxvolumesource">v1.PortworxVolumeSource</h3>
|
||||
<div class="paragraph">
|
||||
<p>PortworxVolumeSource represents a Portworx volume resource.</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">volumeID</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">VolumeID uniquely identifies a Portworx volume</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">fsType</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". 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_localobjectreference">v1.LocalObjectReference</h3>
|
||||
|
@ -4224,6 +4272,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_projectedvolumesource">v1.ProjectedVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">portworxVolume</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">PortworxVolume represents a portworx volume attached and mounted on kubelets host machine</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_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -5321,7 +5376,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-23 20:32:42 UTC
|
||||
Last updated 2017-02-27 07:16:35 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -1763,6 +1763,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_v1_portworxvolumesource">v1.PortworxVolumeSource</h3>
|
||||
<div class="paragraph">
|
||||
<p>PortworxVolumeSource represents a Portworx volume resource.</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">volumeID</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">VolumeID uniquely identifies a Portworx volume</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">fsType</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". 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_capabilities">v1.Capabilities</h3>
|
||||
|
@ -3637,6 +3685,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_projectedvolumesource">v1.ProjectedVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">portworxVolume</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">PortworxVolume represents a portworx volume attached and mounted on kubelets host machine</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_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -7726,7 +7781,7 @@ Both these may change in the future. Incoming requests are matched against the h
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-27 08:17:02 UTC
|
||||
Last updated 2017-02-27 20:18:57 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -1930,6 +1930,54 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_v1_portworxvolumesource">v1.PortworxVolumeSource</h3>
|
||||
<div class="paragraph">
|
||||
<p>PortworxVolumeSource represents a Portworx volume resource.</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">volumeID</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">VolumeID uniquely identifies a Portworx volume</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">fsType</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". 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_podtemplatelist">v1.PodTemplateList</h3>
|
||||
|
@ -4350,6 +4398,13 @@ The resulting set of endpoints can be viewed as:<br>
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_projectedvolumesource">v1.ProjectedVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">portworxVolume</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">PortworxVolume represents a portworx volume attached and mounted on kubelets host machine</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_portworxvolumesource">v1.PortworxVolumeSource</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -7017,6 +7072,13 @@ Examples:<br>
|
|||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">portworxVolume</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">PortworxVolume represents a portworx volume attached and mounted on kubelets host machine</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_portworxvolumesource">v1.PortworxVolumeSource</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 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>
|
||||
|
@ -9652,7 +9714,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-23 20:32:02 UTC
|
||||
Last updated 2017-02-27 07:15:44 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -63,6 +63,30 @@ parameters:
|
|||
|
||||
* `diskformat`: `thin`, `zeroedthick` and `eagerzeroedthick`. See vSphere docs for details. Default: `"thin"`.
|
||||
|
||||
#### Portworx Volume
|
||||
|
||||
```yaml
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: portworx-io-priority-high
|
||||
provisioner: kubernetes.io/portworx-volume
|
||||
parameters:
|
||||
repl: "1"
|
||||
snap_interval: "70"
|
||||
io_priority: "high"
|
||||
|
||||
```
|
||||
|
||||
* `fs`: filesystem to be laid out: [none/xfs/ext4] (default: `ext4`)
|
||||
* `block_size`: block size in Kbytes (default: `32`)
|
||||
* `repl`: replication factor [1..3] (default: `1`)
|
||||
* `io_priority`: IO Priority: [high/medium/low] (default: `low`)
|
||||
* `snap_interval`: snapshot interval in minutes, 0 disables snaps (default: `0`)
|
||||
* `aggregation_level`: specifies the number of chunks the volume would be distributed into, 0 indicates a non-aggregated volume (default: `0`)
|
||||
* `ephemeral`: ephemeral storage [true/false] (default `false`)
|
||||
|
||||
For a complete example refer ([Portworx Volume docs](../../volumes/portworx/README.md))
|
||||
|
||||
#### GLUSTERFS
|
||||
|
||||
|
|
|
@ -0,0 +1,370 @@
|
|||
# Portworx Volume
|
||||
|
||||
- [Portworx](#portworx)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Examples](#examples)
|
||||
- [Using Pre-provisioned Portworx Volumes](#pre-provisioned)
|
||||
- [Running Pod](#running-pod)
|
||||
- [Persistent Volumes](#persistent-volumes)
|
||||
- [Using Dynamic Provisioning](#dynamic-provisioning)
|
||||
- [Storage Class](#storage-class)
|
||||
|
||||
## Portworx
|
||||
|
||||
[Portworx](http://www.portworx.com) can be used as a storage provider for your Kubernetes cluster. Portworx pools your servers capacity and turns your servers
|
||||
or cloud instances into converged, highly available compute and storage nodes
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Portworx instance running on all of your Kubernetes nodes. For
|
||||
more information on how you can install Portworx can be found [here](http://docs.portworx.com)
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples assumes that you already have a running Kubernetes cluster with Portworx installed on all nodes.
|
||||
|
||||
### Using Pre-provisioned Portworx Volumes
|
||||
|
||||
Create a Volume using Portworx CLI.
|
||||
On one of the Kubernetes nodes with Portworx installed run the following command
|
||||
|
||||
```shell
|
||||
/opt/pwx/bin/pxctl volume create <vol-id> --size <size> --fs <fs-type>
|
||||
```
|
||||
|
||||
#### Running Pods
|
||||
|
||||
Create Pod which uses Portworx Volumes
|
||||
|
||||
Example spec:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-portworx-volume-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/google_containers/test-webserver
|
||||
name: test-container
|
||||
volumeMounts:
|
||||
- mountPath: /test-portworx-volume
|
||||
name: test-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
# This Portworx volume must already exist.
|
||||
portworxVolume:
|
||||
volumeID: "<vol-id>"
|
||||
fsType: "<fs-type>"
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-pod.yaml?raw=true)
|
||||
|
||||
Make sure to replace <vol-id> and <fs-type> in the above spec with
|
||||
the ones that you used while creating the volume.
|
||||
|
||||
Create the Pod.
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pod.yaml
|
||||
```
|
||||
|
||||
Verify that pod is running:
|
||||
|
||||
```bash
|
||||
$ kubectl.sh get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
test-portworx-volume-pod 1/1 Running 0 16s
|
||||
```
|
||||
|
||||
#### Persistent Volumes
|
||||
|
||||
1. Create Persistent Volume.
|
||||
|
||||
Example spec:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: <vol-id>
|
||||
spec:
|
||||
capacity:
|
||||
storage: <size>Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
portworxVolume:
|
||||
volumeID: "<vol-id>"
|
||||
fsType: "<fs-type>"
|
||||
```
|
||||
|
||||
Make sure to replace <vol-id>, <size> and <fs-type> in the above spec with
|
||||
the ones that you used while creating the volume.
|
||||
|
||||
[Download example](portworx-volume-pv.yaml?raw=true)
|
||||
|
||||
Creating the persistent volume:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pv.yaml
|
||||
```
|
||||
|
||||
Verifying persistent volume is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl describe pv pv0001
|
||||
Name: pv0001
|
||||
Labels: <none>
|
||||
StorageClass:
|
||||
Status: Available
|
||||
Claim:
|
||||
Reclaim Policy: Retain
|
||||
Access Modes: RWO
|
||||
Capacity: 2Gi
|
||||
Message:
|
||||
Source:
|
||||
Type: PortworxVolume (a Portworx Persistent Volume resource)
|
||||
VolumeID: pv0001
|
||||
FSType: ext4
|
||||
No events.
|
||||
```
|
||||
|
||||
2. Create Persistent Volume Claim.
|
||||
|
||||
Example spec:
|
||||
|
||||
```yaml
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pvc0001
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: <size>Gi
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-pvc.yaml?raw=true)
|
||||
|
||||
Creating the persistent volume claim:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pvc.yaml
|
||||
```
|
||||
|
||||
Verifying persistent volume claim is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl describe pvc pvc0001
|
||||
Name: pvc0001
|
||||
Namespace: default
|
||||
Status: Bound
|
||||
Volume: pv0001
|
||||
Labels: <none>
|
||||
Capacity: 2Gi
|
||||
Access Modes: RWO
|
||||
No events.
|
||||
```
|
||||
|
||||
3. Create Pod which uses Persistent Volume Claim.
|
||||
|
||||
See example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pvpod
|
||||
spec:
|
||||
containers:
|
||||
- name: test-container
|
||||
image: gcr.io/google_containers/test-webserver
|
||||
volumeMounts:
|
||||
- name: test-volume
|
||||
mountPath: /test-portworx-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: pvc0001
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-pvcpod.yaml?raw=true)
|
||||
|
||||
Creating the pod:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pvcpod.yaml
|
||||
```
|
||||
|
||||
Verifying pod is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl get pod pvpod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pvpod 1/1 Running 0 48m
|
||||
```
|
||||
|
||||
### Using Dynamic Provisioning
|
||||
|
||||
Using Dynamic Provisioning and Storage Classes you don't need to
|
||||
create Portworx volumes out of band and they will be created automatically.
|
||||
|
||||
#### Storage Class
|
||||
|
||||
Using Storage Classes objects an admin can define the different classes of Portworx Volumes
|
||||
that are offered in a cluster. Following are the different parameters that can be used to define a Portworx
|
||||
Storage Class
|
||||
|
||||
* `fs`: filesystem to be laid out: none|xfs|ext4 (default: `ext4`)
|
||||
* `block_size`: block size in Kbytes (default: `32`)
|
||||
* `repl`: replication factor [1..3] (default: `1`)
|
||||
* `io_priority`: IO Priority: [high|medium|low] (default: `low`)
|
||||
* `snap_interval`: snapshot interval in minutes, 0 disables snaps (default: `0`)
|
||||
* `aggregation_level`: specifies the number of replication sets the volume can be aggregated from (default: `1`)
|
||||
* `ephemeral`: ephemeral storage [true|false] (default `false`)
|
||||
|
||||
|
||||
1. Create Storage Class.
|
||||
|
||||
See example:
|
||||
|
||||
```yaml
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: portworx-io-priority-high
|
||||
provisioner: kubernetes.io/portworx-volume
|
||||
parameters:
|
||||
repl: "1"
|
||||
snap_interval: "70"
|
||||
io_priority: "high"
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-sc-high.yaml?raw=true)
|
||||
|
||||
Creating the storageclass:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-sc-high.yaml
|
||||
```
|
||||
|
||||
Verifying storage class is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl describe storageclass portworx-io-priority-high
|
||||
Name: portworx-io-priority-high
|
||||
IsDefaultClass: No
|
||||
Annotations: <none>
|
||||
Provisioner: kubernetes.io/portworx-volume
|
||||
Parameters: io_priority=high,repl=1,snapshot_interval=70
|
||||
No events.
|
||||
```
|
||||
|
||||
2. Create Persistent Volume Claim.
|
||||
|
||||
See example:
|
||||
|
||||
```yaml
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pvcsc001
|
||||
annotations:
|
||||
volume.beta.kubernetes.io/storage-class: portworx-io-priority-high
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-pvcsc.yaml?raw=true)
|
||||
|
||||
Creating the persistent volume claim:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pvcsc.yaml
|
||||
```
|
||||
|
||||
Verifying persistent volume claim is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl describe pvc pvcsc001
|
||||
Name: pvcsc001
|
||||
Namespace: default
|
||||
StorageClass: portworx-io-priority-high
|
||||
Status: Bound
|
||||
Volume: pvc-e5578707-c626-11e6-baf6-08002729a32b
|
||||
Labels: <none>
|
||||
Capacity: 2Gi
|
||||
Access Modes: RWO
|
||||
No Events
|
||||
```
|
||||
|
||||
Persistent Volume is automatically created and is bounded to this pvc.
|
||||
|
||||
Verifying persistent volume claim is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl describe pv pvc-e5578707-c626-11e6-baf6-08002729a32b
|
||||
Name: pvc-e5578707-c626-11e6-baf6-08002729a32b
|
||||
Labels: <none>
|
||||
StorageClass: portworx-io-priority-high
|
||||
Status: Bound
|
||||
Claim: default/pvcsc001
|
||||
Reclaim Policy: Delete
|
||||
Access Modes: RWO
|
||||
Capacity: 2Gi
|
||||
Message:
|
||||
Source:
|
||||
Type: PortworxVolume (a Portworx Persistent Volume resource)
|
||||
VolumeID: 374093969022973811
|
||||
No events.
|
||||
```
|
||||
|
||||
3. Create Pod which uses Persistent Volume Claim with storage class.
|
||||
|
||||
See example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pvpod
|
||||
spec:
|
||||
containers:
|
||||
- name: test-container
|
||||
image: gcr.io/google_containers/test-webserver
|
||||
volumeMounts:
|
||||
- name: test-volume
|
||||
mountPath: /test-portworx-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: pvcsc001
|
||||
```
|
||||
|
||||
[Download example](portworx-volume-pvcscpod.yaml?raw=true)
|
||||
|
||||
Creating the pod:
|
||||
|
||||
``` bash
|
||||
$ kubectl create -f examples/volumes/portworx/portworx-volume-pvcscpod.yaml
|
||||
```
|
||||
|
||||
Verifying pod is created:
|
||||
|
||||
``` bash
|
||||
$ kubectl get pod pvpod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pvpod 1/1 Running 0 48m
|
||||
```
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/volumes/portworx/README.md?pixel)]()
|
||||
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-portworx-volume-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/google_containers/test-webserver
|
||||
name: test-container
|
||||
volumeMounts:
|
||||
- mountPath: /test-portworx-volume
|
||||
name: test-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
# This Portworx volume must already exist.
|
||||
portworxVolume:
|
||||
volumeID: "vol1"
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: pv0001
|
||||
spec:
|
||||
capacity:
|
||||
storage: 2Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
portworxVolume:
|
||||
volumeID: "pv0001"
|
|
@ -0,0 +1,10 @@
|
|||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pvc0001
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pvpod
|
||||
spec:
|
||||
containers:
|
||||
- name: test-container
|
||||
image: gcr.io/google_containers/test-webserver
|
||||
volumeMounts:
|
||||
- name: test-volume
|
||||
mountPath: /test-portworx-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: pvc0001
|
|
@ -0,0 +1,12 @@
|
|||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pvcsc001
|
||||
annotations:
|
||||
volume.beta.kubernetes.io/storage-class: portworx-io-priority-high
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pvpod
|
||||
spec:
|
||||
containers:
|
||||
- name: test-container
|
||||
image: gcr.io/google_containers/test-webserver
|
||||
volumeMounts:
|
||||
- name: test-volume
|
||||
mountPath: /test-portworx-volume
|
||||
volumes:
|
||||
- name: test-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: pvcsc001
|
|
@ -0,0 +1,9 @@
|
|||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: portworx-io-priority-high
|
||||
provisioner: kubernetes.io/portworx-volume
|
||||
parameters:
|
||||
repl: "1"
|
||||
snap_interval: "70"
|
||||
io_priority: "high"
|
|
@ -12636,6 +12636,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.kubernetes.pkg.api.v1.PortworxVolumeSource": {
|
||||
"description": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"required": [
|
||||
"volumeID"
|
||||
],
|
||||
"properties": {
|
||||
"fsType": {
|
||||
"description": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.",
|
||||
"type": "string"
|
||||
},
|
||||
"readOnly": {
|
||||
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"volumeID": {
|
||||
"description": "VolumeID uniquely identifies a Portworx volume",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.kubernetes.pkg.api.v1.PreferredSchedulingTerm": {
|
||||
"description": "An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).",
|
||||
"required": [
|
||||
|
@ -13323,6 +13343,10 @@
|
|||
"description": "PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PhotonPersistentDiskVolumeSource"
|
||||
},
|
||||
"portworxVolume": {
|
||||
"description": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.PortworxVolumeSource"
|
||||
},
|
||||
"projected": {
|
||||
"description": "Items for all in one resources secrets, configmaps, and downward API",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ProjectedVolumeSource"
|
||||
|
|
|
@ -296,6 +296,9 @@ type VolumeSource struct {
|
|||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource
|
||||
}
|
||||
|
||||
// Similar to VolumeSource but meant for the administrator who creates PVs.
|
||||
|
@ -358,6 +361,9 @@ type PersistentVolumeSource struct {
|
|||
AzureDisk *AzureDiskVolumeSource
|
||||
// PhotonPersistentDisk represents a Photon Controller persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource
|
||||
}
|
||||
|
||||
type PersistentVolumeClaimVolumeSource struct {
|
||||
|
@ -1001,6 +1007,21 @@ type PhotonPersistentDiskVolumeSource struct {
|
|||
FSType string
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
type PortworxVolumeSource struct {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
VolumeID string
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". 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
|
||||
}
|
||||
|
||||
type AzureDataDiskCachingMode string
|
||||
|
||||
const (
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2128,6 +2128,10 @@ message PersistentVolumeSource {
|
|||
|
||||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 17;
|
||||
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
optional PortworxVolumeSource portworxVolume = 18;
|
||||
}
|
||||
|
||||
// PersistentVolumeSpec is the specification of a persistent volume.
|
||||
|
@ -2790,6 +2794,22 @@ message PodTemplateSpec {
|
|||
optional PodSpec spec = 2;
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
message PortworxVolumeSource {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
optional string volumeID = 1;
|
||||
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified.
|
||||
optional string fsType = 2;
|
||||
|
||||
// Defaults to false (read/write). ReadOnly here will force
|
||||
// the ReadOnly setting in VolumeMounts.
|
||||
// +optional
|
||||
optional bool readOnly = 3;
|
||||
}
|
||||
|
||||
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
|
||||
// +k8s:openapi-gen=false
|
||||
message Preconditions {
|
||||
|
@ -3811,7 +3831,11 @@ message VolumeSource {
|
|||
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23;
|
||||
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
optional ProjectedVolumeSource projected = 24;
|
||||
optional ProjectedVolumeSource projected = 25;
|
||||
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
optional PortworxVolumeSource portworxVolume = 24;
|
||||
}
|
||||
|
||||
// Represents a vSphere volume resource.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -328,6 +328,9 @@ type VolumeSource struct {
|
|||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,23,opt,name=photonPersistentDisk"`
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
|
||||
|
@ -413,6 +416,9 @@ type PersistentVolumeSource struct {
|
|||
AzureDisk *AzureDiskVolumeSource `json:"azureDisk,omitempty" protobuf:"bytes,16,opt,name=azureDisk"`
|
||||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,17,opt,name=photonPersistentDisk"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
|
@ -1107,6 +1113,20 @@ type AzureDiskVolumeSource struct {
|
|||
ReadOnly *bool `json:"readOnly,omitempty" protobuf:"varint,5,opt,name=readOnly"`
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
type PortworxVolumeSource struct {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
VolumeID string `json:"volumeID" protobuf:"bytes,1,opt,name=volumeID"`
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified.
|
||||
FSType string `json:"fsType,omitempty" protobuf:"bytes,2,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,3,opt,name=readOnly"`
|
||||
}
|
||||
|
||||
// Adapts a ConfigMap into a volume.
|
||||
//
|
||||
// The contents of the target ConfigMap's Data field will be presented in a
|
||||
|
|
|
@ -1122,6 +1122,7 @@ var map_PersistentVolumeSource = map[string]string{
|
|||
"quobyte": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime",
|
||||
"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",
|
||||
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
}
|
||||
|
||||
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
|
||||
|
@ -1399,6 +1400,17 @@ func (PodTemplateSpec) SwaggerDoc() map[string]string {
|
|||
return map_PodTemplateSpec
|
||||
}
|
||||
|
||||
var map_PortworxVolumeSource = map[string]string{
|
||||
"": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"volumeID": "VolumeID uniquely identifies a Portworx volume",
|
||||
"fsType": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.",
|
||||
"readOnly": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||
}
|
||||
|
||||
func (PortworxVolumeSource) SwaggerDoc() map[string]string {
|
||||
return map_PortworxVolumeSource
|
||||
}
|
||||
|
||||
var map_Preconditions = map[string]string{
|
||||
"": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.",
|
||||
"uid": "Specifies the target UID.",
|
||||
|
@ -1897,6 +1909,7 @@ var map_VolumeSource = map[string]string{
|
|||
"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",
|
||||
"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",
|
||||
}
|
||||
|
||||
func (VolumeSource) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -275,6 +275,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||
Convert_api_PodTemplateList_To_v1_PodTemplateList,
|
||||
Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec,
|
||||
Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec,
|
||||
Convert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource,
|
||||
Convert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource,
|
||||
Convert_v1_Preconditions_To_api_Preconditions,
|
||||
Convert_api_Preconditions_To_v1_Preconditions,
|
||||
Convert_v1_PreferAvoidPodsEntry_To_api_PreferAvoidPodsEntry,
|
||||
|
@ -2706,6 +2708,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
|
|||
out.Quobyte = (*api.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
||||
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2731,6 +2734,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
|
|||
out.VsphereVolume = (*VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume))
|
||||
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -3341,6 +3345,28 @@ func autoConvert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in *api.PodTemplateSp
|
|||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in *PortworxVolumeSource, out *api.PortworxVolumeSource, s conversion.Scope) error {
|
||||
out.VolumeID = in.VolumeID
|
||||
out.FSType = in.FSType
|
||||
out.ReadOnly = in.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in *PortworxVolumeSource, out *api.PortworxVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in *api.PortworxVolumeSource, out *PortworxVolumeSource, s conversion.Scope) error {
|
||||
out.VolumeID = in.VolumeID
|
||||
out.FSType = in.FSType
|
||||
out.ReadOnly = in.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in *api.PortworxVolumeSource, out *PortworxVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Preconditions_To_api_Preconditions(in *Preconditions, out *api.Preconditions, s conversion.Scope) error {
|
||||
out.UID = (*types.UID)(unsafe.Pointer(in.UID))
|
||||
return nil
|
||||
|
@ -4458,6 +4484,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
|
|||
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
|
||||
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -4490,6 +4517,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
|
|||
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
|
||||
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplate, InType: reflect.TypeOf(&PodTemplate{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplateList, InType: reflect.TypeOf(&PodTemplateList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplateSpec, InType: reflect.TypeOf(&PodTemplateSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PortworxVolumeSource, InType: reflect.TypeOf(&PortworxVolumeSource{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Preconditions, InType: reflect.TypeOf(&Preconditions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PreferAvoidPodsEntry, InType: reflect.TypeOf(&PreferAvoidPodsEntry{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PreferredSchedulingTerm, InType: reflect.TypeOf(&PreferredSchedulingTerm{})},
|
||||
|
@ -2015,6 +2016,11 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv
|
|||
*out = new(PhotonPersistentDiskVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -2513,6 +2519,15 @@ func DeepCopy_v1_PodTemplateSpec(in interface{}, out interface{}, c *conversion.
|
|||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_PortworxVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*PortworxVolumeSource)
|
||||
out := out.(*PortworxVolumeSource)
|
||||
*out = *in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_Preconditions(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*Preconditions)
|
||||
|
@ -3420,6 +3435,11 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo
|
|||
return err
|
||||
}
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,6 +511,14 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
|
|||
allErrs = append(allErrs, validatePhotonPersistentDiskVolumeSource(source.PhotonPersistentDisk, fldPath.Child("photonPersistentDisk"))...)
|
||||
}
|
||||
}
|
||||
if source.PortworxVolume != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("portworxVolume"), "may not specify more than 1 volume type"))
|
||||
} else {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validatePortworxVolumeSource(source.PortworxVolume, fldPath.Child("portworxVolume"))...)
|
||||
}
|
||||
}
|
||||
if source.AzureDisk != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateAzureDisk(source.AzureDisk, fldPath.Child("azureDisk"))...)
|
||||
|
@ -979,6 +987,14 @@ func validatePhotonPersistentDiskVolumeSource(cd *api.PhotonPersistentDiskVolume
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func validatePortworxVolumeSource(pwx *api.PortworxVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(pwx.VolumeID) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("volumeID"), ""))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
||||
// PersistentVolumeName object.
|
||||
var ValidatePersistentVolumeName = NameIsDNSSubdomain
|
||||
|
@ -1138,6 +1154,14 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||
allErrs = append(allErrs, validatePhotonPersistentDiskVolumeSource(pv.Spec.PhotonPersistentDisk, specPath.Child("photonPersistentDisk"))...)
|
||||
}
|
||||
}
|
||||
if pv.Spec.PortworxVolume != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("portworxVolume"), "may not specify more than 1 volume type"))
|
||||
} else {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validatePortworxVolumeSource(pv.Spec.PortworxVolume, specPath.Child("portworxVolume"))...)
|
||||
}
|
||||
}
|
||||
if pv.Spec.AzureDisk != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateAzureDisk(pv.Spec.AzureDisk, specPath.Child("azureDisk"))...)
|
||||
|
|
|
@ -158,6 +158,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplate, InType: reflect.TypeOf(&PodTemplate{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplateList, InType: reflect.TypeOf(&PodTemplateList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplateSpec, InType: reflect.TypeOf(&PodTemplateSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PortworxVolumeSource, InType: reflect.TypeOf(&PortworxVolumeSource{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Preconditions, InType: reflect.TypeOf(&Preconditions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PreferAvoidPodsEntry, InType: reflect.TypeOf(&PreferAvoidPodsEntry{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PreferredSchedulingTerm, InType: reflect.TypeOf(&PreferredSchedulingTerm{})},
|
||||
|
@ -2059,6 +2060,11 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con
|
|||
*out = new(PhotonPersistentDiskVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -2557,6 +2563,15 @@ func DeepCopy_api_PodTemplateSpec(in interface{}, out interface{}, c *conversion
|
|||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_PortworxVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*PortworxVolumeSource)
|
||||
out := out.(*PortworxVolumeSource)
|
||||
*out = *in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_Preconditions(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*Preconditions)
|
||||
|
@ -3447,6 +3462,11 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl
|
|||
return err
|
||||
}
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -917,6 +917,7 @@ var (
|
|||
AzureDisk FSType = "azureDisk"
|
||||
PhotonPersistentDisk FSType = "photonPersistentDisk"
|
||||
Projected FSType = "projected"
|
||||
PortworxVolume FSType = "portworxVolume"
|
||||
All FSType = "*"
|
||||
)
|
||||
|
||||
|
|
|
@ -5572,11 +5572,17 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource"),
|
||||
},
|
||||
},
|
||||
"portworxVolume": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.PersistentVolumeSpec": {
|
||||
Schema: spec.Schema{
|
||||
|
@ -5698,6 +5704,12 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource"),
|
||||
},
|
||||
},
|
||||
"portworxVolume": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource"),
|
||||
},
|
||||
},
|
||||
"accessModes": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "AccessModes contains all ways the volume can be mounted. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes",
|
||||
|
@ -5736,7 +5748,7 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/api/resource.Quantity", "k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ObjectReference", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
"k8s.io/apimachinery/pkg/api/resource.Quantity", "k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ObjectReference", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.PersistentVolumeStatus": {
|
||||
Schema: spec.Schema{
|
||||
|
@ -6839,6 +6851,38 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "k8s.io/kubernetes/pkg/api/v1.PodSpec"},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
Properties: map[string]spec.Schema{
|
||||
"volumeID": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "VolumeID uniquely identifies a Portworx volume",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"fsType": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"readOnly": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"volumeID"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.PreferAvoidPodsEntry": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
|
@ -8691,12 +8735,18 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource"),
|
||||
},
|
||||
},
|
||||
"portworxVolume": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"name"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ConfigMapVolumeSource", "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.EmptyDirVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GitRepoVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.SecretVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ConfigMapVolumeSource", "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.EmptyDirVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GitRepoVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.SecretVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.VolumeMount": {
|
||||
Schema: spec.Schema{
|
||||
|
@ -8915,11 +8965,17 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource"),
|
||||
},
|
||||
},
|
||||
"portworxVolume": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
Ref: ref("k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ConfigMapVolumeSource", "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.EmptyDirVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GitRepoVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.SecretVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
"k8s.io/kubernetes/pkg/api/v1.AWSElasticBlockStoreVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.AzureFileVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CephFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.CinderVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ConfigMapVolumeSource", "k8s.io/kubernetes/pkg/api/v1.DownwardAPIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.EmptyDirVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FCVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlexVolumeSource", "k8s.io/kubernetes/pkg/api/v1.FlockerVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GCEPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GitRepoVolumeSource", "k8s.io/kubernetes/pkg/api/v1.GlusterfsVolumeSource", "k8s.io/kubernetes/pkg/api/v1.HostPathVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ISCSIVolumeSource", "k8s.io/kubernetes/pkg/api/v1.NFSVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PersistentVolumeClaimVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PhotonPersistentDiskVolumeSource", "k8s.io/kubernetes/pkg/api/v1.PortworxVolumeSource", "k8s.io/kubernetes/pkg/api/v1.ProjectedVolumeSource", "k8s.io/kubernetes/pkg/api/v1.QuobyteVolumeSource", "k8s.io/kubernetes/pkg/api/v1.RBDVolumeSource", "k8s.io/kubernetes/pkg/api/v1.SecretVolumeSource", "k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource"},
|
||||
},
|
||||
"k8s.io/kubernetes/pkg/api/v1.VsphereVirtualDiskVolumeSource": {
|
||||
Schema: spec.Schema{
|
||||
|
|
|
@ -623,6 +623,8 @@ func describeVolumes(volumes []api.Volume, w *PrefixWriter, space string) {
|
|||
printCinderVolumeSource(volume.VolumeSource.Cinder, w)
|
||||
case volume.VolumeSource.PhotonPersistentDisk != nil:
|
||||
printPhotonPersistentDiskVolumeSource(volume.VolumeSource.PhotonPersistentDisk, w)
|
||||
case volume.VolumeSource.PortworxVolume != nil:
|
||||
printPortworxVolumeSource(volume.VolumeSource.PortworxVolume, w)
|
||||
default:
|
||||
w.Write(LEVEL_1, "<unknown>\n")
|
||||
}
|
||||
|
@ -696,6 +698,12 @@ func printQuobyteVolumeSource(quobyte *api.QuobyteVolumeSource, w *PrefixWriter)
|
|||
quobyte.Registry, quobyte.Volume, quobyte.ReadOnly)
|
||||
}
|
||||
|
||||
func printPortworxVolumeSource(pwxVolume *api.PortworxVolumeSource, w *PrefixWriter) {
|
||||
w.Write(LEVEL_2, "Type:\tPortworxVolume (a Portworx Volume resource)\n"+
|
||||
" VolumeID:\t%v\n",
|
||||
pwxVolume.VolumeID)
|
||||
}
|
||||
|
||||
func printISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, w *PrefixWriter) {
|
||||
w.Write(LEVEL_2, "Type:\tISCSI (an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod)\n"+
|
||||
" TargetPortal:\t%v\n"+
|
||||
|
@ -841,6 +849,8 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
|
|||
printAzureDiskVolumeSource(pv.Spec.AzureDisk, w)
|
||||
case pv.Spec.PhotonPersistentDisk != nil:
|
||||
printPhotonPersistentDiskVolumeSource(pv.Spec.PhotonPersistentDisk, w)
|
||||
case pv.Spec.PortworxVolume != nil:
|
||||
printPortworxVolumeSource(pv.Spec.PortworxVolume, w)
|
||||
}
|
||||
|
||||
if events != nil {
|
||||
|
|
|
@ -63,6 +63,7 @@ func GetAllFSTypesAsSet() sets.String {
|
|||
string(extensions.AzureDisk),
|
||||
string(extensions.PhotonPersistentDisk),
|
||||
string(extensions.Projected),
|
||||
string(extensions.PortworxVolume),
|
||||
)
|
||||
return fstypes
|
||||
}
|
||||
|
@ -118,6 +119,8 @@ func GetVolumeFSType(v api.Volume) (extensions.FSType, error) {
|
|||
return extensions.PhotonPersistentDisk, nil
|
||||
case v.Projected != nil:
|
||||
return extensions.Projected, nil
|
||||
case v.PortworxVolume != nil:
|
||||
return extensions.PortworxVolume, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unknown volume type for volume: %#v", v)
|
||||
|
|
|
@ -108,6 +108,7 @@ filegroup(
|
|||
"//pkg/volume/iscsi:all-srcs",
|
||||
"//pkg/volume/nfs:all-srcs",
|
||||
"//pkg/volume/photon_pd:all-srcs",
|
||||
"//pkg/volume/portworx:all-srcs",
|
||||
"//pkg/volume/projected:all-srcs",
|
||||
"//pkg/volume/quobyte:all-srcs",
|
||||
"//pkg/volume/rbd:all-srcs",
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
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 = ["portworx_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/client-go/util/testing",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"portworx.go",
|
||||
"portworx_util.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/exec: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/golang/glog",
|
||||
"//vendor:github.com/libopenstorage/openstorage/api",
|
||||
"//vendor:github.com/libopenstorage/openstorage/api/client",
|
||||
"//vendor:github.com/libopenstorage/openstorage/api/client/volume",
|
||||
"//vendor:github.com/libopenstorage/openstorage/api/spec",
|
||||
"//vendor:github.com/libopenstorage/openstorage/volume",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
maintainers:
|
||||
- adityadani
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 portworx contains the internal representation of Portworx
|
||||
// Block Device volumes.
|
||||
package portworx
|
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/exec"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
kstrings "k8s.io/kubernetes/pkg/util/strings"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
// This is the primary entrypoint for volume plugins.
|
||||
func ProbeVolumePlugins() []volume.VolumePlugin {
|
||||
return []volume.VolumePlugin{&portworxVolumePlugin{nil}}
|
||||
}
|
||||
|
||||
type portworxVolumePlugin struct {
|
||||
host volume.VolumeHost
|
||||
}
|
||||
|
||||
var _ volume.VolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.PersistentVolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.DeletableVolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.ProvisionableVolumePlugin = &portworxVolumePlugin{}
|
||||
|
||||
const (
|
||||
portworxVolumePluginName = "kubernetes.io/portworx-volume"
|
||||
)
|
||||
|
||||
func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
|
||||
return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(portworxVolumePluginName), volName)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) Init(host volume.VolumeHost) error {
|
||||
plugin.host = host
|
||||
return nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetPluginName() string {
|
||||
return portworxVolumePluginName
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
||||
volumeSource, _, err := getVolumeSource(spec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return volumeSource.VolumeID, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.PortworxVolume != nil) ||
|
||||
(spec.Volume != nil && spec.Volume.PortworxVolume != nil)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
|
||||
return []v1.PersistentVolumeAccessMode{
|
||||
v1.ReadWriteOnce,
|
||||
v1.ReadWriteMany,
|
||||
}
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
|
||||
return plugin.newMounterInternal(spec, pod.UID, &PortworxVolumeUtil{}, plugin.host.GetMounter())
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager portworxManager, mounter mount.Interface) (volume.Mounter, error) {
|
||||
pwx, readOnly, err := getVolumeSource(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumeID := pwx.VolumeID
|
||||
fsType := pwx.FSType
|
||||
|
||||
return &portworxVolumeMounter{
|
||||
portworxVolume: &portworxVolume{
|
||||
podUID: podUID,
|
||||
volName: spec.Name(),
|
||||
volumeID: volumeID,
|
||||
manager: manager,
|
||||
mounter: mounter,
|
||||
plugin: plugin,
|
||||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
|
||||
},
|
||||
fsType: fsType,
|
||||
readOnly: readOnly,
|
||||
diskMounter: &mount.SafeFormatAndMount{Interface: plugin.host.GetMounter(), Runner: exec.New()}}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
|
||||
return plugin.newUnmounterInternal(volName, podUID, &PortworxVolumeUtil{}, plugin.host.GetMounter())
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newUnmounterInternal(volName string, podUID types.UID, manager portworxManager, mounter mount.Interface) (volume.Unmounter, error) {
|
||||
return &portworxVolumeUnmounter{
|
||||
&portworxVolume{
|
||||
podUID: podUID,
|
||||
volName: volName,
|
||||
manager: manager,
|
||||
mounter: mounter,
|
||||
plugin: plugin,
|
||||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
|
||||
return plugin.newDeleterInternal(spec, &PortworxVolumeUtil{})
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newDeleterInternal(spec *volume.Spec, manager portworxManager) (volume.Deleter, error) {
|
||||
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.PortworxVolume == nil {
|
||||
return nil, fmt.Errorf("spec.PersistentVolumeSource.PortworxVolume is nil")
|
||||
}
|
||||
return &portworxVolumeDeleter{
|
||||
portworxVolume: &portworxVolume{
|
||||
volName: spec.Name(),
|
||||
volumeID: spec.PersistentVolume.Spec.PortworxVolume.VolumeID,
|
||||
manager: manager,
|
||||
plugin: plugin,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
||||
return plugin.newProvisionerInternal(options, &PortworxVolumeUtil{})
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newProvisionerInternal(options volume.VolumeOptions, manager portworxManager) (volume.Provisioner, error) {
|
||||
return &portworxVolumeProvisioner{
|
||||
portworxVolume: &portworxVolume{
|
||||
manager: manager,
|
||||
plugin: plugin,
|
||||
},
|
||||
options: options,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
||||
portworxVolume := &v1.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: volumeName,
|
||||
},
|
||||
},
|
||||
}
|
||||
return volume.NewSpecFromVolume(portworxVolume), nil
|
||||
}
|
||||
|
||||
func getVolumeSource(
|
||||
spec *volume.Spec) (*v1.PortworxVolumeSource, bool, error) {
|
||||
if spec.Volume != nil && spec.Volume.PortworxVolume != nil {
|
||||
return spec.Volume.PortworxVolume, spec.Volume.PortworxVolume.ReadOnly, nil
|
||||
} else if spec.PersistentVolume != nil &&
|
||||
spec.PersistentVolume.Spec.PortworxVolume != nil {
|
||||
return spec.PersistentVolume.Spec.PortworxVolume, spec.ReadOnly, nil
|
||||
}
|
||||
|
||||
return nil, false, fmt.Errorf("Spec does not reference a Portworx Volume type")
|
||||
}
|
||||
|
||||
// Abstract interface to PD operations.
|
||||
type portworxManager interface {
|
||||
// Creates a volume
|
||||
CreateVolume(provisioner *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int, labels map[string]string, err error)
|
||||
// Deletes a volume
|
||||
DeleteVolume(deleter *portworxVolumeDeleter) error
|
||||
// Attach a volume
|
||||
AttachVolume(mounter *portworxVolumeMounter) (string, error)
|
||||
// Detach a volume
|
||||
DetachVolume(unmounter *portworxVolumeUnmounter) error
|
||||
// Mount a volume
|
||||
MountVolume(mounter *portworxVolumeMounter, mountDir string) error
|
||||
// Unmount a volume
|
||||
UnmountVolume(unmounter *portworxVolumeUnmounter, mountDir string) error
|
||||
}
|
||||
|
||||
// portworxVolume volumes are portworx block devices
|
||||
// that are attached to the kubelet's host machine and exposed to the pod.
|
||||
type portworxVolume struct {
|
||||
volName string
|
||||
podUID types.UID
|
||||
// Unique id of the PD, used to find the disk resource in the provider.
|
||||
volumeID string
|
||||
// Utility interface that provides API calls to the provider to attach/detach disks.
|
||||
manager portworxManager
|
||||
// Mounter interface that provides system calls to mount the global path to the pod local path.
|
||||
mounter mount.Interface
|
||||
plugin *portworxVolumePlugin
|
||||
volume.MetricsProvider
|
||||
}
|
||||
|
||||
type portworxVolumeMounter struct {
|
||||
*portworxVolume
|
||||
// Filesystem type, optional.
|
||||
fsType string
|
||||
// Specifies whether the disk will be attached as read-only.
|
||||
readOnly bool
|
||||
// diskMounter provides the interface that is used to mount the actual block device.
|
||||
diskMounter *mount.SafeFormatAndMount
|
||||
}
|
||||
|
||||
var _ volume.Mounter = &portworxVolumeMounter{}
|
||||
|
||||
func (b *portworxVolumeMounter) GetAttributes() volume.Attributes {
|
||||
return volume.Attributes{
|
||||
ReadOnly: b.readOnly,
|
||||
Managed: !b.readOnly,
|
||||
// true ?
|
||||
SupportsSELinux: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Checks prior to mount operations to verify that the required components (binaries, etc.)
|
||||
// to mount the volume are available on the underlying node.
|
||||
// If not, it returns an error
|
||||
func (b *portworxVolumeMounter) CanMount() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetUp attaches the disk and bind mounts to the volume path.
|
||||
func (b *portworxVolumeMounter) SetUp(fsGroup *int64) error {
|
||||
return b.SetUpAt(b.GetPath(), fsGroup)
|
||||
}
|
||||
|
||||
// SetUpAt attaches the disk and bind mounts to the volume path.
|
||||
func (b *portworxVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
|
||||
notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
|
||||
glog.V(4).Infof("Portworx Volume set up: %s %v %v", dir, !notMnt, err)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
glog.Errorf("Cannot validate mountpoint: %s", dir)
|
||||
return err
|
||||
}
|
||||
if !notMnt {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := b.manager.AttachVolume(b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Portworx Volume %s attached", b.volumeID)
|
||||
|
||||
if err := os.MkdirAll(dir, 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := b.manager.MountVolume(b, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
if !b.readOnly {
|
||||
volume.SetVolumeOwnership(b, fsGroup)
|
||||
}
|
||||
glog.V(4).Infof("Portworx Volume %s mounted to %s", b.volumeID, dir)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pwx *portworxVolume) GetPath() string {
|
||||
return getPath(pwx.podUID, pwx.volName, pwx.plugin.host)
|
||||
}
|
||||
|
||||
type portworxVolumeUnmounter struct {
|
||||
*portworxVolume
|
||||
}
|
||||
|
||||
var _ volume.Unmounter = &portworxVolumeUnmounter{}
|
||||
|
||||
// Unmounts the bind mount, and detaches the disk only if the PD
|
||||
// resource was the last reference to that disk on the kubelet.
|
||||
func (c *portworxVolumeUnmounter) TearDown() error {
|
||||
return c.TearDownAt(c.GetPath())
|
||||
}
|
||||
|
||||
// Unmounts the bind mount, and detaches the disk only if the PD
|
||||
// resource was the last reference to that disk on the kubelet.
|
||||
func (c *portworxVolumeUnmounter) TearDownAt(dir string) error {
|
||||
glog.V(4).Infof("Portworx Volume TearDown of %s", dir)
|
||||
// Unmount the bind mount inside the pod
|
||||
if err := util.UnmountPath(dir, c.mounter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Call Portworx Unmount for Portworx's book-keeping.
|
||||
if err := c.manager.UnmountVolume(c, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Call Portworx Detach Volume.
|
||||
if err := c.manager.DetachVolume(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type portworxVolumeDeleter struct {
|
||||
*portworxVolume
|
||||
}
|
||||
|
||||
var _ volume.Deleter = &portworxVolumeDeleter{}
|
||||
|
||||
func (d *portworxVolumeDeleter) GetPath() string {
|
||||
return getPath(d.podUID, d.volName, d.plugin.host)
|
||||
}
|
||||
|
||||
func (d *portworxVolumeDeleter) Delete() error {
|
||||
return d.manager.DeleteVolume(d)
|
||||
}
|
||||
|
||||
type portworxVolumeProvisioner struct {
|
||||
*portworxVolume
|
||||
options volume.VolumeOptions
|
||||
namespace string
|
||||
}
|
||||
|
||||
var _ volume.Provisioner = &portworxVolumeProvisioner{}
|
||||
|
||||
func (c *portworxVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
||||
volumeID, sizeGB, labels, err := c.manager.CreateVolume(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: c.options.PVName,
|
||||
Labels: map[string]string{},
|
||||
Annotations: map[string]string{
|
||||
"kubernetes.io/createdby": "portworx-volume-dynamic-provisioner",
|
||||
},
|
||||
},
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeReclaimPolicy: c.options.PersistentVolumeReclaimPolicy,
|
||||
AccessModes: c.options.PVC.Spec.AccessModes,
|
||||
Capacity: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
|
||||
},
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: volumeID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if len(labels) != 0 {
|
||||
if pv.Labels == nil {
|
||||
pv.Labels = make(map[string]string)
|
||||
}
|
||||
for k, v := range labels {
|
||||
pv.Labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.options.PVC.Spec.AccessModes) == 0 {
|
||||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||
}
|
||||
|
||||
return pv, nil
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
)
|
||||
|
||||
const (
|
||||
PortworxTestVolume = "portworx-test-vol"
|
||||
)
|
||||
|
||||
func TestCanSupport(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
if plug.GetPluginName() != "kubernetes.io/portworx-volume" {
|
||||
t.Errorf("Wrong name: %s", plug.GetPluginName())
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{PortworxVolume: &v1.PortworxVolumeSource{}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{PortworxVolume: &v1.PortworxVolumeSource{}}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModes(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
|
||||
if !contains(plug.GetAccessModes(), v1.ReadWriteOnce) {
|
||||
t.Errorf("Expected to support AccessModeTypes: %s", v1.ReadWriteOnce)
|
||||
}
|
||||
if !contains(plug.GetAccessModes(), v1.ReadWriteMany) {
|
||||
t.Errorf("Expected to support AccessModeTypes: %s", v1.ReadWriteMany)
|
||||
}
|
||||
if contains(plug.GetAccessModes(), v1.ReadOnlyMany) {
|
||||
t.Errorf("Expected not to support AccessModeTypes: %s", v1.ReadOnlyMany)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
|
||||
for _, m := range modes {
|
||||
if m == mode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type fakePortworxManager struct {
|
||||
attachCalled bool
|
||||
mountCalled bool
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) AttachVolume(b *portworxVolumeMounter) (string, error) {
|
||||
fake.attachCalled = true
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) DetachVolume(c *portworxVolumeUnmounter) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) MountVolume(b *portworxVolumeMounter, mountPath string) error {
|
||||
fake.mountCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) UnmountVolume(c *portworxVolumeUnmounter, mountPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) CreateVolume(c *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int, labels map[string]string, err error) {
|
||||
labels = make(map[string]string)
|
||||
labels["fakeportworxmanager"] = "yes"
|
||||
return PortworxTestVolume, 100, labels, nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) DeleteVolume(cd *portworxVolumeDeleter) error {
|
||||
if cd.volumeID != PortworxTestVolume {
|
||||
return fmt.Errorf("Deleter got unexpected volume name: %s", cd.volumeID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPlugin(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
spec := &v1.Volume{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: PortworxTestVolume,
|
||||
FSType: "ext4",
|
||||
},
|
||||
},
|
||||
}
|
||||
fakeManager := &fakePortworxManager{}
|
||||
// Test Mounter
|
||||
fakeMounter := &mount.FakeMounter{}
|
||||
mounter, err := plug.(*portworxVolumePlugin).newMounterInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||
}
|
||||
if mounter == nil {
|
||||
t.Errorf("Got a nil Mounter")
|
||||
}
|
||||
|
||||
volPath := path.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~portworx-volume/vol1")
|
||||
path := mounter.GetPath()
|
||||
if path != volPath {
|
||||
t.Errorf("Got unexpected path: %s", path)
|
||||
}
|
||||
|
||||
if err := mounter.SetUp(nil); err != nil {
|
||||
t.Errorf("Expected success, got: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
||||
} else {
|
||||
t.Errorf("SetUp() failed: %v", err)
|
||||
}
|
||||
}
|
||||
if !fakeManager.attachCalled {
|
||||
t.Errorf("Attach watch not called")
|
||||
}
|
||||
if !fakeManager.mountCalled {
|
||||
t.Errorf("Mount watch not called")
|
||||
}
|
||||
|
||||
// Test Unmounter
|
||||
fakeManager = &fakePortworxManager{}
|
||||
unmounter, err := plug.(*portworxVolumePlugin).newUnmounterInternal("vol1", types.UID("poduid"), fakeManager, fakeMounter)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to make a new Unmounter: %v", err)
|
||||
}
|
||||
if unmounter == nil {
|
||||
t.Errorf("Got a nil Unmounter")
|
||||
}
|
||||
|
||||
if err := unmounter.TearDown(); err != nil {
|
||||
t.Errorf("Expected success, got: %v", err)
|
||||
}
|
||||
|
||||
// Test Provisioner
|
||||
options := volume.VolumeOptions{
|
||||
PVC: volumetest.CreateTestPVC("100Gi", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}),
|
||||
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
|
||||
}
|
||||
|
||||
provisioner, err := plug.(*portworxVolumePlugin).newProvisionerInternal(options, &fakePortworxManager{})
|
||||
persistentSpec, err := provisioner.Provision()
|
||||
if err != nil {
|
||||
t.Errorf("Provision() failed: %v", err)
|
||||
}
|
||||
|
||||
if persistentSpec.Spec.PersistentVolumeSource.PortworxVolume.VolumeID != PortworxTestVolume {
|
||||
t.Errorf("Provision() returned unexpected volume ID: %s", persistentSpec.Spec.PersistentVolumeSource.PortworxVolume.VolumeID)
|
||||
}
|
||||
cap := persistentSpec.Spec.Capacity[v1.ResourceStorage]
|
||||
size := cap.Value()
|
||||
if size != 100*1024*1024*1024 {
|
||||
t.Errorf("Provision() returned unexpected volume size: %v", size)
|
||||
}
|
||||
|
||||
if persistentSpec.Labels["fakeportworxmanager"] != "yes" {
|
||||
t.Errorf("Provision() returned unexpected labels: %v", persistentSpec.Labels)
|
||||
}
|
||||
|
||||
// Test Deleter
|
||||
volSpec := &volume.Spec{
|
||||
PersistentVolume: persistentSpec,
|
||||
}
|
||||
deleter, err := plug.(*portworxVolumePlugin).newDeleterInternal(volSpec, &fakePortworxManager{})
|
||||
err = deleter.Delete()
|
||||
if err != nil {
|
||||
t.Errorf("Deleter() failed: %v", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
osdapi "github.com/libopenstorage/openstorage/api"
|
||||
osdclient "github.com/libopenstorage/openstorage/api/client"
|
||||
volumeclient "github.com/libopenstorage/openstorage/api/client/volume"
|
||||
osdspec "github.com/libopenstorage/openstorage/api/spec"
|
||||
osdvolume "github.com/libopenstorage/openstorage/volume"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
const (
|
||||
osdMgmtPort = "9001"
|
||||
osdDriverVersion = "v1"
|
||||
pxdDriverName = "pxd"
|
||||
pwxSockName = "pwx"
|
||||
pvcClaimLabel = "pvc"
|
||||
)
|
||||
|
||||
type PortworxVolumeUtil struct {
|
||||
portworxClient *osdclient.Client
|
||||
}
|
||||
|
||||
// CreateVolume creates a Portworx volume.
|
||||
func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (string, int, map[string]string, error) {
|
||||
hostname := p.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
}
|
||||
|
||||
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
||||
// Portworx Volumes are specified in GB
|
||||
requestGB := int(volume.RoundUpSize(capacity.Value(), 1024*1024*1024))
|
||||
|
||||
specHandler := osdspec.NewSpecHandler()
|
||||
spec, err := specHandler.SpecFromOpts(p.options.Parameters)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
}
|
||||
spec.Size = uint64(requestGB * 1024 * 1024 * 1024)
|
||||
source := osdapi.Source{}
|
||||
locator := osdapi.VolumeLocator{
|
||||
Name: p.options.PVName,
|
||||
}
|
||||
// Add claim Name as a part of Portworx Volume Labels
|
||||
locator.VolumeLabels = make(map[string]string)
|
||||
locator.VolumeLabels[pvcClaimLabel] = p.options.PVC.Name
|
||||
volumeID, err := client.Create(&locator, &source, spec)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error creating Portworx Volume : %v", err)
|
||||
}
|
||||
return volumeID, requestGB, nil, err
|
||||
}
|
||||
|
||||
// DeleteVolume deletes a Portworx volume
|
||||
func (util *PortworxVolumeUtil) DeleteVolume(d *portworxVolumeDeleter) error {
|
||||
hostname := d.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Delete(d.volumeID)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error deleting Portworx Volume (%v): %v", d.volName, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttachVolume attaches a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) AttachVolume(m *portworxVolumeMounter) (string, error) {
|
||||
hostname := m.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
devicePath, err := client.Attach(m.volName)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error attaching Portworx Volume (%v): %v", m.volName, err)
|
||||
return "", err
|
||||
}
|
||||
return devicePath, nil
|
||||
}
|
||||
|
||||
// DetachVolume detaches a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) DetachVolume(u *portworxVolumeUnmounter) error {
|
||||
hostname := u.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Detach(u.volName)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error detaching Portworx Volume (%v): %v", u.volName, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountVolume mounts a Portworx Volume on the specified mountPath
|
||||
func (util *PortworxVolumeUtil) MountVolume(m *portworxVolumeMounter, mountPath string) error {
|
||||
hostname := m.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Mount(m.volName, mountPath)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error mounting Portworx Volume (%v) on Path (%v): %v", m.volName, mountPath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmountVolume unmounts a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) UnmountVolume(u *portworxVolumeUnmounter, mountPath string) error {
|
||||
hostname := u.plugin.host.GetHostName()
|
||||
client, err := util.osdClient(hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Unmount(u.volName, mountPath)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Error unmounting Portworx Volume (%v) on Path (%v): %v", u.volName, mountPath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (util *PortworxVolumeUtil) osdClient(hostname string) (osdvolume.VolumeDriver, error) {
|
||||
osdEndpoint := "http://" + hostname + ":" + osdMgmtPort
|
||||
if util.portworxClient == nil {
|
||||
driverClient, err := volumeclient.NewDriverClient(osdEndpoint, pxdDriverName, osdDriverVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
util.portworxClient = driverClient
|
||||
}
|
||||
|
||||
return volumeclient.VolumeDriver(util.portworxClient), nil
|
||||
}
|
|
@ -296,6 +296,9 @@ type VolumeSource struct {
|
|||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource
|
||||
}
|
||||
|
||||
// Similar to VolumeSource but meant for the administrator who creates PVs.
|
||||
|
@ -358,6 +361,9 @@ type PersistentVolumeSource struct {
|
|||
AzureDisk *AzureDiskVolumeSource
|
||||
// PhotonPersistentDisk represents a Photon Controller persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource
|
||||
}
|
||||
|
||||
type PersistentVolumeClaimVolumeSource struct {
|
||||
|
@ -1001,6 +1007,21 @@ type PhotonPersistentDiskVolumeSource struct {
|
|||
FSType string
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
type PortworxVolumeSource struct {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
VolumeID string
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". 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
|
||||
}
|
||||
|
||||
type AzureDataDiskCachingMode string
|
||||
|
||||
const (
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2128,6 +2128,10 @@ message PersistentVolumeSource {
|
|||
|
||||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 17;
|
||||
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
optional PortworxVolumeSource portworxVolume = 18;
|
||||
}
|
||||
|
||||
// PersistentVolumeSpec is the specification of a persistent volume.
|
||||
|
@ -2790,6 +2794,22 @@ message PodTemplateSpec {
|
|||
optional PodSpec spec = 2;
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
message PortworxVolumeSource {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
optional string volumeID = 1;
|
||||
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified.
|
||||
optional string fsType = 2;
|
||||
|
||||
// Defaults to false (read/write). ReadOnly here will force
|
||||
// the ReadOnly setting in VolumeMounts.
|
||||
// +optional
|
||||
optional bool readOnly = 3;
|
||||
}
|
||||
|
||||
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
|
||||
// +k8s:openapi-gen=false
|
||||
message Preconditions {
|
||||
|
@ -3811,7 +3831,11 @@ message VolumeSource {
|
|||
optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23;
|
||||
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
optional ProjectedVolumeSource projected = 24;
|
||||
optional ProjectedVolumeSource projected = 25;
|
||||
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
optional PortworxVolumeSource portworxVolume = 24;
|
||||
}
|
||||
|
||||
// Represents a vSphere volume resource.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -328,6 +328,9 @@ type VolumeSource struct {
|
|||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,23,opt,name=photonPersistentDisk"`
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
|
||||
|
@ -413,6 +416,9 @@ type PersistentVolumeSource struct {
|
|||
AzureDisk *AzureDiskVolumeSource `json:"azureDisk,omitempty" protobuf:"bytes,16,opt,name=azureDisk"`
|
||||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,17,opt,name=photonPersistentDisk"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,18,opt,name=portworxVolume"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
|
@ -1107,6 +1113,20 @@ type AzureDiskVolumeSource struct {
|
|||
ReadOnly *bool `json:"readOnly,omitempty" protobuf:"varint,5,opt,name=readOnly"`
|
||||
}
|
||||
|
||||
// PortworxVolumeSource represents a Portworx volume resource.
|
||||
type PortworxVolumeSource struct {
|
||||
// VolumeID uniquely identifies a Portworx volume
|
||||
VolumeID string `json:"volumeID" protobuf:"bytes,1,opt,name=volumeID"`
|
||||
// FSType represents the filesystem type to mount
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified.
|
||||
FSType string `json:"fsType,omitempty" protobuf:"bytes,2,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,3,opt,name=readOnly"`
|
||||
}
|
||||
|
||||
// Adapts a ConfigMap into a volume.
|
||||
//
|
||||
// The contents of the target ConfigMap's Data field will be presented in a
|
||||
|
|
|
@ -1122,6 +1122,7 @@ var map_PersistentVolumeSource = map[string]string{
|
|||
"quobyte": "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime",
|
||||
"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",
|
||||
"portworxVolume": "PortworxVolume represents a portworx volume attached and mounted on kubelets host machine",
|
||||
}
|
||||
|
||||
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
|
||||
|
@ -1399,6 +1400,17 @@ func (PodTemplateSpec) SwaggerDoc() map[string]string {
|
|||
return map_PodTemplateSpec
|
||||
}
|
||||
|
||||
var map_PortworxVolumeSource = map[string]string{
|
||||
"": "PortworxVolumeSource represents a Portworx volume resource.",
|
||||
"volumeID": "VolumeID uniquely identifies a Portworx volume",
|
||||
"fsType": "FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\". Implicitly inferred to be \"ext4\" if unspecified.",
|
||||
"readOnly": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||
}
|
||||
|
||||
func (PortworxVolumeSource) SwaggerDoc() map[string]string {
|
||||
return map_PortworxVolumeSource
|
||||
}
|
||||
|
||||
var map_Preconditions = map[string]string{
|
||||
"": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.",
|
||||
"uid": "Specifies the target UID.",
|
||||
|
@ -1897,6 +1909,7 @@ var map_VolumeSource = map[string]string{
|
|||
"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",
|
||||
"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",
|
||||
}
|
||||
|
||||
func (VolumeSource) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -275,6 +275,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||
Convert_api_PodTemplateList_To_v1_PodTemplateList,
|
||||
Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec,
|
||||
Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec,
|
||||
Convert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource,
|
||||
Convert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource,
|
||||
Convert_v1_Preconditions_To_api_Preconditions,
|
||||
Convert_api_Preconditions_To_v1_Preconditions,
|
||||
Convert_v1_PreferAvoidPodsEntry_To_api_PreferAvoidPodsEntry,
|
||||
|
@ -2706,6 +2708,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
|
|||
out.Quobyte = (*api.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
||||
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2731,6 +2734,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
|
|||
out.VsphereVolume = (*VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume))
|
||||
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -3341,6 +3345,28 @@ func autoConvert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in *api.PodTemplateSp
|
|||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in *PortworxVolumeSource, out *api.PortworxVolumeSource, s conversion.Scope) error {
|
||||
out.VolumeID = in.VolumeID
|
||||
out.FSType = in.FSType
|
||||
out.ReadOnly = in.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in *PortworxVolumeSource, out *api.PortworxVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_v1_PortworxVolumeSource_To_api_PortworxVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in *api.PortworxVolumeSource, out *PortworxVolumeSource, s conversion.Scope) error {
|
||||
out.VolumeID = in.VolumeID
|
||||
out.FSType = in.FSType
|
||||
out.ReadOnly = in.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in *api.PortworxVolumeSource, out *PortworxVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_api_PortworxVolumeSource_To_v1_PortworxVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Preconditions_To_api_Preconditions(in *Preconditions, out *api.Preconditions, s conversion.Scope) error {
|
||||
out.UID = (*types.UID)(unsafe.Pointer(in.UID))
|
||||
return nil
|
||||
|
@ -4458,6 +4484,7 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
|
|||
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*api.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.Projected = (*api.ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
|
||||
out.PortworxVolume = (*api.PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -4490,6 +4517,7 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
|
|||
out.AzureDisk = (*AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
|
||||
out.PhotonPersistentDisk = (*PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
|
||||
out.Projected = (*ProjectedVolumeSource)(unsafe.Pointer(in.Projected))
|
||||
out.PortworxVolume = (*PortworxVolumeSource)(unsafe.Pointer(in.PortworxVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplate, InType: reflect.TypeOf(&PodTemplate{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplateList, InType: reflect.TypeOf(&PodTemplateList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PodTemplateSpec, InType: reflect.TypeOf(&PodTemplateSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PortworxVolumeSource, InType: reflect.TypeOf(&PortworxVolumeSource{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Preconditions, InType: reflect.TypeOf(&Preconditions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PreferAvoidPodsEntry, InType: reflect.TypeOf(&PreferAvoidPodsEntry{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_PreferredSchedulingTerm, InType: reflect.TypeOf(&PreferredSchedulingTerm{})},
|
||||
|
@ -2015,6 +2016,11 @@ func DeepCopy_v1_PersistentVolumeSource(in interface{}, out interface{}, c *conv
|
|||
*out = new(PhotonPersistentDiskVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -2513,6 +2519,15 @@ func DeepCopy_v1_PodTemplateSpec(in interface{}, out interface{}, c *conversion.
|
|||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_PortworxVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*PortworxVolumeSource)
|
||||
out := out.(*PortworxVolumeSource)
|
||||
*out = *in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_Preconditions(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*Preconditions)
|
||||
|
@ -3420,6 +3435,11 @@ func DeepCopy_v1_VolumeSource(in interface{}, out interface{}, c *conversion.Clo
|
|||
return err
|
||||
}
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplate, InType: reflect.TypeOf(&PodTemplate{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplateList, InType: reflect.TypeOf(&PodTemplateList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PodTemplateSpec, InType: reflect.TypeOf(&PodTemplateSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PortworxVolumeSource, InType: reflect.TypeOf(&PortworxVolumeSource{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Preconditions, InType: reflect.TypeOf(&Preconditions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PreferAvoidPodsEntry, InType: reflect.TypeOf(&PreferAvoidPodsEntry{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_PreferredSchedulingTerm, InType: reflect.TypeOf(&PreferredSchedulingTerm{})},
|
||||
|
@ -2059,6 +2060,11 @@ func DeepCopy_api_PersistentVolumeSource(in interface{}, out interface{}, c *con
|
|||
*out = new(PhotonPersistentDiskVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -2557,6 +2563,15 @@ func DeepCopy_api_PodTemplateSpec(in interface{}, out interface{}, c *conversion
|
|||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_PortworxVolumeSource(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*PortworxVolumeSource)
|
||||
out := out.(*PortworxVolumeSource)
|
||||
*out = *in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_Preconditions(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*Preconditions)
|
||||
|
@ -3447,6 +3462,11 @@ func DeepCopy_api_VolumeSource(in interface{}, out interface{}, c *conversion.Cl
|
|||
return err
|
||||
}
|
||||
}
|
||||
if in.PortworxVolume != nil {
|
||||
in, out := &in.PortworxVolume, &out.PortworxVolume
|
||||
*out = new(PortworxVolumeSource)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -917,6 +917,7 @@ var (
|
|||
AzureDisk FSType = "azureDisk"
|
||||
PhotonPersistentDisk FSType = "photonPersistentDisk"
|
||||
Projected FSType = "projected"
|
||||
PortworxVolume FSType = "portworxVolume"
|
||||
All FSType = "*"
|
||||
)
|
||||
|
||||
|
|
|
@ -16604,3 +16604,86 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/api",
|
||||
srcs = [
|
||||
"github.com/libopenstorage/openstorage/api/api.go",
|
||||
"github.com/libopenstorage/openstorage/api/api.pb.go",
|
||||
"github.com/libopenstorage/openstorage/api/status.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/golang/protobuf/proto",
|
||||
"//vendor:go.pedge.io/pb/go/google/protobuf",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/api/client",
|
||||
srcs = [
|
||||
"github.com/libopenstorage/openstorage/api/client/client.go",
|
||||
"github.com/libopenstorage/openstorage/api/client/request.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/api/client/volume",
|
||||
srcs = [
|
||||
"github.com/libopenstorage/openstorage/api/client/volume/client.go",
|
||||
"github.com/libopenstorage/openstorage/api/client/volume/volume.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/libopenstorage/openstorage/api",
|
||||
"//vendor:github.com/libopenstorage/openstorage/api/client",
|
||||
"//vendor:github.com/libopenstorage/openstorage/volume",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/api/spec",
|
||||
srcs = ["github.com/libopenstorage/openstorage/api/spec/spec_handler.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/libopenstorage/openstorage/api",
|
||||
"//vendor:github.com/libopenstorage/openstorage/pkg/units",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/pkg/units",
|
||||
srcs = ["github.com/libopenstorage/openstorage/pkg/units/units.go"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "github.com/libopenstorage/openstorage/volume",
|
||||
srcs = [
|
||||
"github.com/libopenstorage/openstorage/volume/volume.go",
|
||||
"github.com/libopenstorage/openstorage/volume/volume_driver_registry.go",
|
||||
"github.com/libopenstorage/openstorage/volume/volume_not_supported.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor:github.com/libopenstorage/openstorage/api"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go.pedge.io/pb/go/google/protobuf",
|
||||
srcs = [
|
||||
"go.pedge.io/pb/go/google/protobuf/any.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/api.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/duration.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/empty.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/field_mask.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/protobuf.gen.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/source_context.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/struct.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/timestamp.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/type.pb.go",
|
||||
"go.pedge.io/pb/go/google/protobuf/wrappers.pb.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor:github.com/golang/protobuf/proto"],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2015 Openstorage.org.
|
||||
|
||||
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.
|
|
@ -0,0 +1,208 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Strings for VolumeSpec
|
||||
const (
|
||||
Name = "name"
|
||||
SpecEphemeral = "ephemeral"
|
||||
SpecShared = "shared"
|
||||
SpecSize = "size"
|
||||
SpecScale = "scale"
|
||||
SpecFilesystem = "fs"
|
||||
SpecBlockSize = "block_size"
|
||||
SpecHaLevel = "repl"
|
||||
SpecPriority = "io_priority"
|
||||
SpecSnapshotInterval = "snap_interval"
|
||||
SpecAggregationLevel = "aggregation_level"
|
||||
SpecDedupe = "dedupe"
|
||||
SpecPassphrase = "passphrase"
|
||||
)
|
||||
|
||||
// OptionKey specifies a set of recognized query params.
|
||||
const (
|
||||
// OptName query parameter used to lookup volume by name.
|
||||
OptName = "Name"
|
||||
// OptVolumeID query parameter used to lookup volume by ID.
|
||||
OptVolumeID = "VolumeID"
|
||||
// OptLabel query parameter used to lookup volume by set of labels.
|
||||
OptLabel = "Label"
|
||||
// OptConfigLabel query parameter used to lookup volume by set of labels.
|
||||
OptConfigLabel = "ConfigLabel"
|
||||
// OptCumulative query parameter used to request cumulative stats.
|
||||
OptCumulative = "Cumulative"
|
||||
)
|
||||
|
||||
// Api client-server Constants
|
||||
const (
|
||||
OsdVolumePath = "osd-volumes"
|
||||
OsdSnapshotPath = "osd-snapshot"
|
||||
)
|
||||
// Node describes the state of a node.
|
||||
// It includes the current physical state (CPU, memory, storage, network usage) as
|
||||
// well as the containers running on the system.
|
||||
type Node struct {
|
||||
Id string
|
||||
Cpu float64 // percentage.
|
||||
MemTotal uint64
|
||||
MemUsed uint64
|
||||
MemFree uint64
|
||||
Avgload int
|
||||
Status Status
|
||||
GenNumber uint64
|
||||
Disks map[string]StorageResource
|
||||
MgmtIp string
|
||||
DataIp string
|
||||
Timestamp time.Time
|
||||
StartTime time.Time
|
||||
Hostname string
|
||||
NodeData map[string]interface{}
|
||||
// User defined labels for node. Key Value pairs
|
||||
NodeLabels map[string]string
|
||||
}
|
||||
|
||||
// Cluster represents the state of the cluster.
|
||||
type Cluster struct {
|
||||
Status Status
|
||||
|
||||
// Id is the ID of the cluster.
|
||||
Id string
|
||||
|
||||
// NodeId is the ID of the node on which this cluster object
|
||||
// is initialized
|
||||
NodeId string
|
||||
|
||||
// Nodes is an array of all the nodes in the cluster.
|
||||
Nodes []Node
|
||||
}
|
||||
|
||||
// StatPoint represents the basic structure of a single Stat reported
|
||||
// TODO: This is the first step to introduce stats in openstorage.
|
||||
// Follow up task is to introduce an API for logging stats
|
||||
type StatPoint struct {
|
||||
// Name of the Stat
|
||||
Name string
|
||||
// Tags for the Stat
|
||||
Tags map[string]string
|
||||
// Fields and values of the stat
|
||||
Fields map[string]interface{}
|
||||
// Timestamp in Unix format
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
func DriverTypeSimpleValueOf(s string) (DriverType, error) {
|
||||
obj, err := simpleValueOf("driver_type", DriverType_value, s)
|
||||
return DriverType(obj), err
|
||||
}
|
||||
|
||||
func (x DriverType) SimpleString() string {
|
||||
return simpleString("driver_type", DriverType_name, int32(x))
|
||||
}
|
||||
|
||||
func FSTypeSimpleValueOf(s string) (FSType, error) {
|
||||
obj, err := simpleValueOf("fs_type", FSType_value, s)
|
||||
return FSType(obj), err
|
||||
}
|
||||
|
||||
func (x FSType) SimpleString() string {
|
||||
return simpleString("fs_type", FSType_name, int32(x))
|
||||
}
|
||||
|
||||
func CosTypeSimpleValueOf(s string) (CosType, error) {
|
||||
obj, err := simpleValueOf("cos_type", CosType_value, s)
|
||||
return CosType(obj), err
|
||||
}
|
||||
|
||||
func (x CosType) SimpleString() string {
|
||||
return simpleString("cos_type", CosType_name, int32(x))
|
||||
}
|
||||
|
||||
func GraphDriverChangeTypeSimpleValueOf(s string) (GraphDriverChangeType, error) {
|
||||
obj, err := simpleValueOf("graph_driver_change_type", GraphDriverChangeType_value, s)
|
||||
return GraphDriverChangeType(obj), err
|
||||
}
|
||||
|
||||
func (x GraphDriverChangeType) SimpleString() string {
|
||||
return simpleString("graph_driver_change_type", GraphDriverChangeType_name, int32(x))
|
||||
}
|
||||
|
||||
func VolumeActionParamSimpleValueOf(s string) (VolumeActionParam, error) {
|
||||
obj, err := simpleValueOf("volume_action_param", VolumeActionParam_value, s)
|
||||
return VolumeActionParam(obj), err
|
||||
}
|
||||
|
||||
func (x VolumeActionParam) SimpleString() string {
|
||||
return simpleString("volume_action_param", VolumeActionParam_name, int32(x))
|
||||
}
|
||||
|
||||
func VolumeStateSimpleValueOf(s string) (VolumeState, error) {
|
||||
obj, err := simpleValueOf("volume_state", VolumeState_value, s)
|
||||
return VolumeState(obj), err
|
||||
}
|
||||
|
||||
func (x VolumeState) SimpleString() string {
|
||||
return simpleString("volume_state", VolumeState_name, int32(x))
|
||||
}
|
||||
|
||||
func VolumeStatusSimpleValueOf(s string) (VolumeStatus, error) {
|
||||
obj, err := simpleValueOf("volume_status", VolumeStatus_value, s)
|
||||
return VolumeStatus(obj), err
|
||||
}
|
||||
|
||||
func (x VolumeStatus) SimpleString() string {
|
||||
return simpleString("volume_status", VolumeStatus_name, int32(x))
|
||||
}
|
||||
|
||||
func simpleValueOf(typeString string, valueMap map[string]int32, s string) (int32, error) {
|
||||
obj, ok := valueMap[strings.ToUpper(fmt.Sprintf("%s_%s", typeString, s))]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("no openstorage.%s for %s", strings.ToUpper(typeString), s)
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func simpleString(typeString string, nameMap map[int32]string, v int32) string {
|
||||
s, ok := nameMap[v]
|
||||
if !ok {
|
||||
return strconv.Itoa(int(v))
|
||||
}
|
||||
return strings.TrimPrefix(strings.ToLower(s), fmt.Sprintf("%s_", strings.ToLower(typeString)))
|
||||
}
|
||||
|
||||
func toSec(ms uint64) uint64 {
|
||||
return ms / 1000
|
||||
}
|
||||
|
||||
func (v *Stats) WriteThroughput() uint64 {
|
||||
if v.IntervalMs == 0 {
|
||||
return 0
|
||||
}
|
||||
return (v.WriteBytes) / toSec(v.IntervalMs)
|
||||
}
|
||||
|
||||
func (v *Stats) ReadThroughput() uint64 {
|
||||
if v.IntervalMs == 0 {
|
||||
return 0
|
||||
}
|
||||
return (v.ReadBytes) / toSec(v.IntervalMs)
|
||||
}
|
||||
|
||||
func (v *Stats) Latency() uint64 {
|
||||
ops := v.Writes + v.Reads
|
||||
if ops == 0 {
|
||||
return 0
|
||||
}
|
||||
return (uint64)((v.IoMs * 1000) / (v.Writes + v.Reads))
|
||||
}
|
||||
|
||||
func (v *Stats) Iops() uint64 {
|
||||
if v.IntervalMs == 0 {
|
||||
return 0
|
||||
}
|
||||
return (v.Writes + v.Reads) / toSec(v.IntervalMs)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,398 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
package openstorage.api;
|
||||
|
||||
option go_package = "api";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.openstorage.api";
|
||||
|
||||
enum Status {
|
||||
STATUS_NONE = 0;
|
||||
STATUS_INIT = 1;
|
||||
STATUS_OK = 2;
|
||||
STATUS_OFFLINE = 3;
|
||||
STATUS_ERROR = 4;
|
||||
STATUS_NOT_IN_QUORUM = 5;
|
||||
STATUS_DECOMMISSION = 6;
|
||||
STATUS_MAINTENANCE = 7;
|
||||
STATUS_STORAGE_DOWN = 8;
|
||||
STATUS_STORAGE_DEGRADED = 9;
|
||||
STATUS_NEEDS_REBOOT = 10;
|
||||
STATUS_STORAGE_REBALANCE = 11;
|
||||
STATUS_STORAGE_DRIVE_REPLACE = 12;
|
||||
// Add statuses before MAX and update the number for MAX
|
||||
STATUS_MAX = 13;
|
||||
}
|
||||
|
||||
enum DriverType {
|
||||
DRIVER_TYPE_NONE = 0;
|
||||
DRIVER_TYPE_FILE = 1;
|
||||
DRIVER_TYPE_BLOCK = 2;
|
||||
DRIVER_TYPE_OBJECT = 3;
|
||||
DRIVER_TYPE_CLUSTERED = 4;
|
||||
DRIVER_TYPE_GRAPH = 5;
|
||||
}
|
||||
|
||||
enum FSType {
|
||||
FS_TYPE_NONE = 0;
|
||||
FS_TYPE_BTRFS = 1;
|
||||
FS_TYPE_EXT4 = 2;
|
||||
FS_TYPE_FUSE = 3;
|
||||
FS_TYPE_NFS = 4;
|
||||
FS_TYPE_VFS = 5;
|
||||
FS_TYPE_XFS = 6;
|
||||
FS_TYPE_ZFS = 7;
|
||||
}
|
||||
|
||||
enum GraphDriverChangeType {
|
||||
GRAPH_DRIVER_CHANGE_TYPE_NONE = 0;
|
||||
GRAPH_DRIVER_CHANGE_TYPE_MODIFIED = 1;
|
||||
GRAPH_DRIVER_CHANGE_TYPE_ADDED = 2;
|
||||
GRAPH_DRIVER_CHANGE_TYPE_DELETED = 3;
|
||||
}
|
||||
|
||||
enum SeverityType {
|
||||
SEVERITY_TYPE_NONE = 0;
|
||||
SEVERITY_TYPE_ALARM = 1;
|
||||
SEVERITY_TYPE_WARNING = 2;
|
||||
SEVERITY_TYPE_NOTIFY = 3;
|
||||
}
|
||||
|
||||
enum ResourceType {
|
||||
RESOURCE_TYPE_NONE = 0;
|
||||
RESOURCE_TYPE_VOLUME = 1;
|
||||
RESOURCE_TYPE_NODE = 2;
|
||||
RESOURCE_TYPE_CLUSTER = 3;
|
||||
RESOURCE_TYPE_DRIVE = 4;
|
||||
}
|
||||
|
||||
enum AlertActionType {
|
||||
ALERT_ACTION_TYPE_NONE = 0;
|
||||
ALERT_ACTION_TYPE_DELETE = 1;
|
||||
ALERT_ACTION_TYPE_CREATE = 2;
|
||||
ALERT_ACTION_TYPE_UPDATE = 3;
|
||||
}
|
||||
|
||||
enum VolumeActionParam {
|
||||
VOLUME_ACTION_PARAM_NONE = 0;
|
||||
// Maps to the boolean value false
|
||||
VOLUME_ACTION_PARAM_OFF = 1;
|
||||
// Maps to the boolean value true.
|
||||
VOLUME_ACTION_PARAM_ON = 2;
|
||||
}
|
||||
|
||||
enum CosType {
|
||||
NONE = 0;
|
||||
LOW = 1;
|
||||
MEDIUM = 2;
|
||||
HIGH = 3;
|
||||
}
|
||||
|
||||
// VolumeState represents the state of a volume.
|
||||
enum VolumeState {
|
||||
VOLUME_STATE_NONE = 0;
|
||||
// Volume is transitioning to new state
|
||||
VOLUME_STATE_PENDING = 1;
|
||||
// Volume is ready to be assigned to a container
|
||||
VOLUME_STATE_AVAILABLE = 2;
|
||||
// Volume is attached to container
|
||||
VOLUME_STATE_ATTACHED = 3;
|
||||
// Volume is detached but associated with a container
|
||||
VOLUME_STATE_DETACHED = 4;
|
||||
// Volume detach is in progress
|
||||
VOLUME_STATE_DETATCHING = 5;
|
||||
// Volume is in error state
|
||||
VOLUME_STATE_ERROR = 6;
|
||||
// Volume is deleted, it will remain in this state
|
||||
// while resources are asynchronously reclaimed
|
||||
VOLUME_STATE_DELETED = 7;
|
||||
}
|
||||
|
||||
// VolumeStatus represents a health status for a volume.
|
||||
enum VolumeStatus {
|
||||
VOLUME_STATUS_NONE = 0;
|
||||
// Volume is not present
|
||||
VOLUME_STATUS_NOT_PRESENT = 1;
|
||||
// Volume is healthy
|
||||
VOLUME_STATUS_UP = 2;
|
||||
// Volume is in fail mode
|
||||
VOLUME_STATUS_DOWN = 3;
|
||||
// Volume is up but with degraded performance
|
||||
// In a RAID group, this may indicate a problem with one or more drives
|
||||
VOLUME_STATUS_DEGRADED = 4;
|
||||
}
|
||||
|
||||
enum StorageMedium {
|
||||
// Magnetic spinning disk.
|
||||
STORAGE_MEDIUM_MAGNETIC = 0;
|
||||
// SSD disk
|
||||
STORAGE_MEDIUM_SSD = 1;
|
||||
// NVME disk
|
||||
STORAGE_MEDIUM_NVME = 2;
|
||||
}
|
||||
|
||||
enum ClusterNotify {
|
||||
// Node is down
|
||||
CLUSTER_NOTIFY_DOWN = 0;
|
||||
}
|
||||
|
||||
// StorageResource groups properties of a storage device.
|
||||
message StorageResource {
|
||||
// Id is the LUN identifier.
|
||||
string id = 1;
|
||||
// Path device path for this storage resource.
|
||||
string path = 2;
|
||||
// Storage medium.
|
||||
StorageMedium medium = 3;
|
||||
// True if this device is online.
|
||||
bool online = 4;;
|
||||
// IOPS
|
||||
uint64 iops = 5;;
|
||||
// SeqWrite
|
||||
double seq_write = 6;
|
||||
// SeqRead
|
||||
double seq_read = 7;
|
||||
// RandRW
|
||||
double randRW = 8;
|
||||
// Total size in bytes.
|
||||
uint64 size = 9;;
|
||||
// Physical Bytes used.
|
||||
uint64 used = 10;
|
||||
// True if this device is rotational.
|
||||
string rotation_speed = 11;
|
||||
// Timestamp of last time this device was scanned.
|
||||
google.protobuf.Timestamp last_scan = 12;
|
||||
}
|
||||
|
||||
// VolumeLocator is a structure that is attached to a volume
|
||||
// and is used to carry opaque metadata.
|
||||
message VolumeLocator {
|
||||
// User friendly identifier
|
||||
string name = 1;
|
||||
// A set of name-value pairs that acts as search filters
|
||||
map<string, string> volume_labels = 2;
|
||||
}
|
||||
|
||||
message Source {
|
||||
// A volume id, if specified will create a clone of the parent.
|
||||
string parent = 1;
|
||||
// Seed will seed the volume from the specified URI
|
||||
// Any additional config for the source comes from the labels in the spec
|
||||
string seed = 2;
|
||||
}
|
||||
|
||||
// VolumeSpec has the properties needed to create a volume.
|
||||
message VolumeSpec {
|
||||
// Ephemeral storage
|
||||
bool ephemeral = 1;
|
||||
// Thin provisioned volume size in bytes
|
||||
uint64 size = 2;
|
||||
// Format disk with this FSType
|
||||
FSType format = 3;
|
||||
// Block size for filesystem
|
||||
int64 block_size = 4;
|
||||
// Specifies the number of nodes that are
|
||||
// allowed to fail, and yet data is available
|
||||
// A value of 0 implies that data is not erasure coded,
|
||||
// a failure of a node will lead to data loss
|
||||
int64 ha_level = 5;
|
||||
// The COS, 1 to 9
|
||||
CosType cos = 6;
|
||||
// Perform dedupe on this disk
|
||||
bool dedupe = 7;
|
||||
// SnapshotInterval in minutes, set to 0 to disable snapshots
|
||||
uint32 snapshot_interval = 8;
|
||||
// Volume configuration labels
|
||||
map<string, string> volume_labels = 9;
|
||||
// Shared is true if this volume can be remotely accessed.
|
||||
bool shared = 10;
|
||||
// ReplicaSet is the desired replicaSet the volume want to be placed.
|
||||
ReplicaSet replica_set = 11;
|
||||
// Specifies the number of parts the volume can be aggregated from.
|
||||
uint32 aggregation_level = 12;
|
||||
// Encrypted is true if this volume will be cryptographically secured.
|
||||
bool encrypted = 13;
|
||||
// User passphrase if this is an encrypted volume
|
||||
string passphrase = 14;
|
||||
// SnapshotSchedule
|
||||
string snapshot_schedule = 15;
|
||||
// Scale allows autocreation of volumes.
|
||||
uint32 scale = 16;
|
||||
}
|
||||
|
||||
// Set of machine IDs (nodes) to which part of this volume is erasure coded - for clustered storage arrays
|
||||
message ReplicaSet {
|
||||
repeated string nodes = 1;
|
||||
}
|
||||
|
||||
// List of name value mapping of driver specific runtime information.
|
||||
message RuntimeStateMap {
|
||||
map<string, string> runtime_state = 1;
|
||||
}
|
||||
|
||||
// Volume represents a live, created volume.
|
||||
message Volume {
|
||||
// Self referential volume ID
|
||||
string id = 1;
|
||||
Source source = 2;
|
||||
bool readonly = 3;
|
||||
// User specified locator
|
||||
VolumeLocator locator = 4;
|
||||
// Volume creation time
|
||||
google.protobuf.Timestamp ctime = 5;
|
||||
// User specified VolumeSpec
|
||||
VolumeSpec spec = 6;
|
||||
// Volume usage
|
||||
uint64 usage = 7;
|
||||
// Time when an integrity check for run
|
||||
google.protobuf.Timestamp last_scan = 8;
|
||||
// Format FSType type if any
|
||||
FSType format = 9;
|
||||
VolumeStatus status = 10;
|
||||
VolumeState state = 11;
|
||||
// Machine ID (node) on which this volume is attached
|
||||
// Machine ID is a node instance identifier for clustered systems.
|
||||
string attached_on = 12;
|
||||
string device_path = 14;
|
||||
repeated string attach_path = 15;
|
||||
// List of ReplicaSets which provide storage for this volume, for clustered storage arrays
|
||||
repeated ReplicaSet replica_sets = 16;
|
||||
// Last recorded error
|
||||
string error = 17;
|
||||
// List of name value mapping of driver specific runtime information.
|
||||
repeated RuntimeStateMap runtime_state = 18;
|
||||
string secure_device_path = 19;
|
||||
// BackgroundProcessing is true if volume is attached but not by the user
|
||||
bool background_processing = 20;
|
||||
}
|
||||
|
||||
message Stats {
|
||||
// Reads completed successfully
|
||||
uint64 reads = 1;
|
||||
// Time spent in reads in ms
|
||||
uint64 read_ms = 2;
|
||||
uint64 read_bytes = 3;
|
||||
// Writes completed successfully
|
||||
uint64 writes = 4;
|
||||
// Time spent in writes in ms
|
||||
uint64 write_ms = 5;
|
||||
uint64 write_bytes = 6;
|
||||
// IOs curently in progress
|
||||
uint64 io_progress = 7;
|
||||
// Time spent doing IOs ms
|
||||
uint64 io_ms = 8;
|
||||
// BytesUsed
|
||||
uint64 bytes_used = 9;
|
||||
// Interval in ms during which stats were collected
|
||||
uint64 interval_ms = 10;
|
||||
}
|
||||
|
||||
message Alert {
|
||||
// Id for Alert
|
||||
int64 id = 1;
|
||||
// Severity of the Alert
|
||||
SeverityType severity = 2;
|
||||
// AlertType user defined alert type
|
||||
int64 alert_type = 3;
|
||||
// Message describing the Alert
|
||||
string message = 4;
|
||||
//Timestamp when Alert occured
|
||||
google.protobuf.Timestamp timestamp = 5;
|
||||
// ResourceId where Alert occured
|
||||
string resource_id = 6;
|
||||
// Resource where Alert occured
|
||||
ResourceType resource = 7;
|
||||
// Cleared Flag
|
||||
bool cleared = 8;
|
||||
// TTL in seconds for this Alert
|
||||
uint64 ttl = 9;
|
||||
}
|
||||
|
||||
message Alerts {
|
||||
repeated Alert alert = 1;
|
||||
}
|
||||
|
||||
message VolumeCreateRequest {
|
||||
// User specified volume name and labels
|
||||
VolumeLocator locator = 1;
|
||||
// Source to create volume
|
||||
Source source = 2;
|
||||
// The storage spec for the volume
|
||||
VolumeSpec spec = 3;
|
||||
}
|
||||
|
||||
message VolumeResponse {
|
||||
string error = 1;
|
||||
}
|
||||
|
||||
message VolumeCreateResponse {
|
||||
// ID of the newly created volume
|
||||
string id = 1;
|
||||
VolumeResponse volume_response = 2;
|
||||
}
|
||||
|
||||
// VolumeStateAction specifies desired actions.
|
||||
message VolumeStateAction {
|
||||
// Attach or Detach volume
|
||||
VolumeActionParam attach = 1;
|
||||
// Mount or unmount volume
|
||||
VolumeActionParam mount = 2;
|
||||
string mount_path = 3;
|
||||
// Device path returned in attach
|
||||
string device_path = 4;
|
||||
}
|
||||
|
||||
message VolumeSetRequest {
|
||||
// User specified volume name and labels
|
||||
VolumeLocator locator = 1;
|
||||
// The storage spec for the volume
|
||||
VolumeSpec spec = 2;
|
||||
// State modification on this volume.
|
||||
VolumeStateAction action = 3;
|
||||
}
|
||||
|
||||
message VolumeSetResponse {
|
||||
Volume volume = 1;
|
||||
VolumeResponse volume_response = 2;
|
||||
}
|
||||
|
||||
message SnapCreateRequest {
|
||||
// volume id
|
||||
string id = 1;
|
||||
VolumeLocator locator = 2;
|
||||
bool readonly = 3;
|
||||
}
|
||||
|
||||
message SnapCreateResponse {
|
||||
VolumeCreateResponse volume_create_response = 1;
|
||||
}
|
||||
|
||||
message VolumeInfo {
|
||||
string volume_id = 1;
|
||||
string path = 2;
|
||||
VolumeSpec storage = 3;
|
||||
}
|
||||
|
||||
// GraphDriverChanges represent a list of changes between the filesystem layers
|
||||
// specified by the ID and Parent. // Parent may be an empty string, in which
|
||||
// case there is no parent.
|
||||
// Where the Path is the filesystem path within the layered filesystem
|
||||
message GraphDriverChanges {
|
||||
string path = 1;
|
||||
GraphDriverChangeType kind = 2;
|
||||
}
|
||||
|
||||
message ClusterResponse {
|
||||
string error = 1;
|
||||
}
|
||||
|
||||
message ActiveRequest {
|
||||
map<int64, string> ReqestKV = 1;
|
||||
}
|
||||
|
||||
message ActiveRequests {
|
||||
int64 RequestCount = 1;
|
||||
repeated ActiveRequest ActiveRequest = 2;
|
||||
}
|
141
vendor/github.com/libopenstorage/openstorage/api/client/client.go
generated
vendored
Normal file
141
vendor/github.com/libopenstorage/openstorage/api/client/client.go
generated
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
httpCache = make(map[string]*http.Client)
|
||||
cacheLock sync.Mutex
|
||||
)
|
||||
|
||||
// NewClient returns a new REST client for specified server.
|
||||
func NewClient(host string, version string) (*Client, error) {
|
||||
baseURL, err := url.Parse(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if baseURL.Path == "" {
|
||||
baseURL.Path = "/"
|
||||
}
|
||||
unix2HTTP(baseURL)
|
||||
c := &Client{
|
||||
base: baseURL,
|
||||
version: version,
|
||||
httpClient: getHttpClient(host),
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func GetUnixServerPath(socketName string, paths ...string) string {
|
||||
serverPath := "unix://"
|
||||
for _, path := range paths {
|
||||
serverPath = serverPath + path
|
||||
}
|
||||
serverPath = serverPath + socketName + ".sock"
|
||||
return serverPath
|
||||
}
|
||||
|
||||
|
||||
// Client is an HTTP REST wrapper. Use one of Get/Post/Put/Delete to get a request
|
||||
// object.
|
||||
type Client struct {
|
||||
base *url.URL
|
||||
version string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// Status sends a Status request at the /status REST endpoint.
|
||||
func (c *Client) Status() (*Status, error) {
|
||||
status := &Status{}
|
||||
err := c.Get().UsePath("/status").Do().Unmarshal(status)
|
||||
return status, err
|
||||
}
|
||||
|
||||
// Version send a request at the /versions REST endpoint.
|
||||
func (c *Client) Versions(endpoint string) ([]string, error) {
|
||||
versions := []string{}
|
||||
err := c.Get().Resource(endpoint + "/versions").Do().Unmarshal(&versions)
|
||||
return versions, err
|
||||
}
|
||||
|
||||
// Get returns a Request object setup for GET call.
|
||||
func (c *Client) Get() *Request {
|
||||
return NewRequest(c.httpClient, c.base, "GET", c.version)
|
||||
}
|
||||
|
||||
// Post returns a Request object setup for POST call.
|
||||
func (c *Client) Post() *Request {
|
||||
return NewRequest(c.httpClient, c.base, "POST", c.version)
|
||||
}
|
||||
|
||||
// Put returns a Request object setup for PUT call.
|
||||
func (c *Client) Put() *Request {
|
||||
return NewRequest(c.httpClient, c.base, "PUT", c.version)
|
||||
}
|
||||
|
||||
// Put returns a Request object setup for DELETE call.
|
||||
func (c *Client) Delete() *Request {
|
||||
return NewRequest(c.httpClient, c.base, "DELETE", c.version)
|
||||
}
|
||||
|
||||
func unix2HTTP(u *url.URL) {
|
||||
if u.Scheme == "unix" {
|
||||
// Override the main URL object so the HTTP lib won't complain
|
||||
u.Scheme = "http"
|
||||
u.Host = "unix.sock"
|
||||
u.Path = ""
|
||||
}
|
||||
}
|
||||
|
||||
func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
|
||||
httpTransport := &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "unix":
|
||||
socketPath := u.Path
|
||||
unixDial := func(proto, addr string) (net.Conn, error) {
|
||||
ret, err := net.DialTimeout("unix", socketPath, timeout)
|
||||
return ret, err
|
||||
}
|
||||
httpTransport.Dial = unixDial
|
||||
unix2HTTP(u)
|
||||
default:
|
||||
httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
|
||||
return net.DialTimeout(proto, addr, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
return &http.Client{Transport: httpTransport}
|
||||
}
|
||||
|
||||
func getHttpClient(host string) *http.Client {
|
||||
c, ok := httpCache[host]
|
||||
if !ok {
|
||||
cacheLock.Lock()
|
||||
defer cacheLock.Unlock()
|
||||
c, ok = httpCache[host]
|
||||
if !ok {
|
||||
u, err := url.Parse(host)
|
||||
if err != nil {
|
||||
// TODO(pedge): clean up
|
||||
fmt.Println("Failed to parse into url", host)
|
||||
return nil
|
||||
}
|
||||
if u.Path == "" {
|
||||
u.Path = "/"
|
||||
}
|
||||
c = newHTTPClient(u, nil, 10*time.Second)
|
||||
httpCache[host] = c
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
304
vendor/github.com/libopenstorage/openstorage/api/client/request.go
generated
vendored
Normal file
304
vendor/github.com/libopenstorage/openstorage/api/client/request.go
generated
vendored
Normal file
|
@ -0,0 +1,304 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Request is contructed iteratively by the client and finally dispatched.
|
||||
// A REST endpoint is accessed with the following convention:
|
||||
// base_url/<version>/<resource>/[<instance>]
|
||||
type Request struct {
|
||||
client *http.Client
|
||||
version string
|
||||
verb string
|
||||
path string
|
||||
base *url.URL
|
||||
params url.Values
|
||||
headers http.Header
|
||||
resource string
|
||||
instance string
|
||||
err error
|
||||
body []byte
|
||||
req *http.Request
|
||||
resp *http.Response
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// Response is a representation of HTTP response received from the server.
|
||||
type Response struct {
|
||||
status string
|
||||
statusCode int
|
||||
err error
|
||||
body []byte
|
||||
}
|
||||
|
||||
// Status upon error, attempts to parse the body of a response into a meaningful status.
|
||||
type Status struct {
|
||||
Message string
|
||||
ErrorCode int
|
||||
}
|
||||
|
||||
// NewRequest instance
|
||||
func NewRequest(client *http.Client, base *url.URL, verb string, version string) *Request {
|
||||
return &Request{
|
||||
client: client,
|
||||
verb: verb,
|
||||
base: base,
|
||||
path: base.Path,
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
|
||||
func checkExists(mustExist string, before string) error {
|
||||
if len(mustExist) == 0 {
|
||||
return fmt.Errorf("%q should be set before setting %q", mustExist, before)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkSet(name string, s *string, newval string) error {
|
||||
if len(*s) != 0 {
|
||||
return fmt.Errorf("%q already set to %q, cannot change to %q",
|
||||
name, *s, newval)
|
||||
}
|
||||
*s = newval
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resource specifies the resource to be accessed.
|
||||
func (r *Request) Resource(resource string) *Request {
|
||||
if r.err == nil {
|
||||
r.err = checkSet("resource", &r.resource, resource)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Instance specifies the instance of the resource to be accessed.
|
||||
func (r *Request) Instance(instance string) *Request {
|
||||
if r.err == nil {
|
||||
r.err = checkExists("resource", "instance")
|
||||
if r.err == nil {
|
||||
r.err = checkSet("instance", &r.instance, instance)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// UsePath use the specified path and don't build up a request.
|
||||
func (r *Request) UsePath(path string) *Request {
|
||||
if r.err == nil {
|
||||
r.err = checkSet("path", &r.path, path)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// QueryOption adds specified options to query.
|
||||
func (r *Request) QueryOption(key string, value string) *Request {
|
||||
if r.err != nil {
|
||||
return r
|
||||
}
|
||||
if r.params == nil {
|
||||
r.params = make(url.Values)
|
||||
}
|
||||
r.params.Add(string(key), value)
|
||||
return r
|
||||
}
|
||||
|
||||
// QueryOptionLabel adds specified label to query.
|
||||
func (r *Request) QueryOptionLabel(key string, labels map[string]string) *Request {
|
||||
if r.err != nil {
|
||||
return r
|
||||
}
|
||||
if b, err := json.Marshal(labels); err != nil {
|
||||
r.err = err
|
||||
} else {
|
||||
if r.params == nil {
|
||||
r.params = make(url.Values)
|
||||
}
|
||||
r.params.Add(string(key), string(b))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// SetHeader adds specified header values to query.
|
||||
func (r *Request) SetHeader(key, value string) *Request {
|
||||
if r.headers == nil {
|
||||
r.headers = http.Header{}
|
||||
}
|
||||
r.headers.Set(key, value)
|
||||
return r
|
||||
}
|
||||
|
||||
// Timeout makes the request use the given duration as a timeout. Sets the "timeout"
|
||||
// parameter.
|
||||
func (r *Request) Timeout(d time.Duration) *Request {
|
||||
if r.err != nil {
|
||||
return r
|
||||
}
|
||||
r.timeout = d
|
||||
return r
|
||||
}
|
||||
|
||||
// Body sets the request Body.
|
||||
func (r *Request) Body(v interface{}) *Request {
|
||||
var err error
|
||||
if r.err != nil {
|
||||
return r
|
||||
}
|
||||
r.body, err = json.Marshal(v)
|
||||
if err != nil {
|
||||
r.err = err
|
||||
return r
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// URL returns the current working URL.
|
||||
func (r *Request) URL() *url.URL {
|
||||
u := *r.base
|
||||
p := r.path
|
||||
|
||||
if len(r.version) != 0 {
|
||||
p = path.Join(p, strings.ToLower(r.version))
|
||||
}
|
||||
if len(r.resource) != 0 {
|
||||
p = path.Join(p, strings.ToLower(r.resource))
|
||||
if len(r.instance) != 0 {
|
||||
p = path.Join(p, r.instance)
|
||||
}
|
||||
}
|
||||
|
||||
u.Path = p
|
||||
|
||||
query := url.Values{}
|
||||
for key, values := range r.params {
|
||||
for _, value := range values {
|
||||
query.Add(key, value)
|
||||
}
|
||||
}
|
||||
if r.timeout != 0 {
|
||||
query.Set("timeout", r.timeout.String())
|
||||
}
|
||||
u.RawQuery = query.Encode()
|
||||
return &u
|
||||
}
|
||||
|
||||
// headerVal for key as an int. Return false if header is not present or valid.
|
||||
func headerVal(key string, resp *http.Response) (int, bool) {
|
||||
if h := resp.Header.Get(key); len(h) > 0 {
|
||||
if i, err := strconv.Atoi(h); err == nil {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func parseHTTPStatus(resp *http.Response, body []byte) error {
|
||||
|
||||
var (
|
||||
status *Status
|
||||
err error
|
||||
)
|
||||
|
||||
httpOK := resp.StatusCode >= http.StatusOK && resp.StatusCode <= http.StatusPartialContent
|
||||
hasStatus := false
|
||||
if body != nil {
|
||||
err = json.Unmarshal(body, status)
|
||||
if err == nil && status.Message != "" {
|
||||
hasStatus = true
|
||||
}
|
||||
}
|
||||
// If the status is NG, return an error regardless of HTTP status.
|
||||
if hasStatus && status.ErrorCode != 0 {
|
||||
return fmt.Errorf("Error %v : %v", status.ErrorCode, status.Message)
|
||||
}
|
||||
|
||||
// Status is good and HTTP status is good, everything is good
|
||||
if httpOK {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If HTTP status is NG, return an error.
|
||||
return fmt.Errorf("HTTP error %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Do executes the request and returns a Response.
|
||||
func (r *Request) Do() *Response {
|
||||
var (
|
||||
err error
|
||||
req *http.Request
|
||||
resp *http.Response
|
||||
url string
|
||||
body []byte
|
||||
)
|
||||
if r.err != nil {
|
||||
return &Response{err: r.err}
|
||||
}
|
||||
url = r.URL().String()
|
||||
req, err = http.NewRequest(r.verb, url, bytes.NewBuffer(r.body))
|
||||
if err != nil {
|
||||
return &Response{err: err}
|
||||
}
|
||||
if r.headers == nil {
|
||||
r.headers = http.Header{}
|
||||
}
|
||||
req.Header = r.headers
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err = r.client.Do(req)
|
||||
if err != nil {
|
||||
return &Response{err: err}
|
||||
}
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
body, err = ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
if err != nil {
|
||||
return &Response{err: err}
|
||||
}
|
||||
return &Response{
|
||||
status: resp.Status,
|
||||
statusCode: resp.StatusCode,
|
||||
body: body,
|
||||
err: parseHTTPStatus(resp, body),
|
||||
}
|
||||
}
|
||||
|
||||
// Body return http body, valid only if there is no error
|
||||
func (r Response) Body() ([]byte, error) {
|
||||
return r.body, r.err
|
||||
}
|
||||
|
||||
// StatusCode HTTP status code returned.
|
||||
func (r Response) StatusCode() int {
|
||||
return r.statusCode
|
||||
}
|
||||
|
||||
// Unmarshal result into obj
|
||||
func (r Response) Unmarshal(v interface{}) error {
|
||||
if r.err != nil {
|
||||
return r.err
|
||||
}
|
||||
return json.Unmarshal(r.body, v)
|
||||
}
|
||||
|
||||
// Error executing the request.
|
||||
func (r Response) Error() error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
func (r Response) FormatError() error {
|
||||
if len(r.body) == 0 {
|
||||
return fmt.Errorf("Error: %v", r.err)
|
||||
} else {
|
||||
return fmt.Errorf("HTTP-%d: %s", r.statusCode, string(r.body))
|
||||
}
|
||||
}
|
387
vendor/github.com/libopenstorage/openstorage/api/client/volume/client.go
generated
vendored
Normal file
387
vendor/github.com/libopenstorage/openstorage/api/client/volume/client.go
generated
vendored
Normal file
|
@ -0,0 +1,387 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
|
||||
"github.com/libopenstorage/openstorage/api"
|
||||
"github.com/libopenstorage/openstorage/api/client"
|
||||
"github.com/libopenstorage/openstorage/volume"
|
||||
)
|
||||
|
||||
const (
|
||||
graphPath = "/graph"
|
||||
volumePath = "/osd-volumes"
|
||||
snapPath = "/osd-snapshot"
|
||||
)
|
||||
|
||||
type volumeClient struct {
|
||||
volume.IODriver
|
||||
c *client.Client
|
||||
}
|
||||
|
||||
func newVolumeClient(c *client.Client) volume.VolumeDriver {
|
||||
return &volumeClient{volume.IONotSupported, c}
|
||||
}
|
||||
|
||||
// String description of this driver.
|
||||
func (v *volumeClient) Name() string {
|
||||
return "VolumeDriver"
|
||||
}
|
||||
|
||||
func (v *volumeClient) Type() api.DriverType {
|
||||
// Block drivers implement the superset.
|
||||
return api.DriverType_DRIVER_TYPE_BLOCK
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverCreate(id string, parent string) error {
|
||||
response := ""
|
||||
if err := v.c.Put().Resource(graphPath + "/create").Instance(id).Do().Unmarshal(&response); err != nil {
|
||||
return err
|
||||
}
|
||||
if response != id {
|
||||
return fmt.Errorf("Invalid response: %s", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverRemove(id string) error {
|
||||
response := ""
|
||||
if err := v.c.Put().Resource(graphPath + "/remove").Instance(id).Do().Unmarshal(&response); err != nil {
|
||||
return err
|
||||
}
|
||||
if response != id {
|
||||
return fmt.Errorf("Invalid response: %s", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverGet(id string, mountLabel string) (string, error) {
|
||||
response := ""
|
||||
if err := v.c.Get().Resource(graphPath + "/inspect").Instance(id).Do().Unmarshal(&response); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverRelease(id string) error {
|
||||
response := ""
|
||||
if err := v.c.Put().Resource(graphPath + "/release").Instance(id).Do().Unmarshal(&response); err != nil {
|
||||
return err
|
||||
}
|
||||
if response != id {
|
||||
return fmt.Errorf("Invalid response: %v", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverExists(id string) bool {
|
||||
response := false
|
||||
v.c.Get().Resource(graphPath + "/exists").Instance(id).Do().Unmarshal(&response)
|
||||
return response
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverDiff(id string, parent string) io.Writer {
|
||||
body, _ := v.c.Get().Resource(graphPath + "/diff?id=" + id + "&parent=" + parent).Do().Body()
|
||||
return bytes.NewBuffer(body)
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverChanges(id string, parent string) ([]api.GraphDriverChanges, error) {
|
||||
var changes []api.GraphDriverChanges
|
||||
err := v.c.Get().Resource(graphPath + "/changes").Instance(id).Do().Unmarshal(&changes)
|
||||
return changes, err
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverApplyDiff(id string, parent string, diff io.Reader) (int, error) {
|
||||
b, err := ioutil.ReadAll(diff)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
response := 0
|
||||
if err = v.c.Put().Resource(graphPath + "/diff?id=" + id + "&parent=" + parent).Instance(id).Body(b).Do().Unmarshal(&response); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (v *volumeClient) GraphDriverDiffSize(id string, parent string) (int, error) {
|
||||
size := 0
|
||||
err := v.c.Get().Resource(graphPath + "/diffsize").Instance(id).Do().Unmarshal(&size)
|
||||
return size, err
|
||||
}
|
||||
|
||||
// Create a new Vol for the specific volume spev.c.
|
||||
// It returns a system generated VolumeID that uniquely identifies the volume
|
||||
func (v *volumeClient) Create(locator *api.VolumeLocator, source *api.Source,
|
||||
spec *api.VolumeSpec) (string, error) {
|
||||
response := &api.VolumeCreateResponse{}
|
||||
request := &api.VolumeCreateRequest{
|
||||
Locator: locator,
|
||||
Source: source,
|
||||
Spec: spec,
|
||||
}
|
||||
if err := v.c.Post().Resource(volumePath).Body(request).Do().Unmarshal(response); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if response.VolumeResponse != nil && response.VolumeResponse.Error != "" {
|
||||
return "", errors.New(response.VolumeResponse.Error)
|
||||
}
|
||||
return response.Id, nil
|
||||
}
|
||||
|
||||
// Status diagnostic information
|
||||
func (v *volumeClient) Status() [][2]string {
|
||||
return [][2]string{}
|
||||
}
|
||||
|
||||
// Inspect specified volumes.
|
||||
// Errors ErrEnoEnt may be returned.
|
||||
func (v *volumeClient) Inspect(ids []string) ([]*api.Volume, error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var volumes []*api.Volume
|
||||
request := v.c.Get().Resource(volumePath)
|
||||
for _, id := range ids {
|
||||
request.QueryOption(api.OptVolumeID, id)
|
||||
}
|
||||
if err := request.Do().Unmarshal(&volumes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return volumes, nil
|
||||
}
|
||||
|
||||
// Delete volume.
|
||||
// Errors ErrEnoEnt, ErrVolHasSnaps may be returned.
|
||||
func (v *volumeClient) Delete(volumeID string) error {
|
||||
response := &api.VolumeResponse{}
|
||||
if err := v.c.Delete().Resource(volumePath).Instance(volumeID).Do().Unmarshal(response); err != nil {
|
||||
return err
|
||||
}
|
||||
if response.Error != "" {
|
||||
return errors.New(response.Error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Snap specified volume. IO to the underlying volume should be quiesced before
|
||||
// calling this function.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
func (v *volumeClient) Snapshot(volumeID string, readonly bool,
|
||||
locator *api.VolumeLocator) (string, error) {
|
||||
response := &api.SnapCreateResponse{}
|
||||
request := &api.SnapCreateRequest{
|
||||
Id: volumeID,
|
||||
Readonly: readonly,
|
||||
Locator: locator,
|
||||
}
|
||||
if err := v.c.Post().Resource(snapPath).Body(request).Do().Unmarshal(response); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// TODO(pedge): this probably should not be embedded in this way
|
||||
if response.VolumeCreateResponse != nil &&
|
||||
response.VolumeCreateResponse.VolumeResponse != nil &&
|
||||
response.VolumeCreateResponse.VolumeResponse.Error != "" {
|
||||
return "", errors.New(
|
||||
response.VolumeCreateResponse.VolumeResponse.Error)
|
||||
}
|
||||
if response.VolumeCreateResponse != nil {
|
||||
return response.VolumeCreateResponse.Id, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Stats for specified volume.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
func (v *volumeClient) Stats(
|
||||
volumeID string,
|
||||
cumulative bool,
|
||||
) (*api.Stats, error) {
|
||||
stats := &api.Stats{}
|
||||
req := v.c.Get().Resource(volumePath + "/stats").Instance(volumeID)
|
||||
req.QueryOption(api.OptCumulative, strconv.FormatBool(cumulative))
|
||||
|
||||
if err := req.Do().Unmarshal(stats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// Alerts on this volume.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
func (v *volumeClient) Alerts(volumeID string) (*api.Alerts, error) {
|
||||
alerts := &api.Alerts{}
|
||||
if err := v.c.Get().Resource(volumePath + "/alerts").Instance(volumeID).Do().Unmarshal(alerts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return alerts, nil
|
||||
}
|
||||
|
||||
// Active Requests on all volume.
|
||||
func (v *volumeClient) GetActiveRequests() (*api.ActiveRequests, error) {
|
||||
|
||||
requests := &api.ActiveRequests{}
|
||||
resp := v.c.Get().Resource(volumePath + "/requests").Instance("vol_id").Do()
|
||||
|
||||
if resp.Error() != nil {
|
||||
return nil, resp.FormatError()
|
||||
}
|
||||
|
||||
if err := resp.Unmarshal(requests); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return requests, nil
|
||||
}
|
||||
|
||||
// Shutdown and cleanup.
|
||||
func (v *volumeClient) Shutdown() {}
|
||||
|
||||
// Enumerate volumes that map to the volumeLocator. Locator fields may be regexp.
|
||||
// If locator fields are left blank, this will return all volumes.
|
||||
func (v *volumeClient) Enumerate(locator *api.VolumeLocator,
|
||||
labels map[string]string) ([]*api.Volume, error) {
|
||||
var volumes []*api.Volume
|
||||
req := v.c.Get().Resource(volumePath)
|
||||
if locator.Name != "" {
|
||||
req.QueryOption(api.OptName, locator.Name)
|
||||
}
|
||||
if len(locator.VolumeLabels) != 0 {
|
||||
req.QueryOptionLabel(api.OptLabel, locator.VolumeLabels)
|
||||
}
|
||||
if len(labels) != 0 {
|
||||
req.QueryOptionLabel(api.OptConfigLabel, labels)
|
||||
}
|
||||
resp := req.Do()
|
||||
if resp.Error() != nil {
|
||||
return nil, resp.FormatError()
|
||||
}
|
||||
if err := resp.Unmarshal(&volumes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return volumes, nil
|
||||
}
|
||||
|
||||
// Enumerate snaps for specified volume
|
||||
// Count indicates the number of snaps populated.
|
||||
func (v *volumeClient) SnapEnumerate(ids []string,
|
||||
snapLabels map[string]string) ([]*api.Volume, error) {
|
||||
var volumes []*api.Volume
|
||||
request := v.c.Get().Resource(snapPath)
|
||||
for _, id := range ids {
|
||||
request.QueryOption(api.OptVolumeID, id)
|
||||
}
|
||||
if len(snapLabels) != 0 {
|
||||
request.QueryOptionLabel(api.OptLabel, snapLabels)
|
||||
}
|
||||
if err := request.Do().Unmarshal(&volumes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return volumes, nil
|
||||
}
|
||||
|
||||
// Attach map device to the host.
|
||||
// On success the devicePath specifies location where the device is exported
|
||||
// Errors ErrEnoEnt, ErrVolAttached may be returned.
|
||||
func (v *volumeClient) Attach(volumeID string) (string, error) {
|
||||
response, err := v.doVolumeSetGetResponse(
|
||||
volumeID,
|
||||
&api.VolumeSetRequest{
|
||||
Action: &api.VolumeStateAction{
|
||||
Attach: api.VolumeActionParam_VOLUME_ACTION_PARAM_ON,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if response.Volume != nil {
|
||||
if response.Volume.Spec.Encrypted {
|
||||
return response.Volume.SecureDevicePath, nil
|
||||
} else {
|
||||
return response.Volume.DevicePath, nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Detach device from the host.
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
func (v *volumeClient) Detach(volumeID string) error {
|
||||
return v.doVolumeSet(
|
||||
volumeID,
|
||||
&api.VolumeSetRequest{
|
||||
Action: &api.VolumeStateAction{
|
||||
Attach: api.VolumeActionParam_VOLUME_ACTION_PARAM_OFF,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (v *volumeClient) MountedAt(mountPath string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Mount volume at specified path
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
func (v *volumeClient) Mount(volumeID string, mountPath string) error {
|
||||
return v.doVolumeSet(
|
||||
volumeID,
|
||||
&api.VolumeSetRequest{
|
||||
Action: &api.VolumeStateAction{
|
||||
Mount: api.VolumeActionParam_VOLUME_ACTION_PARAM_ON,
|
||||
MountPath: mountPath,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Unmount volume at specified path
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
func (v *volumeClient) Unmount(volumeID string, mountPath string) error {
|
||||
return v.doVolumeSet(
|
||||
volumeID,
|
||||
&api.VolumeSetRequest{
|
||||
Action: &api.VolumeStateAction{
|
||||
Mount: api.VolumeActionParam_VOLUME_ACTION_PARAM_OFF,
|
||||
MountPath: mountPath,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Update volume
|
||||
func (v *volumeClient) Set(volumeID string, locator *api.VolumeLocator,
|
||||
spec *api.VolumeSpec) error {
|
||||
return v.doVolumeSet(
|
||||
volumeID,
|
||||
&api.VolumeSetRequest{
|
||||
Locator: locator,
|
||||
Spec: spec,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (v *volumeClient) doVolumeSet(volumeID string,
|
||||
request *api.VolumeSetRequest) error {
|
||||
_, err := v.doVolumeSetGetResponse(volumeID, request)
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *volumeClient) doVolumeSetGetResponse(volumeID string,
|
||||
request *api.VolumeSetRequest) (*api.VolumeSetResponse, error) {
|
||||
response := &api.VolumeSetResponse{}
|
||||
if err := v.c.Put().Resource(volumePath).Instance(volumeID).Body(request).Do().Unmarshal(response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.VolumeResponse != nil && response.VolumeResponse.Error != "" {
|
||||
return nil, errors.New(response.VolumeResponse.Error)
|
||||
}
|
||||
return response, nil
|
||||
}
|
50
vendor/github.com/libopenstorage/openstorage/api/client/volume/volume.go
generated
vendored
Normal file
50
vendor/github.com/libopenstorage/openstorage/api/client/volume/volume.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/libopenstorage/openstorage/api/client"
|
||||
"github.com/libopenstorage/openstorage/volume"
|
||||
"github.com/libopenstorage/openstorage/api"
|
||||
)
|
||||
|
||||
// VolumeDriver returns a REST wrapper for the VolumeDriver interface.
|
||||
func VolumeDriver(c *client.Client) volume.VolumeDriver {
|
||||
return newVolumeClient(c)
|
||||
}
|
||||
|
||||
// NewDriver returns a new REST client of the supplied version for specified driver.
|
||||
// host: REST endpoint [http://<ip>:<port> OR unix://<path-to-unix-socket>]. default: [unix:///var/lib/osd/<driverName>.sock]
|
||||
// version: Volume API version
|
||||
func NewDriverClient(host, driverName, version string) (*client.Client, error) {
|
||||
if driverName == "" {
|
||||
return nil, fmt.Errorf("Driver Name cannot be empty")
|
||||
}
|
||||
if host == "" {
|
||||
host = client.GetUnixServerPath(driverName, volume.DriverAPIBase)
|
||||
}
|
||||
if version == "" {
|
||||
// Set the default version
|
||||
version = volume.APIVersion
|
||||
}
|
||||
return client.NewClient(host, version)
|
||||
}
|
||||
|
||||
// GetSupportedDriverVersions returns a list of supported versions
|
||||
// for the provided driver. It uses the given server endpoint or the
|
||||
// standard unix domain socket
|
||||
func GetSupportedDriverVersions(driverName, host string) ([]string, error) {
|
||||
// Get a client handler
|
||||
if host == "" {
|
||||
host = client.GetUnixServerPath(driverName, volume.DriverAPIBase)
|
||||
}
|
||||
|
||||
client, err := client.NewClient(host, "")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
versions, err := client.Versions(api.OsdVolumePath)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
return versions, nil
|
||||
}
|
192
vendor/github.com/libopenstorage/openstorage/api/spec/spec_handler.go
generated
vendored
Normal file
192
vendor/github.com/libopenstorage/openstorage/api/spec/spec_handler.go
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
package spec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/libopenstorage/openstorage/api"
|
||||
"github.com/libopenstorage/openstorage/pkg/units"
|
||||
)
|
||||
|
||||
// SpecHandler provides conversion function from what gets passed in over the
|
||||
// plugin API to an api.VolumeSpec object.
|
||||
type SpecHandler interface {
|
||||
// SpecFromString parses options from the name.
|
||||
// If the scheduler was unable to pass in the volume spec via the API,
|
||||
// the spec can be passed in via the name in the format:
|
||||
// "key=value;key=value;name=volname"
|
||||
// If the spec was parsed, it returns:
|
||||
// (true, parsed_spec, parsed_name)
|
||||
// If the input string didn't contain the string, it returns:
|
||||
// (false, DefaultSpec(), inputString)
|
||||
SpecFromString(inputString string) (bool, *api.VolumeSpec, string)
|
||||
|
||||
// SpecFromOpts parses in docker options passed in the the docker run
|
||||
// command of the form --opt name=value
|
||||
// If the options are validated then it returns:
|
||||
// (resultant_VolumeSpec, nil)
|
||||
// If the options have invalid values then it returns:
|
||||
// (nil, error)
|
||||
|
||||
SpecFromOpts(opts map[string]string) (*api.VolumeSpec, error)
|
||||
// Returns a default VolumeSpec if no docker options or string encoding
|
||||
// was provided.
|
||||
DefaultSpec() *api.VolumeSpec
|
||||
}
|
||||
|
||||
var (
|
||||
nameRegex = regexp.MustCompile(api.Name + "=([0-9A-Za-z]+),?")
|
||||
sizeRegex = regexp.MustCompile(api.SpecSize + "=([0-9A-Za-z]+),?")
|
||||
scaleRegex = regexp.MustCompile(api.SpecScale + "=([0-9A-Za-z]+),?")
|
||||
fsRegex = regexp.MustCompile(api.SpecFilesystem + "=([0-9A-Za-z]+),?")
|
||||
bsRegex = regexp.MustCompile(api.SpecBlockSize + "=([0-9]+),?")
|
||||
haRegex = regexp.MustCompile(api.SpecHaLevel + "=([0-9]+),?")
|
||||
cosRegex = regexp.MustCompile(api.SpecPriority + "=([A-Za-z]+),?")
|
||||
sharedRegex = regexp.MustCompile(api.SpecShared + "=([A-Za-z]+),?")
|
||||
passphraseRegex = regexp.MustCompile(api.SpecPassphrase + "=([0-9A-Za-z_@./#&+-]+),?")
|
||||
)
|
||||
|
||||
type specHandler struct {
|
||||
}
|
||||
|
||||
func NewSpecHandler() SpecHandler {
|
||||
return &specHandler{}
|
||||
}
|
||||
|
||||
func (d *specHandler) cosLevel(cos string) (uint32, error) {
|
||||
switch cos {
|
||||
case "high", "3":
|
||||
return uint32(api.CosType_HIGH), nil
|
||||
case "medium", "2":
|
||||
return uint32(api.CosType_MEDIUM), nil
|
||||
case "low", "1", "":
|
||||
return uint32(api.CosType_LOW), nil
|
||||
}
|
||||
return uint32(api.CosType_LOW),
|
||||
fmt.Errorf("Cos must be one of %q | %q | %q", "high", "medium", "low")
|
||||
}
|
||||
|
||||
func (d *specHandler) getVal(r *regexp.Regexp, str string) (bool, string) {
|
||||
found := r.FindString(str)
|
||||
if found == "" {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
submatches := r.FindStringSubmatch(str)
|
||||
if len(submatches) < 2 {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
val := submatches[1]
|
||||
|
||||
return true, val
|
||||
}
|
||||
|
||||
func (d *specHandler) DefaultSpec() *api.VolumeSpec {
|
||||
return &api.VolumeSpec{
|
||||
VolumeLabels: make(map[string]string),
|
||||
Format: api.FSType_FS_TYPE_EXT4,
|
||||
HaLevel: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *specHandler) SpecFromOpts(
|
||||
opts map[string]string,
|
||||
) (*api.VolumeSpec, error) {
|
||||
spec := d.DefaultSpec()
|
||||
|
||||
for k, v := range opts {
|
||||
switch k {
|
||||
case api.SpecEphemeral:
|
||||
spec.Ephemeral, _ = strconv.ParseBool(v)
|
||||
case api.SpecSize:
|
||||
if size, err := units.Parse(v); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
spec.Size = uint64(size)
|
||||
}
|
||||
case api.SpecFilesystem:
|
||||
if value, err := api.FSTypeSimpleValueOf(v); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
spec.Format = value
|
||||
}
|
||||
case api.SpecBlockSize:
|
||||
if blockSize, err := units.Parse(v); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
spec.BlockSize = blockSize
|
||||
}
|
||||
case api.SpecHaLevel:
|
||||
haLevel, _ := strconv.ParseInt(v, 10, 64)
|
||||
spec.HaLevel = haLevel
|
||||
case api.SpecPriority:
|
||||
cos, _ := api.CosTypeSimpleValueOf(v)
|
||||
spec.Cos = cos
|
||||
case api.SpecDedupe:
|
||||
spec.Dedupe, _ = strconv.ParseBool(v)
|
||||
case api.SpecSnapshotInterval:
|
||||
snapshotInterval, _ := strconv.ParseUint(v, 10, 32)
|
||||
spec.SnapshotInterval = uint32(snapshotInterval)
|
||||
case api.SpecAggregationLevel:
|
||||
aggregationLevel, _ := strconv.ParseUint(v, 10, 32)
|
||||
spec.AggregationLevel = uint32(aggregationLevel)
|
||||
case api.SpecShared:
|
||||
if shared, err := strconv.ParseBool(v); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
spec.Shared = shared
|
||||
}
|
||||
case api.SpecPassphrase:
|
||||
spec.Encrypted = true
|
||||
spec.Passphrase = v
|
||||
default:
|
||||
spec.VolumeLabels[k] = v
|
||||
}
|
||||
}
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (d *specHandler) SpecFromString(
|
||||
str string,
|
||||
) (bool, *api.VolumeSpec, string) {
|
||||
// If we can't parse the name, the rest of the spec is invalid.
|
||||
ok, name := d.getVal(nameRegex, str)
|
||||
if !ok {
|
||||
return false, d.DefaultSpec(), str
|
||||
}
|
||||
|
||||
opts := make(map[string]string)
|
||||
|
||||
if ok, sz := d.getVal(sizeRegex, str); ok {
|
||||
opts[api.SpecSize] = sz
|
||||
}
|
||||
if ok, scale := d.getVal(scaleRegex, str); ok {
|
||||
opts[api.SpecScale] = scale
|
||||
}
|
||||
if ok, fs := d.getVal(fsRegex, str); ok {
|
||||
opts[api.SpecFilesystem] = fs
|
||||
}
|
||||
if ok, bs := d.getVal(bsRegex, str); ok {
|
||||
opts[api.SpecBlockSize] = bs
|
||||
}
|
||||
if ok, ha := d.getVal(haRegex, str); ok {
|
||||
opts[api.SpecHaLevel] = ha
|
||||
}
|
||||
if ok, priority := d.getVal(cosRegex, str); ok {
|
||||
opts[api.SpecPriority] = priority
|
||||
}
|
||||
if ok, shared := d.getVal(sharedRegex, str); ok {
|
||||
opts[api.SpecShared] = shared
|
||||
}
|
||||
if ok, passphrase := d.getVal(passphraseRegex, str); ok {
|
||||
opts[api.SpecPassphrase] = passphrase
|
||||
}
|
||||
|
||||
spec, err := d.SpecFromOpts(opts)
|
||||
if err != nil {
|
||||
return false, d.DefaultSpec(), name
|
||||
}
|
||||
return true, spec, name
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package api
|
||||
|
||||
type StatusKind int32
|
||||
|
||||
const (
|
||||
// StatusSeverityLow indicates an OK status
|
||||
StatusSeverityLow StatusKind = iota
|
||||
// StatusSeverityMedium indicates a status which is in transition from OK to BAD or vice versa
|
||||
StatusSeverityMedium
|
||||
// StatusSeverityHigh indicates a BAD status
|
||||
StatusSeverityHigh
|
||||
)
|
||||
|
||||
var statusToStatusKind = map[Status]StatusKind{
|
||||
Status_STATUS_NONE: StatusSeverityHigh,
|
||||
Status_STATUS_INIT: StatusSeverityMedium,
|
||||
Status_STATUS_OK: StatusSeverityLow,
|
||||
Status_STATUS_OFFLINE: StatusSeverityHigh,
|
||||
Status_STATUS_ERROR: StatusSeverityHigh,
|
||||
Status_STATUS_NOT_IN_QUORUM: StatusSeverityHigh,
|
||||
Status_STATUS_DECOMMISSION: StatusSeverityHigh,
|
||||
Status_STATUS_MAINTENANCE: StatusSeverityHigh,
|
||||
Status_STATUS_STORAGE_DOWN: StatusSeverityHigh,
|
||||
Status_STATUS_STORAGE_DEGRADED: StatusSeverityHigh,
|
||||
Status_STATUS_NEEDS_REBOOT: StatusSeverityHigh,
|
||||
Status_STATUS_STORAGE_REBALANCE: StatusSeverityMedium,
|
||||
Status_STATUS_STORAGE_DRIVE_REPLACE: StatusSeverityMedium,
|
||||
// Add statuses before MAX
|
||||
Status_STATUS_MAX: StatusSeverityHigh,
|
||||
}
|
||||
|
||||
func StatusSimpleValueOf(s string) (Status, error) {
|
||||
obj, err := simpleValueOf("status", Status_value, s)
|
||||
return Status(obj), err
|
||||
}
|
||||
|
||||
func (x Status) SimpleString() string {
|
||||
return simpleString("status", Status_name, int32(x))
|
||||
}
|
||||
|
||||
func (x Status) StatusKind() StatusKind {
|
||||
statusType, _ := statusToStatusKind[x]
|
||||
return statusType
|
||||
}
|
||||
|
||||
// StatusKindMapLength used only for unit testing
|
||||
func StatusKindMapLength() int {
|
||||
return len(statusToStatusKind)
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package units
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
// KiB 1024 bytes
|
||||
KiB = 1 << (10 * iota)
|
||||
// MiB 1024 KiB
|
||||
MiB
|
||||
// GiB 1024 MiB
|
||||
GiB
|
||||
// TiB 1024 GiB
|
||||
TiB
|
||||
// PiB 1024 TiB
|
||||
PiB
|
||||
)
|
||||
|
||||
const (
|
||||
// KB 1000 bytes
|
||||
KB = 1000
|
||||
// MB 1000 KB
|
||||
MB = KB * 1000
|
||||
// GB 1000 MB
|
||||
GB = MB * 1000
|
||||
// TB 1000 GB
|
||||
TB = GB * 1000
|
||||
// PB 1000 TB
|
||||
PB = TB * 1000
|
||||
)
|
||||
|
||||
var (
|
||||
unitMap = map[string]int64{
|
||||
"B": 1,
|
||||
"b": 1,
|
||||
|
||||
"KB": KB,
|
||||
"kb": KB,
|
||||
"MB": MB,
|
||||
"mb": MB,
|
||||
"GB": GB,
|
||||
"gb": GB,
|
||||
"TB": TB,
|
||||
"tb": TB,
|
||||
"PB": PB,
|
||||
"pb": PB,
|
||||
|
||||
"K": KiB,
|
||||
"k": KiB,
|
||||
"M": MiB,
|
||||
"m": MiB,
|
||||
"G": GiB,
|
||||
"g": GiB,
|
||||
"T": TiB,
|
||||
"t": TiB,
|
||||
"P": PiB,
|
||||
"p": PiB,
|
||||
|
||||
"KiB": KiB,
|
||||
"MiB": MiB,
|
||||
"GiB": GiB,
|
||||
"TiB": TiB,
|
||||
"PiB": PiB,
|
||||
|
||||
"Mi": MiB,
|
||||
"Gi": GiB,
|
||||
"Ti": TiB,
|
||||
"Pi": PiB,
|
||||
}
|
||||
)
|
||||
|
||||
var unitPattern = regexp.MustCompile(
|
||||
"([0-9]+)(.[0-9]+)*\\s*(B|b|K|k|M|m|G|g|T|t|P|p|KB|kb|KiB|MB|mb|MiB|Mi|GB|gb|GiB|Gi|TB|tb|TiB|Ti|PB|pb|PiB|Pi|)")
|
||||
var BadUnit = errors.New("Bad unit")
|
||||
|
||||
func String(b uint64) string {
|
||||
if b > PiB {
|
||||
return fmt.Sprintf("%.2f PiB", float64(b)/float64(PiB))
|
||||
}
|
||||
if b > TiB {
|
||||
return fmt.Sprintf("%.2f TiB", float64(b)/float64(TiB))
|
||||
}
|
||||
if b > GiB {
|
||||
return fmt.Sprintf("%.1f TiB", float64(b)/float64(GiB))
|
||||
}
|
||||
if b > MiB {
|
||||
return fmt.Sprintf("%v MiB", b/MiB)
|
||||
}
|
||||
if b > KiB {
|
||||
return fmt.Sprintf("%v KiB", b/KiB)
|
||||
}
|
||||
return fmt.Sprintf("%v bytes", b)
|
||||
}
|
||||
|
||||
func Parse(bUnit string) (int64, error) {
|
||||
ustring := strings.TrimSpace(bUnit)
|
||||
unitPattern.Longest()
|
||||
if !unitPattern.MatchString(ustring) {
|
||||
return -1, fmt.Errorf("Unit parse error: %s", bUnit)
|
||||
}
|
||||
matches := unitPattern.FindStringSubmatch(ustring)
|
||||
|
||||
if len(matches) == 0 || len(matches) > 4 {
|
||||
return -1, fmt.Errorf(
|
||||
"Unit parse error: invalid count of fields (%v)",
|
||||
len(matches))
|
||||
}
|
||||
if len(matches) == 1 {
|
||||
return strconv.ParseInt(ustring, 10, 64)
|
||||
}
|
||||
shift := 0
|
||||
if len(matches) == 4 {
|
||||
shift = 1
|
||||
}
|
||||
if len(matches) == 2 {
|
||||
return -1, fmt.Errorf("Unit parse error: invalid fields %v",
|
||||
matches)
|
||||
}
|
||||
if ustring != matches[0] {
|
||||
return -1, fmt.Errorf("Unit parse error: invalid fields %v",
|
||||
matches)
|
||||
}
|
||||
multiplier, ok := unitMap[matches[2+shift]]
|
||||
if !ok {
|
||||
multiplier = unitMap["G"]
|
||||
}
|
||||
base, err := strconv.ParseInt(matches[1], 10, 64)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("Invalid number")
|
||||
}
|
||||
|
||||
return base * multiplier, nil
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
## Volume Drivers
|
||||
|
||||
Volume drivers implement the [Volume Plugin Interface](https://docs.docker.com/engine/extend/plugins_volume/).
|
||||
This provides an interface to register a volume driver and advertise the driver to Docker. Registering a driver with this volume interface will cause Docker to be able to communicate with the driver to create and assign volumes to a container.
|
||||
|
||||
A volume spec is needed to create a volume. A volume spec looks like:
|
||||
|
||||
```
|
||||
// VolumeSpec has the properties needed to create a volume.
|
||||
type VolumeSpec struct {
|
||||
// Ephemeral storage
|
||||
Ephemeral bool
|
||||
// Thin provisioned volume size in bytes
|
||||
Size uint64
|
||||
// Format disk with this FileSystem
|
||||
Format Filesystem
|
||||
// BlockSize for file system
|
||||
BlockSize int
|
||||
// HA Level specifies the number of nodes that are
|
||||
// allowed to fail, and yet data is availabel.
|
||||
// A value of 0 implies that data is not erasure coded,
|
||||
// a failure of a node will lead to data loss.
|
||||
HALevel int
|
||||
// This disk's CoS
|
||||
Cos VolumeCos
|
||||
// Perform dedupe on this disk
|
||||
Dedupe bool
|
||||
// SnapshotInterval in minutes, set to 0 to disable Snapshots
|
||||
SnapshotInterval int
|
||||
// Volume configuration labels
|
||||
ConfigLabels Labels
|
||||
}
|
||||
```
|
||||
|
||||
Various volume driver implementations can be found in the `drivers` directory.
|
||||
|
||||
### Block Drivers
|
||||
Block drivers operate at the block layer. They provide raw volumes formatted with a user specified filesystem. This volume is then mounted into the container at a path specified using the `docker run -v` option.
|
||||
|
||||
### File Drivers
|
||||
File drivers operate at the filesystem layer.
|
|
@ -0,0 +1,171 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/libopenstorage/openstorage/api"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAlreadyShutdown = errors.New("VolumeDriverProvider already shutdown")
|
||||
ErrExist = errors.New("Driver already exists")
|
||||
ErrDriverNotFound = errors.New("Driver implementation not found")
|
||||
ErrDriverInitializing = errors.New("Driver is initializing")
|
||||
ErrEnoEnt = errors.New("Volume does not exist.")
|
||||
ErrEnomem = errors.New("Out of memory.")
|
||||
ErrEinval = errors.New("Invalid argument")
|
||||
ErrVolDetached = errors.New("Volume is detached")
|
||||
ErrVolAttached = errors.New("Volume is attached")
|
||||
ErrVolAttachedOnRemoteNode = errors.New("Volume is attached on another node")
|
||||
ErrVolAttachedScale = errors.New("Volume is attached but can be scaled")
|
||||
ErrVolHasSnaps = errors.New("Volume has snapshots associated")
|
||||
ErrNotSupported = errors.New("Operation not supported")
|
||||
)
|
||||
|
||||
// Constants used by the VolumeDriver
|
||||
const (
|
||||
APIVersion = "v1"
|
||||
PluginAPIBase = "/run/docker/plugins/"
|
||||
DriverAPIBase = "/var/lib/osd/driver/"
|
||||
MountBase = "/var/lib/osd/mounts/"
|
||||
VolumeBase = "/var/lib/osd/"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
// Lock volume specified by volumeID.
|
||||
Lock(volumeID string) (interface{}, error)
|
||||
// Lock volume with token obtained from call to Lock.
|
||||
Unlock(token interface{}) error
|
||||
// CreateVol returns error if volume with the same ID already existe.
|
||||
CreateVol(vol *api.Volume) error
|
||||
// GetVol from volumeID.
|
||||
GetVol(volumeID string) (*api.Volume, error)
|
||||
// UpdateVol with vol
|
||||
UpdateVol(vol *api.Volume) error
|
||||
// DeleteVol. Returns error if volume does not exist.
|
||||
DeleteVol(volumeID string) error
|
||||
}
|
||||
|
||||
// VolumeDriver is the main interface to be implemented by any storage driver.
|
||||
// Every driver must at minimum implement the ProtoDriver sub interface.
|
||||
type VolumeDriver interface {
|
||||
IODriver
|
||||
ProtoDriver
|
||||
BlockDriver
|
||||
Enumerator
|
||||
}
|
||||
|
||||
// IODriver interfaces applicable to object store interfaces.
|
||||
type IODriver interface {
|
||||
// Read sz bytes from specified volume at specified offset.
|
||||
// Return number of bytes read and error.
|
||||
Read(volumeID string, buf []byte, sz uint64, offset int64) (int64, error)
|
||||
// Write sz bytes from specified volume at specified offset.
|
||||
// Return number of bytes written and error.
|
||||
Write(volumeID string, buf []byte, sz uint64, offset int64) (int64, error)
|
||||
// Flush writes to stable storage.
|
||||
// Return error.
|
||||
Flush(volumeID string) error
|
||||
}
|
||||
|
||||
type SnapshotDriver interface {
|
||||
// Snapshot create volume snapshot.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
Snapshot(volumeID string, readonly bool, locator *api.VolumeLocator) (string, error)
|
||||
}
|
||||
|
||||
// ProtoDriver must be implemented by all volume drivers. It specifies the
|
||||
// most basic functionality, such as creating and deleting volumes.
|
||||
type ProtoDriver interface {
|
||||
SnapshotDriver
|
||||
// Name returns the name of the driver.
|
||||
Name() string
|
||||
// Type of this driver
|
||||
Type() api.DriverType
|
||||
// Create a new Vol for the specific volume spec.
|
||||
// It returns a system generated VolumeID that uniquely identifies the volume
|
||||
Create(locator *api.VolumeLocator, Source *api.Source, spec *api.VolumeSpec) (string, error)
|
||||
// Delete volume.
|
||||
// Errors ErrEnoEnt, ErrVolHasSnaps may be returned.
|
||||
Delete(volumeID string) error
|
||||
// Mount volume at specified path
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
Mount(volumeID string, mountPath string) error
|
||||
// MountedAt return volume mounted at specified mountpath.
|
||||
MountedAt(mountPath string) string
|
||||
// Unmount volume at specified path
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
Unmount(volumeID string, mountPath string) error
|
||||
// Update not all fields of the spec are supported, ErrNotSupported will be thrown for unsupported
|
||||
// updates.
|
||||
Set(volumeID string, locator *api.VolumeLocator, spec *api.VolumeSpec) error
|
||||
// Stats for specified volume.
|
||||
// cumulative stats are /proc/diskstats style stats.
|
||||
// nonCumulative stats are stats for specific duration.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
Stats(volumeID string, cumulative bool) (*api.Stats, error)
|
||||
// Alerts on this volume.
|
||||
// Errors ErrEnoEnt may be returned
|
||||
Alerts(volumeID string) (*api.Alerts, error)
|
||||
// GetActiveRequests get active requests
|
||||
GetActiveRequests() (*api.ActiveRequests, error)
|
||||
// Status returns a set of key-value pairs which give low
|
||||
// level diagnostic status about this driver.
|
||||
Status() [][2]string
|
||||
// Shutdown and cleanup.
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
// Enumerator provides a set of interfaces to get details on a set of volumes.
|
||||
type Enumerator interface {
|
||||
// Inspect specified volumes.
|
||||
// Returns slice of volumes that were found.
|
||||
Inspect(volumeIDs []string) ([]*api.Volume, error)
|
||||
// Enumerate volumes that map to the volumeLocator. Locator fields may be regexp.
|
||||
// If locator fields are left blank, this will return all volumes.
|
||||
Enumerate(locator *api.VolumeLocator, labels map[string]string) ([]*api.Volume, error)
|
||||
// Enumerate snaps for specified volumes
|
||||
SnapEnumerate(volID []string, snapLabels map[string]string) ([]*api.Volume, error)
|
||||
}
|
||||
|
||||
type StoreEnumerator interface {
|
||||
Store
|
||||
Enumerator
|
||||
}
|
||||
|
||||
// BlockDriver needs to be implemented by block volume drivers. Filesystem volume
|
||||
// drivers can ignore this interface and include the builtin DefaultBlockDriver.
|
||||
type BlockDriver interface {
|
||||
// Attach map device to the host.
|
||||
// On success the devicePath specifies location where the device is exported
|
||||
// Errors ErrEnoEnt, ErrVolAttached may be returned.
|
||||
Attach(volumeID string) (string, error)
|
||||
// Detach device from the host.
|
||||
// Errors ErrEnoEnt, ErrVolDetached may be returned.
|
||||
Detach(volumeID string) error
|
||||
}
|
||||
|
||||
// VolumeDriverProvider provides VolumeDrivers.
|
||||
type VolumeDriverProvider interface {
|
||||
// Get gets the VolumeDriver for the given name.
|
||||
// If a VolumeDriver was not created for the given name, the error ErrDriverNotFound is returned.
|
||||
Get(name string) (VolumeDriver, error)
|
||||
// Shutdown shuts down all volume drivers.
|
||||
Shutdown() error
|
||||
}
|
||||
|
||||
// VolumeDriverRegistry registers VolumeDrivers.
|
||||
type VolumeDriverRegistry interface {
|
||||
VolumeDriverProvider
|
||||
// New creates the VolumeDriver for the given name.
|
||||
// If a VolumeDriver was already created for the given name, the error ErrExist is returned.
|
||||
Register(name string, params map[string]string) error
|
||||
|
||||
// Add inserts a new VolumeDriver provider with a well known name.
|
||||
Add(name string, init func(map[string]string) (VolumeDriver, error)) error
|
||||
}
|
||||
|
||||
// VolumeDriverRegistry constructs a new VolumeDriverRegistry.
|
||||
func NewVolumeDriverRegistry(nameToInitFunc map[string]func(map[string]string) (VolumeDriver, error)) VolumeDriverRegistry {
|
||||
return newVolumeDriverRegistry(nameToInitFunc)
|
||||
}
|
71
vendor/github.com/libopenstorage/openstorage/volume/volume_driver_registry.go
generated
vendored
Normal file
71
vendor/github.com/libopenstorage/openstorage/volume/volume_driver_registry.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
package volume
|
||||
|
||||
import "sync"
|
||||
|
||||
type volumeDriverRegistry struct {
|
||||
nameToInitFunc map[string]func(map[string]string) (VolumeDriver, error)
|
||||
nameToVolumeDriver map[string]VolumeDriver
|
||||
lock *sync.RWMutex
|
||||
isShutdown bool
|
||||
}
|
||||
|
||||
func newVolumeDriverRegistry(nameToInitFunc map[string]func(map[string]string) (VolumeDriver, error)) *volumeDriverRegistry {
|
||||
return &volumeDriverRegistry{
|
||||
nameToInitFunc,
|
||||
make(map[string]VolumeDriver),
|
||||
&sync.RWMutex{},
|
||||
false,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *volumeDriverRegistry) Get(name string) (VolumeDriver, error) {
|
||||
v.lock.RLock()
|
||||
defer v.lock.RUnlock()
|
||||
if v.isShutdown {
|
||||
return nil, ErrAlreadyShutdown
|
||||
}
|
||||
volumeDriver, ok := v.nameToVolumeDriver[name]
|
||||
if !ok {
|
||||
return nil, ErrDriverNotFound
|
||||
}
|
||||
return volumeDriver, nil
|
||||
}
|
||||
|
||||
func (v *volumeDriverRegistry) Add(name string, init func(map[string]string) (VolumeDriver, error)) error {
|
||||
v.nameToInitFunc[name] = init
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeDriverRegistry) Register(name string, params map[string]string) error {
|
||||
initFunc, ok := v.nameToInitFunc[name]
|
||||
if !ok {
|
||||
return ErrNotSupported
|
||||
}
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
if v.isShutdown {
|
||||
return ErrAlreadyShutdown
|
||||
}
|
||||
if _, ok := v.nameToVolumeDriver[name]; ok {
|
||||
return ErrExist
|
||||
}
|
||||
volumeDriver, err := initFunc(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.nameToVolumeDriver[name] = volumeDriver
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *volumeDriverRegistry) Shutdown() error {
|
||||
v.lock.Lock()
|
||||
if v.isShutdown {
|
||||
return ErrAlreadyShutdown
|
||||
}
|
||||
for _, volumeDriver := range v.nameToVolumeDriver {
|
||||
volumeDriver.Shutdown()
|
||||
}
|
||||
v.isShutdown = true
|
||||
return nil
|
||||
}
|
45
vendor/github.com/libopenstorage/openstorage/volume/volume_not_supported.go
generated
vendored
Normal file
45
vendor/github.com/libopenstorage/openstorage/volume/volume_not_supported.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"github.com/libopenstorage/openstorage/api"
|
||||
)
|
||||
|
||||
var (
|
||||
// BlockNotSupported is a default (null) block driver implementation. This can be
|
||||
// used by drivers that do not want to (or care about) implementing the attach,
|
||||
// format and detach interfaces.
|
||||
BlockNotSupported = &blockNotSupported{}
|
||||
SnapshotNotSupported = &snapshotNotSupported{}
|
||||
IONotSupported = &ioNotSupported{}
|
||||
)
|
||||
|
||||
|
||||
type blockNotSupported struct{}
|
||||
|
||||
func (b *blockNotSupported) Attach(volumeID string) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *blockNotSupported) Detach(volumeID string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
type snapshotNotSupported struct{}
|
||||
|
||||
func (s *snapshotNotSupported) Snapshot(volumeID string, readonly bool, locator *api.VolumeLocator) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
type ioNotSupported struct{}
|
||||
|
||||
func (i *ioNotSupported) Read(volumeID string, buffer []byte, size uint64, offset int64) (int64, error) {
|
||||
return 0, ErrNotSupported
|
||||
}
|
||||
|
||||
func (i *ioNotSupported) Write(volumeID string, buffer []byte, size uint64, offset int64) (int64, error) {
|
||||
return 0, ErrNotSupported
|
||||
}
|
||||
|
||||
func (i *ioNotSupported) Flush(volumeID string) error {
|
||||
return ErrNotSupported
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Peter Edge
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/any.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// `Any` contains an arbitrary serialized message along with a URL
|
||||
// that describes the type of the serialized message.
|
||||
//
|
||||
//
|
||||
// JSON
|
||||
// ====
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
type Any struct {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized message.
|
||||
//
|
||||
// For URLs which use the schema `http`, `https`, or no schema, the
|
||||
// following restrictions and interpretations apply:
|
||||
//
|
||||
// * If no schema is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Schemas other than `http`, `https` (or the empty schema) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
|
||||
// Must be valid serialized data of the above specified type.
|
||||
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Any) Reset() { *m = Any{} }
|
||||
func (m *Any) String() string { return proto.CompactTextString(m) }
|
||||
func (*Any) ProtoMessage() {}
|
||||
func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 160 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||
0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x25, 0x33, 0x2e, 0x66, 0xc7, 0xbc, 0x4a,
|
||||
0x21, 0x49, 0x2e, 0x8e, 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46,
|
||||
0x0d, 0xce, 0x20, 0x76, 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7,
|
||||
0x34, 0x55, 0x82, 0x09, 0x28, 0xce, 0x13, 0x04, 0xe1, 0x38, 0x79, 0x73, 0x09, 0x27, 0xe7, 0xe7,
|
||||
0xea, 0xa1, 0x19, 0xe7, 0xc4, 0x01, 0x34, 0x2c, 0x00, 0xc4, 0x09, 0x60, 0x5c, 0xc0, 0xc8, 0xb8,
|
||||
0x88, 0x89, 0xd9, 0x3d, 0xc0, 0x69, 0x15, 0x93, 0x9c, 0x3b, 0x44, 0x59, 0x00, 0x54, 0x99, 0x5e,
|
||||
0x78, 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0xd0, 0x92, 0xe2, 0x24, 0x36, 0xb0,
|
||||
0x7e, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x83, 0x49, 0xa8, 0x53, 0xb9, 0x00, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/api.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// Api is a light-weight descriptor for a protocol buffer service.
|
||||
type Api struct {
|
||||
// The fully qualified name of this api, including package name
|
||||
// followed by the api's simple name.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// The methods of this api, in unspecified order.
|
||||
Methods []*Method `protobuf:"bytes,2,rep,name=methods" json:"methods,omitempty"`
|
||||
// Any metadata attached to the API.
|
||||
Options []*Option `protobuf:"bytes,3,rep,name=options" json:"options,omitempty"`
|
||||
// A version string for this api. If specified, must have the form
|
||||
// `major-version.minor-version`, as in `1.10`. If the minor version
|
||||
// is omitted, it defaults to zero. If the entire version field is
|
||||
// empty, the major version is derived from the package name, as
|
||||
// outlined below. If the field is not empty, the version in the
|
||||
// package name will be verified to be consistent with what is
|
||||
// provided here.
|
||||
//
|
||||
// The versioning schema uses [semantic
|
||||
// versioning](http://semver.org) where the major version number
|
||||
// indicates a breaking change and the minor version an additive,
|
||||
// non-breaking change. Both version numbers are signals to users
|
||||
// what to expect from different versions, and should be carefully
|
||||
// chosen based on the product plan.
|
||||
//
|
||||
// The major version is also reflected in the package name of the
|
||||
// API, which must end in `v<major-version>`, as in
|
||||
// `google.feature.v1`. For major versions 0 and 1, the suffix can
|
||||
// be omitted. Zero major versions must only be used for
|
||||
// experimental, none-GA apis.
|
||||
//
|
||||
//
|
||||
Version string `protobuf:"bytes,4,opt,name=version" json:"version,omitempty"`
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext *SourceContext `protobuf:"bytes,5,opt,name=source_context,json=sourceContext" json:"source_context,omitempty"`
|
||||
// Included APIs. See [Mixin][].
|
||||
Mixins []*Mixin `protobuf:"bytes,6,rep,name=mixins" json:"mixins,omitempty"`
|
||||
// The source syntax of the service.
|
||||
Syntax Syntax `protobuf:"varint,7,opt,name=syntax,enum=google.protobuf.Syntax" json:"syntax,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Api) Reset() { *m = Api{} }
|
||||
func (m *Api) String() string { return proto.CompactTextString(m) }
|
||||
func (*Api) ProtoMessage() {}
|
||||
func (*Api) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *Api) GetMethods() []*Method {
|
||||
if m != nil {
|
||||
return m.Methods
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Api) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Api) GetSourceContext() *SourceContext {
|
||||
if m != nil {
|
||||
return m.SourceContext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Api) GetMixins() []*Mixin {
|
||||
if m != nil {
|
||||
return m.Mixins
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Method represents a method of an api.
|
||||
type Method struct {
|
||||
// The simple name of this method.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// A URL of the input message type.
|
||||
RequestTypeUrl string `protobuf:"bytes,2,opt,name=request_type_url,json=requestTypeUrl" json:"request_type_url,omitempty"`
|
||||
// If true, the request is streamed.
|
||||
RequestStreaming bool `protobuf:"varint,3,opt,name=request_streaming,json=requestStreaming" json:"request_streaming,omitempty"`
|
||||
// The URL of the output message type.
|
||||
ResponseTypeUrl string `protobuf:"bytes,4,opt,name=response_type_url,json=responseTypeUrl" json:"response_type_url,omitempty"`
|
||||
// If true, the response is streamed.
|
||||
ResponseStreaming bool `protobuf:"varint,5,opt,name=response_streaming,json=responseStreaming" json:"response_streaming,omitempty"`
|
||||
// Any metadata attached to the method.
|
||||
Options []*Option `protobuf:"bytes,6,rep,name=options" json:"options,omitempty"`
|
||||
// The source syntax of this method.
|
||||
Syntax Syntax `protobuf:"varint,7,opt,name=syntax,enum=google.protobuf.Syntax" json:"syntax,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Method) Reset() { *m = Method{} }
|
||||
func (m *Method) String() string { return proto.CompactTextString(m) }
|
||||
func (*Method) ProtoMessage() {}
|
||||
func (*Method) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
|
||||
|
||||
func (m *Method) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Declares an API to be included in this API. The including API must
|
||||
// redeclare all the methods from the included API, but documentation
|
||||
// and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including API plus the [root][] path if specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inherting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
type Mixin struct {
|
||||
// The fully qualified name of the API which is included.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
Root string `protobuf:"bytes,2,opt,name=root" json:"root,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Mixin) Reset() { *m = Mixin{} }
|
||||
func (m *Mixin) String() string { return proto.CompactTextString(m) }
|
||||
func (*Mixin) ProtoMessage() {}
|
||||
func (*Mixin) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Api)(nil), "google.protobuf.Api")
|
||||
proto.RegisterType((*Method)(nil), "google.protobuf.Method")
|
||||
proto.RegisterType((*Mixin)(nil), "google.protobuf.Mixin")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/api.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 408 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x92, 0xd1, 0x4e, 0xc2, 0x30,
|
||||
0x14, 0x86, 0xb3, 0x0d, 0x06, 0x96, 0x08, 0x5a, 0x13, 0x9d, 0x5c, 0x10, 0x42, 0xbc, 0x58, 0x34,
|
||||
0x6e, 0x11, 0x9f, 0x40, 0x8c, 0xe1, 0x82, 0x18, 0x97, 0xa1, 0xf1, 0x92, 0x0c, 0xac, 0xb8, 0x64,
|
||||
0x5b, 0x67, 0xdb, 0x29, 0xbc, 0x8d, 0xf1, 0xd2, 0x4b, 0xdf, 0xc0, 0x37, 0xb3, 0xeb, 0x56, 0xc0,
|
||||
0x81, 0x89, 0xde, 0xf5, 0x9c, 0xff, 0xeb, 0xdf, 0x73, 0xfe, 0x0d, 0x1c, 0x4e, 0x31, 0x9e, 0x06,
|
||||
0xc8, 0x8e, 0x09, 0x66, 0x78, 0x9c, 0x3c, 0xda, 0x5e, 0xec, 0x5b, 0xa2, 0x80, 0x8d, 0x4c, 0xb2,
|
||||
0xa4, 0xd4, 0x3c, 0x2a, 0xb2, 0x14, 0x27, 0x64, 0x82, 0x46, 0x13, 0x1c, 0x31, 0x34, 0x63, 0x19,
|
||||
0xd8, 0x6c, 0x16, 0x29, 0x36, 0x8f, 0x73, 0x93, 0xce, 0x97, 0x0a, 0xb4, 0x8b, 0xd8, 0x87, 0x10,
|
||||
0x94, 0x22, 0x2f, 0x44, 0x86, 0xd2, 0x56, 0xcc, 0x2d, 0x57, 0x9c, 0xe1, 0x19, 0xa8, 0x84, 0x88,
|
||||
0x3d, 0xe1, 0x07, 0x6a, 0xa8, 0x6d, 0xcd, 0xac, 0x75, 0x0f, 0xac, 0xc2, 0x00, 0xd6, 0xb5, 0xd0,
|
||||
0x5d, 0xc9, 0xa5, 0x57, 0x70, 0xcc, 0x7c, 0x1c, 0x51, 0x43, 0xfb, 0xe5, 0xca, 0x8d, 0xd0, 0x5d,
|
||||
0xc9, 0x41, 0x03, 0x54, 0x5e, 0x10, 0xa1, 0xfc, 0x6c, 0x94, 0xc4, 0xe3, 0xb2, 0x84, 0x57, 0xa0,
|
||||
0xfe, 0x73, 0x1f, 0xa3, 0xcc, 0x81, 0x5a, 0xb7, 0xb5, 0xe6, 0x39, 0x14, 0xd8, 0x65, 0x46, 0xb9,
|
||||
0xdb, 0x74, 0xb5, 0x84, 0x16, 0xd0, 0x43, 0x7f, 0xe6, 0xf3, 0x91, 0x74, 0x31, 0xd2, 0xfe, 0xfa,
|
||||
0x16, 0xa9, 0xec, 0xe6, 0x14, 0xb4, 0x81, 0x4e, 0xe7, 0x11, 0xf3, 0x66, 0x46, 0x85, 0x3f, 0x57,
|
||||
0xdf, 0xb0, 0xc2, 0x50, 0xc8, 0x6e, 0x8e, 0x75, 0x3e, 0x55, 0xa0, 0x67, 0x41, 0x6c, 0x8c, 0xd1,
|
||||
0x04, 0x3b, 0x04, 0x3d, 0x27, 0x88, 0xb2, 0x51, 0x1a, 0xfc, 0x28, 0x21, 0x01, 0xcf, 0x33, 0xd5,
|
||||
0xeb, 0x79, 0xff, 0x96, 0xb7, 0xef, 0x48, 0x00, 0x4f, 0xc0, 0xae, 0x24, 0x29, 0x23, 0xc8, 0x0b,
|
||||
0xfd, 0x68, 0xca, 0x73, 0x54, 0xcc, 0xaa, 0x2b, 0x2d, 0x86, 0xb2, 0x0f, 0x8f, 0x53, 0x98, 0xc6,
|
||||
0x3c, 0x42, 0xb4, 0xf4, 0xcd, 0x12, 0x6c, 0x48, 0x41, 0x1a, 0x9f, 0x02, 0xb8, 0x60, 0x97, 0xce,
|
||||
0x65, 0xe1, 0xbc, 0x70, 0x59, 0x5a, 0xaf, 0x7c, 0x45, 0xfd, 0x8f, 0x5f, 0xf1, 0xdf, 0xa1, 0xd9,
|
||||
0xa0, 0x2c, 0x62, 0xdf, 0x18, 0x19, 0xef, 0x11, 0x8c, 0x59, 0x1e, 0x93, 0x38, 0xf7, 0x06, 0x60,
|
||||
0x6f, 0x82, 0xc3, 0xa2, 0x6d, 0xaf, 0xca, 0xff, 0x5e, 0x27, 0x2d, 0x1c, 0xe5, 0x4d, 0x51, 0xde,
|
||||
0x55, 0xad, 0xef, 0xf4, 0x3e, 0xd4, 0x56, 0x3f, 0xc3, 0x1c, 0xf9, 0xfa, 0x3d, 0x0a, 0x82, 0x41,
|
||||
0x84, 0x5f, 0xa3, 0x34, 0x12, 0x3a, 0xd6, 0xc5, 0xfd, 0xf3, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xa4, 0x45, 0xd6, 0xc6, 0x6d, 0x03, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/duration.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// A Duration represents a signed, fixed-length span of time represented
|
||||
// as a count of seconds and fractions of seconds at nanosecond
|
||||
// resolution. It is independent of any calendar and concepts like "day"
|
||||
// or "month". It is related to Timestamp in that the difference between
|
||||
// two Timestamp values is a Duration and it can be added or subtracted
|
||||
// from a Timestamp. Range is approximately +-10,000 years.
|
||||
//
|
||||
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Timestamp end = ...;
|
||||
// Duration duration = ...;
|
||||
//
|
||||
// duration.seconds = end.seconds - start.seconds;
|
||||
// duration.nanos = end.nanos - start.nanos;
|
||||
//
|
||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||
// duration.seconds += 1;
|
||||
// duration.nanos -= 1000000000;
|
||||
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
||||
// duration.seconds -= 1;
|
||||
// duration.nanos += 1000000000;
|
||||
// }
|
||||
//
|
||||
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Duration duration = ...;
|
||||
// Timestamp end = ...;
|
||||
//
|
||||
// end.seconds = start.seconds + duration.seconds;
|
||||
// end.nanos = start.nanos + duration.nanos;
|
||||
//
|
||||
// if (end.nanos < 0) {
|
||||
// end.seconds -= 1;
|
||||
// end.nanos += 1000000000;
|
||||
// } else if (end.nanos >= 1000000000) {
|
||||
// end.seconds += 1;
|
||||
// end.nanos -= 1000000000;
|
||||
// }
|
||||
//
|
||||
type Duration struct {
|
||||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||
// to +315,576,000,000 inclusive.
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||
// Signed fractions of a second at nanosecond resolution of the span
|
||||
// of time. Durations less than one second are represented with a 0
|
||||
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||
// of one second or more, a non-zero value for the `nanos` field must be
|
||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||
// to +999,999,999 inclusive.
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Duration) Reset() { *m = Duration{} }
|
||||
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||
func (*Duration) ProtoMessage() {}
|
||||
func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
|
||||
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor2) }
|
||||
|
||||
var fileDescriptor2 = []byte{
|
||||
// 161 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
||||
0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0x56,
|
||||
0x5c, 0x1c, 0x2e, 0x50, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0xc9, 0xf9, 0x79, 0x29, 0xc5,
|
||||
0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x5e, 0x62, 0x5e,
|
||||
0x7e, 0xb1, 0x04, 0x13, 0x50, 0x9c, 0x35, 0x08, 0xc2, 0x71, 0x0a, 0xe0, 0x12, 0x4e, 0xce, 0xcf,
|
||||
0xd5, 0x43, 0x33, 0xd2, 0x89, 0x17, 0x66, 0x60, 0x00, 0x48, 0x24, 0x80, 0x71, 0x01, 0x23, 0xe3,
|
||||
0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, 0xb5, 0x01, 0x50, 0xb5, 0x7a,
|
||||
0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c,
|
||||
0x60, 0x43, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xa9, 0x05, 0xfd, 0xc7, 0x00, 0x00,
|
||||
0x00,
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/empty.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// A generic empty message that you can re-use to avoid defining duplicated
|
||||
// empty messages in your APIs. A typical example is to use it as the request
|
||||
// or the response type of an API method. For instance:
|
||||
//
|
||||
// service Foo {
|
||||
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
// }
|
||||
//
|
||||
// The JSON representation for `Empty` is empty JSON object `{}`.
|
||||
type Empty struct {
|
||||
}
|
||||
|
||||
func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
|
||||
func (*Empty) XXX_WellKnownType() string { return "Empty" }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Empty)(nil), "google.protobuf.Empty")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/empty.proto", fileDescriptor3) }
|
||||
|
||||
var fileDescriptor3 = []byte{
|
||||
// 124 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcd, 0x2d, 0x28,
|
||||
0xa9, 0xd4, 0x03, 0x73, 0x85, 0xf8, 0x21, 0x92, 0x7a, 0x30, 0x49, 0x25, 0x76, 0x2e, 0x56, 0x57,
|
||||
0x90, 0xbc, 0x53, 0x00, 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0xbc, 0x13, 0x17, 0x58, 0x36,
|
||||
0x00, 0xc4, 0x0d, 0x60, 0x5c, 0xc0, 0xc8, 0xf8, 0x83, 0x91, 0x71, 0x11, 0x13, 0xb3, 0x7b, 0x80,
|
||||
0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xda, 0x00, 0xa8, 0x5a, 0xbd, 0xf0, 0xd4, 0x9c, 0x1c, 0xef,
|
||||
0xbc, 0xfc, 0xf2, 0xbc, 0x90, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0x21, 0xc6, 0x80, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xac, 0xca, 0x5b, 0xd0, 0x91, 0x00, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/field_mask.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// `FieldMask` represents a set of symbolic field paths, for example:
|
||||
//
|
||||
// paths: "f.a"
|
||||
// paths: "f.b.d"
|
||||
//
|
||||
// Here `f` represents a field in some root message, `a` and `b`
|
||||
// fields in the message found in `f`, and `d` a field found in the
|
||||
// message in `f.b`.
|
||||
//
|
||||
// Field masks are used to specify a subset of fields that should be
|
||||
// returned by a get operation or modified by an update operation.
|
||||
// Field masks also have a custom JSON encoding (see below).
|
||||
//
|
||||
// # Field Masks in Projections
|
||||
//
|
||||
// When used in the context of a projection, a response message or
|
||||
// sub-message is filtered by the API to only contain those fields as
|
||||
// specified in the mask. For example, if the mask in the previous
|
||||
// example is applied to a response message as follows:
|
||||
//
|
||||
// f {
|
||||
// a : 22
|
||||
// b {
|
||||
// d : 1
|
||||
// x : 2
|
||||
// }
|
||||
// y : 13
|
||||
// }
|
||||
// z: 8
|
||||
//
|
||||
// The result will not contain specific values for fields x,y and z
|
||||
// (their value will be set to the default, and omitted in proto text
|
||||
// output):
|
||||
//
|
||||
//
|
||||
// f {
|
||||
// a : 22
|
||||
// b {
|
||||
// d : 1
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// A repeated field is not allowed except at the last position of a
|
||||
// field mask.
|
||||
//
|
||||
// If a FieldMask object is not present in a get operation, the
|
||||
// operation applies to all fields (as if a FieldMask of all fields
|
||||
// had been specified).
|
||||
//
|
||||
// Note that a field mask does not necessarily applies to the
|
||||
// top-level response message. In case of a REST get operation, the
|
||||
// field mask applies directly to the response, but in case of a REST
|
||||
// list operation, the mask instead applies to each individual message
|
||||
// in the returned resource list. In case of a REST custom method,
|
||||
// other definitions may be used. Where the mask applies will be
|
||||
// clearly documented together with its declaration in the API. In
|
||||
// any case, the effect on the returned resource/resources is required
|
||||
// behavior for APIs.
|
||||
//
|
||||
// # Field Masks in Update Operations
|
||||
//
|
||||
// A field mask in update operations specifies which fields of the
|
||||
// targeted resource are going to be updated. The API is required
|
||||
// to only change the values of the fields as specified in the mask
|
||||
// and leave the others untouched. If a resource is passed in to
|
||||
// describe the updated values, the API ignores the values of all
|
||||
// fields not covered by the mask.
|
||||
//
|
||||
// In order to reset a field's value to the default, the field must
|
||||
// be in the mask and set to the default value in the provided resource.
|
||||
// Hence, in order to reset all fields of a resource, provide a default
|
||||
// instance of the resource and set all fields in the mask, or do
|
||||
// not provide a mask as described below.
|
||||
//
|
||||
// If a field mask is not present on update, the operation applies to
|
||||
// all fields (as if a field mask of all fields has been specified).
|
||||
// Note that in the presence of schema evolution, this may mean that
|
||||
// fields the client does not know and has therefore not filled into
|
||||
// the request will be reset to their default. If this is unwanted
|
||||
// behavior, a specific service may require a client to always specify
|
||||
// a field mask, producing an error if not.
|
||||
//
|
||||
// As with get operations, the location of the resource which
|
||||
// describes the updated values in the request message depends on the
|
||||
// operation kind. In any case, the effect of the field mask is
|
||||
// required to be honored by the API.
|
||||
//
|
||||
// ## Considerations for HTTP REST
|
||||
//
|
||||
// The HTTP kind of an update operation which uses a field mask must
|
||||
// be set to PATCH instead of PUT in order to satisfy HTTP semantics
|
||||
// (PUT must only be used for full updates).
|
||||
//
|
||||
// # JSON Encoding of Field Masks
|
||||
//
|
||||
// In JSON, a field mask is encoded as a single string where paths are
|
||||
// separated by a comma. Fields name in each path are converted
|
||||
// to/from lower-camel naming conventions.
|
||||
//
|
||||
// As an example, consider the following message declarations:
|
||||
//
|
||||
// message Profile {
|
||||
// User user = 1;
|
||||
// Photo photo = 2;
|
||||
// }
|
||||
// message User {
|
||||
// string display_name = 1;
|
||||
// string address = 2;
|
||||
// }
|
||||
//
|
||||
// In proto a field mask for `Profile` may look as such:
|
||||
//
|
||||
// mask {
|
||||
// paths: "user.display_name"
|
||||
// paths: "photo"
|
||||
// }
|
||||
//
|
||||
// In JSON, the same mask is represented as below:
|
||||
//
|
||||
// {
|
||||
// mask: "user.displayName,photo"
|
||||
// }
|
||||
//
|
||||
type FieldMask struct {
|
||||
// The set of field mask paths.
|
||||
Paths []string `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"`
|
||||
}
|
||||
|
||||
func (m *FieldMask) Reset() { *m = FieldMask{} }
|
||||
func (m *FieldMask) String() string { return proto.CompactTextString(m) }
|
||||
func (*FieldMask) ProtoMessage() {}
|
||||
func (*FieldMask) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*FieldMask)(nil), "google.protobuf.FieldMask")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/field_mask.proto", fileDescriptor4) }
|
||||
|
||||
var fileDescriptor4 = []byte{
|
||||
// 147 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcb, 0x4c, 0xcd,
|
||||
0x49, 0x89, 0xcf, 0x4d, 0x2c, 0xce, 0xd6, 0x03, 0x8b, 0x09, 0xf1, 0x43, 0x54, 0xe8, 0xc1, 0x54,
|
||||
0x28, 0x29, 0x72, 0x71, 0xba, 0x81, 0x14, 0xf9, 0x02, 0xd5, 0x08, 0x89, 0x70, 0xb1, 0x16, 0x24,
|
||||
0x96, 0x64, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x06, 0x41, 0x38, 0x4e, 0x81, 0x5c, 0xc2,
|
||||
0xc9, 0xf9, 0xb9, 0x7a, 0x68, 0x3a, 0x9d, 0xf8, 0xe0, 0xfa, 0x02, 0x40, 0x42, 0x01, 0x8c, 0x0b,
|
||||
0x18, 0x19, 0x17, 0x31, 0x31, 0xbb, 0x07, 0x38, 0xad, 0x62, 0x92, 0x73, 0x87, 0x28, 0x0e, 0x80,
|
||||
0x2a, 0xd6, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0xa9, 0x2c, 0x48, 0x2d,
|
||||
0x4e, 0x62, 0x03, 0x9b, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x21, 0xb1, 0xe8, 0x01, 0xb1,
|
||||
0x00, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package google_protobuf
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// EmptyInstance is an instance of Empty.
|
||||
EmptyInstance = &Empty{}
|
||||
)
|
||||
|
||||
// Now returns the current time as a protobuf Timestamp.
|
||||
func Now() *Timestamp {
|
||||
return TimeToProto(time.Now().UTC())
|
||||
}
|
||||
|
||||
// TimeToProto converts a go Time to a protobuf Timestamp.
|
||||
func TimeToProto(t time.Time) *Timestamp {
|
||||
return &Timestamp{
|
||||
Seconds: t.UnixNano() / int64(time.Second),
|
||||
Nanos: int32(t.UnixNano() % int64(time.Second)),
|
||||
}
|
||||
}
|
||||
|
||||
// GoTime converts a protobuf Timestamp to a go Time.
|
||||
func (t *Timestamp) GoTime() time.Time {
|
||||
if t == nil {
|
||||
return time.Unix(0, 0).UTC()
|
||||
}
|
||||
return time.Unix(
|
||||
t.Seconds,
|
||||
int64(t.Nanos),
|
||||
).UTC()
|
||||
}
|
||||
|
||||
// Before returns true if t is before j.
|
||||
func (t *Timestamp) Before(j *Timestamp) bool {
|
||||
if j == nil {
|
||||
return false
|
||||
}
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
if t.Seconds < j.Seconds {
|
||||
return true
|
||||
}
|
||||
if t.Seconds > j.Seconds {
|
||||
return false
|
||||
}
|
||||
return t.Nanos < j.Nanos
|
||||
}
|
||||
|
||||
// DurationToProto converts a go Duration to a protobuf Duration.
|
||||
func DurationToProto(d time.Duration) *Duration {
|
||||
return &Duration{
|
||||
Seconds: int64(d) / int64(time.Second),
|
||||
Nanos: int32(int64(d) % int64(time.Second)),
|
||||
}
|
||||
}
|
||||
|
||||
// GoDuration converts a protobuf Duration to a go Duration.
|
||||
func (d *Duration) GoDuration() time.Duration {
|
||||
if d == nil {
|
||||
return 0
|
||||
}
|
||||
return time.Duration((d.Seconds * int64(time.Second)) + int64(d.Nanos))
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/source_context.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// `SourceContext` represents information about the source of a
|
||||
// protobuf element, like the file in which it is defined.
|
||||
type SourceContext struct {
|
||||
// The path-qualified name of the .proto file that contained the associated
|
||||
// protobuf element. For example: `"google/protobuf/source.proto"`.
|
||||
FileName string `protobuf:"bytes,1,opt,name=file_name,json=fileName" json:"file_name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SourceContext) Reset() { *m = SourceContext{} }
|
||||
func (m *SourceContext) String() string { return proto.CompactTextString(m) }
|
||||
func (*SourceContext) ProtoMessage() {}
|
||||
func (*SourceContext) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SourceContext)(nil), "google.protobuf.SourceContext")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/source_context.proto", fileDescriptor5) }
|
||||
|
||||
var fileDescriptor5 = []byte{
|
||||
// 159 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x49, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xce, 0x2f, 0x2d,
|
||||
0x4a, 0x4e, 0x8d, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xad, 0x28, 0xd1, 0x03, 0x8b, 0x0b, 0xf1, 0x43,
|
||||
0x54, 0xe9, 0xc1, 0x54, 0x29, 0xe9, 0x70, 0xf1, 0x06, 0x83, 0x15, 0x3a, 0x43, 0xd4, 0x09, 0x49,
|
||||
0x73, 0x71, 0xa6, 0x65, 0xe6, 0xa4, 0xc6, 0xe7, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a,
|
||||
0x70, 0x06, 0x71, 0x80, 0x04, 0xfc, 0x80, 0x7c, 0xa7, 0x50, 0x2e, 0xe1, 0xe4, 0xfc, 0x5c, 0x3d,
|
||||
0x34, 0x43, 0x9c, 0x84, 0x50, 0x8c, 0x08, 0x00, 0x09, 0x07, 0x30, 0x2e, 0x60, 0x64, 0x5c, 0xc4,
|
||||
0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0xa2, 0x21, 0x00, 0xaa, 0x41, 0x2f, 0x3c,
|
||||
0x35, 0x27, 0xc7, 0x3b, 0x2f, 0xbf, 0x3c, 0x2f, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x6c,
|
||||
0x92, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x80, 0x1f, 0xc2, 0xc4, 0x00, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/struct.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// `NullValue` is a singleton enumeration to represent the null value for the
|
||||
// `Value` type union.
|
||||
//
|
||||
// The JSON representation for `NullValue` is JSON `null`.
|
||||
type NullValue int32
|
||||
|
||||
const (
|
||||
// Null value.
|
||||
NullValue_NULL_VALUE NullValue = 0
|
||||
)
|
||||
|
||||
var NullValue_name = map[int32]string{
|
||||
0: "NULL_VALUE",
|
||||
}
|
||||
var NullValue_value = map[string]int32{
|
||||
"NULL_VALUE": 0,
|
||||
}
|
||||
|
||||
func (x NullValue) String() string {
|
||||
return proto.EnumName(NullValue_name, int32(x))
|
||||
}
|
||||
func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptor6, []int{0} }
|
||||
func (NullValue) XXX_WellKnownType() string { return "NullValue" }
|
||||
|
||||
// `Struct` represents a structured data value, consisting of fields
|
||||
// which map to dynamically typed values. In some languages, `Struct`
|
||||
// might be supported by a native representation. For example, in
|
||||
// scripting languages like JS a struct is represented as an
|
||||
// object. The details of that representation are described together
|
||||
// with the proto support for the language.
|
||||
//
|
||||
// The JSON representation for `Struct` is JSON object.
|
||||
type Struct struct {
|
||||
// Map of dynamically typed values.
|
||||
Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Struct) Reset() { *m = Struct{} }
|
||||
func (m *Struct) String() string { return proto.CompactTextString(m) }
|
||||
func (*Struct) ProtoMessage() {}
|
||||
func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} }
|
||||
func (*Struct) XXX_WellKnownType() string { return "Struct" }
|
||||
|
||||
func (m *Struct) GetFields() map[string]*Value {
|
||||
if m != nil {
|
||||
return m.Fields
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// `Value` represents a dynamically typed value which can be either
|
||||
// null, a number, a string, a boolean, a recursive struct value, or a
|
||||
// list of values. A producer of value is expected to set one of that
|
||||
// variants, absence of any variant indicates an error.
|
||||
//
|
||||
// The JSON representation for `Value` is JSON value.
|
||||
type Value struct {
|
||||
// The kind of value.
|
||||
//
|
||||
// Types that are valid to be assigned to Kind:
|
||||
// *Value_NullValue
|
||||
// *Value_NumberValue
|
||||
// *Value_StringValue
|
||||
// *Value_BoolValue
|
||||
// *Value_StructValue
|
||||
// *Value_ListValue
|
||||
Kind isValue_Kind `protobuf_oneof:"kind"`
|
||||
}
|
||||
|
||||
func (m *Value) Reset() { *m = Value{} }
|
||||
func (m *Value) String() string { return proto.CompactTextString(m) }
|
||||
func (*Value) ProtoMessage() {}
|
||||
func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} }
|
||||
func (*Value) XXX_WellKnownType() string { return "Value" }
|
||||
|
||||
type isValue_Kind interface {
|
||||
isValue_Kind()
|
||||
}
|
||||
|
||||
type Value_NullValue struct {
|
||||
NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,enum=google.protobuf.NullValue,oneof"`
|
||||
}
|
||||
type Value_NumberValue struct {
|
||||
NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,oneof"`
|
||||
}
|
||||
type Value_StringValue struct {
|
||||
StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,oneof"`
|
||||
}
|
||||
type Value_BoolValue struct {
|
||||
BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,oneof"`
|
||||
}
|
||||
type Value_StructValue struct {
|
||||
StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,oneof"`
|
||||
}
|
||||
type Value_ListValue struct {
|
||||
ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,oneof"`
|
||||
}
|
||||
|
||||
func (*Value_NullValue) isValue_Kind() {}
|
||||
func (*Value_NumberValue) isValue_Kind() {}
|
||||
func (*Value_StringValue) isValue_Kind() {}
|
||||
func (*Value_BoolValue) isValue_Kind() {}
|
||||
func (*Value_StructValue) isValue_Kind() {}
|
||||
func (*Value_ListValue) isValue_Kind() {}
|
||||
|
||||
func (m *Value) GetKind() isValue_Kind {
|
||||
if m != nil {
|
||||
return m.Kind
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Value) GetNullValue() NullValue {
|
||||
if x, ok := m.GetKind().(*Value_NullValue); ok {
|
||||
return x.NullValue
|
||||
}
|
||||
return NullValue_NULL_VALUE
|
||||
}
|
||||
|
||||
func (m *Value) GetNumberValue() float64 {
|
||||
if x, ok := m.GetKind().(*Value_NumberValue); ok {
|
||||
return x.NumberValue
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Value) GetStringValue() string {
|
||||
if x, ok := m.GetKind().(*Value_StringValue); ok {
|
||||
return x.StringValue
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Value) GetBoolValue() bool {
|
||||
if x, ok := m.GetKind().(*Value_BoolValue); ok {
|
||||
return x.BoolValue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Value) GetStructValue() *Struct {
|
||||
if x, ok := m.GetKind().(*Value_StructValue); ok {
|
||||
return x.StructValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Value) GetListValue() *ListValue {
|
||||
if x, ok := m.GetKind().(*Value_ListValue); ok {
|
||||
return x.ListValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// XXX_OneofFuncs is for the internal use of the proto package.
|
||||
func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
||||
return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{
|
||||
(*Value_NullValue)(nil),
|
||||
(*Value_NumberValue)(nil),
|
||||
(*Value_StringValue)(nil),
|
||||
(*Value_BoolValue)(nil),
|
||||
(*Value_StructValue)(nil),
|
||||
(*Value_ListValue)(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
|
||||
m := msg.(*Value)
|
||||
// kind
|
||||
switch x := m.Kind.(type) {
|
||||
case *Value_NullValue:
|
||||
b.EncodeVarint(1<<3 | proto.WireVarint)
|
||||
b.EncodeVarint(uint64(x.NullValue))
|
||||
case *Value_NumberValue:
|
||||
b.EncodeVarint(2<<3 | proto.WireFixed64)
|
||||
b.EncodeFixed64(math.Float64bits(x.NumberValue))
|
||||
case *Value_StringValue:
|
||||
b.EncodeVarint(3<<3 | proto.WireBytes)
|
||||
b.EncodeStringBytes(x.StringValue)
|
||||
case *Value_BoolValue:
|
||||
t := uint64(0)
|
||||
if x.BoolValue {
|
||||
t = 1
|
||||
}
|
||||
b.EncodeVarint(4<<3 | proto.WireVarint)
|
||||
b.EncodeVarint(t)
|
||||
case *Value_StructValue:
|
||||
b.EncodeVarint(5<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.StructValue); err != nil {
|
||||
return err
|
||||
}
|
||||
case *Value_ListValue:
|
||||
b.EncodeVarint(6<<3 | proto.WireBytes)
|
||||
if err := b.EncodeMessage(x.ListValue); err != nil {
|
||||
return err
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
return fmt.Errorf("Value.Kind has unexpected type %T", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
|
||||
m := msg.(*Value)
|
||||
switch tag {
|
||||
case 1: // kind.null_value
|
||||
if wire != proto.WireVarint {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeVarint()
|
||||
m.Kind = &Value_NullValue{NullValue(x)}
|
||||
return true, err
|
||||
case 2: // kind.number_value
|
||||
if wire != proto.WireFixed64 {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeFixed64()
|
||||
m.Kind = &Value_NumberValue{math.Float64frombits(x)}
|
||||
return true, err
|
||||
case 3: // kind.string_value
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeStringBytes()
|
||||
m.Kind = &Value_StringValue{x}
|
||||
return true, err
|
||||
case 4: // kind.bool_value
|
||||
if wire != proto.WireVarint {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeVarint()
|
||||
m.Kind = &Value_BoolValue{x != 0}
|
||||
return true, err
|
||||
case 5: // kind.struct_value
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(Struct)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Kind = &Value_StructValue{msg}
|
||||
return true, err
|
||||
case 6: // kind.list_value
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
msg := new(ListValue)
|
||||
err := b.DecodeMessage(msg)
|
||||
m.Kind = &Value_ListValue{msg}
|
||||
return true, err
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func _Value_OneofSizer(msg proto.Message) (n int) {
|
||||
m := msg.(*Value)
|
||||
// kind
|
||||
switch x := m.Kind.(type) {
|
||||
case *Value_NullValue:
|
||||
n += proto.SizeVarint(1<<3 | proto.WireVarint)
|
||||
n += proto.SizeVarint(uint64(x.NullValue))
|
||||
case *Value_NumberValue:
|
||||
n += proto.SizeVarint(2<<3 | proto.WireFixed64)
|
||||
n += 8
|
||||
case *Value_StringValue:
|
||||
n += proto.SizeVarint(3<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(len(x.StringValue)))
|
||||
n += len(x.StringValue)
|
||||
case *Value_BoolValue:
|
||||
n += proto.SizeVarint(4<<3 | proto.WireVarint)
|
||||
n += 1
|
||||
case *Value_StructValue:
|
||||
s := proto.Size(x.StructValue)
|
||||
n += proto.SizeVarint(5<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case *Value_ListValue:
|
||||
s := proto.Size(x.ListValue)
|
||||
n += proto.SizeVarint(6<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(s))
|
||||
n += s
|
||||
case nil:
|
||||
default:
|
||||
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// `ListValue` is a wrapper around a repeated field of values.
|
||||
//
|
||||
// The JSON representation for `ListValue` is JSON array.
|
||||
type ListValue struct {
|
||||
// Repeated field of dynamically typed values.
|
||||
Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ListValue) Reset() { *m = ListValue{} }
|
||||
func (m *ListValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListValue) ProtoMessage() {}
|
||||
func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} }
|
||||
func (*ListValue) XXX_WellKnownType() string { return "ListValue" }
|
||||
|
||||
func (m *ListValue) GetValues() []*Value {
|
||||
if m != nil {
|
||||
return m.Values
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Struct)(nil), "google.protobuf.Struct")
|
||||
proto.RegisterType((*Value)(nil), "google.protobuf.Value")
|
||||
proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue")
|
||||
proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/struct.proto", fileDescriptor6) }
|
||||
|
||||
var fileDescriptor6 = []byte{
|
||||
// 378 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x91, 0x4b, 0x4f, 0xe2, 0x50,
|
||||
0x14, 0xc7, 0xb9, 0x2d, 0x34, 0xd3, 0xd3, 0x09, 0x43, 0x3a, 0xc9, 0x0c, 0x61, 0x26, 0x6a, 0x60,
|
||||
0x43, 0x8c, 0x29, 0x09, 0x6e, 0x8c, 0xb8, 0xb1, 0x09, 0x62, 0x62, 0x43, 0x6a, 0x15, 0x5c, 0x12,
|
||||
0x0b, 0x85, 0x34, 0x5c, 0xee, 0x25, 0x7d, 0x68, 0xf8, 0x26, 0x2e, 0x8d, 0x4b, 0x97, 0x7e, 0x42,
|
||||
0xef, 0xa3, 0xad, 0x06, 0xc2, 0xee, 0x9e, 0xff, 0xf9, 0x9d, 0xff, 0x79, 0x5c, 0xf8, 0xbf, 0xa0,
|
||||
0x74, 0x81, 0x83, 0xce, 0x3a, 0xa2, 0x09, 0xf5, 0xd3, 0x79, 0x27, 0x4e, 0xa2, 0x74, 0x9a, 0x58,
|
||||
0x22, 0x36, 0x7f, 0xc9, 0xac, 0x95, 0x67, 0x9b, 0x2f, 0x08, 0xb4, 0x3b, 0x41, 0x98, 0x3d, 0xd0,
|
||||
0xe6, 0x61, 0x80, 0x67, 0x71, 0x1d, 0x1d, 0xa9, 0x6d, 0xa3, 0xdb, 0xb2, 0xb6, 0x60, 0x4b, 0x82,
|
||||
0xd6, 0x95, 0xa0, 0xfa, 0x24, 0x89, 0x36, 0x5e, 0x56, 0xd2, 0xb8, 0x05, 0xe3, 0x9b, 0x6c, 0xd6,
|
||||
0x40, 0x5d, 0x06, 0x1b, 0x66, 0x84, 0xda, 0xba, 0xc7, 0x9f, 0xe6, 0x09, 0x54, 0x9e, 0x1e, 0x71,
|
||||
0x1a, 0xd4, 0x15, 0xa6, 0x19, 0xdd, 0x3f, 0x3b, 0xe6, 0x63, 0x9e, 0xf5, 0x24, 0x74, 0xae, 0x9c,
|
||||
0xa1, 0xe6, 0x87, 0x02, 0x15, 0x21, 0xb2, 0xc9, 0x80, 0xa4, 0x18, 0x4f, 0xa4, 0x01, 0x37, 0xad,
|
||||
0x76, 0x1b, 0x3b, 0x06, 0x43, 0x86, 0x08, 0xfe, 0xba, 0xe4, 0xe9, 0x24, 0x0f, 0xcc, 0x16, 0xfc,
|
||||
0x24, 0xe9, 0xca, 0x0f, 0xa2, 0xc9, 0x57, 0x7f, 0xc4, 0x10, 0x43, 0xaa, 0x05, 0xc4, 0xee, 0x14,
|
||||
0x92, 0x45, 0x06, 0xa9, 0x7c, 0x70, 0x0e, 0x49, 0x55, 0x42, 0x87, 0x00, 0x3e, 0xa5, 0xf9, 0x18,
|
||||
0x65, 0x86, 0xfc, 0xe0, 0xad, 0xb8, 0x26, 0x81, 0x0b, 0xe1, 0xc2, 0x4e, 0x94, 0x21, 0x15, 0xb1,
|
||||
0xea, 0xdf, 0x3d, 0x77, 0xcc, 0xec, 0xd9, 0xab, 0xd8, 0x12, 0x87, 0x71, 0x5e, 0xab, 0x89, 0xda,
|
||||
0xdd, 0x2d, 0x1d, 0x86, 0x14, 0x5b, 0xe2, 0x3c, 0xb0, 0x35, 0x28, 0x2f, 0x43, 0x32, 0x6b, 0xf6,
|
||||
0x40, 0x2f, 0x08, 0xd3, 0x02, 0x4d, 0x98, 0xe5, 0x3f, 0xba, 0xef, 0xe8, 0x19, 0x75, 0xfc, 0x0f,
|
||||
0xf4, 0xe2, 0x88, 0x66, 0x15, 0x60, 0x38, 0x72, 0x9c, 0xc9, 0xf8, 0xd2, 0x19, 0xf5, 0x6b, 0x25,
|
||||
0x7b, 0x08, 0xbf, 0xa7, 0x74, 0xb5, 0xed, 0x60, 0x1b, 0x72, 0x19, 0x97, 0xc7, 0x2e, 0x7a, 0x45,
|
||||
0xe8, 0x4d, 0x51, 0x07, 0xae, 0xfd, 0xae, 0x1c, 0x0c, 0x24, 0xe9, 0xe6, 0xbd, 0x1e, 0x02, 0x8c,
|
||||
0x6f, 0x08, 0x7d, 0x26, 0xf7, 0x9b, 0x75, 0x10, 0xfb, 0x9a, 0xb0, 0x38, 0xfd, 0x0c, 0x00, 0x00,
|
||||
0xff, 0xff, 0x08, 0x22, 0x4f, 0xb6, 0xb1, 0x02, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/timestamp.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// A Timestamp represents a point in time independent of any time zone
|
||||
// or calendar, represented as seconds and fractions of seconds at
|
||||
// nanosecond resolution in UTC Epoch time. It is encoded using the
|
||||
// Proleptic Gregorian Calendar which extends the Gregorian calendar
|
||||
// backwards to year one. It is encoded assuming all minutes are 60
|
||||
// seconds long, i.e. leap seconds are "smeared" so that no leap second
|
||||
// table is needed for interpretation. Range is from
|
||||
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
|
||||
// By restricting to that range, we ensure that we can convert to
|
||||
// and from RFC 3339 date strings.
|
||||
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
|
||||
//
|
||||
// Example 1: Compute Timestamp from POSIX `time()`.
|
||||
//
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds(time(NULL));
|
||||
// timestamp.set_nanos(0);
|
||||
//
|
||||
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||
//
|
||||
// struct timeval tv;
|
||||
// gettimeofday(&tv, NULL);
|
||||
//
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds(tv.tv_sec);
|
||||
// timestamp.set_nanos(tv.tv_usec * 1000);
|
||||
//
|
||||
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||
//
|
||||
// FILETIME ft;
|
||||
// GetSystemTimeAsFileTime(&ft);
|
||||
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
//
|
||||
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||
//
|
||||
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||
//
|
||||
// long millis = System.currentTimeMillis();
|
||||
//
|
||||
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||
//
|
||||
//
|
||||
// Example 5: Compute Timestamp from current time in Python.
|
||||
//
|
||||
// now = time.time()
|
||||
// seconds = int(now)
|
||||
// nanos = int((now - seconds) * 10**9)
|
||||
// timestamp = Timestamp(seconds=seconds, nanos=nanos)
|
||||
//
|
||||
//
|
||||
type Timestamp struct {
|
||||
// Represents seconds of UTC time since Unix epoch
|
||||
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
|
||||
// 9999-12-31T23:59:59Z inclusive.
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||
// second values with fractions must still have non-negative nanos values
|
||||
// that count forward in time. Must be from 0 to 999,999,999
|
||||
// inclusive.
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor7, []int{0} }
|
||||
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor7) }
|
||||
|
||||
var fileDescriptor7 = []byte{
|
||||
// 165 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
||||
0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x03, 0x0b, 0x09, 0xf1, 0x43, 0x14, 0xe8, 0xc1, 0x14, 0x28,
|
||||
0x59, 0x73, 0x71, 0x86, 0xc0, 0xd4, 0x08, 0x49, 0x70, 0xb1, 0x17, 0xa7, 0x26, 0xe7, 0xe7, 0xa5,
|
||||
0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0xc1, 0xb8, 0x42, 0x22, 0x5c, 0xac, 0x79, 0x89,
|
||||
0x79, 0xf9, 0xc5, 0x12, 0x4c, 0x40, 0x71, 0xd6, 0x20, 0x08, 0xc7, 0x29, 0x84, 0x4b, 0x38, 0x39,
|
||||
0x3f, 0x57, 0x0f, 0xcd, 0x4c, 0x27, 0x3e, 0xb8, 0x89, 0x01, 0x20, 0xa1, 0x00, 0xc6, 0x05, 0x8c,
|
||||
0x8c, 0x3f, 0x18, 0x19, 0x17, 0x31, 0x31, 0xbb, 0x07, 0x38, 0xad, 0x62, 0x92, 0x73, 0x87, 0xa8,
|
||||
0x0f, 0x80, 0xaa, 0xd7, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0xa9, 0x2c,
|
||||
0x48, 0x2d, 0x4e, 0x62, 0x03, 0x1b, 0x64, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x10, 0x2f, 0xb9,
|
||||
0x47, 0xcd, 0x00, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/type.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// The syntax in which a protocol buffer element is defined.
|
||||
type Syntax int32
|
||||
|
||||
const (
|
||||
// Syntax `proto2`.
|
||||
Syntax_SYNTAX_PROTO2 Syntax = 0
|
||||
// Syntax `proto3`.
|
||||
Syntax_SYNTAX_PROTO3 Syntax = 1
|
||||
)
|
||||
|
||||
var Syntax_name = map[int32]string{
|
||||
0: "SYNTAX_PROTO2",
|
||||
1: "SYNTAX_PROTO3",
|
||||
}
|
||||
var Syntax_value = map[string]int32{
|
||||
"SYNTAX_PROTO2": 0,
|
||||
"SYNTAX_PROTO3": 1,
|
||||
}
|
||||
|
||||
func (x Syntax) String() string {
|
||||
return proto.EnumName(Syntax_name, int32(x))
|
||||
}
|
||||
func (Syntax) EnumDescriptor() ([]byte, []int) { return fileDescriptor8, []int{0} }
|
||||
|
||||
// Basic field types.
|
||||
type Field_Kind int32
|
||||
|
||||
const (
|
||||
// Field type unknown.
|
||||
Field_TYPE_UNKNOWN Field_Kind = 0
|
||||
// Field type double.
|
||||
Field_TYPE_DOUBLE Field_Kind = 1
|
||||
// Field type float.
|
||||
Field_TYPE_FLOAT Field_Kind = 2
|
||||
// Field type int64.
|
||||
Field_TYPE_INT64 Field_Kind = 3
|
||||
// Field type uint64.
|
||||
Field_TYPE_UINT64 Field_Kind = 4
|
||||
// Field type int32.
|
||||
Field_TYPE_INT32 Field_Kind = 5
|
||||
// Field type fixed64.
|
||||
Field_TYPE_FIXED64 Field_Kind = 6
|
||||
// Field type fixed32.
|
||||
Field_TYPE_FIXED32 Field_Kind = 7
|
||||
// Field type bool.
|
||||
Field_TYPE_BOOL Field_Kind = 8
|
||||
// Field type string.
|
||||
Field_TYPE_STRING Field_Kind = 9
|
||||
// Field type group. Proto2 syntax only, and deprecated.
|
||||
Field_TYPE_GROUP Field_Kind = 10
|
||||
// Field type message.
|
||||
Field_TYPE_MESSAGE Field_Kind = 11
|
||||
// Field type bytes.
|
||||
Field_TYPE_BYTES Field_Kind = 12
|
||||
// Field type uint32.
|
||||
Field_TYPE_UINT32 Field_Kind = 13
|
||||
// Field type enum.
|
||||
Field_TYPE_ENUM Field_Kind = 14
|
||||
// Field type sfixed32.
|
||||
Field_TYPE_SFIXED32 Field_Kind = 15
|
||||
// Field type sfixed64.
|
||||
Field_TYPE_SFIXED64 Field_Kind = 16
|
||||
// Field type sint32.
|
||||
Field_TYPE_SINT32 Field_Kind = 17
|
||||
// Field type sint64.
|
||||
Field_TYPE_SINT64 Field_Kind = 18
|
||||
)
|
||||
|
||||
var Field_Kind_name = map[int32]string{
|
||||
0: "TYPE_UNKNOWN",
|
||||
1: "TYPE_DOUBLE",
|
||||
2: "TYPE_FLOAT",
|
||||
3: "TYPE_INT64",
|
||||
4: "TYPE_UINT64",
|
||||
5: "TYPE_INT32",
|
||||
6: "TYPE_FIXED64",
|
||||
7: "TYPE_FIXED32",
|
||||
8: "TYPE_BOOL",
|
||||
9: "TYPE_STRING",
|
||||
10: "TYPE_GROUP",
|
||||
11: "TYPE_MESSAGE",
|
||||
12: "TYPE_BYTES",
|
||||
13: "TYPE_UINT32",
|
||||
14: "TYPE_ENUM",
|
||||
15: "TYPE_SFIXED32",
|
||||
16: "TYPE_SFIXED64",
|
||||
17: "TYPE_SINT32",
|
||||
18: "TYPE_SINT64",
|
||||
}
|
||||
var Field_Kind_value = map[string]int32{
|
||||
"TYPE_UNKNOWN": 0,
|
||||
"TYPE_DOUBLE": 1,
|
||||
"TYPE_FLOAT": 2,
|
||||
"TYPE_INT64": 3,
|
||||
"TYPE_UINT64": 4,
|
||||
"TYPE_INT32": 5,
|
||||
"TYPE_FIXED64": 6,
|
||||
"TYPE_FIXED32": 7,
|
||||
"TYPE_BOOL": 8,
|
||||
"TYPE_STRING": 9,
|
||||
"TYPE_GROUP": 10,
|
||||
"TYPE_MESSAGE": 11,
|
||||
"TYPE_BYTES": 12,
|
||||
"TYPE_UINT32": 13,
|
||||
"TYPE_ENUM": 14,
|
||||
"TYPE_SFIXED32": 15,
|
||||
"TYPE_SFIXED64": 16,
|
||||
"TYPE_SINT32": 17,
|
||||
"TYPE_SINT64": 18,
|
||||
}
|
||||
|
||||
func (x Field_Kind) String() string {
|
||||
return proto.EnumName(Field_Kind_name, int32(x))
|
||||
}
|
||||
func (Field_Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptor8, []int{1, 0} }
|
||||
|
||||
// Whether a field is optional, required, or repeated.
|
||||
type Field_Cardinality int32
|
||||
|
||||
const (
|
||||
// For fields with unknown cardinality.
|
||||
Field_CARDINALITY_UNKNOWN Field_Cardinality = 0
|
||||
// For optional fields.
|
||||
Field_CARDINALITY_OPTIONAL Field_Cardinality = 1
|
||||
// For required fields. Proto2 syntax only.
|
||||
Field_CARDINALITY_REQUIRED Field_Cardinality = 2
|
||||
// For repeated fields.
|
||||
Field_CARDINALITY_REPEATED Field_Cardinality = 3
|
||||
)
|
||||
|
||||
var Field_Cardinality_name = map[int32]string{
|
||||
0: "CARDINALITY_UNKNOWN",
|
||||
1: "CARDINALITY_OPTIONAL",
|
||||
2: "CARDINALITY_REQUIRED",
|
||||
3: "CARDINALITY_REPEATED",
|
||||
}
|
||||
var Field_Cardinality_value = map[string]int32{
|
||||
"CARDINALITY_UNKNOWN": 0,
|
||||
"CARDINALITY_OPTIONAL": 1,
|
||||
"CARDINALITY_REQUIRED": 2,
|
||||
"CARDINALITY_REPEATED": 3,
|
||||
}
|
||||
|
||||
func (x Field_Cardinality) String() string {
|
||||
return proto.EnumName(Field_Cardinality_name, int32(x))
|
||||
}
|
||||
func (Field_Cardinality) EnumDescriptor() ([]byte, []int) { return fileDescriptor8, []int{1, 1} }
|
||||
|
||||
// A protocol buffer message type.
|
||||
type Type struct {
|
||||
// The fully qualified message name.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// The list of fields.
|
||||
Fields []*Field `protobuf:"bytes,2,rep,name=fields" json:"fields,omitempty"`
|
||||
// The list of types appearing in `oneof` definitions in this type.
|
||||
Oneofs []string `protobuf:"bytes,3,rep,name=oneofs" json:"oneofs,omitempty"`
|
||||
// The protocol buffer options.
|
||||
Options []*Option `protobuf:"bytes,4,rep,name=options" json:"options,omitempty"`
|
||||
// The source context.
|
||||
SourceContext *SourceContext `protobuf:"bytes,5,opt,name=source_context,json=sourceContext" json:"source_context,omitempty"`
|
||||
// The source syntax.
|
||||
Syntax Syntax `protobuf:"varint,6,opt,name=syntax,enum=google.protobuf.Syntax" json:"syntax,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Type) Reset() { *m = Type{} }
|
||||
func (m *Type) String() string { return proto.CompactTextString(m) }
|
||||
func (*Type) ProtoMessage() {}
|
||||
func (*Type) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{0} }
|
||||
|
||||
func (m *Type) GetFields() []*Field {
|
||||
if m != nil {
|
||||
return m.Fields
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Type) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Type) GetSourceContext() *SourceContext {
|
||||
if m != nil {
|
||||
return m.SourceContext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A single field of a message type.
|
||||
type Field struct {
|
||||
// The field type.
|
||||
Kind Field_Kind `protobuf:"varint,1,opt,name=kind,enum=google.protobuf.Field_Kind" json:"kind,omitempty"`
|
||||
// The field cardinality.
|
||||
Cardinality Field_Cardinality `protobuf:"varint,2,opt,name=cardinality,enum=google.protobuf.Field_Cardinality" json:"cardinality,omitempty"`
|
||||
// The field number.
|
||||
Number int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"`
|
||||
// The field name.
|
||||
Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"`
|
||||
// The field type URL, without the scheme, for message or enumeration
|
||||
// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
|
||||
TypeUrl string `protobuf:"bytes,6,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
|
||||
// The index of the field type in `Type.oneofs`, for message or enumeration
|
||||
// types. The first type has index 1; zero means the type is not in the list.
|
||||
OneofIndex int32 `protobuf:"varint,7,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"`
|
||||
// Whether to use alternative packed wire representation.
|
||||
Packed bool `protobuf:"varint,8,opt,name=packed" json:"packed,omitempty"`
|
||||
// The protocol buffer options.
|
||||
Options []*Option `protobuf:"bytes,9,rep,name=options" json:"options,omitempty"`
|
||||
// The field JSON name.
|
||||
JsonName string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"`
|
||||
// The string value of the default value of this field. Proto2 syntax only.
|
||||
DefaultValue string `protobuf:"bytes,11,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Field) Reset() { *m = Field{} }
|
||||
func (m *Field) String() string { return proto.CompactTextString(m) }
|
||||
func (*Field) ProtoMessage() {}
|
||||
func (*Field) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{1} }
|
||||
|
||||
func (m *Field) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enum type definition.
|
||||
type Enum struct {
|
||||
// Enum type name.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// Enum value definitions.
|
||||
Enumvalue []*EnumValue `protobuf:"bytes,2,rep,name=enumvalue" json:"enumvalue,omitempty"`
|
||||
// Protocol buffer options.
|
||||
Options []*Option `protobuf:"bytes,3,rep,name=options" json:"options,omitempty"`
|
||||
// The source context.
|
||||
SourceContext *SourceContext `protobuf:"bytes,4,opt,name=source_context,json=sourceContext" json:"source_context,omitempty"`
|
||||
// The source syntax.
|
||||
Syntax Syntax `protobuf:"varint,5,opt,name=syntax,enum=google.protobuf.Syntax" json:"syntax,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Enum) Reset() { *m = Enum{} }
|
||||
func (m *Enum) String() string { return proto.CompactTextString(m) }
|
||||
func (*Enum) ProtoMessage() {}
|
||||
func (*Enum) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{2} }
|
||||
|
||||
func (m *Enum) GetEnumvalue() []*EnumValue {
|
||||
if m != nil {
|
||||
return m.Enumvalue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Enum) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Enum) GetSourceContext() *SourceContext {
|
||||
if m != nil {
|
||||
return m.SourceContext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enum value definition.
|
||||
type EnumValue struct {
|
||||
// Enum value name.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// Enum value number.
|
||||
Number int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"`
|
||||
// Protocol buffer options.
|
||||
Options []*Option `protobuf:"bytes,3,rep,name=options" json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EnumValue) Reset() { *m = EnumValue{} }
|
||||
func (m *EnumValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*EnumValue) ProtoMessage() {}
|
||||
func (*EnumValue) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{3} }
|
||||
|
||||
func (m *EnumValue) GetOptions() []*Option {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A protocol buffer option, which can be attached to a message, field,
|
||||
// enumeration, etc.
|
||||
type Option struct {
|
||||
// The option's name. For example, `"java_package"`.
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// The option's value. For example, `"com.google.protobuf"`.
|
||||
Value *Any `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Option) Reset() { *m = Option{} }
|
||||
func (m *Option) String() string { return proto.CompactTextString(m) }
|
||||
func (*Option) ProtoMessage() {}
|
||||
func (*Option) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{4} }
|
||||
|
||||
func (m *Option) GetValue() *Any {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Type)(nil), "google.protobuf.Type")
|
||||
proto.RegisterType((*Field)(nil), "google.protobuf.Field")
|
||||
proto.RegisterType((*Enum)(nil), "google.protobuf.Enum")
|
||||
proto.RegisterType((*EnumValue)(nil), "google.protobuf.EnumValue")
|
||||
proto.RegisterType((*Option)(nil), "google.protobuf.Option")
|
||||
proto.RegisterEnum("google.protobuf.Syntax", Syntax_name, Syntax_value)
|
||||
proto.RegisterEnum("google.protobuf.Field_Kind", Field_Kind_name, Field_Kind_value)
|
||||
proto.RegisterEnum("google.protobuf.Field_Cardinality", Field_Cardinality_name, Field_Cardinality_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/type.proto", fileDescriptor8) }
|
||||
|
||||
var fileDescriptor8 = []byte{
|
||||
// 768 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x55, 0xcd, 0x6e, 0xda, 0x58,
|
||||
0x14, 0x1e, 0x83, 0x31, 0xf8, 0x38, 0x10, 0xe7, 0x26, 0x4a, 0x1c, 0x22, 0x65, 0x22, 0x66, 0x16,
|
||||
0x51, 0x16, 0x44, 0x43, 0x46, 0xa3, 0xd9, 0x42, 0x70, 0x18, 0x2b, 0xc4, 0xf6, 0x5c, 0x4c, 0x13,
|
||||
0x56, 0xc8, 0x01, 0x13, 0x91, 0x38, 0x36, 0xc2, 0xa6, 0x0d, 0x0f, 0xd1, 0x77, 0xa8, 0xba, 0xec,
|
||||
0xba, 0x0f, 0xd1, 0xb7, 0x6a, 0xef, 0xbd, 0x06, 0x63, 0x7e, 0x2a, 0xa5, 0xed, 0x8e, 0xf3, 0x7d,
|
||||
0xdf, 0xf9, 0xbd, 0xc7, 0x07, 0x28, 0x3e, 0xf8, 0xfe, 0x83, 0xeb, 0x9c, 0x8f, 0xc6, 0x7e, 0xe8,
|
||||
0xdf, 0x4f, 0x06, 0xe7, 0xe1, 0x74, 0xe4, 0x94, 0x99, 0x85, 0xb6, 0x23, 0xae, 0x3c, 0xe7, 0x8a,
|
||||
0x87, 0xab, 0x62, 0xdb, 0x9b, 0x46, 0x6c, 0xf1, 0xcf, 0x55, 0x2a, 0xf0, 0x27, 0xe3, 0x9e, 0xd3,
|
||||
0xed, 0xf9, 0x5e, 0xe8, 0xbc, 0x84, 0x91, 0xaa, 0xf4, 0x3e, 0x05, 0xbc, 0x45, 0x12, 0x20, 0x04,
|
||||
0xbc, 0x67, 0x3f, 0x3b, 0x0a, 0x77, 0xc2, 0x9d, 0x8a, 0x98, 0xfd, 0x46, 0x65, 0x10, 0x06, 0x43,
|
||||
0xc7, 0xed, 0x07, 0x4a, 0xea, 0x24, 0x7d, 0x2a, 0x55, 0xf6, 0xcb, 0x2b, 0xf9, 0xcb, 0x57, 0x94,
|
||||
0xc6, 0x33, 0x15, 0xda, 0x07, 0xc1, 0xf7, 0x1c, 0x7f, 0x10, 0x28, 0x69, 0xa2, 0x17, 0xf1, 0xcc,
|
||||
0x42, 0x7f, 0x41, 0xd6, 0x1f, 0x85, 0x43, 0xdf, 0x0b, 0x14, 0x9e, 0x05, 0x3a, 0x58, 0x0b, 0x64,
|
||||
0x30, 0x1e, 0xcf, 0x75, 0x48, 0x85, 0xc2, 0x72, 0xbd, 0x4a, 0x86, 0x14, 0x26, 0x55, 0x8e, 0xd7,
|
||||
0x3c, 0x5b, 0x4c, 0x76, 0x19, 0xa9, 0x70, 0x3e, 0x48, 0x9a, 0xe8, 0x1c, 0x84, 0x60, 0xea, 0x85,
|
||||
0xf6, 0x8b, 0x22, 0x10, 0xf7, 0xc2, 0x86, 0xc4, 0x2d, 0x46, 0xe3, 0x99, 0xac, 0xf4, 0x59, 0x80,
|
||||
0x0c, 0x6b, 0x8a, 0xb8, 0xf2, 0x4f, 0x43, 0xaf, 0xcf, 0x06, 0x52, 0xa8, 0x1c, 0x6d, 0x6e, 0xbd,
|
||||
0x7c, 0x4d, 0x24, 0x98, 0x09, 0x51, 0x1d, 0xa4, 0x9e, 0x3d, 0xee, 0x0f, 0x3d, 0xdb, 0x1d, 0x86,
|
||||
0x53, 0x32, 0x32, 0xea, 0x57, 0xfa, 0x8e, 0xdf, 0xe5, 0x42, 0x89, 0x93, 0x6e, 0x74, 0x86, 0xde,
|
||||
0xe4, 0xf9, 0xde, 0x19, 0x93, 0x19, 0x72, 0xa7, 0x19, 0x3c, 0xb3, 0xe2, 0xf7, 0xe1, 0x13, 0xef,
|
||||
0x73, 0x08, 0x39, 0xba, 0x1c, 0xdd, 0xc9, 0xd8, 0x65, 0xfd, 0x89, 0x38, 0x4b, 0xed, 0xf6, 0xd8,
|
||||
0x45, 0xbf, 0x83, 0xc4, 0x86, 0xdf, 0x25, 0x95, 0x39, 0x2f, 0x4a, 0x96, 0xc5, 0x02, 0x06, 0x69,
|
||||
0x14, 0xa1, 0x79, 0x46, 0x76, 0xef, 0xc9, 0xe9, 0x2b, 0x39, 0xc2, 0xe5, 0xf0, 0xcc, 0x4a, 0xbe,
|
||||
0x95, 0xf8, 0xca, 0xb7, 0x3a, 0x02, 0xf1, 0x31, 0xf0, 0xbd, 0x2e, 0xab, 0x0f, 0x58, 0x1d, 0x39,
|
||||
0x0a, 0xe8, 0xb4, 0xc6, 0x3f, 0x20, 0xdf, 0x77, 0x06, 0xf6, 0xc4, 0x0d, 0xbb, 0x6f, 0x6d, 0x77,
|
||||
0xe2, 0x28, 0x12, 0x13, 0x6c, 0xcd, 0xc0, 0x37, 0x14, 0x2b, 0x7d, 0x21, 0x5b, 0x48, 0x27, 0x89,
|
||||
0x64, 0xd8, 0xb2, 0x3a, 0xa6, 0xda, 0x6d, 0xeb, 0xd7, 0xba, 0x71, 0xab, 0xcb, 0xbf, 0xa1, 0x6d,
|
||||
0x90, 0x18, 0x52, 0x37, 0xda, 0xb5, 0xa6, 0x2a, 0x73, 0xa8, 0x00, 0xc0, 0x80, 0xab, 0xa6, 0x51,
|
||||
0xb5, 0xe4, 0x54, 0x6c, 0x6b, 0xba, 0xf5, 0xcf, 0xdf, 0x72, 0x3a, 0x76, 0x68, 0x47, 0x00, 0x9f,
|
||||
0x14, 0x5c, 0x54, 0xe4, 0x4c, 0x9c, 0xe3, 0x4a, 0xbb, 0x53, 0xeb, 0x44, 0x21, 0x2c, 0x23, 0x44,
|
||||
0x93, 0x45, 0x79, 0x10, 0x19, 0x52, 0x33, 0x8c, 0xa6, 0x9c, 0x8b, 0x63, 0xb6, 0x2c, 0xac, 0xe9,
|
||||
0x0d, 0x59, 0x8c, 0x63, 0x36, 0xb0, 0xd1, 0x36, 0x65, 0x88, 0x23, 0xdc, 0xa8, 0xad, 0x56, 0xb5,
|
||||
0xa1, 0xca, 0x52, 0xac, 0xa8, 0x75, 0x2c, 0xb5, 0x25, 0x6f, 0x2d, 0x95, 0x45, 0x52, 0xe4, 0xe3,
|
||||
0x14, 0xaa, 0xde, 0xbe, 0x91, 0x0b, 0x68, 0x07, 0xf2, 0x51, 0x8a, 0x79, 0x11, 0xdb, 0x2b, 0x10,
|
||||
0xa9, 0x54, 0x5e, 0x14, 0x12, 0x45, 0xd9, 0x59, 0x02, 0x88, 0x02, 0x95, 0x42, 0x90, 0x12, 0xbb,
|
||||
0x85, 0x0e, 0x60, 0xf7, 0xb2, 0x8a, 0xeb, 0x9a, 0x5e, 0x6d, 0x6a, 0x56, 0x27, 0x31, 0x57, 0x05,
|
||||
0xf6, 0x92, 0x84, 0x61, 0x5a, 0x9a, 0x41, 0x7e, 0x93, 0x01, 0xaf, 0x30, 0x58, 0xfd, 0xbf, 0xad,
|
||||
0x61, 0xb5, 0x4e, 0x46, 0xbd, 0xc6, 0x98, 0x6a, 0xd5, 0x22, 0x4c, 0xba, 0xf4, 0x95, 0x03, 0x5e,
|
||||
0x25, 0x9b, 0xba, 0xf1, 0x8c, 0xfc, 0x0b, 0xa2, 0x43, 0xb8, 0xe8, 0xf9, 0xa3, 0x4b, 0x52, 0x5c,
|
||||
0x5b, 0x2a, 0xea, 0xcd, 0x96, 0x01, 0x2f, 0xc4, 0xc9, 0x65, 0x4c, 0xff, 0xf4, 0xe1, 0xe0, 0x7f,
|
||||
0xed, 0x70, 0x64, 0x5e, 0x77, 0x38, 0x1e, 0x41, 0x8c, 0x5b, 0xd8, 0x38, 0x85, 0xc5, 0x87, 0x9d,
|
||||
0x5a, 0xfa, 0xb0, 0x7f, 0xbc, 0xc7, 0xd2, 0x7f, 0x20, 0x44, 0xd0, 0xc6, 0x44, 0x67, 0x90, 0x99,
|
||||
0x8f, 0x9a, 0x36, 0xbe, 0xb7, 0x16, 0xae, 0xea, 0x4d, 0x71, 0x24, 0x39, 0x23, 0x17, 0x3e, 0xea,
|
||||
0x83, 0x2e, 0x5b, 0xab, 0xa3, 0x5b, 0xd5, 0xbb, 0xae, 0x89, 0x0d, 0xcb, 0xa8, 0x90, 0x15, 0x59,
|
||||
0x81, 0x2e, 0x64, 0xae, 0xd6, 0x84, 0xdd, 0x9e, 0xff, 0xbc, 0x1a, 0xb1, 0x26, 0xd2, 0xbf, 0x10,
|
||||
0x93, 0x5a, 0x26, 0xf7, 0x81, 0xe3, 0x3e, 0xa6, 0xd2, 0x0d, 0xb3, 0xf6, 0x29, 0x75, 0xdc, 0x88,
|
||||
0x74, 0xe6, 0x3c, 0xf3, 0xad, 0xe3, 0xba, 0xd7, 0x9e, 0xff, 0xce, 0xa3, 0xfa, 0xe0, 0x5e, 0x60,
|
||||
0x01, 0x2e, 0xbe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x95, 0xbb, 0xeb, 0x52, 0xf3, 0x06, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/wrappers.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// Wrapper message for `double`.
|
||||
//
|
||||
// The JSON representation for `DoubleValue` is JSON number.
|
||||
type DoubleValue struct {
|
||||
// The double value.
|
||||
Value float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DoubleValue) Reset() { *m = DoubleValue{} }
|
||||
func (m *DoubleValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*DoubleValue) ProtoMessage() {}
|
||||
func (*DoubleValue) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{0} }
|
||||
func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" }
|
||||
|
||||
// Wrapper message for `float`.
|
||||
//
|
||||
// The JSON representation for `FloatValue` is JSON number.
|
||||
type FloatValue struct {
|
||||
// The float value.
|
||||
Value float32 `protobuf:"fixed32,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *FloatValue) Reset() { *m = FloatValue{} }
|
||||
func (m *FloatValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*FloatValue) ProtoMessage() {}
|
||||
func (*FloatValue) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{1} }
|
||||
func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" }
|
||||
|
||||
// Wrapper message for `int64`.
|
||||
//
|
||||
// The JSON representation for `Int64Value` is JSON string.
|
||||
type Int64Value struct {
|
||||
// The int64 value.
|
||||
Value int64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Int64Value) Reset() { *m = Int64Value{} }
|
||||
func (m *Int64Value) String() string { return proto.CompactTextString(m) }
|
||||
func (*Int64Value) ProtoMessage() {}
|
||||
func (*Int64Value) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{2} }
|
||||
func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" }
|
||||
|
||||
// Wrapper message for `uint64`.
|
||||
//
|
||||
// The JSON representation for `UInt64Value` is JSON string.
|
||||
type UInt64Value struct {
|
||||
// The uint64 value.
|
||||
Value uint64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *UInt64Value) Reset() { *m = UInt64Value{} }
|
||||
func (m *UInt64Value) String() string { return proto.CompactTextString(m) }
|
||||
func (*UInt64Value) ProtoMessage() {}
|
||||
func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{3} }
|
||||
func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" }
|
||||
|
||||
// Wrapper message for `int32`.
|
||||
//
|
||||
// The JSON representation for `Int32Value` is JSON number.
|
||||
type Int32Value struct {
|
||||
// The int32 value.
|
||||
Value int32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Int32Value) Reset() { *m = Int32Value{} }
|
||||
func (m *Int32Value) String() string { return proto.CompactTextString(m) }
|
||||
func (*Int32Value) ProtoMessage() {}
|
||||
func (*Int32Value) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{4} }
|
||||
func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" }
|
||||
|
||||
// Wrapper message for `uint32`.
|
||||
//
|
||||
// The JSON representation for `UInt32Value` is JSON number.
|
||||
type UInt32Value struct {
|
||||
// The uint32 value.
|
||||
Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *UInt32Value) Reset() { *m = UInt32Value{} }
|
||||
func (m *UInt32Value) String() string { return proto.CompactTextString(m) }
|
||||
func (*UInt32Value) ProtoMessage() {}
|
||||
func (*UInt32Value) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{5} }
|
||||
func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" }
|
||||
|
||||
// Wrapper message for `bool`.
|
||||
//
|
||||
// The JSON representation for `BoolValue` is JSON `true` and `false`.
|
||||
type BoolValue struct {
|
||||
// The bool value.
|
||||
Value bool `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *BoolValue) Reset() { *m = BoolValue{} }
|
||||
func (m *BoolValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*BoolValue) ProtoMessage() {}
|
||||
func (*BoolValue) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{6} }
|
||||
func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" }
|
||||
|
||||
// Wrapper message for `string`.
|
||||
//
|
||||
// The JSON representation for `StringValue` is JSON string.
|
||||
type StringValue struct {
|
||||
// The string value.
|
||||
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *StringValue) Reset() { *m = StringValue{} }
|
||||
func (m *StringValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*StringValue) ProtoMessage() {}
|
||||
func (*StringValue) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{7} }
|
||||
func (*StringValue) XXX_WellKnownType() string { return "StringValue" }
|
||||
|
||||
// Wrapper message for `bytes`.
|
||||
//
|
||||
// The JSON representation for `BytesValue` is JSON string.
|
||||
type BytesValue struct {
|
||||
// The bytes value.
|
||||
Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *BytesValue) Reset() { *m = BytesValue{} }
|
||||
func (m *BytesValue) String() string { return proto.CompactTextString(m) }
|
||||
func (*BytesValue) ProtoMessage() {}
|
||||
func (*BytesValue) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{8} }
|
||||
func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue")
|
||||
proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue")
|
||||
proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value")
|
||||
proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value")
|
||||
proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value")
|
||||
proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value")
|
||||
proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue")
|
||||
proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue")
|
||||
proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/wrappers.proto", fileDescriptor9) }
|
||||
|
||||
var fileDescriptor9 = []byte{
|
||||
// 233 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x2f, 0x4a, 0x2c,
|
||||
0x28, 0x48, 0x2d, 0x2a, 0xd6, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0xca,
|
||||
0x5c, 0xdc, 0x2e, 0xf9, 0xa5, 0x49, 0x39, 0xa9, 0x61, 0x89, 0x39, 0xa5, 0xa9, 0x42, 0x22, 0x5c,
|
||||
0xac, 0x65, 0x20, 0x86, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x63, 0x10, 0x84, 0xa3, 0xa4, 0xc4, 0xc5,
|
||||
0xe5, 0x96, 0x93, 0x9f, 0x58, 0x82, 0x45, 0x0d, 0x13, 0x92, 0x1a, 0xcf, 0xbc, 0x12, 0x33, 0x13,
|
||||
0x2c, 0x6a, 0x98, 0x61, 0x6a, 0x80, 0x96, 0x85, 0xe2, 0x52, 0xc4, 0x82, 0x6a, 0x90, 0xb1, 0x11,
|
||||
0x16, 0x35, 0xac, 0x68, 0x06, 0x61, 0x55, 0xc4, 0x0b, 0x53, 0xa4, 0xc8, 0xc5, 0xe9, 0x94, 0x9f,
|
||||
0x9f, 0x83, 0x45, 0x09, 0x07, 0x92, 0x39, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x58, 0x14, 0x71,
|
||||
0x22, 0x39, 0xc8, 0xa9, 0xb2, 0x24, 0xb5, 0x18, 0x8b, 0x1a, 0x1e, 0xa8, 0x1a, 0xa7, 0x60, 0x2e,
|
||||
0xe1, 0xe4, 0xfc, 0x5c, 0x3d, 0xb4, 0xd0, 0x75, 0xe2, 0x0d, 0x87, 0x06, 0x7f, 0x00, 0x48, 0x24,
|
||||
0x80, 0x71, 0x01, 0x23, 0xe3, 0x0f, 0x46, 0xc6, 0x45, 0x4c, 0xcc, 0xee, 0x01, 0x4e, 0xab, 0x98,
|
||||
0xe4, 0xdc, 0x21, 0xca, 0x03, 0xa0, 0xca, 0xf5, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb,
|
||||
0xf3, 0x42, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0xe6, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff,
|
||||
0xff, 0xd8, 0xa5, 0x6f, 0xc9, 0xd5, 0x01, 0x00, 0x00,
|
||||
}
|
Loading…
Reference in New Issue