mirror of https://github.com/k3s-io/k3s
Merge pull request #48789 from mtanino/issue/47311
Automatic merge from submit-queue (batch tested with PRs 50806, 48789, 49922, 49935, 50438) iSCSI volume plugin: iSCSI initiatorname support **What this PR does / why we need it**: This PR adds iSCSI initiatorname parameter to ISCSIVolumeSource to enable automatic configuration of initiator name per volume. This would allow for more fine grained configuration, and remove the need to configure the initiator name on the host by administrator. **Which issue this PR fixes**: fixes #47311 **Special notes for your reviewer**: /cc @rootfs @jsafrane @msau42 **Release note**: ``` iSCSI volume plugin: Support customization of iSCSI initiator name per volume ```pull/6/head
commit
d235fa3f1c
|
@ -59432,6 +59432,10 @@
|
|||
"description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi",
|
||||
"type": "string"
|
||||
},
|
||||
"initiatorName": {
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection.",
|
||||
"type": "string"
|
||||
},
|
||||
"iqn": {
|
||||
"description": "Target iSCSI Qualified Name.",
|
||||
"type": "string"
|
||||
|
|
|
@ -4349,6 +4349,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -6487,6 +6487,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1931,6 +1931,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1986,6 +1986,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1986,6 +1986,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7041,6 +7041,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1787,6 +1787,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -19153,6 +19153,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2012,6 +2012,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -2110,6 +2110,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -1629,6 +1629,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -1670,6 +1670,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -1629,6 +1629,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -2524,6 +2524,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -2147,6 +2147,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -2713,6 +2713,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -10630,6 +10630,10 @@
|
|||
"description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi",
|
||||
"type": "string"
|
||||
},
|
||||
"initiatorName": {
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection.",
|
||||
"type": "string"
|
||||
},
|
||||
"iqn": {
|
||||
"description": "Target iSCSI Qualified Name.",
|
||||
"type": "string"
|
||||
|
|
|
@ -5400,6 +5400,10 @@
|
|||
"secretRef": {
|
||||
"$ref": "v1.LocalObjectReference",
|
||||
"description": "CHAP secret for iSCSI target and initiator authentication"
|
||||
},
|
||||
"initiatorName": {
|
||||
"type": "string",
|
||||
"description": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface \u003ctarget portal\u003e:\u003cvolume name\u003e will be created for the connection."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2361,6 +2361,13 @@ When an object is created, the system will populate this list with the current s
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">initiatorName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.</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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -709,6 +709,11 @@ type ISCSIVolumeSource struct {
|
|||
// The secret is used if either DiscoveryCHAPAuth or SessionCHAPAuth is true
|
||||
// +optional
|
||||
SecretRef *LocalObjectReference
|
||||
// Optional: Custom initiator name per volume.
|
||||
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
|
||||
// <target portal>:<volume name> will be created for the connection.
|
||||
// +optional
|
||||
InitiatorName *string
|
||||
}
|
||||
|
||||
// Represents a Fibre Channel volume.
|
||||
|
|
|
@ -1870,6 +1870,7 @@ func autoConvert_v1_ISCSIVolumeSource_To_api_ISCSIVolumeSource(in *v1.ISCSIVolum
|
|||
out.DiscoveryCHAPAuth = in.DiscoveryCHAPAuth
|
||||
out.SessionCHAPAuth = in.SessionCHAPAuth
|
||||
out.SecretRef = (*api.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
|
||||
out.InitiatorName = (*string)(unsafe.Pointer(in.InitiatorName))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1889,6 +1890,7 @@ func autoConvert_api_ISCSIVolumeSource_To_v1_ISCSIVolumeSource(in *api.ISCSIVolu
|
|||
out.DiscoveryCHAPAuth = in.DiscoveryCHAPAuth
|
||||
out.SessionCHAPAuth = in.SessionCHAPAuth
|
||||
out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
|
||||
out.InitiatorName = (*string)(unsafe.Pointer(in.InitiatorName))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,10 @@ var volumeModeErrorMsg string = "must be a number between 0 and 0777 (octal), bo
|
|||
// BannedOwners is a black list of object that are not allowed to be owners.
|
||||
var BannedOwners = genericvalidation.BannedOwners
|
||||
|
||||
var iscsiInitiatorIqnRegex = regexp.MustCompile(`iqn\.\d{4}-\d{2}\.([[:alnum:]-.]+)(:[^,;*&$|\s]+)$`)
|
||||
var iscsiInitiatorEuiRegex = regexp.MustCompile(`^eui.[[:alnum:]]{16}$`)
|
||||
var iscsiInitiatorNaaRegex = regexp.MustCompile(`^naa.[[:alnum:]]{32}$`)
|
||||
|
||||
// ValidateHasLabel requires that metav1.ObjectMeta has a Label with key and expectedValue
|
||||
func ValidateHasLabel(meta metav1.ObjectMeta, fldPath *field.Path, key, expectedValue string) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
@ -358,7 +362,7 @@ func ValidateVolumes(volumes []api.Volume, fldPath *field.Path) (sets.String, fi
|
|||
for i, vol := range volumes {
|
||||
idxPath := fldPath.Index(i)
|
||||
namePath := idxPath.Child("name")
|
||||
el := validateVolumeSource(&vol.VolumeSource, idxPath)
|
||||
el := validateVolumeSource(&vol.VolumeSource, idxPath, vol.Name)
|
||||
if len(vol.Name) == 0 {
|
||||
el = append(el, field.Required(namePath, ""))
|
||||
} else {
|
||||
|
@ -377,7 +381,7 @@ func ValidateVolumes(volumes []api.Volume, fldPath *field.Path) (sets.String, fi
|
|||
return allNames, allErrs
|
||||
}
|
||||
|
||||
func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path, volName string) field.ErrorList {
|
||||
numVolumes := 0
|
||||
allErrs := field.ErrorList{}
|
||||
if source.EmptyDir != nil {
|
||||
|
@ -444,6 +448,10 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
|
|||
numVolumes++
|
||||
allErrs = append(allErrs, validateISCSIVolumeSource(source.ISCSI, fldPath.Child("iscsi"))...)
|
||||
}
|
||||
if source.ISCSI.InitiatorName != nil && len(volName+":"+source.ISCSI.TargetPortal) > 64 {
|
||||
tooLongErr := "Total length of <volume name>:<iscsi.targetPortal> must be under 64 characters if iscsi.initiatorName is specified."
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), volName, tooLongErr))
|
||||
}
|
||||
}
|
||||
if source.Glusterfs != nil {
|
||||
if numVolumes > 0 {
|
||||
|
@ -636,6 +644,16 @@ func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, fldPath *field.Path
|
|||
}
|
||||
if len(iscsi.IQN) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("iqn"), ""))
|
||||
} else {
|
||||
if !strings.HasPrefix(iscsi.IQN, "iqn") && !strings.HasPrefix(iscsi.IQN, "eui") && !strings.HasPrefix(iscsi.IQN, "naa") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
|
||||
} else if strings.HasPrefix(iscsi.IQN, "iqn") && !iscsiInitiatorIqnRegex.MatchString(iscsi.IQN) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
|
||||
} else if strings.HasPrefix(iscsi.IQN, "eui") && !iscsiInitiatorEuiRegex.MatchString(iscsi.IQN) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
|
||||
} else if strings.HasPrefix(iscsi.IQN, "naa") && !iscsiInitiatorNaaRegex.MatchString(iscsi.IQN) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
|
||||
}
|
||||
}
|
||||
if iscsi.Lun < 0 || iscsi.Lun > 255 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("lun"), iscsi.Lun, validation.InclusiveRangeError(0, 255)))
|
||||
|
@ -643,6 +661,19 @@ func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, fldPath *field.Path
|
|||
if (iscsi.DiscoveryCHAPAuth || iscsi.SessionCHAPAuth) && iscsi.SecretRef == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("secretRef"), ""))
|
||||
}
|
||||
if iscsi.InitiatorName != nil {
|
||||
initiator := *iscsi.InitiatorName
|
||||
if !strings.HasPrefix(initiator, "iqn") && !strings.HasPrefix(initiator, "eui") && !strings.HasPrefix(initiator, "naa") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
|
||||
}
|
||||
if strings.HasPrefix(initiator, "iqn") && !iscsiInitiatorIqnRegex.MatchString(initiator) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
|
||||
} else if strings.HasPrefix(initiator, "eui") && !iscsiInitiatorEuiRegex.MatchString(initiator) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
|
||||
} else if strings.HasPrefix(initiator, "naa") && !iscsiInitiatorNaaRegex.MatchString(initiator) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -1292,6 +1323,10 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||
numVolumes++
|
||||
allErrs = append(allErrs, validateISCSIVolumeSource(pv.Spec.ISCSI, specPath.Child("iscsi"))...)
|
||||
}
|
||||
if pv.Spec.ISCSI.InitiatorName != nil && len(pv.ObjectMeta.Name+":"+pv.Spec.ISCSI.TargetPortal) > 64 {
|
||||
tooLongErr := "Total length of <volume name>:<iscsi.targetPortal> must be under 64 characters if iscsi.initiatorName is specified."
|
||||
allErrs = append(allErrs, field.Invalid(metaPath.Child("name"), pv.ObjectMeta.Name, tooLongErr))
|
||||
}
|
||||
}
|
||||
if pv.Spec.Cinder != nil {
|
||||
if numVolumes > 0 {
|
||||
|
|
|
@ -1025,6 +1025,8 @@ func newInt32(val int) *int32 {
|
|||
// type on its own, but we want to also make sure that the logic works through
|
||||
// the one-of wrapper, so we just do it all in one place.
|
||||
func TestValidateVolumes(t *testing.T) {
|
||||
validInitiatorName := "iqn.2015-02.example.com:init"
|
||||
invalidInitiatorName := "2015-02.example.com:init"
|
||||
testCases := []struct {
|
||||
name string
|
||||
vol api.Volume
|
||||
|
@ -1268,6 +1270,36 @@ func TestValidateVolumes(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid IQN: eui format",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "eui.0123456789ABCDEF",
|
||||
Lun: 1,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid IQN: naa format",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "naa.62004567BA64678D0123456789ABCDEF",
|
||||
Lun: 1,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty portal",
|
||||
vol: api.Volume{
|
||||
|
@ -1302,6 +1334,91 @@ func TestValidateVolumes(t *testing.T) {
|
|||
errtype: field.ErrorTypeRequired,
|
||||
errfield: "iscsi.iqn",
|
||||
},
|
||||
{
|
||||
name: "invalid IQN: iqn format",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "iqn.2015-02.example.com:test;ls;",
|
||||
Lun: 1,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
errtype: field.ErrorTypeInvalid,
|
||||
errfield: "iscsi.iqn",
|
||||
},
|
||||
{
|
||||
name: "invalid IQN: eui format",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "eui.0123456789ABCDEFGHIJ",
|
||||
Lun: 1,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
errtype: field.ErrorTypeInvalid,
|
||||
errfield: "iscsi.iqn",
|
||||
},
|
||||
{
|
||||
name: "invalid IQN: naa format",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "naa.62004567BA_4-78D.123456789ABCDEF",
|
||||
Lun: 1,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
errtype: field.ErrorTypeInvalid,
|
||||
errfield: "iscsi.iqn",
|
||||
},
|
||||
{
|
||||
name: "valid initiatorName",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "iqn.2015-02.example.com:test",
|
||||
Lun: 1,
|
||||
InitiatorName: &validInitiatorName,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid initiatorName",
|
||||
vol: api.Volume{
|
||||
Name: "iscsi",
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
TargetPortal: "127.0.0.1",
|
||||
IQN: "iqn.2015-02.example.com:test",
|
||||
Lun: 1,
|
||||
InitiatorName: &invalidInitiatorName,
|
||||
FSType: "ext4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
errtype: field.ErrorTypeInvalid,
|
||||
errfield: "iscsi.initiatorname",
|
||||
},
|
||||
{
|
||||
name: "empty secret",
|
||||
vol: api.Volume{
|
||||
|
@ -2475,7 +2592,7 @@ func TestAlphaLocalStorageCapacityIsolation(t *testing.T) {
|
|||
return
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
if errs := validateVolumeSource(&tc, field.NewPath("spec")); len(errs) != 0 {
|
||||
if errs := validateVolumeSource(&tc, field.NewPath("spec"), "tmpvol"); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
@ -2486,7 +2603,7 @@ func TestAlphaLocalStorageCapacityIsolation(t *testing.T) {
|
|||
return
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
if errs := validateVolumeSource(&tc, field.NewPath("spec")); len(errs) == 0 {
|
||||
if errs := validateVolumeSource(&tc, field.NewPath("spec"), "tmpvol"); len(errs) == 0 {
|
||||
t.Errorf("expected failure: %v", errs)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2333,6 +2333,15 @@ func (in *ISCSIVolumeSource) DeepCopyInto(out *ISCSIVolumeSource) {
|
|||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.InitiatorName != nil {
|
||||
in, out := &in.InitiatorName, &out.InitiatorName
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ go_test(
|
|||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ type diskManager interface {
|
|||
|
||||
// utility to mount a disk based filesystem
|
||||
func diskSetUp(manager diskManager, b iscsiDiskMounter, volPath string, mounter mount.Interface, fsGroup *int64) error {
|
||||
globalPDPath := manager.MakeGlobalPDName(*b.iscsiDisk)
|
||||
// TODO: handle failed mounts here.
|
||||
notMnt, err := mounter.IsLikelyNotMountPoint(volPath)
|
||||
|
||||
|
@ -60,6 +59,7 @@ func diskSetUp(manager diskManager, b iscsiDiskMounter, volPath string, mounter
|
|||
if b.readOnly {
|
||||
options = append(options, "ro")
|
||||
}
|
||||
globalPDPath := manager.MakeGlobalPDName(*b.iscsiDisk)
|
||||
mountOptions := volume.JoinMountOptions(b.mountOptions, options)
|
||||
err = mounter.Mount(globalPDPath, volPath, "", mountOptions)
|
||||
if err != nil {
|
||||
|
|
|
@ -132,6 +132,11 @@ func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UI
|
|||
}
|
||||
iface := iscsi.ISCSIInterface
|
||||
|
||||
var initiatorName string
|
||||
if iscsi.InitiatorName != nil {
|
||||
initiatorName = *iscsi.InitiatorName
|
||||
}
|
||||
|
||||
return &iscsiDiskMounter{
|
||||
iscsiDisk: &iscsiDisk{
|
||||
podUID: podUID,
|
||||
|
@ -143,6 +148,7 @@ func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UI
|
|||
chap_discovery: iscsi.DiscoveryCHAPAuth,
|
||||
chap_session: iscsi.SessionCHAPAuth,
|
||||
secret: secret,
|
||||
InitiatorName: initiatorName,
|
||||
manager: manager,
|
||||
plugin: plugin},
|
||||
fsType: iscsi.FSType,
|
||||
|
@ -198,6 +204,7 @@ type iscsiDisk struct {
|
|||
chap_discovery bool
|
||||
chap_session bool
|
||||
secret map[string]string
|
||||
InitiatorName string
|
||||
plugin *iscsiPlugin
|
||||
// Utility interface that provides API calls to the provider to attach/detach disks.
|
||||
manager diskManager
|
||||
|
|
|
@ -205,6 +205,20 @@ func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) error {
|
|||
iscsiTransport = extractTransportname(string(out))
|
||||
|
||||
bkpPortal := b.Portals
|
||||
|
||||
// create new iface and copy parameters from pre-configured iface to the created iface
|
||||
if b.InitiatorName != "" {
|
||||
// new iface name is <target portal>:<volume name>
|
||||
newIface := bkpPortal[0] + ":" + b.volName
|
||||
err = cloneIface(b, newIface)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to clone iface: %s error: %v", b.Iface, err)
|
||||
return err
|
||||
}
|
||||
// update iface name
|
||||
b.Iface = newIface
|
||||
}
|
||||
|
||||
for _, tp := range bkpPortal {
|
||||
// Rescan sessions to discover newly mapped LUNs. Do not specify the interface when rescanning
|
||||
// to avoid establishing additional sessions to the same target.
|
||||
|
@ -268,6 +282,8 @@ func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) error {
|
|||
}
|
||||
|
||||
if len(devicePaths) == 0 {
|
||||
// delete cloned iface
|
||||
b.plugin.execCommand("iscsiadm", []string{"-m", "iface", "-I", b.Iface, "-o", "delete"})
|
||||
glog.Errorf("iscsi: failed to get any path for iscsi disk, last err seen:\n%v", lastErr)
|
||||
return fmt.Errorf("failed to get any path for iscsi disk, last err seen:\n%v", lastErr)
|
||||
}
|
||||
|
@ -331,12 +347,13 @@ func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, mntPath string) error {
|
|||
refCount, err := getDevicePrefixRefCount(c.mounter, prefix)
|
||||
if err == nil && refCount == 0 {
|
||||
var bkpPortal []string
|
||||
var iqn, iface string
|
||||
var iqn, iface, initiatorName string
|
||||
found := true
|
||||
|
||||
// load iscsi disk config from json file
|
||||
if err := util.loadISCSI(c.iscsiDisk, mntPath); err == nil {
|
||||
bkpPortal, iqn, iface = c.iscsiDisk.Portals, c.iscsiDisk.Iqn, c.iscsiDisk.Iface
|
||||
initiatorName = c.iscsiDisk.InitiatorName
|
||||
} else {
|
||||
// If the iscsi disk config is not found, fall back to the original behavior.
|
||||
// This portal/iqn/iface is no longer referenced, log out.
|
||||
|
@ -351,7 +368,12 @@ func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, mntPath string) error {
|
|||
// Logout may fail as no session may exist for the portal/IQN on the specified interface.
|
||||
iface, found = extractIface(mntPath)
|
||||
}
|
||||
for _, portal := range removeDuplicate(bkpPortal) {
|
||||
portals := removeDuplicate(bkpPortal)
|
||||
if len(portals) == 0 {
|
||||
return fmt.Errorf("iscsi detach disk: failed to detach iscsi disk. Couldn't get connected portals from configurations.")
|
||||
}
|
||||
|
||||
for _, portal := range portals {
|
||||
logout := []string{"-m", "node", "-p", portal, "-T", iqn, "--logout"}
|
||||
delete := []string{"-m", "node", "-p", portal, "-T", iqn, "-o", "delete"}
|
||||
if found {
|
||||
|
@ -370,6 +392,16 @@ func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, mntPath string) error {
|
|||
glog.Errorf("iscsi: failed to delete node record Error: %s", string(out))
|
||||
}
|
||||
}
|
||||
// Delete the iface after all sessions have logged out
|
||||
// If the iface is not created via iscsi plugin, skip to delete
|
||||
if initiatorName != "" && found && iface == (portals[0]+":"+c.volName) {
|
||||
delete := []string{"-m", "iface", "-I", iface, "-o", "delete"}
|
||||
out, err := c.plugin.execCommand("iscsiadm", delete)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to delete iface Error: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -448,3 +480,57 @@ func removeDuplicate(s []string) []string {
|
|||
s = s[:len(m)]
|
||||
return s
|
||||
}
|
||||
|
||||
func parseIscsiadmShow(output string) (map[string]string, error) {
|
||||
params := make(map[string]string)
|
||||
slice := strings.Split(output, "\n")
|
||||
for _, line := range slice {
|
||||
if !strings.HasPrefix(line, "iface.") || strings.Contains(line, "<empty>") {
|
||||
continue
|
||||
}
|
||||
iface := strings.Fields(line)
|
||||
if len(iface) != 3 || iface[1] != "=" {
|
||||
return nil, fmt.Errorf("Error: invalid iface setting: %v", iface)
|
||||
}
|
||||
// iscsi_ifacename is immutable once the iface is created
|
||||
if iface[0] == "iface.iscsi_ifacename" {
|
||||
continue
|
||||
}
|
||||
params[iface[0]] = iface[2]
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func cloneIface(b iscsiDiskMounter, newIface string) error {
|
||||
var lastErr error
|
||||
// get pre-configured iface records
|
||||
out, err := b.plugin.execCommand("iscsiadm", []string{"-m", "iface", "-I", b.Iface, "-o", "show"})
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to show iface records: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// parse obtained records
|
||||
params, err := parseIscsiadmShow(string(out))
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to parse iface records: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// update initiatorname
|
||||
params["iface.initiatorname"] = b.InitiatorName
|
||||
// create new iface
|
||||
out, err = b.plugin.execCommand("iscsiadm", []string{"-m", "iface", "-I", newIface, "-o", "new"})
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to create new iface: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// update new iface records
|
||||
for key, val := range params {
|
||||
_, err = b.plugin.execCommand("iscsiadm", []string{"-m", "iface", "-I", newIface, "-o", "update", "-n", key, "-v", val})
|
||||
if err != nil {
|
||||
b.plugin.execCommand("iscsiadm", []string{"-m", "iface", "-I", newIface, "-o", "delete"})
|
||||
lastErr = fmt.Errorf("iscsi: failed to update iface records: %s (%v). iface(%s) will be used", string(out), err, b.Iface)
|
||||
break
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
|
|
|
@ -17,12 +17,16 @@ limitations under the License.
|
|||
package iscsi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/utils/exec"
|
||||
fakeexec "k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
func TestGetDevicePrefixRefCount(t *testing.T) {
|
||||
|
@ -183,3 +187,177 @@ func TestWaitForPathToExist(t *testing.T) {
|
|||
t.Errorf("waitForPathToExist: wrong code path called for %s", devicePath[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIscsiadmShow(t *testing.T) {
|
||||
fakeIscsiadmOutput1 := "# BEGIN RECORD 2.0-873\n" +
|
||||
"iface.iscsi_ifacename = default\n" +
|
||||
"iface.transport_name = tcp\n" +
|
||||
"iface.initiatorname = <empty>\n" +
|
||||
"iface.mtu = 0\n" +
|
||||
"# END RECORD"
|
||||
|
||||
fakeIscsiadmOutput2 := "# BEGIN RECORD 2.0-873\n" +
|
||||
"iface.iscsi_ifacename = default\n" +
|
||||
"iface.transport_name = cxgb4i\n" +
|
||||
"iface.initiatorname = <empty>\n" +
|
||||
"iface.mtu = 0\n" +
|
||||
"# END RECORD"
|
||||
|
||||
fakeIscsiadmOutput3 := "# BEGIN RECORD 2.0-873\n" +
|
||||
"iface.iscsi_ifacename = custom\n" +
|
||||
"iface.transport_name = <empty>\n" +
|
||||
"iface.initiatorname = <empty>\n" +
|
||||
"iface.mtu = 0\n" +
|
||||
"# END RECORD"
|
||||
|
||||
fakeIscsiadmOutput4 := "iface.iscsi_ifacename=error"
|
||||
fakeIscsiadmOutput5 := "iface.iscsi_ifacename + error"
|
||||
|
||||
expectedIscsiadmOutput1 := map[string]string{
|
||||
"iface.transport_name": "tcp",
|
||||
"iface.mtu": "0"}
|
||||
|
||||
expectedIscsiadmOutput2 := map[string]string{
|
||||
"iface.transport_name": "cxgb4i",
|
||||
"iface.mtu": "0"}
|
||||
|
||||
expectedIscsiadmOutput3 := map[string]string{
|
||||
"iface.mtu": "0"}
|
||||
|
||||
params, _ := parseIscsiadmShow(fakeIscsiadmOutput1)
|
||||
if !reflect.DeepEqual(params, expectedIscsiadmOutput1) {
|
||||
t.Errorf("parseIscsiadmShow: Fail to parse iface record: %s", params)
|
||||
}
|
||||
params, _ = parseIscsiadmShow(fakeIscsiadmOutput2)
|
||||
if !reflect.DeepEqual(params, expectedIscsiadmOutput2) {
|
||||
t.Errorf("parseIscsiadmShow: Fail to parse iface record: %s", params)
|
||||
}
|
||||
params, _ = parseIscsiadmShow(fakeIscsiadmOutput3)
|
||||
if !reflect.DeepEqual(params, expectedIscsiadmOutput3) {
|
||||
t.Errorf("parseIscsiadmShow: Fail to parse iface record: %s", params)
|
||||
}
|
||||
_, err := parseIscsiadmShow(fakeIscsiadmOutput4)
|
||||
if err == nil {
|
||||
t.Errorf("parseIscsiadmShow: Fail to handle invalid record: iface %s", fakeIscsiadmOutput4)
|
||||
}
|
||||
_, err = parseIscsiadmShow(fakeIscsiadmOutput5)
|
||||
if err == nil {
|
||||
t.Errorf("parseIscsiadmShow: Fail to handle invalid record: iface %s", fakeIscsiadmOutput5)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClonedIface(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
// iscsiadm -m iface -I <iface> -o show
|
||||
func() ([]byte, error) {
|
||||
return []byte("iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n"), nil
|
||||
},
|
||||
// iscsiadm -m iface -I <newIface> -o new
|
||||
func() ([]byte, error) { return []byte("New interface 192.168.1.10:pv0001 added"), nil },
|
||||
// iscsiadm -m iface -I <newIface> -o update -n <key> -v <val>
|
||||
func() ([]byte, error) { return []byte(""), nil },
|
||||
func() ([]byte, error) { return []byte(""), nil },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
}
|
||||
plugins := []volume.VolumePlugin{
|
||||
&iscsiPlugin{
|
||||
host: nil,
|
||||
exe: &fexec,
|
||||
},
|
||||
}
|
||||
plugin := plugins[0]
|
||||
fakeMounter := iscsiDiskMounter{
|
||||
iscsiDisk: &iscsiDisk{
|
||||
plugin: plugin.(*iscsiPlugin)},
|
||||
}
|
||||
newIface := "192.168.1.10:pv0001"
|
||||
cloneIface(fakeMounter, newIface)
|
||||
if fcmd.CombinedOutputCalls != 4 {
|
||||
t.Errorf("expected 4 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestClonedIfaceShowError(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
// iscsiadm -m iface -I <iface> -o show, return test error
|
||||
func() ([]byte, error) { return []byte(""), errors.New("test error") },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
}
|
||||
plugins := []volume.VolumePlugin{
|
||||
&iscsiPlugin{
|
||||
host: nil,
|
||||
exe: &fexec,
|
||||
},
|
||||
}
|
||||
plugin := plugins[0]
|
||||
fakeMounter := iscsiDiskMounter{
|
||||
iscsiDisk: &iscsiDisk{
|
||||
plugin: plugin.(*iscsiPlugin)},
|
||||
}
|
||||
newIface := "192.168.1.10:pv0001"
|
||||
cloneIface(fakeMounter, newIface)
|
||||
if fcmd.CombinedOutputCalls != 1 {
|
||||
t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestClonedIfaceUpdateError(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
// iscsiadm -m iface -I <iface> -o show
|
||||
func() ([]byte, error) {
|
||||
return []byte("iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n"), nil
|
||||
},
|
||||
// iscsiadm -m iface -I <newIface> -o new
|
||||
func() ([]byte, error) { return []byte("New interface 192.168.1.10:pv0001 added"), nil },
|
||||
// iscsiadm -m iface -I <newIface> -o update -n <key> -v <val>
|
||||
func() ([]byte, error) { return []byte(""), nil },
|
||||
func() ([]byte, error) { return []byte(""), errors.New("test error") },
|
||||
// iscsiadm -m iface -I <newIface> -o delete
|
||||
func() ([]byte, error) { return []byte(""), nil },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
}
|
||||
plugins := []volume.VolumePlugin{
|
||||
&iscsiPlugin{
|
||||
host: nil,
|
||||
exe: &fexec,
|
||||
},
|
||||
}
|
||||
plugin := plugins[0]
|
||||
fakeMounter := iscsiDiskMounter{
|
||||
iscsiDisk: &iscsiDisk{
|
||||
plugin: plugin.(*iscsiPlugin)},
|
||||
}
|
||||
newIface := "192.168.1.10:pv0001"
|
||||
cloneIface(fakeMounter, newIface)
|
||||
if fcmd.CombinedOutputCalls != 5 {
|
||||
t.Errorf("expected 5 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1274,6 +1274,12 @@ message ISCSIVolumeSource {
|
|||
// CHAP secret for iSCSI target and initiator authentication
|
||||
// +optional
|
||||
optional LocalObjectReference secretRef = 10;
|
||||
|
||||
// Custom iSCSI initiator name.
|
||||
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
|
||||
// <target portal>:<volume name> will be created for the connection.
|
||||
// +optional
|
||||
optional string initiatorName = 12;
|
||||
}
|
||||
|
||||
// Maps a string key to a path within a volume.
|
||||
|
|
|
@ -16506,7 +16506,7 @@ func (x *ISCSIVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
} else {
|
||||
yysep2 := !z.EncBinary()
|
||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||
var yyq2 [10]bool
|
||||
var yyq2 [11]bool
|
||||
_, _, _ = yysep2, yyq2, yy2arr2
|
||||
const yyr2 bool = false
|
||||
yyq2[3] = x.ISCSIInterface != ""
|
||||
|
@ -16516,9 +16516,10 @@ func (x *ISCSIVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
yyq2[7] = x.DiscoveryCHAPAuth != false
|
||||
yyq2[8] = x.SessionCHAPAuth != false
|
||||
yyq2[9] = x.SecretRef != nil
|
||||
yyq2[10] = x.InitiatorName != nil
|
||||
var yynn2 int
|
||||
if yyr2 || yy2arr2 {
|
||||
r.EncodeArrayStart(10)
|
||||
r.EncodeArrayStart(11)
|
||||
} else {
|
||||
yynn2 = 3
|
||||
for _, b := range yyq2 {
|
||||
|
@ -16767,6 +16768,41 @@ func (x *ISCSIVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if yyq2[10] {
|
||||
if x.InitiatorName == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yy34 := *x.InitiatorName
|
||||
yym35 := z.EncBinary()
|
||||
_ = yym35
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(yy34))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r.EncodeNil()
|
||||
}
|
||||
} else {
|
||||
if yyq2[10] {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("initiatorName"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
if x.InitiatorName == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yy36 := *x.InitiatorName
|
||||
yym37 := z.EncBinary()
|
||||
_ = yym37
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(yy36))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
} else {
|
||||
|
@ -16947,6 +16983,22 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromMap(l int, d *codec1978.Decoder)
|
|||
}
|
||||
x.SecretRef.CodecDecodeSelf(d)
|
||||
}
|
||||
case "initiatorName":
|
||||
if r.TryDecodeAsNil() {
|
||||
if x.InitiatorName != nil {
|
||||
x.InitiatorName = nil
|
||||
}
|
||||
} else {
|
||||
if x.InitiatorName == nil {
|
||||
x.InitiatorName = new(string)
|
||||
}
|
||||
yym24 := z.DecBinary()
|
||||
_ = yym24
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(x.InitiatorName)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
default:
|
||||
z.DecStructFieldNotFound(-1, yys3)
|
||||
} // end switch yys3
|
||||
|
@ -16958,16 +17010,16 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj23 int
|
||||
var yyb23 bool
|
||||
var yyhl23 bool = l >= 0
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
var yyj25 int
|
||||
var yyb25 bool
|
||||
var yyhl25 bool = l >= 0
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -16975,29 +17027,7 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.TargetPortal = ""
|
||||
} else {
|
||||
yyv24 := &x.TargetPortal
|
||||
yym25 := z.DecBinary()
|
||||
_ = yym25
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv24)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.IQN = ""
|
||||
} else {
|
||||
yyv26 := &x.IQN
|
||||
yyv26 := &x.TargetPortal
|
||||
yym27 := z.DecBinary()
|
||||
_ = yym27
|
||||
if false {
|
||||
|
@ -17005,13 +17035,35 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
*((*string)(yyv26)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.IQN = ""
|
||||
} else {
|
||||
yyv28 := &x.IQN
|
||||
yym29 := z.DecBinary()
|
||||
_ = yym29
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv28)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17019,21 +17071,21 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Lun = 0
|
||||
} else {
|
||||
yyv28 := &x.Lun
|
||||
yym29 := z.DecBinary()
|
||||
_ = yym29
|
||||
yyv30 := &x.Lun
|
||||
yym31 := z.DecBinary()
|
||||
_ = yym31
|
||||
if false {
|
||||
} else {
|
||||
*((*int32)(yyv28)) = int32(r.DecodeInt(32))
|
||||
*((*int32)(yyv30)) = int32(r.DecodeInt(32))
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17041,29 +17093,7 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.ISCSIInterface = ""
|
||||
} else {
|
||||
yyv30 := &x.ISCSIInterface
|
||||
yym31 := z.DecBinary()
|
||||
_ = yym31
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv30)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.FSType = ""
|
||||
} else {
|
||||
yyv32 := &x.FSType
|
||||
yyv32 := &x.ISCSIInterface
|
||||
yym33 := z.DecBinary()
|
||||
_ = yym33
|
||||
if false {
|
||||
|
@ -17071,13 +17101,35 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
*((*string)(yyv32)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.FSType = ""
|
||||
} else {
|
||||
yyv34 := &x.FSType
|
||||
yym35 := z.DecBinary()
|
||||
_ = yym35
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv34)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17085,21 +17137,21 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.ReadOnly = false
|
||||
} else {
|
||||
yyv34 := &x.ReadOnly
|
||||
yym35 := z.DecBinary()
|
||||
_ = yym35
|
||||
yyv36 := &x.ReadOnly
|
||||
yym37 := z.DecBinary()
|
||||
_ = yym37
|
||||
if false {
|
||||
} else {
|
||||
*((*bool)(yyv34)) = r.DecodeBool()
|
||||
*((*bool)(yyv36)) = r.DecodeBool()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17107,21 +17159,21 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Portals = nil
|
||||
} else {
|
||||
yyv36 := &x.Portals
|
||||
yym37 := z.DecBinary()
|
||||
_ = yym37
|
||||
yyv38 := &x.Portals
|
||||
yym39 := z.DecBinary()
|
||||
_ = yym39
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecSliceStringX(yyv36, false, d)
|
||||
z.F.DecSliceStringX(yyv38, false, d)
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17129,29 +17181,7 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
if r.TryDecodeAsNil() {
|
||||
x.DiscoveryCHAPAuth = false
|
||||
} else {
|
||||
yyv38 := &x.DiscoveryCHAPAuth
|
||||
yym39 := z.DecBinary()
|
||||
_ = yym39
|
||||
if false {
|
||||
} else {
|
||||
*((*bool)(yyv38)) = r.DecodeBool()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.SessionCHAPAuth = false
|
||||
} else {
|
||||
yyv40 := &x.SessionCHAPAuth
|
||||
yyv40 := &x.DiscoveryCHAPAuth
|
||||
yym41 := z.DecBinary()
|
||||
_ = yym41
|
||||
if false {
|
||||
|
@ -17159,13 +17189,35 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
*((*bool)(yyv40)) = r.DecodeBool()
|
||||
}
|
||||
}
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb23 {
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.SessionCHAPAuth = false
|
||||
} else {
|
||||
yyv42 := &x.SessionCHAPAuth
|
||||
yym43 := z.DecBinary()
|
||||
_ = yym43
|
||||
if false {
|
||||
} else {
|
||||
*((*bool)(yyv42)) = r.DecodeBool()
|
||||
}
|
||||
}
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -17180,18 +17232,44 @@ func (x *ISCSIVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder
|
|||
}
|
||||
x.SecretRef.CodecDecodeSelf(d)
|
||||
}
|
||||
for {
|
||||
yyj23++
|
||||
if yyhl23 {
|
||||
yyb23 = yyj23 > l
|
||||
} else {
|
||||
yyb23 = r.CheckBreak()
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb25 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
if x.InitiatorName != nil {
|
||||
x.InitiatorName = nil
|
||||
}
|
||||
if yyb23 {
|
||||
} else {
|
||||
if x.InitiatorName == nil {
|
||||
x.InitiatorName = new(string)
|
||||
}
|
||||
yym46 := z.DecBinary()
|
||||
_ = yym46
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(x.InitiatorName)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
for {
|
||||
yyj25++
|
||||
if yyhl25 {
|
||||
yyb25 = yyj25 > l
|
||||
} else {
|
||||
yyb25 = r.CheckBreak()
|
||||
}
|
||||
if yyb25 {
|
||||
break
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
z.DecStructFieldNotFound(yyj23-1, "")
|
||||
z.DecStructFieldNotFound(yyj25-1, "")
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
|
|
@ -1095,6 +1095,11 @@ type ISCSIVolumeSource struct {
|
|||
// CHAP secret for iSCSI target and initiator authentication
|
||||
// +optional
|
||||
SecretRef *LocalObjectReference `json:"secretRef,omitempty" protobuf:"bytes,10,opt,name=secretRef"`
|
||||
// Custom iSCSI initiator name.
|
||||
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
|
||||
// <target portal>:<volume name> will be created for the connection.
|
||||
// +optional
|
||||
InitiatorName *string `json:"initiatorName,omitempty" protobuf:"bytes,12,opt,name=initiatorName"`
|
||||
}
|
||||
|
||||
// Represents a Fibre Channel volume.
|
||||
|
|
|
@ -674,6 +674,7 @@ var map_ISCSIVolumeSource = map[string]string{
|
|||
"chapAuthDiscovery": "whether support iSCSI Discovery CHAP authentication",
|
||||
"chapAuthSession": "whether support iSCSI Session CHAP authentication",
|
||||
"secretRef": "CHAP secret for iSCSI target and initiator authentication",
|
||||
"initiatorName": "Custom iSCSI initiator name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection.",
|
||||
}
|
||||
|
||||
func (ISCSIVolumeSource) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -2333,6 +2333,15 @@ func (in *ISCSIVolumeSource) DeepCopyInto(out *ISCSIVolumeSource) {
|
|||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.InitiatorName != nil {
|
||||
in, out := &in.InitiatorName, &out.InitiatorName
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue