Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
bb34a0b7
Commit
bb34a0b7
authored
Aug 28, 2017
by
Huamin Chen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use SecretObject to reference iSCSI CHAP secret
Signed-off-by:
Huamin Chen
<
hchen@redhat.com
>
parent
02f803cc
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
553 additions
and
65 deletions
+553
-65
util.go
pkg/api/persistentvolume/util.go
+10
-2
util_test.go
pkg/api/persistentvolume/util_test.go
+10
-2
fuzzer.go
pkg/apis/core/fuzzer/fuzzer.go
+6
-0
types.go
pkg/apis/core/types.go
+50
-2
defaults.go
pkg/apis/core/v1/defaults.go
+5
-0
validation.go
pkg/apis/core/validation/validation.go
+46
-1
describe.go
pkg/printers/internalversion/describe.go
+21
-1
describe_test.go
pkg/printers/internalversion/describe_test.go
+1
-1
BUILD
pkg/volume/iscsi/BUILD
+1
-0
attacher.go
pkg/volume/iscsi/attacher.go
+66
-19
iscsi.go
pkg/volume/iscsi/iscsi.go
+138
-28
iscsi_test.go
pkg/volume/iscsi/iscsi_test.go
+145
-2
types.go
staging/src/k8s.io/api/core/v1/types.go
+54
-7
No files found.
pkg/api/persistentvolume/util.go
View file @
bb34a0b7
...
@@ -88,8 +88,16 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
...
@@ -88,8 +88,16 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
}
}
}
}
case
source
.
ISCSI
!=
nil
:
case
source
.
ISCSI
!=
nil
:
if
source
.
ISCSI
.
SecretRef
!=
nil
&&
!
visitor
(
getClaimRefNamespace
(
pv
),
source
.
ISCSI
.
SecretRef
.
Name
)
{
if
source
.
ISCSI
.
SecretRef
!=
nil
{
return
false
// previously persisted PV objects use claimRef namespace
ns
:=
getClaimRefNamespace
(
pv
)
if
len
(
source
.
ISCSI
.
SecretRef
.
Namespace
)
>
0
{
// use the secret namespace if namespace is set
ns
=
source
.
ISCSI
.
SecretRef
.
Namespace
}
if
!
visitor
(
ns
,
source
.
ISCSI
.
SecretRef
.
Name
)
{
return
false
}
}
}
case
source
.
StorageOS
!=
nil
:
case
source
.
StorageOS
!=
nil
:
if
source
.
StorageOS
.
SecretRef
!=
nil
&&
!
visitor
(
source
.
StorageOS
.
SecretRef
.
Namespace
,
source
.
StorageOS
.
SecretRef
.
Name
)
{
if
source
.
StorageOS
.
SecretRef
!=
nil
&&
!
visitor
(
source
.
StorageOS
.
SecretRef
.
Namespace
,
source
.
StorageOS
.
SecretRef
.
Name
)
{
...
...
pkg/api/persistentvolume/util_test.go
View file @
bb34a0b7
...
@@ -93,8 +93,15 @@ func TestPVSecrets(t *testing.T) {
...
@@ -93,8 +93,15 @@ func TestPVSecrets(t *testing.T) {
{
Spec
:
api
.
PersistentVolumeSpec
{
{
Spec
:
api
.
PersistentVolumeSpec
{
ClaimRef
:
&
api
.
ObjectReference
{
Namespace
:
"claimrefns"
,
Name
:
"claimrefname"
},
ClaimRef
:
&
api
.
ObjectReference
{
Namespace
:
"claimrefns"
,
Name
:
"claimrefname"
},
PersistentVolumeSource
:
api
.
PersistentVolumeSource
{
PersistentVolumeSource
:
api
.
PersistentVolumeSource
{
ISCSI
:
&
api
.
ISCSIVolumeSource
{
ISCSI
:
&
api
.
ISCSIPersistentVolumeSource
{
SecretRef
:
&
api
.
LocalObjectReference
{
SecretRef
:
&
api
.
SecretReference
{
Name
:
"Spec.PersistentVolumeSource.ISCSI.SecretRef"
,
Namespace
:
"iscsi"
}}}}},
{
Spec
:
api
.
PersistentVolumeSpec
{
ClaimRef
:
&
api
.
ObjectReference
{
Namespace
:
"claimrefns"
,
Name
:
"claimrefname"
},
PersistentVolumeSource
:
api
.
PersistentVolumeSource
{
ISCSI
:
&
api
.
ISCSIPersistentVolumeSource
{
SecretRef
:
&
api
.
SecretReference
{
Name
:
"Spec.PersistentVolumeSource.ISCSI.SecretRef"
}}}}},
Name
:
"Spec.PersistentVolumeSource.ISCSI.SecretRef"
}}}}},
{
Spec
:
api
.
PersistentVolumeSpec
{
{
Spec
:
api
.
PersistentVolumeSpec
{
ClaimRef
:
&
api
.
ObjectReference
{
Namespace
:
"claimrefns"
,
Name
:
"claimrefname"
},
ClaimRef
:
&
api
.
ObjectReference
{
Namespace
:
"claimrefns"
,
Name
:
"claimrefname"
},
...
@@ -161,6 +168,7 @@ func TestPVSecrets(t *testing.T) {
...
@@ -161,6 +168,7 @@ func TestPVSecrets(t *testing.T) {
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef"
,
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef"
,
"scaleions/Spec.PersistentVolumeSource.ScaleIO.SecretRef"
,
"scaleions/Spec.PersistentVolumeSource.ScaleIO.SecretRef"
,
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef"
,
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef"
,
"iscsi/Spec.PersistentVolumeSource.ISCSI.SecretRef"
,
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef"
,
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef"
,
)
)
if
missingNames
:=
expectedNamespacedNames
.
Difference
(
extractedNamesWithNamespace
);
len
(
missingNames
)
>
0
{
if
missingNames
:=
expectedNamespacedNames
.
Difference
(
extractedNamesWithNamespace
);
len
(
missingNames
)
>
0
{
...
...
pkg/apis/core/fuzzer/fuzzer.go
View file @
bb34a0b7
...
@@ -245,6 +245,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
...
@@ -245,6 +245,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
i
.
ISCSIInterface
=
"default"
i
.
ISCSIInterface
=
"default"
}
}
},
},
func
(
i
*
core
.
ISCSIPersistentVolumeSource
,
c
fuzz
.
Continue
)
{
i
.
ISCSIInterface
=
c
.
RandString
()
if
i
.
ISCSIInterface
==
""
{
i
.
ISCSIInterface
=
"default"
}
},
func
(
d
*
core
.
DNSPolicy
,
c
fuzz
.
Continue
)
{
func
(
d
*
core
.
DNSPolicy
,
c
fuzz
.
Continue
)
{
policies
:=
[]
core
.
DNSPolicy
{
core
.
DNSClusterFirst
,
core
.
DNSDefault
}
policies
:=
[]
core
.
DNSPolicy
{
core
.
DNSClusterFirst
,
core
.
DNSDefault
}
*
d
=
policies
[
c
.
Rand
.
Intn
(
len
(
policies
))]
*
d
=
policies
[
c
.
Rand
.
Intn
(
len
(
policies
))]
...
...
pkg/apis/core/types.go
View file @
bb34a0b7
...
@@ -347,10 +347,10 @@ type PersistentVolumeSource struct {
...
@@ -347,10 +347,10 @@ type PersistentVolumeSource struct {
// Quobyte represents a Quobyte mount on the host that shares a pod's lifetime
// Quobyte represents a Quobyte mount on the host that shares a pod's lifetime
// +optional
// +optional
Quobyte
*
QuobyteVolumeSource
Quobyte
*
QuobyteVolumeSource
// ISCSIVolumeSource represents an ISCSI resource that is attached to a
// ISCSI
Persistent
VolumeSource represents an ISCSI resource that is attached to a
// kubelet's host machine and then exposed to the pod.
// kubelet's host machine and then exposed to the pod.
// +optional
// +optional
ISCSI
*
ISCSIVolumeSource
ISCSI
*
ISCSI
Persistent
VolumeSource
// FlexVolume represents a generic volume resource that is
// FlexVolume represents a generic volume resource that is
// provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.
// provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.
// +optional
// +optional
...
@@ -793,6 +793,54 @@ type ISCSIVolumeSource struct {
...
@@ -793,6 +793,54 @@ type ISCSIVolumeSource struct {
InitiatorName
*
string
InitiatorName
*
string
}
}
// ISCSIPersistentVolumeSource represents an ISCSI disk.
// ISCSI volumes can only be mounted as read/write once.
// ISCSI volumes support ownership management and SELinux relabeling.
type
ISCSIPersistentVolumeSource
struct
{
// Required: iSCSI target portal
// the portal is either an IP or ip_addr:port if port is other than default (typically TCP ports 860 and 3260)
// +optional
TargetPortal
string
// Required: target iSCSI Qualified Name
// +optional
IQN
string
// Required: iSCSI target lun number
// +optional
Lun
int32
// Optional: Defaults to 'default' (tcp). iSCSI interface name that uses an iSCSI transport.
// +optional
ISCSIInterface
string
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
// TODO: how do we prevent errors in the filesystem from compromising the machine
// +optional
FSType
string
// Optional: Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly
bool
// Optional: list of iSCSI target portal ips for high availability.
// the portal is either an IP or ip_addr:port if port is other than default (typically TCP ports 860 and 3260)
// +optional
Portals
[]
string
// Optional: whether support iSCSI Discovery CHAP authentication
// +optional
DiscoveryCHAPAuth
bool
// Optional: whether support iSCSI Session CHAP authentication
// +optional
SessionCHAPAuth
bool
// Optional: CHAP secret for iSCSI target and initiator authentication.
// The secret is used if either DiscoveryCHAPAuth or SessionCHAPAuth is true
// +optional
SecretRef
*
SecretReference
// 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.
// Represents a Fibre Channel volume.
// Fibre Channel volumes can only be mounted as read/write once.
// Fibre Channel volumes can only be mounted as read/write once.
// Fibre Channel volumes support ownership management and SELinux relabeling.
// Fibre Channel volumes support ownership management and SELinux relabeling.
...
...
pkg/apis/core/v1/defaults.go
View file @
bb34a0b7
...
@@ -249,6 +249,11 @@ func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
...
@@ -249,6 +249,11 @@ func SetDefaults_ISCSIVolumeSource(obj *v1.ISCSIVolumeSource) {
obj
.
ISCSIInterface
=
"default"
obj
.
ISCSIInterface
=
"default"
}
}
}
}
func
SetDefaults_ISCSIPersistentVolumeSource
(
obj
*
v1
.
ISCSIPersistentVolumeSource
)
{
if
obj
.
ISCSIInterface
==
""
{
obj
.
ISCSIInterface
=
"default"
}
}
func
SetDefaults_AzureDiskVolumeSource
(
obj
*
v1
.
AzureDiskVolumeSource
)
{
func
SetDefaults_AzureDiskVolumeSource
(
obj
*
v1
.
AzureDiskVolumeSource
)
{
if
obj
.
CachingMode
==
nil
{
if
obj
.
CachingMode
==
nil
{
obj
.
CachingMode
=
new
(
v1
.
AzureDataDiskCachingMode
)
obj
.
CachingMode
=
new
(
v1
.
AzureDataDiskCachingMode
)
...
...
pkg/apis/core/validation/validation.go
View file @
bb34a0b7
...
@@ -720,6 +720,46 @@ func validateISCSIVolumeSource(iscsi *core.ISCSIVolumeSource, fldPath *field.Pat
...
@@ -720,6 +720,46 @@ func validateISCSIVolumeSource(iscsi *core.ISCSIVolumeSource, fldPath *field.Pat
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"iqn"
),
""
))
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"iqn"
),
""
))
}
else
{
}
else
{
if
!
strings
.
HasPrefix
(
iscsi
.
IQN
,
"iqn"
)
&&
!
strings
.
HasPrefix
(
iscsi
.
IQN
,
"eui"
)
&&
!
strings
.
HasPrefix
(
iscsi
.
IQN
,
"naa"
)
{
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 starting with iqn, eui, or naa"
))
}
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
)))
}
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 starting with iqn, eui, or naa"
))
}
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
}
func
validateISCSIPersistentVolumeSource
(
iscsi
*
core
.
ISCSIPersistentVolumeSource
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
allErrs
:=
field
.
ErrorList
{}
if
len
(
iscsi
.
TargetPortal
)
==
0
{
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"targetPortal"
),
""
))
}
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"
))
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
)
{
}
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"
))
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"iqn"
),
iscsi
.
IQN
,
"must be valid format"
))
...
@@ -735,6 +775,11 @@ func validateISCSIVolumeSource(iscsi *core.ISCSIVolumeSource, fldPath *field.Pat
...
@@ -735,6 +775,11 @@ func validateISCSIVolumeSource(iscsi *core.ISCSIVolumeSource, fldPath *field.Pat
if
(
iscsi
.
DiscoveryCHAPAuth
||
iscsi
.
SessionCHAPAuth
)
&&
iscsi
.
SecretRef
==
nil
{
if
(
iscsi
.
DiscoveryCHAPAuth
||
iscsi
.
SessionCHAPAuth
)
&&
iscsi
.
SecretRef
==
nil
{
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"secretRef"
),
""
))
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"secretRef"
),
""
))
}
}
if
iscsi
.
SecretRef
!=
nil
{
if
len
(
iscsi
.
SecretRef
.
Name
)
==
0
{
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"secretRef"
,
"name"
),
""
))
}
}
if
iscsi
.
InitiatorName
!=
nil
{
if
iscsi
.
InitiatorName
!=
nil
{
initiator
:=
*
iscsi
.
InitiatorName
initiator
:=
*
iscsi
.
InitiatorName
if
!
strings
.
HasPrefix
(
initiator
,
"iqn"
)
&&
!
strings
.
HasPrefix
(
initiator
,
"eui"
)
&&
!
strings
.
HasPrefix
(
initiator
,
"naa"
)
{
if
!
strings
.
HasPrefix
(
initiator
,
"iqn"
)
&&
!
strings
.
HasPrefix
(
initiator
,
"eui"
)
&&
!
strings
.
HasPrefix
(
initiator
,
"naa"
)
{
...
@@ -1517,7 +1562,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
...
@@ -1517,7 +1562,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
allErrs
=
append
(
allErrs
,
field
.
Forbidden
(
specPath
.
Child
(
"iscsi"
),
"may not specify more than 1 volume type"
))
allErrs
=
append
(
allErrs
,
field
.
Forbidden
(
specPath
.
Child
(
"iscsi"
),
"may not specify more than 1 volume type"
))
}
else
{
}
else
{
numVolumes
++
numVolumes
++
allErrs
=
append
(
allErrs
,
validateISCSIVolumeSource
(
pv
.
Spec
.
ISCSI
,
specPath
.
Child
(
"iscsi"
))
...
)
allErrs
=
append
(
allErrs
,
validateISCSI
Persistent
VolumeSource
(
pv
.
Spec
.
ISCSI
,
specPath
.
Child
(
"iscsi"
))
...
)
}
}
if
pv
.
Spec
.
ISCSI
.
InitiatorName
!=
nil
&&
len
(
pv
.
ObjectMeta
.
Name
+
":"
+
pv
.
Spec
.
ISCSI
.
TargetPortal
)
>
64
{
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."
tooLongErr
:=
"Total length of <volume name>:<iscsi.targetPortal> must be under 64 characters if iscsi.initiatorName is specified."
...
...
pkg/printers/internalversion/describe.go
View file @
bb34a0b7
...
@@ -856,6 +856,26 @@ func printISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, w PrefixWriter) {
...
@@ -856,6 +856,26 @@ func printISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, w PrefixWriter) {
iscsi
.
TargetPortal
,
iscsi
.
IQN
,
iscsi
.
Lun
,
iscsi
.
ISCSIInterface
,
iscsi
.
FSType
,
iscsi
.
ReadOnly
,
iscsi
.
Portals
,
iscsi
.
DiscoveryCHAPAuth
,
iscsi
.
SessionCHAPAuth
,
iscsi
.
SecretRef
,
initiator
)
iscsi
.
TargetPortal
,
iscsi
.
IQN
,
iscsi
.
Lun
,
iscsi
.
ISCSIInterface
,
iscsi
.
FSType
,
iscsi
.
ReadOnly
,
iscsi
.
Portals
,
iscsi
.
DiscoveryCHAPAuth
,
iscsi
.
SessionCHAPAuth
,
iscsi
.
SecretRef
,
initiator
)
}
}
func
printISCSIPersistentVolumeSource
(
iscsi
*
api
.
ISCSIPersistentVolumeSource
,
w
PrefixWriter
)
{
initiatorName
:=
"<none>"
if
iscsi
.
InitiatorName
!=
nil
{
initiatorName
=
*
iscsi
.
InitiatorName
}
w
.
Write
(
LEVEL_2
,
"Type:
\t
ISCSI (an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod)
\n
"
+
" TargetPortal:
\t
%v
\n
"
+
" IQN:
\t
%v
\n
"
+
" Lun:
\t
%v
\n
"
+
" ISCSIInterface
\t
%v
\n
"
+
" FSType:
\t
%v
\n
"
+
" ReadOnly:
\t
%v
\n
"
+
" Portals:
\t
%v
\n
"
+
" DiscoveryCHAPAuth:
\t
%v
\n
"
+
" SessionCHAPAuth:
\t
%v
\n
"
+
" SecretRef:
\t
%v
\n
"
+
" InitiatorName:
\t
%v
\n
"
,
iscsi
.
TargetPortal
,
iscsi
.
IQN
,
iscsi
.
Lun
,
iscsi
.
ISCSIInterface
,
iscsi
.
FSType
,
iscsi
.
ReadOnly
,
iscsi
.
Portals
,
iscsi
.
DiscoveryCHAPAuth
,
iscsi
.
SessionCHAPAuth
,
iscsi
.
SecretRef
,
initiatorName
)
}
func
printGlusterfsVolumeSource
(
glusterfs
*
api
.
GlusterfsVolumeSource
,
w
PrefixWriter
)
{
func
printGlusterfsVolumeSource
(
glusterfs
*
api
.
GlusterfsVolumeSource
,
w
PrefixWriter
)
{
w
.
Write
(
LEVEL_2
,
"Type:
\t
Glusterfs (a Glusterfs mount on the host that shares a pod's lifetime)
\n
"
+
w
.
Write
(
LEVEL_2
,
"Type:
\t
Glusterfs (a Glusterfs mount on the host that shares a pod's lifetime)
\n
"
+
" EndpointsName:
\t
%v
\n
"
+
" EndpointsName:
\t
%v
\n
"
+
...
@@ -1131,7 +1151,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
...
@@ -1131,7 +1151,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case
pv
.
Spec
.
NFS
!=
nil
:
case
pv
.
Spec
.
NFS
!=
nil
:
printNFSVolumeSource
(
pv
.
Spec
.
NFS
,
w
)
printNFSVolumeSource
(
pv
.
Spec
.
NFS
,
w
)
case
pv
.
Spec
.
ISCSI
!=
nil
:
case
pv
.
Spec
.
ISCSI
!=
nil
:
printISCSIVolumeSource
(
pv
.
Spec
.
ISCSI
,
w
)
printISCSI
Persistent
VolumeSource
(
pv
.
Spec
.
ISCSI
,
w
)
case
pv
.
Spec
.
Glusterfs
!=
nil
:
case
pv
.
Spec
.
Glusterfs
!=
nil
:
printGlusterfsVolumeSource
(
pv
.
Spec
.
Glusterfs
,
w
)
printGlusterfsVolumeSource
(
pv
.
Spec
.
Glusterfs
,
w
)
case
pv
.
Spec
.
RBD
!=
nil
:
case
pv
.
Spec
.
RBD
!=
nil
:
...
...
pkg/printers/internalversion/describe_test.go
View file @
bb34a0b7
...
@@ -853,7 +853,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
...
@@ -853,7 +853,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"bar"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"bar"
},
Spec
:
api
.
PersistentVolumeSpec
{
Spec
:
api
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
api
.
PersistentVolumeSource
{
PersistentVolumeSource
:
api
.
PersistentVolumeSource
{
ISCSI
:
&
api
.
ISCSIVolumeSource
{},
ISCSI
:
&
api
.
ISCSI
Persistent
VolumeSource
{},
},
},
},
},
},
},
...
...
pkg/volume/iscsi/BUILD
View file @
bb34a0b7
...
@@ -23,6 +23,7 @@ go_library(
...
@@ -23,6 +23,7 @@ go_library(
"//pkg/volume/util:go_default_library",
"//pkg/volume/util:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
],
],
)
)
...
...
pkg/volume/iscsi/attacher.go
View file @
bb34a0b7
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"github.com/golang/glog"
"github.com/golang/glog"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume"
...
@@ -100,7 +101,7 @@ func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string,
...
@@ -100,7 +101,7 @@ func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string,
return
err
return
err
}
}
}
}
volumeSource
,
readOnly
,
err
:=
getVolumeSource
(
spec
)
readOnly
,
fsType
,
err
:=
getISCSIVolumeInfo
(
spec
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -112,7 +113,7 @@ func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string,
...
@@ -112,7 +113,7 @@ func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string,
if
notMnt
{
if
notMnt
{
diskMounter
:=
&
mount
.
SafeFormatAndMount
{
Interface
:
mounter
,
Exec
:
attacher
.
host
.
GetExec
(
iscsiPluginName
)}
diskMounter
:=
&
mount
.
SafeFormatAndMount
{
Interface
:
mounter
,
Exec
:
attacher
.
host
.
GetExec
(
iscsiPluginName
)}
mountOptions
:=
volume
.
MountOptionFromSpec
(
spec
,
options
...
)
mountOptions
:=
volume
.
MountOptionFromSpec
(
spec
,
options
...
)
err
=
diskMounter
.
FormatAndMount
(
devicePath
,
deviceMountPath
,
volumeSource
.
FS
Type
,
mountOptions
)
err
=
diskMounter
.
FormatAndMount
(
devicePath
,
deviceMountPath
,
fs
Type
,
mountOptions
)
if
err
!=
nil
{
if
err
!=
nil
{
os
.
Remove
(
deviceMountPath
)
os
.
Remove
(
deviceMountPath
)
return
err
return
err
...
@@ -159,29 +160,75 @@ func (detacher *iscsiDetacher) UnmountDevice(deviceMountPath string) error {
...
@@ -159,29 +160,75 @@ func (detacher *iscsiDetacher) UnmountDevice(deviceMountPath string) error {
func
(
attacher
*
iscsiAttacher
)
volumeSpecToMounter
(
spec
*
volume
.
Spec
,
host
volume
.
VolumeHost
,
pod
*
v1
.
Pod
)
(
*
iscsiDiskMounter
,
error
)
{
func
(
attacher
*
iscsiAttacher
)
volumeSpecToMounter
(
spec
*
volume
.
Spec
,
host
volume
.
VolumeHost
,
pod
*
v1
.
Pod
)
(
*
iscsiDiskMounter
,
error
)
{
var
secret
map
[
string
]
string
var
secret
map
[
string
]
string
var
bkportal
[]
string
var
bkportal
[]
string
iscsi
,
readOnly
,
err
:=
getVolumeSource
(
spec
)
readOnly
,
fsType
,
err
:=
getISCSIVolumeInfo
(
spec
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// Obtain secret for AttachDisk
if
pod
!=
nil
{
if
iscsi
.
SecretRef
!=
nil
&&
pod
!=
nil
{
chapDiscovery
,
err
:=
getISCSIDiscoveryCHAPInfo
(
spec
)
if
secret
,
err
=
volumeutil
.
GetSecretForPod
(
pod
,
iscsi
.
SecretRef
.
Name
,
host
.
GetKubeClient
());
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"Couldn't get secret from %v/%v"
,
pod
.
Namespace
,
iscsi
.
SecretRef
)
return
nil
,
err
}
chapSession
,
err
:=
getISCSISessionCHAPInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
chapDiscovery
||
chapSession
{
secretName
,
secretNamespace
,
err
:=
getISCSISecretNameAndNamespace
(
spec
,
pod
.
Namespace
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
secretNamespace
)
==
0
||
len
(
secretName
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"CHAP enabled but secret name or namespace is empty"
)
}
// if secret is provided, retrieve it
kubeClient
:=
host
.
GetKubeClient
()
if
kubeClient
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Cannot get kube client"
)
}
secretObj
,
err
:=
kubeClient
.
Core
()
.
Secrets
(
secretNamespace
)
.
Get
(
secretName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Couldn't get secret %v/%v error: %v"
,
secretNamespace
,
secretName
,
err
)
return
nil
,
err
}
secret
=
make
(
map
[
string
]
string
)
for
name
,
data
:=
range
secretObj
.
Data
{
glog
.
V
(
6
)
.
Infof
(
"retrieving CHAP secret name: %s"
,
name
)
secret
[
name
]
=
string
(
data
)
}
}
}
tp
,
portals
,
iqn
,
lunStr
,
err
:=
getISCSITargetInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
}
lun
:=
strconv
.
Itoa
(
int
(
iscsi
.
Lun
))
portal
:=
portalMounter
(
iscsi
.
TargetPortal
)
lun
:=
strconv
.
Itoa
(
int
(
lunStr
))
portal
:=
portalMounter
(
tp
)
bkportal
=
append
(
bkportal
,
portal
)
bkportal
=
append
(
bkportal
,
portal
)
for
_
,
tp
:=
range
iscsi
.
P
ortals
{
for
_
,
p
:=
range
p
ortals
{
bkportal
=
append
(
bkportal
,
portalMounter
(
string
(
t
p
)))
bkportal
=
append
(
bkportal
,
portalMounter
(
string
(
p
)))
}
}
iface
:=
iscsi
.
ISCSIInterface
exec
:=
attacher
.
host
.
GetExec
(
iscsiPluginName
)
iface
,
initiatorNamePtr
,
err
:=
getISCSIInitiatorInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
var
initiatorName
string
var
initiatorName
string
if
i
scsi
.
InitiatorName
!=
nil
{
if
i
nitiatorNamePtr
!=
nil
{
initiatorName
=
*
i
scsi
.
InitiatorName
initiatorName
=
*
i
nitiatorNamePtr
}
}
chapDiscovery
,
err
:=
getISCSIDiscoveryCHAPInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
chapSession
,
err
:=
getISCSISessionCHAPInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
exec
:=
attacher
.
host
.
GetExec
(
iscsiPluginName
)
return
&
iscsiDiskMounter
{
return
&
iscsiDiskMounter
{
iscsiDisk
:
&
iscsiDisk
{
iscsiDisk
:
&
iscsiDisk
{
...
@@ -190,15 +237,15 @@ func (attacher *iscsiAttacher) volumeSpecToMounter(spec *volume.Spec, host volum
...
@@ -190,15 +237,15 @@ func (attacher *iscsiAttacher) volumeSpecToMounter(spec *volume.Spec, host volum
},
},
VolName
:
spec
.
Name
(),
VolName
:
spec
.
Name
(),
Portals
:
bkportal
,
Portals
:
bkportal
,
Iqn
:
i
scsi
.
IQN
,
Iqn
:
i
qn
,
lun
:
lun
,
lun
:
lun
,
Iface
:
iface
,
Iface
:
iface
,
chap_discovery
:
iscsi
.
DiscoveryCHAPAuth
,
chap_discovery
:
chapDiscovery
,
chap_session
:
iscsi
.
SessionCHAPAuth
,
chap_session
:
chapSession
,
secret
:
secret
,
secret
:
secret
,
InitiatorName
:
initiatorName
,
InitiatorName
:
initiatorName
,
manager
:
&
ISCSIUtil
{}},
manager
:
&
ISCSIUtil
{}},
fsType
:
iscsi
.
FS
Type
,
fsType
:
fs
Type
,
readOnly
:
readOnly
,
readOnly
:
readOnly
,
mounter
:
&
mount
.
SafeFormatAndMount
{
Interface
:
host
.
GetMounter
(
iscsiPluginName
),
Exec
:
exec
},
mounter
:
&
mount
.
SafeFormatAndMount
{
Interface
:
host
.
GetMounter
(
iscsiPluginName
),
Exec
:
exec
},
exec
:
exec
,
exec
:
exec
,
...
...
pkg/volume/iscsi/iscsi.go
View file @
bb34a0b7
...
@@ -23,6 +23,7 @@ import (
...
@@ -23,6 +23,7 @@ import (
"github.com/golang/glog"
"github.com/golang/glog"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/util/mount"
utilstrings
"k8s.io/kubernetes/pkg/util/strings"
utilstrings
"k8s.io/kubernetes/pkg/util/strings"
...
@@ -56,16 +57,12 @@ func (plugin *iscsiPlugin) GetPluginName() string {
...
@@ -56,16 +57,12 @@ func (plugin *iscsiPlugin) GetPluginName() string {
}
}
func
(
plugin
*
iscsiPlugin
)
GetVolumeName
(
spec
*
volume
.
Spec
)
(
string
,
error
)
{
func
(
plugin
*
iscsiPlugin
)
GetVolumeName
(
spec
*
volume
.
Spec
)
(
string
,
error
)
{
volumeSource
,
_
,
err
:=
getVolumeSource
(
spec
)
tp
,
_
,
iqn
,
lun
,
err
:=
getISCSITargetInfo
(
spec
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
return
fmt
.
Sprintf
(
return
fmt
.
Sprintf
(
"%v:%v:%v"
,
tp
,
iqn
,
lun
),
nil
"%v:%v:%v"
,
volumeSource
.
TargetPortal
,
volumeSource
.
IQN
,
volumeSource
.
Lun
),
nil
}
}
func
(
plugin
*
iscsiPlugin
)
CanSupport
(
spec
*
volume
.
Spec
)
bool
{
func
(
plugin
*
iscsiPlugin
)
CanSupport
(
spec
*
volume
.
Spec
)
bool
{
...
@@ -98,41 +95,80 @@ func (plugin *iscsiPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
...
@@ -98,41 +95,80 @@ func (plugin *iscsiPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
func
(
plugin
*
iscsiPlugin
)
NewMounter
(
spec
*
volume
.
Spec
,
pod
*
v1
.
Pod
,
_
volume
.
VolumeOptions
)
(
volume
.
Mounter
,
error
)
{
func
(
plugin
*
iscsiPlugin
)
NewMounter
(
spec
*
volume
.
Spec
,
pod
*
v1
.
Pod
,
_
volume
.
VolumeOptions
)
(
volume
.
Mounter
,
error
)
{
// Inject real implementations here, test through the internal function.
// Inject real implementations here, test through the internal function.
var
secret
map
[
string
]
string
var
secret
map
[
string
]
string
source
,
_
,
err
:=
getVolumeSource
(
spec
)
if
pod
==
nil
{
return
nil
,
fmt
.
Errorf
(
"nil pod"
)
}
chapDiscover
,
err
:=
getISCSIDiscoveryCHAPInfo
(
spec
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
chapSession
,
err
:=
getISCSISessionCHAPInfo
(
spec
)
if
source
.
SecretRef
!=
nil
{
if
err
!=
nil
{
if
secret
,
err
=
ioutil
.
GetSecretForPod
(
pod
,
source
.
SecretRef
.
Name
,
plugin
.
host
.
GetKubeClient
());
err
!=
nil
{
return
nil
,
err
glog
.
Errorf
(
"Couldn't get secret from %v/%v"
,
pod
.
Namespace
,
source
.
SecretRef
)
}
if
chapDiscover
||
chapSession
{
secretName
,
secretNamespace
,
err
:=
getISCSISecretNameAndNamespace
(
spec
,
pod
.
Namespace
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
}
if
len
(
secretName
)
>
0
&&
len
(
secretNamespace
)
>
0
{
// if secret is provideded, retrieve it
kubeClient
:=
plugin
.
host
.
GetKubeClient
()
if
kubeClient
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Cannot get kube client"
)
}
secretObj
,
err
:=
kubeClient
.
Core
()
.
Secrets
(
secretNamespace
)
.
Get
(
secretName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Couldn't get secret %v/%v error: %v"
,
secretNamespace
,
secretName
,
err
)
return
nil
,
err
}
secret
=
make
(
map
[
string
]
string
)
for
name
,
data
:=
range
secretObj
.
Data
{
glog
.
V
(
4
)
.
Infof
(
"retrieving CHAP secret name: %s"
,
name
)
secret
[
name
]
=
string
(
data
)
}
}
}
return
plugin
.
newMounterInternal
(
spec
,
pod
.
UID
,
&
ISCSIUtil
{},
plugin
.
host
.
GetMounter
(
plugin
.
GetPluginName
()),
plugin
.
host
.
GetExec
(
plugin
.
GetPluginName
()),
secret
)
return
plugin
.
newMounterInternal
(
spec
,
pod
.
UID
,
&
ISCSIUtil
{},
plugin
.
host
.
GetMounter
(
plugin
.
GetPluginName
()),
plugin
.
host
.
GetExec
(
plugin
.
GetPluginName
()),
secret
)
}
}
func
(
plugin
*
iscsiPlugin
)
newMounterInternal
(
spec
*
volume
.
Spec
,
podUID
types
.
UID
,
manager
diskManager
,
mounter
mount
.
Interface
,
exec
mount
.
Exec
,
secret
map
[
string
]
string
)
(
volume
.
Mounter
,
error
)
{
func
(
plugin
*
iscsiPlugin
)
newMounterInternal
(
spec
*
volume
.
Spec
,
podUID
types
.
UID
,
manager
diskManager
,
mounter
mount
.
Interface
,
exec
mount
.
Exec
,
secret
map
[
string
]
string
)
(
volume
.
Mounter
,
error
)
{
// iscsi volumes used directly in a pod have a ReadOnly flag set by the pod author.
// iscsi volumes used directly in a pod have a ReadOnly flag set by the pod author.
// iscsi volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
// iscsi volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
iscsi
,
readOnly
,
err
:=
getVolumeSource
(
spec
)
readOnly
,
fsType
,
err
:=
getISCSIVolumeInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
tp
,
portals
,
iqn
,
lunStr
,
err
:=
getISCSITargetInfo
(
spec
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
lun
:=
strconv
.
Itoa
(
int
(
iscsi
.
Lun
))
lun
:=
strconv
.
Itoa
(
int
(
lunStr
))
portal
:=
portalMounter
(
iscsi
.
TargetPortal
)
portal
:=
portalMounter
(
tp
)
var
bkportal
[]
string
var
bkportal
[]
string
bkportal
=
append
(
bkportal
,
portal
)
bkportal
=
append
(
bkportal
,
portal
)
for
_
,
tp
:=
range
iscsi
.
Portals
{
for
_
,
p
:=
range
portals
{
bkportal
=
append
(
bkportal
,
portalMounter
(
string
(
tp
)))
bkportal
=
append
(
bkportal
,
portalMounter
(
string
(
p
)))
}
iface
,
initiatorNamePtr
,
err
:=
getISCSIInitiatorInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
}
iface
:=
iscsi
.
ISCSIInterface
var
initiatorName
string
var
initiatorName
string
if
iscsi
.
InitiatorName
!=
nil
{
if
initiatorNamePtr
!=
nil
{
initiatorName
=
*
iscsi
.
InitiatorName
initiatorName
=
*
initiatorNamePtr
}
chapDiscovery
,
err
:=
getISCSIDiscoveryCHAPInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
chapSession
,
err
:=
getISCSISessionCHAPInfo
(
spec
)
if
err
!=
nil
{
return
nil
,
err
}
}
return
&
iscsiDiskMounter
{
return
&
iscsiDiskMounter
{
...
@@ -140,16 +176,16 @@ func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UI
...
@@ -140,16 +176,16 @@ func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UI
podUID
:
podUID
,
podUID
:
podUID
,
VolName
:
spec
.
Name
(),
VolName
:
spec
.
Name
(),
Portals
:
bkportal
,
Portals
:
bkportal
,
Iqn
:
i
scsi
.
IQN
,
Iqn
:
i
qn
,
lun
:
lun
,
lun
:
lun
,
Iface
:
iface
,
Iface
:
iface
,
chap_discovery
:
iscsi
.
DiscoveryCHAPAuth
,
chap_discovery
:
chapDiscovery
,
chap_session
:
iscsi
.
SessionCHAPAuth
,
chap_session
:
chapSession
,
secret
:
secret
,
secret
:
secret
,
InitiatorName
:
initiatorName
,
InitiatorName
:
initiatorName
,
manager
:
manager
,
manager
:
manager
,
plugin
:
plugin
},
plugin
:
plugin
},
fsType
:
iscsi
.
FS
Type
,
fsType
:
fs
Type
,
readOnly
:
readOnly
,
readOnly
:
readOnly
,
mounter
:
&
mount
.
SafeFormatAndMount
{
Interface
:
mounter
,
Exec
:
exec
},
mounter
:
&
mount
.
SafeFormatAndMount
{
Interface
:
mounter
,
Exec
:
exec
},
exec
:
exec
,
exec
:
exec
,
...
@@ -277,13 +313,87 @@ func portalMounter(portal string) string {
...
@@ -277,13 +313,87 @@ func portalMounter(portal string) string {
return
portal
return
portal
}
}
func
getVolumeSource
(
spec
*
volume
.
Spec
)
(
*
v1
.
ISCSIVolumeSource
,
bool
,
error
)
{
// get iSCSI volume info: readOnly and fstype
func
getISCSIVolumeInfo
(
spec
*
volume
.
Spec
)
(
bool
,
string
,
error
)
{
// for volume source, readonly is in volume spec
// for PV, readonly is in PV spec
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
return
spec
.
Volume
.
ISCSI
.
ReadOnly
,
spec
.
Volume
.
ISCSI
.
FSType
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
return
spec
.
ReadOnly
,
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
FSType
,
nil
}
return
false
,
""
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
// get iSCSI target info: target portal, portals, iqn, and lun
func
getISCSITargetInfo
(
spec
*
volume
.
Spec
)
(
string
,
[]
string
,
string
,
int32
,
error
)
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
return
spec
.
Volume
.
ISCSI
.
TargetPortal
,
spec
.
Volume
.
ISCSI
.
Portals
,
spec
.
Volume
.
ISCSI
.
IQN
,
spec
.
Volume
.
ISCSI
.
Lun
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
return
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
TargetPortal
,
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
Portals
,
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
IQN
,
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
Lun
,
nil
}
return
""
,
nil
,
""
,
0
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
// get iSCSI initiator info: iface and initiator name
func
getISCSIInitiatorInfo
(
spec
*
volume
.
Spec
)
(
string
,
*
string
,
error
)
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
return
spec
.
Volume
.
ISCSI
,
spec
.
Volume
.
ISCSI
.
ReadOnly
,
nil
return
spec
.
Volume
.
ISCSI
.
ISCSIInterface
,
spec
.
Volume
.
ISCSI
.
InitiatorName
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
return
spec
.
PersistentVolume
.
Spec
.
ISCSI
,
spec
.
ReadOnly
,
nil
return
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
ISCSIInterface
,
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
InitiatorName
,
nil
}
return
""
,
nil
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
// get iSCSI Discovery CHAP boolean
func
getISCSIDiscoveryCHAPInfo
(
spec
*
volume
.
Spec
)
(
bool
,
error
)
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
return
spec
.
Volume
.
ISCSI
.
DiscoveryCHAPAuth
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
return
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
DiscoveryCHAPAuth
,
nil
}
return
false
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
// get iSCSI Session CHAP boolean
func
getISCSISessionCHAPInfo
(
spec
*
volume
.
Spec
)
(
bool
,
error
)
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
return
spec
.
Volume
.
ISCSI
.
SessionCHAPAuth
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
return
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
SessionCHAPAuth
,
nil
}
return
false
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
// get iSCSI CHAP Secret info: secret name and namespace
func
getISCSISecretNameAndNamespace
(
spec
*
volume
.
Spec
,
defaultSecretNamespace
string
)
(
string
,
string
,
error
)
{
if
spec
.
Volume
!=
nil
&&
spec
.
Volume
.
ISCSI
!=
nil
{
if
spec
.
Volume
.
ISCSI
.
SecretRef
!=
nil
{
return
spec
.
Volume
.
ISCSI
.
SecretRef
.
Name
,
defaultSecretNamespace
,
nil
}
return
""
,
""
,
nil
}
else
if
spec
.
PersistentVolume
!=
nil
&&
spec
.
PersistentVolume
.
Spec
.
ISCSI
!=
nil
{
secretRef
:=
spec
.
PersistentVolume
.
Spec
.
ISCSI
.
SecretRef
secretNs
:=
defaultSecretNamespace
if
secretRef
!=
nil
{
if
len
(
secretRef
.
Namespace
)
!=
0
{
secretNs
=
secretRef
.
Namespace
}
return
secretRef
.
Name
,
secretNs
,
nil
}
return
""
,
""
,
nil
}
}
return
nil
,
false
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
return
""
,
""
,
fmt
.
Errorf
(
"Spec does not reference an ISCSI volume type"
)
}
}
pkg/volume/iscsi/iscsi_test.go
View file @
bb34a0b7
...
@@ -205,7 +205,7 @@ func TestPluginPersistentVolume(t *testing.T) {
...
@@ -205,7 +205,7 @@ func TestPluginPersistentVolume(t *testing.T) {
},
},
Spec
:
v1
.
PersistentVolumeSpec
{
Spec
:
v1
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
ISCSI
:
&
v1
.
ISCSIVolumeSource
{
ISCSI
:
&
v1
.
ISCSI
Persistent
VolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
FSType
:
"ext4"
,
...
@@ -230,7 +230,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
...
@@ -230,7 +230,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
},
},
Spec
:
v1
.
PersistentVolumeSpec
{
Spec
:
v1
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
ISCSI
:
&
v1
.
ISCSIVolumeSource
{
ISCSI
:
&
v1
.
ISCSI
Persistent
VolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
FSType
:
"ext4"
,
...
@@ -283,3 +283,146 @@ func TestPortalMounter(t *testing.T) {
...
@@ -283,3 +283,146 @@ func TestPortalMounter(t *testing.T) {
t
.
Errorf
(
"wrong portal: %s"
,
portal
)
t
.
Errorf
(
"wrong portal: %s"
,
portal
)
}
}
}
}
type
testcase
struct
{
name
string
defaultNs
string
spec
*
volume
.
Spec
// Expected return of the test
expectedName
string
expectedNs
string
expectedIface
string
expectedError
error
}
func
TestGetSecretNameAndNamespaceForPV
(
t
*
testing
.
T
)
{
tests
:=
[]
testcase
{
{
name
:
"persistent volume source"
,
defaultNs
:
"default"
,
spec
:
&
volume
.
Spec
{
PersistentVolume
:
&
v1
.
PersistentVolume
{
Spec
:
v1
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
ISCSI
:
&
v1
.
ISCSIPersistentVolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
Lun
:
0
,
SecretRef
:
&
v1
.
SecretReference
{
Name
:
"name"
,
Namespace
:
"ns"
,
},
},
},
},
},
},
expectedName
:
"name"
,
expectedNs
:
"ns"
,
expectedError
:
nil
,
},
{
name
:
"persistent volume source without namespace"
,
defaultNs
:
"default"
,
spec
:
&
volume
.
Spec
{
PersistentVolume
:
&
v1
.
PersistentVolume
{
Spec
:
v1
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
ISCSI
:
&
v1
.
ISCSIPersistentVolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
Lun
:
0
,
SecretRef
:
&
v1
.
SecretReference
{
Name
:
"name"
,
},
},
},
},
},
},
expectedName
:
"name"
,
expectedNs
:
"default"
,
expectedError
:
nil
,
},
{
name
:
"pod volume source"
,
defaultNs
:
"default"
,
spec
:
&
volume
.
Spec
{
Volume
:
&
v1
.
Volume
{
VolumeSource
:
v1
.
VolumeSource
{
ISCSI
:
&
v1
.
ISCSIVolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
Lun
:
0
,
},
},
},
},
expectedName
:
""
,
expectedNs
:
""
,
expectedError
:
nil
,
},
}
for
_
,
testcase
:=
range
tests
{
resultName
,
resultNs
,
err
:=
getISCSISecretNameAndNamespace
(
testcase
.
spec
,
testcase
.
defaultNs
)
if
err
!=
testcase
.
expectedError
||
resultName
!=
testcase
.
expectedName
||
resultNs
!=
testcase
.
expectedNs
{
t
.
Errorf
(
"%s failed: expected err=%v ns=%q name=%q, got %v/%q/%q"
,
testcase
.
name
,
testcase
.
expectedError
,
testcase
.
expectedNs
,
testcase
.
expectedName
,
err
,
resultNs
,
resultName
)
}
}
}
func
TestGetISCSIInitiatorInfo
(
t
*
testing
.
T
)
{
tests
:=
[]
testcase
{
{
name
:
"persistent volume source"
,
spec
:
&
volume
.
Spec
{
PersistentVolume
:
&
v1
.
PersistentVolume
{
Spec
:
v1
.
PersistentVolumeSpec
{
PersistentVolumeSource
:
v1
.
PersistentVolumeSource
{
ISCSI
:
&
v1
.
ISCSIPersistentVolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
Lun
:
0
,
ISCSIInterface
:
"tcp"
,
},
},
},
},
},
expectedIface
:
"tcp"
,
expectedError
:
nil
,
},
{
name
:
"pod volume source"
,
spec
:
&
volume
.
Spec
{
Volume
:
&
v1
.
Volume
{
VolumeSource
:
v1
.
VolumeSource
{
ISCSI
:
&
v1
.
ISCSIVolumeSource
{
TargetPortal
:
"127.0.0.1:3260"
,
IQN
:
"iqn.2014-12.server:storage.target01"
,
FSType
:
"ext4"
,
Lun
:
0
,
ISCSIInterface
:
"tcp"
,
},
},
},
},
expectedIface
:
"tcp"
,
expectedError
:
nil
,
},
}
for
_
,
testcase
:=
range
tests
{
resultIface
,
_
,
err
:=
getISCSIInitiatorInfo
(
testcase
.
spec
)
if
err
!=
testcase
.
expectedError
||
resultIface
!=
testcase
.
expectedIface
{
t
.
Errorf
(
"%s failed: expected err=%v iface=%s, got %v/%s"
,
testcase
.
name
,
testcase
.
expectedError
,
testcase
.
expectedIface
,
err
,
resultIface
)
}
}
}
staging/src/k8s.io/api/core/v1/types.go
View file @
bb34a0b7
...
@@ -402,7 +402,7 @@ type PersistentVolumeSource struct {
...
@@ -402,7 +402,7 @@ type PersistentVolumeSource struct {
// ISCSI represents an ISCSI Disk resource that is attached to a
// 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.
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
// +optional
// +optional
ISCSI
*
ISCSIVolumeSource
`json:"iscsi,omitempty" protobuf:"bytes,7,opt,name=iscsi"`
ISCSI
*
ISCSI
Persistent
VolumeSource
`json:"iscsi,omitempty" protobuf:"bytes,7,opt,name=iscsi"`
// Cinder represents a cinder volume attached and mounted on kubelets host machine
// Cinder represents a cinder volume attached and mounted on kubelets host machine
// More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md
// More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md
// +optional
// +optional
...
@@ -1236,14 +1236,15 @@ type NFSVolumeSource struct {
...
@@ -1236,14 +1236,15 @@ type NFSVolumeSource struct {
// ISCSI volumes can only be mounted as read/write once.
// ISCSI volumes can only be mounted as read/write once.
// ISCSI volumes support ownership management and SELinux relabeling.
// ISCSI volumes support ownership management and SELinux relabeling.
type
ISCSIVolumeSource
struct
{
type
ISCSIVolumeSource
struct
{
// iSCSI
target portal. The p
ortal is either an IP or ip_addr:port if the port
// iSCSI
Target Portal. The P
ortal is either an IP or ip_addr:port if the port
// is other than default (typically TCP ports 860 and 3260).
// is other than default (typically TCP ports 860 and 3260).
TargetPortal
string
`json:"targetPortal" protobuf:"bytes,1,opt,name=targetPortal"`
TargetPortal
string
`json:"targetPortal" protobuf:"bytes,1,opt,name=targetPortal"`
// Target iSCSI Qualified Name.
// Target iSCSI Qualified Name.
IQN
string
`json:"iqn" protobuf:"bytes,2,opt,name=iqn"`
IQN
string
`json:"iqn" protobuf:"bytes,2,opt,name=iqn"`
// iSCSI
target l
un number.
// iSCSI
Target L
un number.
Lun
int32
`json:"lun" protobuf:"varint,3,opt,name=lun"`
Lun
int32
`json:"lun" protobuf:"varint,3,opt,name=lun"`
// Optional: Defaults to 'default' (tcp). iSCSI interface name that uses an iSCSI transport.
// iSCSI Interface Name that uses an iSCSI transport.
// Defaults to 'default' (tcp).
// +optional
// +optional
ISCSIInterface
string
`json:"iscsiInterface,omitempty" protobuf:"bytes,4,opt,name=iscsiInterface"`
ISCSIInterface
string
`json:"iscsiInterface,omitempty" protobuf:"bytes,4,opt,name=iscsiInterface"`
// Filesystem type of the volume that you want to mount.
// Filesystem type of the volume that you want to mount.
...
@@ -1257,7 +1258,7 @@ type ISCSIVolumeSource struct {
...
@@ -1257,7 +1258,7 @@ type ISCSIVolumeSource struct {
// Defaults to false.
// Defaults to false.
// +optional
// +optional
ReadOnly
bool
`json:"readOnly,omitempty" protobuf:"varint,6,opt,name=readOnly"`
ReadOnly
bool
`json:"readOnly,omitempty" protobuf:"varint,6,opt,name=readOnly"`
// iSCSI
target p
ortal List. The portal is either an IP or ip_addr:port if the port
// iSCSI
Target P
ortal List. The portal is either an IP or ip_addr:port if the port
// is other than default (typically TCP ports 860 and 3260).
// is other than default (typically TCP ports 860 and 3260).
// +optional
// +optional
Portals
[]
string
`json:"portals,omitempty" protobuf:"bytes,7,opt,name=portals"`
Portals
[]
string
`json:"portals,omitempty" protobuf:"bytes,7,opt,name=portals"`
...
@@ -1267,10 +1268,56 @@ type ISCSIVolumeSource struct {
...
@@ -1267,10 +1268,56 @@ type ISCSIVolumeSource struct {
// whether support iSCSI Session CHAP authentication
// whether support iSCSI Session CHAP authentication
// +optional
// +optional
SessionCHAPAuth
bool
`json:"chapAuthSession,omitempty" protobuf:"varint,11,opt,name=chapAuthSession"`
SessionCHAPAuth
bool
`json:"chapAuthSession,omitempty" protobuf:"varint,11,opt,name=chapAuthSession"`
// CHAP
s
ecret for iSCSI target and initiator authentication
// CHAP
S
ecret for iSCSI target and initiator authentication
// +optional
// +optional
SecretRef
*
LocalObjectReference
`json:"secretRef,omitempty" protobuf:"bytes,10,opt,name=secretRef"`
SecretRef
*
LocalObjectReference
`json:"secretRef,omitempty" protobuf:"bytes,10,opt,name=secretRef"`
// Custom iSCSI initiator name.
// 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"`
}
// ISCSIPersistentVolumeSource represents an ISCSI disk.
// ISCSI volumes can only be mounted as read/write once.
// ISCSI volumes support ownership management and SELinux relabeling.
type
ISCSIPersistentVolumeSource
struct
{
// iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port
// is other than default (typically TCP ports 860 and 3260).
TargetPortal
string
`json:"targetPortal" protobuf:"bytes,1,opt,name=targetPortal"`
// Target iSCSI Qualified Name.
IQN
string
`json:"iqn" protobuf:"bytes,2,opt,name=iqn"`
// iSCSI Target Lun number.
Lun
int32
`json:"lun" protobuf:"varint,3,opt,name=lun"`
// iSCSI Interface Name that uses an iSCSI transport.
// Defaults to 'default' (tcp).
// +optional
ISCSIInterface
string
`json:"iscsiInterface,omitempty" protobuf:"bytes,4,opt,name=iscsiInterface"`
// 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
// TODO: how do we prevent errors in the filesystem from compromising the machine
// +optional
FSType
string
`json:"fsType,omitempty" protobuf:"bytes,5,opt,name=fsType"`
// ReadOnly here will force the ReadOnly setting in VolumeMounts.
// Defaults to false.
// +optional
ReadOnly
bool
`json:"readOnly,omitempty" protobuf:"varint,6,opt,name=readOnly"`
// iSCSI Target Portal List. The Portal is either an IP or ip_addr:port if the port
// is other than default (typically TCP ports 860 and 3260).
// +optional
Portals
[]
string
`json:"portals,omitempty" protobuf:"bytes,7,opt,name=portals"`
// whether support iSCSI Discovery CHAP authentication
// +optional
DiscoveryCHAPAuth
bool
`json:"chapAuthDiscovery,omitempty" protobuf:"varint,8,opt,name=chapAuthDiscovery"`
// whether support iSCSI Session CHAP authentication
// +optional
SessionCHAPAuth
bool
`json:"chapAuthSession,omitempty" protobuf:"varint,11,opt,name=chapAuthSession"`
// CHAP Secret for iSCSI target and initiator authentication
// +optional
SecretRef
*
SecretReference
`json:"secretRef,omitempty" protobuf:"bytes,10,opt,name=secretRef"`
// Custom iSCSI Initiator Name.
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
// <target portal>:<volume name> will be created for the connection.
// <target portal>:<volume name> will be created for the connection.
// +optional
// +optional
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment