Skip to content

Commit

Permalink
Merge pull request kubernetes#44640 from msau42/local-pv-api
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue

LocalStorage api

**What this PR does / why we need it**:
API changes to support persistent local volumes, as described [here](kubernetes/community#306)

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #
Part of kubernetes#43640

**Special notes for your reviewer**:
There were a few items I was concerned about.  Will add review comments in those places.

**Release note**:

NONE

Note will be added in subsequent PR with the volume plugin changes
  • Loading branch information
Kubernetes Submit Queue committed May 22, 2017
2 parents 12fbd82 + 936269a commit f6b3d08
Show file tree
Hide file tree
Showing 31 changed files with 4,486 additions and 2,588 deletions.
16 changes: 16 additions & 0 deletions api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -44496,6 +44496,18 @@
}
}
},
"io.k8s.kubernetes.pkg.api.v1.LocalVolumeSource": {
"description": "Local represents directly-attached storage with node affinity",
"required": [
"path"
],
"properties": {
"path": {
"description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device",
"type": "string"
}
}
},
"io.k8s.kubernetes.pkg.api.v1.NFSVolumeSource": {
"description": "Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do not support ownership management or SELinux relabeling.",
"required": [
Expand Down Expand Up @@ -45273,6 +45285,10 @@
"description": "ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin.",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.ISCSIVolumeSource"
},
"local": {
"description": "Local represents directly-attached storage with node affinity",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.LocalVolumeSource"
},
"nfs": {
"description": "NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs",
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.NFSVolumeSource"
Expand Down
17 changes: 17 additions & 0 deletions api/swagger-spec/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -18966,6 +18966,10 @@
"$ref": "v1.ScaleIOVolumeSource",
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes."
},
"local": {
"$ref": "v1.LocalVolumeSource",
"description": "Local represents directly-attached storage with node affinity"
},
"accessModes": {
"type": "array",
"items": {
Expand Down Expand Up @@ -19536,6 +19540,19 @@
}
}
},
"v1.LocalVolumeSource": {
"id": "v1.LocalVolumeSource",
"description": "Local represents directly-attached storage with node affinity",
"required": [
"path"
],
"properties": {
"path": {
"type": "string",
"description": "The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device"
}
}
},
"v1.PersistentVolumeStatus": {
"id": "v1.PersistentVolumeStatus",
"description": "PersistentVolumeStatus is the current status of a persistent volume.",
Expand Down
99 changes: 70 additions & 29 deletions docs/api-reference/v1/definitions.html
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,40 @@ <h3 id="_v1_nodeselectorterm">v1.NodeSelectorTerm</h3>
</tbody>
</table>

</div>
<div class="sect2">
<h3 id="_v1_localvolumesource">v1.LocalVolumeSource</h3>
<div class="paragraph">
<p>Local represents directly-attached storage with node affinity</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">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The full path to the volume on the node For alpha, this path must be a directory Once block as a source is supported, then this path can point to a block device</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>
</tbody>
</table>

</div>
<div class="sect2">
<h3 id="_v1_preconditions">v1.Preconditions</h3>
Expand Down Expand Up @@ -4926,9 +4960,9 @@ <h3 id="_v1_podstatus">v1.PodStatus</h3>

</div>
<div class="sect2">
<h3 id="_v1_limitrange">v1.LimitRange</h3>
<h3 id="_v1_downwardapivolumefile">v1.DownwardAPIVolumeFile</h3>
<div class="paragraph">
<p>LimitRange sets resource usage limits for each kind of resource in a Namespace.</p>
<p>DownwardAPIVolumeFile represents information to create the file containing the pod field</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
Expand All @@ -4949,41 +4983,41 @@ <h3 id="_v1_limitrange">v1.LimitRange</h3>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Required: Path is the relative path name of the file to be created. Must not be absolute or contain the <em>..</em> path. Must be utf-8 encoded. The first item of the relative path must not start with <em>..</em></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">apiVersion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">fieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.</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"><p class="tableblock"><a href="#_v1_objectfieldselector">v1.ObjectFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">metadata</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard object&#8217;s metadata. More info: <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata">https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">resourceFieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.</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_objectmeta">v1.ObjectMeta</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_resourcefieldselector">v1.ResourceFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">spec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spec defines the limits enforced. More info: <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status">https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</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_limitrangespec">v1.LimitRangeSpec</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>

</div>
<div class="sect2">
<h3 id="_v1_downwardapivolumefile">v1.DownwardAPIVolumeFile</h3>
<h3 id="_v1_limitrange">v1.LimitRange</h3>
<div class="paragraph">
<p>DownwardAPIVolumeFile represents information to create the file containing the pod field</p>
<p>LimitRange sets resource usage limits for each kind of resource in a Namespace.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
Expand All @@ -5004,31 +5038,31 @@ <h3 id="_v1_downwardapivolumefile">v1.DownwardAPIVolumeFile</h3>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Required: Path is the relative path name of the file to be created. Must not be absolute or contain the <em>..</em> path. Must be utf-8 encoded. The first item of the relative path must not start with <em>..</em></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">kind</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">apiVersion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_objectfieldselector">v1.ObjectFieldSelector</a></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">resourceFieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">metadata</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard object&#8217;s metadata. More info: <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata">https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_resourcefieldselector">v1.ResourceFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_objectmeta">v1.ObjectMeta</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">spec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spec defines the limits enforced. More info: <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status">https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_limitrangespec">v1.LimitRangeSpec</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
Expand Down Expand Up @@ -7342,6 +7376,13 @@ <h3 id="_v1_persistentvolumespec">v1.PersistentVolumeSpec</h3>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">local</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Local represents directly-attached storage with node affinity</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_localvolumesource">v1.LocalVolumeSource</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="https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes">https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
Expand Down Expand Up @@ -10043,7 +10084,7 @@ <h3 id="_any">any</h3>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-05-18 19:28:13 UTC
Last updated 2017-05-21 19:00:06 UTC
</div>
</div>
</body>
Expand Down
26 changes: 26 additions & 0 deletions pkg/api/helper/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,3 +594,29 @@ func PersistentVolumeClaimHasClass(claim *api.PersistentVolumeClaim) bool {

return false
}

// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations
// and converts it to the NodeAffinity type in api.
// TODO: update when storage node affinity graduates to beta
func GetStorageNodeAffinityFromAnnotation(annotations map[string]string) (*api.NodeAffinity, error) {
if len(annotations) > 0 && annotations[api.AlphaStorageNodeAffinityAnnotation] != "" {
var affinity api.NodeAffinity
err := json.Unmarshal([]byte(annotations[api.AlphaStorageNodeAffinityAnnotation]), &affinity)
if err != nil {
return nil, err
}
return &affinity, nil
}
return nil, nil
}

// Converts NodeAffinity type to Alpha annotation for use in PersistentVolumes
// TODO: update when storage node affinity graduates to beta
func StorageNodeAffinityToAlphaAnnotation(annotations map[string]string, affinity *api.NodeAffinity) error {
json, err := json.Marshal(*affinity)
if err != nil {
return err
}
annotations[api.AlphaStorageNodeAffinityAnnotation] = string(json)
return nil
}
87 changes: 87 additions & 0 deletions pkg/api/helper/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,90 @@ func TestSysctlsFromPodAnnotation(t *testing.T) {
}
}
}

// TODO: remove when alpha support for topology constraints is removed
func TestGetNodeAffinityFromAnnotations(t *testing.T) {
testCases := []struct {
annotations map[string]string
expectErr bool
}{
{
annotations: nil,
expectErr: false,
},
{
annotations: map[string]string{},
expectErr: false,
},
{
annotations: map[string]string{
api.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}`,
},
expectErr: false,
},
{
annotations: map[string]string{
api.AlphaStorageNodeAffinityAnnotation: `[{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}]`,
},
expectErr: true,
},
{
annotations: map[string]string{
api.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms":
"matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
}
}`,
},
expectErr: true,
},
}

for i, tc := range testCases {
_, err := GetStorageNodeAffinityFromAnnotation(tc.annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
}
}
Loading

0 comments on commit f6b3d08

Please sign in to comment.