From 695701c94cd9dde03fb7c6533783b0c56f5fcfa4 Mon Sep 17 00:00:00 2001 From: grosnj1 Date: Tue, 22 Sep 2020 15:24:38 -0400 Subject: [PATCH] release-1.2 --- .gitignore | 11 +- ...r for Dell EMC VxFlex OS Product Guide.pdf | Bin 154674 -> 207759 bytes ...r for Dell EMC VxFlex OS Release Notes.pdf | Bin 26756 -> 49132 bytes Dockerfile | 79 ++- Makefile | 54 +- README.md | 39 +- core/semver/semver.go | 3 + dell-csi-helm-installer/README.md | 157 +++++ ....storage.k8s.io_volumesnapshotclasses.yaml | 85 +++ ...storage.k8s.io_volumesnapshotcontents.yaml | 233 +++++++ ...apshot.storage.k8s.io_volumesnapshots.yaml | 188 ++++++ dell-csi-helm-installer/common.sh | 114 ++++ dell-csi-helm-installer/csi-install.sh | 391 +++++++++++ dell-csi-helm-installer/csi-uninstall.sh | 130 ++++ dell-csi-helm-installer/verify.sh | 605 ++++++++++++++++++ docker.mk | 18 +- go.mod | 6 +- go.sum | 21 +- helm/betasnapshotclass.yaml | 6 + helm/common.bash | 28 - helm/csi-vxflexos/Chart.yaml | 5 +- helm/csi-vxflexos/driver-image.yaml | 4 + ...-1.14-values.yaml => k8s-1.17-values.yaml} | 12 +- ...-1.13-values.yaml => k8s-1.18-values.yaml} | 14 +- ...-1.16-values.yaml => k8s-1.19-values.yaml} | 15 +- helm/csi-vxflexos/templates/controller.yaml | 25 +- helm/csi-vxflexos/templates/node.yaml | 5 + helm/csi-vxflexos/templates/snapclass.yaml | 6 + .../templates/storageclass-xfs.yaml | 9 + helm/csi-vxflexos/templates/storageclass.yaml | 7 + helm/csi-vxflexos/values.yaml | 24 - helm/install.vxflexos | 59 -- helm/uninstall.vxflexos | 9 - helm/verify.kubernetes | 76 --- helm/volumesnapshotclass.yaml | 5 - licenses/LICENSE | 202 ++++++ overrides.mk | 65 ++ service/controller.go | 112 +++- service/envvars.go | 15 +- service/features/authorization_failure.json | 6 + service/features/get_system_instances.json | 1 + .../features/node_publish_unpublish.feature | 109 ++-- service/features/service.feature | 99 ++- service/features/volume.json.template | 2 +- service/identity.go | 7 + service/mount.go | 356 +++++++---- service/node.go | 307 ++++++++- service/service.go | 9 +- service/service_test.go | 2 +- service/step_defs_test.go | 212 +++++- service/step_handlers_test.go | 20 + test/helm/betasnap1.yaml | 9 + test/helm/betasnap2.yaml | 9 + .../block1 => block/block-rwx}/Chart.yaml | 2 +- test/helm/block/block-rwx/templates/test.yaml | 47 ++ test/helm/block/block-rwx/values.yaml | 1 + test/helm/block/block1/Chart.yaml | 10 + test/helm/block/block1/templates/test.yaml | 41 ++ test/helm/block/block1/values.yaml | 2 + .../{unsupported => block}/block2/Chart.yaml | 2 +- test/helm/block/block2/templates/test.yaml | 53 ++ test/helm/block/block2/values.yaml | 2 + test/helm/blocksnap/1snap/Chart.yaml | 11 + .../helm/blocksnap/1snap/templates/snap1.yaml | 9 + test/helm/blocksnap/1vol/Chart.yaml | 11 + test/helm/blocksnap/1vol/templates/test.yaml | 47 ++ test/helm/blocksnap/1volfromsnap/Chart.yaml | 11 + .../1volfromsnap/templates/test.yaml | 49 ++ test/helm/blocksnap/README.md | 26 + test/helm/blocksnap/run.sh | 89 +++ test/helm/common.bash | 2 + test/helm/deletepvcs.sh | 2 +- test/helm/get.volume.ids | 2 +- test/helm/postgres.sh | 2 +- test/helm/snap1.yaml | 10 - test/helm/snap2.yaml | 10 - test/helm/snapcg.yaml | 10 - test/helm/snapcgtest.sh | 34 - test/helm/snaprestoretest.sh | 6 +- test/helm/snaptest.sh | 21 +- test/helm/starttest.sh | 2 +- test/helm/stoptest.sh | 2 +- .../block1/templates/block-pvc.yaml | 14 - .../unsupported/block1/templates/test.yaml | 33 - .../block2/templates/block-pv.yaml | 16 - .../block2/templates/block-pvc.yaml | 14 - .../unsupported/block2/templates/test.yaml | 34 - test/helm/volumesnapshotclass.yaml | 9 +- test/integration/features/integration.feature | 115 +++- test/integration/integration_test.go | 2 +- test/integration/run.sh | 2 +- test/integration/step_defs_test.go | 132 +++- test/sanity/run.sh | 2 +- 93 files changed, 4102 insertions(+), 772 deletions(-) create mode 100644 dell-csi-helm-installer/README.md create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml create mode 100644 dell-csi-helm-installer/common.sh create mode 100755 dell-csi-helm-installer/csi-install.sh create mode 100755 dell-csi-helm-installer/csi-uninstall.sh create mode 100755 dell-csi-helm-installer/verify.sh create mode 100644 helm/betasnapshotclass.yaml delete mode 100644 helm/common.bash create mode 100644 helm/csi-vxflexos/driver-image.yaml rename helm/csi-vxflexos/{k8s-1.14-values.yaml => k8s-1.17-values.yaml} (62%) rename helm/csi-vxflexos/{k8s-1.13-values.yaml => k8s-1.18-values.yaml} (54%) rename helm/csi-vxflexos/{k8s-1.16-values.yaml => k8s-1.19-values.yaml} (53%) create mode 100644 helm/csi-vxflexos/templates/snapclass.yaml delete mode 100755 helm/install.vxflexos delete mode 100755 helm/uninstall.vxflexos delete mode 100755 helm/verify.kubernetes delete mode 100644 helm/volumesnapshotclass.yaml create mode 100644 licenses/LICENSE create mode 100644 overrides.mk create mode 100644 service/features/authorization_failure.json create mode 100644 test/helm/betasnap1.yaml create mode 100644 test/helm/betasnap2.yaml rename test/helm/{unsupported/block1 => block/block-rwx}/Chart.yaml (88%) create mode 100644 test/helm/block/block-rwx/templates/test.yaml create mode 100644 test/helm/block/block-rwx/values.yaml create mode 100644 test/helm/block/block1/Chart.yaml create mode 100644 test/helm/block/block1/templates/test.yaml create mode 100644 test/helm/block/block1/values.yaml rename test/helm/{unsupported => block}/block2/Chart.yaml (88%) create mode 100644 test/helm/block/block2/templates/test.yaml create mode 100644 test/helm/block/block2/values.yaml create mode 100644 test/helm/blocksnap/1snap/Chart.yaml create mode 100644 test/helm/blocksnap/1snap/templates/snap1.yaml create mode 100644 test/helm/blocksnap/1vol/Chart.yaml create mode 100644 test/helm/blocksnap/1vol/templates/test.yaml create mode 100644 test/helm/blocksnap/1volfromsnap/Chart.yaml create mode 100644 test/helm/blocksnap/1volfromsnap/templates/test.yaml create mode 100644 test/helm/blocksnap/README.md create mode 100644 test/helm/blocksnap/run.sh mode change 100644 => 100755 test/helm/common.bash mode change 100644 => 100755 test/helm/deletepvcs.sh mode change 100644 => 100755 test/helm/postgres.sh delete mode 100644 test/helm/snap1.yaml delete mode 100644 test/helm/snap2.yaml delete mode 100644 test/helm/snapcg.yaml delete mode 100644 test/helm/snapcgtest.sh mode change 100644 => 100755 test/helm/snaprestoretest.sh mode change 100644 => 100755 test/helm/snaptest.sh delete mode 100644 test/helm/unsupported/block1/templates/block-pvc.yaml delete mode 100644 test/helm/unsupported/block1/templates/test.yaml delete mode 100644 test/helm/unsupported/block2/templates/block-pv.yaml delete mode 100644 test/helm/unsupported/block2/templates/block-pvc.yaml delete mode 100644 test/helm/unsupported/block2/templates/test.yaml diff --git a/.gitignore b/.gitignore index ba5090c9..b154780d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,10 @@ -csi-scaleio + +/csi-vxflexos +helm/.ps.out +service/c.out +service/test/ +test/integration/c.linux.out +test/integration/stderr +semver.mk +goscaleio/ +gofsutil/ diff --git a/CSI Driver for Dell EMC VxFlex OS Product Guide.pdf b/CSI Driver for Dell EMC VxFlex OS Product Guide.pdf index af20ef33547e94bfc9cf07044c9e18fd2fd25e16..9a8f7784d1d424b98eefceef710978cea130504e 100644 GIT binary patch literal 207759 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

6&*?`NV2S3wlmEFdD*Kv59S9zwiIz;bhW z>;n>ftTd;uAo_gG!7!dtepVHEFgzgGL~^$@9B~PUD7Uq=kR~t)xAkX(jpT4wi#2;p zrD}DTycf`pwQ=#y4-ZOG&{iNew+B)8BR@=a#u8AH;K)`~q4=TVhl{j*jx)a>ZzdF0 zCLr4!^q)Dizb*=v1a@-YM(L$L z_ji^AT$RoUo{PWgBbC3~C>~?=Qr<>Ki@&63ZN56Srx09^sZh^6Ex2Q(h2T5fqh0KVDPi0e@Q|(ON zPZbTspI6AUEvDMGX!!(Uam+|@S{H9)M;I3 zHD8Fv&=qNQ#o&)}!F?c$AA`9cXE~Y-LL}WtzfGAegWIq!C!^LkedPbZP}0*HB*cWq^Q@QZ*)d#qF(^=9iTBQtt@d^< zNy&ce=Pf4)+V&2}WT%GKJiVqU|aT5s4!mB~9I?4CS`~ zo-nc_rR^%klTkRVoa5tVBn8b|DM|`z9{u?ne=}R`f=rCStc0#q2_Eg@A{N9YGCigD zcnWDn7PEk8vm_lA-Dg32`%any)MK>S3smF}cs(Sqx!>8(yI+pEC9(Et;xx z2$^YCG5hTNh1l3N$vJkvbW5*vvy-XRzm?orT9EXNS~ynz;V2)Bg=FjvM*NPwf+V&7 zooBM6e6dq${yqn>VM(Ee)Gk4)0FW1(S~Gdv>En6Zz80*nD!ahdiD%M?cZ7qRp(I(%f58pC`ogr%Y7lqP@We^0b&k`H&S8`liid4LkJSi zJdB1IvBwz{{fD!mUJEypb65dAlr3O$YtXiF$Hw?!dz_9=PAtB;H~^k0muBK~TZpGs z9hrkA%xvKo{LTh8cR~gi^<7;CNd3dQDxui&ypO_OrkV51X%Sk)MKIn$nDEFK+`|b@HDd03X$bwt z5rj`iKF#{*n(q&ivJ&1by!-pTJZG}oz*bjcFXo)ZQcVGQ!;Nhw*w2=G(ZiOS@@-2R z1)I=M#35I0_!06D7!?`9mQ+7sq;l5DaPOK8Q!ae#I#?|VNNXEIeOsU(JXE}QmqiNJ z?WNsN0eWGC-o7w6;e=*&njESr)E-GvvqvpL>Rz_(gQB#FQzY1_lBQkn*9xf(g7)+Q z#F2%nfjbYqpq{yOON+p0nYUj(ZtsQS172qbNy$%=4(iA0x;x)K1rLm}NeMz9=G4C( z3V`;E+!cgl=N(&GafFQ7aapf+U+VKH{Um@sW^+EP`My9(Kfr}euPEOvp)Wr~=bJcw zr#Vp1`ZzMRn1xkuRu`KRieh3kXX>#|Ha((+-ibh4-3Z3hr(wRp;W6PLXyfr>4SPjI z)Fp<>bvR0)Q8e!3Q0?})?}Bc(m5v-q=Ayc;JHo5L?EN0+BL$81A5JvqL>Lj$C2160 z7XxHp#7V@pmyGReFiuh^_`dWHc!Mc(D)GPU-*j3ZC#>T-+4hP$=45vk?(A&4P&z7A zU5-X!e~=7^*TQd`ggVqxRxG8zSd2HQcBpBk4!`lxCE)$~dFAg7JAu~LdIt_gevNff zK%vM~B)cmw&aCrGW?JBmHjFMAy!loWF{&$0kE75AL^!-UKFI=f`x9#d3K7WgN(idw z$9@1aD35z#y5nASbg`tLLkgRn^UG9UY%e+jLK`R9Ls>zZQPqFiC^5GpwY1Vpm z#e?7S0ks=3Y;1Wn25C5yIRPqK0^FiuBYW3GJ!RpTX;iWfQL0g0P{q zZLxqFaWoIo78_k$$nyx*)>56j-dx0yhL)?-=%%t+h6%Dp9(>)CeLsir)N_2vMA*Tc z{)$5RBxT1IPD88I7qneMW{~;PRW6_Nxc@||;Bl_(6rm+iCX(TmUz9Nztvv&p5b*@F z<#v^hLP|es+5ot0E}IW-boMA!04ELJ!e{Wrp!TA=| z_j(|r_xSQPm34%UKt|qgH$Q;qg2cMR%cOTb((!^LpYWxlq!eYpurkmaC&gFnF&_`) zy%rCos4|3OhGe8Xz~B98Fl>-><kqYqq?b`+(jImytKW@c01w2>+tBG^W43)X#h| zg#j0>GzPhhovgC39Z>w|t`hK)(-O?zW4=|d?nnzs$CApFzy3T(;r#L*{`iD)nn24p zij6OB@8N!DqafG<;L<(<|D_!8_$3vd6DL3b^E&HyNg4}JlDJ=@-y7JD_Gz~-mBsre zd>N~w!tC{Q!#Fk0_IAIqVl(YQVe|t-7)poXkE0={oFwvPqY^$lw@q?7Ez9WiD;P>P zT)U0XJo9~D1gQ)+#vFfP;%_0Zh9*sWryhIfD~ViKo&Yb;JP^wNgS)p1iYt2CJ#lw; z4IbRx-CcqOcke)>!QBFc0Kwf|f=iGyIg1>?VcmpGEHkZNRI|(wmIO z8ob{USks85KQ8Ns5vuvSon=*fmmJhfUgy6das<}X|96t>f5_4QYf(0QeoD8lrVBVaIkKHIRHE1eT*v*asZQ!f81tQt#+XxD^&)?mzWd$xN$gY7F;`$-sM z-;^LE9W{hd7b)t{aQH{M1B1y60q`Ged-hB7*MIj*{wEXh|3TaS2f)>#5&kb&mPYu$ zl-U1wnC<^AWB>nDl;%_r_@__*m+t=mMW6nkyv+a2X3YP9Z~y7j|7#qV*{A=&xBqeB zTF=EAZE@ym*po52Z3yI)cy`UNUWR}C)7I9Rk$(QT%_;TugTxh1QMyll+iHzmOh^9n z)7Ps$zy6?WdpgM*p{xIjTE+-Oncm;hrc(1$JL&fm^}78-lu{5 z+mPEcYWZBHL(17NnbJq8?}@?jCu<{ ze5s}WtZUdX@88I3G$7ui|98dlbseegebzxF_#VN1>Z=Cvq`;EvWuXUFk0I9wZ|zS! zea&rsZr(`qKmUP4@mkq~{`yRx&HX%0BMMXSLy3{CZjF0tZn?$OJ{J5zzCiPk&y$pf zkkc&98SS^>ELZ77=8=g81Wl5ql0=)+*?gw`!<+7%!qfOPdt8WD(0k0Jq9b6T*BDrg z6Jnj8f&MmK|EQqyiBlgkY)`T*Q>n#o^D2bNI~%bR`7t?i7QWFYsx^wDTp=;7bw z_(}H`qn}M1Kjc-d3w&d6S!!XjNDYBtL*viizL)WeCRCRr)KDczEt*xGZ3 z`Hm79@B<0nC9Bj&+s_6zA9!$Dulv6$_oEvglqq2C)12b#2nW~o0-aBQv?#Q#J12Xrv6?| zks1~tKPyQ;lDw2MX0VE5S!5{^im*l<(^^}A(e%?bWFx^`gomU-&vi??OSrsdhrRUT zyQN-(GGjulkV=U-)8kM4&j<Ht0o7x6*;`&1HXRfG3uT+U0 zu@=aA-`1EWP75@8$TE`}wu(Hr)W4a_a*||(z=oT`Wu6G+GdrVL|6phxgb#)%zauv# zTjvvci{uz7M4^8cIO>_c(TI&?PKVw2J5fx7?zd-eeva%& z178@-QSylr=`}7yYsAroyj1Bw#2-R|D~;Fvg(6lH4;b6gL!8JU=N>v&EVUYzh+pYIH#T=fhA;0(CS@c^@(8V zx(p6oHiDs3vZoS*)d7&PsDH4_9e3kYhoZ7mO^KUvV#^uva{XER8U1xE;KYuApPk$} z``+2-mC<#C{p7x##R(WJ{i`6%60X$0Rs=?7|*kg}}5Tmh_j z&^&)!zPcq2iEf^jYn`PPzO#~xjYdK95dTWyQL@k}-EsRQT^1MhPvuywIb-exF8x_u z$m(yU-Pl|_?po(yKAV}6MZz=#;|4|}vXw!F$Sv6uEk&K`1-j#GG;PE0qJR2x55g}$ zloxRmP8QWn7cHWuN?XfOMT=ZASYj;$9Sk+6X(HP6>)KjFhxqyt3Xog?1?^cmqtyrEQR$U62;6N-koI6 z)wK~}v%L$xK*1H$T95cM!Q{{!=4e$1h|oEXDsr@sCz|m?wVg*3%`iZbb|Dx23;Orf z+OH=G9RRItqtCt!e1jPBn?orcmtπ|tl+G4}91oUjPq1rfMW;P&s#C9(mG)};dW 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 U?fZ*qvWC}$LD2~44{G!O0IN2IX8-^I literal 154674 zcmd?QWmII#vM!3dLnDn9H16(=J2dX@g}b}cxNGC??(Xi=IE}lzb6IPjbI-nStZU=_ zdgIlfs+^fKG9og*n3XZ}Bb5^trDddJMI_zcnVLg{V`gUoFaT@}%n^Bb=%vl9jrHx# z+>MO@jP%j~MizEvHYR#m05dxqy~tlp7FK#003$2C(r1H>gNc(~9H0qc;a~=^FtTg& z@*)~r8~r5;@b90`IXM1p4q;Z9RMu!a`whXW`>S7_5emE zUS4`pGfPKfdwNkzeMjSe-9j%RtjWX3D8Mc#B*Mum%*w#X$|fKxz#<|b%FfCt%)rJV z%)-IT!ywGa#vsDTC?vor%+AKbA;`?c!pXuYz|6ob$im3N%&Sc=VQpmWs`;1Y%%MujFQHOs}S3 zY(lT9$p~NqFn)T#!O`AW-wF}Vbi=^F2t`lNK#vX-Euu~!@as=aWResE{xudr4;45` zpr>!3I9m({=|p$`@GzVaBLl-WV99$Yz98mtD&`sq&<(<_2E%{|_vz99koh0Jb#T?S1@krhRR`!|0h!m%(i{MV9-0RCFSfAZ$1K^*^SFEi8M%gn+?uLxk` zVE!NM(9_cc%jJSH0pRp?Px*qpB9!wF_jcE0kBI4miKQXBM8`vb=kY5bjcEcE?U)M_ zVjzKJP?Yod6UNgB@H4a#VQzH4K<0cFiU_Eodf5=lqQq zZR^YE+CdW5xoX@)0XC&u72qAo5MI8u@#jnvuD{U8U72J9sohTc;jpB%vs*1HFUXn$ zt>ofT?@b3+A)un529co13ZkMum8_WQ>85}%VusOhboA9)2ZcbCmi)?}nGG$M?gvZK z-JK1Vlh88@(Dvtt(%}R3BLna2as^Bv_4jV_!y0S?wR-A;zVT1%7fNXZryw{7-Jm_N zu_5jXdGxGPyuvahehLUbgR9XReg_X2K|%@e^IHZL|HZ^$CkbMvr$$W!J*$Est#XXw zHfRU}3I!6NXJ-8mOZcxy`cKU1TLUSKt!b4NDd~S0JL((hJL&^i+5QeS8GS2b2LLn2 zzXDIz$sve6 z>i?yd+rNPI_rT9Y@Z&Qr=>IQ8e&&)-9X?HF`dbABV+R{2`%mjWXA%9>@2@Y0PX#&t z?iFSHbl=~)e#(}!w=q;ScGRT*Op5eM#;%U^5>}t?6Z!=5C*~bLQxAaQU)ucT)qnRA z`=_w~Sipb4mZ+J%gCpP*P5+rrI5|J_CfmP6$r_j|I$HfZ#Of2xWN{f$f$fRNQ3#VF<1O3NZ5EMGyuE;@KhR@*Gc_Uyhg=7l?{^UE)Le*C|7(%s1DFR z)em%88uGx~L=k)RHT3K!Pv67+7H=(2prPL9k zi^07`pAROMGgosF+MmaJ#GwrzJ>a-wSR2l~X!0^aU-PbT&tE5TSU&qRu%iyTR=n6o zHvUxMxM*I6sV$BM?L77mi|xDpNqipP>vr}Z+4|qkQ!VI|DM3T(K(nq3BP+u*&c*Dh zc<0ppN~kq&xvF^++dGy%`DH;(F`_~qLe_BFWvl`}K7FY^P! zWnGVKK==ntZ~33prr*EX?wQFEs4d_frloAquZ4P+$-Va9nENftcYmSQIc31S5rQFr zTo&+d{$u|93(Nm=`27d!nAq9>3uUe=%JLKD!3-$v2bA|qvqA=)8nl7@H5fd%AuCvy z;bmXU5f}+PU#xT0+-*}OoK1#@%br^r4MENZbv+fG$#2RK!Zj$w3s8|)(3F1EuNM?vdL_VOe z>En{7Gi%xgRr@ujc*l>wvnIC6M)uQ*h96wm)rH$c6TU#k_x$YsN8fV(ANiK!|KZy) z>p%vC_M0!fjmMzk$=XyR;+mzBc+YZ2$VLGVdLwqGrwAZ z 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 JYubrf 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�mW%oZKJy;K(1a6AQ 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 rrsemver.mk -# Tags the release with the Tag parameters set above -tag: - -git tag -d v$(MAJOR).$(MINOR).$(PATCH)$(NOTES) - git tag -a -m $(TAGMSG) v$(MAJOR).$(MINOR).$(PATCH)$(NOTES) +# Build the driver locally +build: dependencies + CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build # Generates the docker container (but does not push) -docker: - go generate - go run core/semver/semver.go -f mk >semver.mk +docker: dependencies make -f docker.mk docker # Pushes container to the repository -push: docker +push: docker make -f docker.mk push # Windows or Linux; requires no hardware diff --git a/README.md b/README.md index 43c37690..78d83696 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ -# CSI Driver for VxFlex OS +# CSI Driver for PowerFlex (Formerly VxFlex OS) + +[![Go Report Card](https://goreportcard.com/badge/github.com/dell/csi-vxflexos)](https://goreportcard.com/report/github.com/dell/csi-vxflexos) +[![License](https://img.shields.io/github/license/dell/csi-vxflexos)](https://github.com/dell/csi-vxflexos/blob/master/LICENSE) +[![Docker](https://img.shields.io/docker/pulls/dellemc/csi-vxflexos.svg?logo=docker)](https://hub.docker.com/r/dellemc/csi-vxflexos) +[![Last Release](https://img.shields.io/github/v/release/dell/csi-vxflexos?label=latest&style=flat-square)](https://github.com/dell/csi-vxflexos/releases) ## Description -CSI Driver for VxFlex OS is a Container Storage Interface ([CSI](https://github.com/container-storage-interface/spec)) -driver that provides VxFlex OS support. It supports CSI specification version 1.1. +CSI Driver for PowerFlex is a Container Storage Interface ([CSI](https://github.com/container-storage-interface/spec)) +driver that provides PowerFlex support. It supports CSI specification version 1.1. This project may be compiled as a stand-alone binary using Golang that, when run, provides a valid CSI endpoint. This project can also be built as a Golang plug-in in order to extend the functionality of other programs. +## Support +The CSI Driver for Dell EMC PowerFlex image, which is the built driver code, is available on Dockerhub and is officially supported by Dell EMC. + +The source code for CSI Driver for Dell EMC PowerFlex available on Github is unsupported and provided solely under the terms of the license attached to the source code. For clarity, Dell EMC does not provide support for any source code modifications. + +For any CSI driver issues, questions or feedback, join the [Dell EMC Container community](https://www.dell.com/community/Containers/bd-p/Containers). + ## Building This project is a Go module (see golang.org Module information for explanation). @@ -20,24 +32,20 @@ To run unit tests, execute `make unit-test`. To build a docker image, execute `make docker`. You can run an integration test on a Linux system by populating the file `env.sh` -with values for your VxFlex OS system and then run "make integration-test". +with values for your PowerFlex system and then run "make integration-test". ## Runtime Dependencies The Node portion of the driver can be run on any node that is configured as a -VxFlex OS SDC. This means that the `scini` kernel module must be loaded. Also, +PowerFlex SDC. This means that the `scini` kernel module must be loaded. Also, if the `X_CSI_VXFLEXOS_SDCGUID` environment variable is not set, the driver will try to query the SDC GUID by executing the binary `/opt/emc/scaleio/sdc/bin/drv_cfg`. If that binary is not present, the Node Service cannot be run. ## Installation +Installation in a Kubernetes cluster should be done using the scripts within the `dell-csi-helm-installer` directory. -Installation in Kubernetes should be done using the `install.vxflexos` script -and accompanying Helm chart in the helm directory. For more information, please refer -to the `CSI Driver for VxFlex OS Product Guide` and `CSI Driver for VxFlex OS Release Notes`. -The driver will be started in Kubernetes as a result of executing the installation -script. - +For more information, consult the [README.md](dell-csi-helm-installer/README.md) ## Using driver @@ -121,12 +129,3 @@ This means that giving a workload read-only access to a block device is not supported. In general, volumes should be formatted with xfs or ext4. - -## Support -The CSI Driver for Dell EMC VxFlex OS image available on Dockerhub is officially supported by Dell EMC. - -The source code available on Github is unsupported and provided solely under the terms of the license attached to the source code. For clarity, Dell EMC does not provide support for any source code modifications. - -For any CSI driver setup, configuration issues, questions or feedback, join the Dell EMC Container community athttps://www.dell.com/community/Containers/bd-p/Containers - -For any Dell EMC storage issues, please contact Dell support at: https://www.dell.com/support. diff --git a/core/semver/semver.go b/core/semver/semver.go index d4d17f11..5da4cf2b 100644 --- a/core/semver/semver.go +++ b/core/semver/semver.go @@ -56,6 +56,7 @@ func main() { } else if strings.EqualFold("ver", format) { format = "ver" } else { + /* #nosec G304 */ if fileExists(format) { buf, err := ioutil.ReadFile(format) if err != nil { @@ -76,6 +77,7 @@ func main() { os.Exit(1) } w = fout + /* #nosec G307 */ defer fout.Close() } @@ -163,6 +165,7 @@ func main() { } func doExec(cmd string, args ...string) ([]byte, error) { + /* #nosec G204 */ c := exec.Command(cmd, args...) c.Stderr = os.Stderr return c.Output() diff --git a/dell-csi-helm-installer/README.md b/dell-csi-helm-installer/README.md new file mode 100644 index 00000000..211717a4 --- /dev/null +++ b/dell-csi-helm-installer/README.md @@ -0,0 +1,157 @@ +# Helm Installer for Dell EMC CSI Storage Providers + +## Description + +This directory provides scripts to install, upgrade, uninstall the CSI drivers, and to verify the Kubernetes environment. +These same scripts are present in all Dell EMC Container Storage Interface ([CSI](https://github.com/container-storage-interface/spec)) drivers. This includes the drivers for: +* [PowerFlex](https://github.com/dell/csi-vxflexos) +* [PowerMax](https://github.com/dell/csi-powermax) +* [PowerScale](https://github.com/dell/csi-powerscale) +* [PowerStore](https://github.com/dell/csi-powerstore) +* [Unity](https://github.com/dell/csi-unity) + +NOTE: This documentation uses the PowerFlex driver as an example. If working with a different driver, substitute the name as appropriate. + +## Dependencies + +Installing any of the Dell EMC CSI Drivers requires a few utilities to be installed on the system running the installation. + +| Dependency | Usage | +| ------------- | ----- | +| `kubectl` | Kubectl is used to validate that the Kubernetes system meets the requirements of the driver. | +| `helm` | Helm v3 is used as the deployment tool for Charts. See, [Install HELM 3](https://helm.sh/docs/intro/install/) for instructions to install HELM 3. | + + +In order to use these tools, a valid `KUBECONFIG` is required. Ensure that either a valid configuration is in the default location or that the `KUBECONFIG` environment variable points to a valid confiugration before using these tools. + +## Capabilities + +This project provides the following capabilitites, each one is discussed in detail later in this document. + +* Install a driver. When installing a driver, options are provided to specify the target namespace as well as options to control the types of verifications to be performed on the target system. +* Upgrade a driver. Upgrading a driver is an effective way to either deploy a new version of the driver or to modify the parameters used in an initial deployment. +* Uninstall a driver. This removes the driver and any installed storage classes. +* Verify a Kubernetes system for suitability with a driver. These verification steps differ, slightly, from driver to driver but include verifiying version compatibility, namespace availability, existance of required secrets, and validating worker node compatibility with driver protocols such as iSCSI, Fibre Channel, NFS, etc + + +Most of these usages require the creation/specification of a values file. These files specify configuration settings that are passed into the driver and configure it for use. To create one of these files, the following steps should be followed: +1. Copy a template file for the driver to a new location, naming this new file is at the users discretion. The template files are always found within the driver repo at `helm/csi-/values.yaml` +2. Edit the file such that it contains the proper configuration settings for the specific environment. These files are yaml formatted so maintaining the file structure is important. + +For example, to create a values file for the PowerFlex driver the following steps can be executed +``` +# cd to the installation script directory +cd dell-csi-helm-installer + +# copy the template file +cp ../helm/csi-vxflexos/values.yaml ./my-vxflexos-settings.yaml + +# edit the newly created values file +vi my-vxflexos-settings.yaml +``` + +These values files can then be archived for later reference or for usage when upgrading the driver. + + +### Install A Driver + +Installing a driver is performed via the `csi-install.sh` script. This script requires a few arguments: the target namespace and the user created values file. By default, this will verify the Kubernetes environment and present a list of warnings and/or errors. Errors must be addressed before installing, warning should be examined for their applicability. For example, in order to install the PowerFlex driver into a namespace called "vxflexos", the following command should be run: +``` +./csi-install.sh --namespace vxflexos --values ./my-vxflexos-settings.yaml +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-install.sh -h +Help for ./csi-install.sh + +Usage: ./csi-install.sh options... +Options: + Required + --namespace[=] Kubernetes namespace containing the CSI driver + --values[=] Values file, which defines configuration values + Optional + --release[=] Name to register with helm, default value will match the driver name + --upgrade Perform an upgrade of the specified driver, default is false + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification + --skip-verify-node Skip worker node verification checks + --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes. + -h Help +``` + +### Upgrade A Driver + +Upgrading a driver is very similar to installation. The `csi-install.sh` script is run, with the same required arguments, along with a `--upgrade` argument. For example, to upgrade the previously installed PowerFlex driver, the following command can be supplied: + +``` +./csi-install.sh --namespace vxflexos --values ./my-vxflexos-settings.yaml --upgrade +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-install.sh -h +Help for ./csi-install.sh + +Usage: ./csi-install.sh options... +Options: + Required + --namespace[=] Kubernetes namespace containing the CSI driver + --values[=] Values file, which defines configuration values + Optional + --release[=] Name to register with helm, default value will match the driver name + --upgrade Perform an upgrade of the specified driver, default is false + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification + --skip-verify-node Skip worker node verification checks + --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes. + -h Help +``` + +### Uninstall A Driver + +To uninstall a driver, the `csi-uninstall.sh` script provides a handy wrapper around the `helm` utility. The only required argument for uninstallation is the namespace name. To uninstall the PowerFlex driver: + +``` +./csi-uninstall.sh --namespace vxflexos +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-uninstall.sh -h +Help for ./csi-uninstall.sh + +Usage: ./csi-uninstall.sh options... +Options: + Required + --namespace[=] Kubernetes namespace to uninstall the CSI driver from + Optional + --release[=] Name to register with helm, default value will match the driver name + -h Help +``` + +### Verify A Kubernetes Environment + +The `verify.sh` script is run, automatically, as part of the installation and upgrade procedures and can also be run by itself. This provides a handy means to validate a Kubernetes system without meaning to actually perform the installation. To verify an environment, run `verify.sh` with the namespace name and values file options. + +``` +./verify.sh --namespace vxflexos --values ./my-vxflexos-settings.yaml +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./verify.sh -h +Help for ./verify.sh + +Usage: ./verify.sh options... +Options: + Required + --namespace[=] Kubernetes namespace to install the CSI driver + --values[=] Values file, which defines configuration values + Optional + --skip-verify-node Skip worker node verification checks + --release[=] Name to register with helm, default value will match the driver name + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + -h Help Help +``` + diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml new file mode 100644 index 00000000..4aa980cc --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml @@ -0,0 +1,85 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .driver + name: Driver + type: string + - JSONPath: .deletionPolicy + description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass + should be deleted when its bound VolumeSnapshot is deleted. + name: DeletionPolicy + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + singular: volumesnapshotclass + preserveUnknownFields: false + scope: Cluster + subresources: {} + validation: + openAPIV3Schema: + description: VolumeSnapshotClass specifies parameters that a underlying storage + system uses when creating a volume snapshot. A specific VolumeSnapshotClass + is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses + are non-namespaced + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + deletionPolicy: + description: deletionPolicy determines whether a VolumeSnapshotContent created + through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot + is deleted. Supported values are "Retain" and "Delete". "Retain" means + that the VolumeSnapshotContent and its physical snapshot on underlying + storage system are kept. "Delete" means that the VolumeSnapshotContent + and its physical snapshot on underlying storage system are deleted. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the storage driver that handles this + VolumeSnapshotClass. Required. + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + parameters: + additionalProperties: + type: string + description: parameters is a key-value map with storage driver specific + parameters for creating snapshots. These values are opaque to Kubernetes. + type: object + required: + - deletionPolicy + - driver + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml new file mode 100644 index 00000000..34c51ad6 --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml @@ -0,0 +1,233 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.readyToUse + description: Indicates if a snapshot is ready to be used to restore a volume. + name: ReadyToUse + type: boolean + - JSONPath: .status.restoreSize + description: Represents the complete size of the snapshot in bytes + name: RestoreSize + type: integer + - JSONPath: .spec.deletionPolicy + description: Determines whether this VolumeSnapshotContent and its physical snapshot + on the underlying storage system should be deleted when its bound VolumeSnapshot + is deleted. + name: DeletionPolicy + type: string + - JSONPath: .spec.driver + description: Name of the CSI driver used to create the physical snapshot on the + underlying storage system. + name: Driver + type: string + - JSONPath: .spec.volumeSnapshotClassName + description: Name of the VolumeSnapshotClass to which this snapshot belongs. + name: VolumeSnapshotClass + type: string + - JSONPath: .spec.volumeSnapshotRef.name + description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent + object is bound. + name: VolumeSnapshot + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + singular: volumesnapshotcontent + preserveUnknownFields: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: VolumeSnapshotContent represents the actual "on-disk" snapshot + object in the underlying storage system + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + spec: + description: spec defines properties of a VolumeSnapshotContent created + by the underlying storage system. Required. + properties: + deletionPolicy: + description: deletionPolicy determines whether this VolumeSnapshotContent + and its physical snapshot on the underlying storage system should + be deleted when its bound VolumeSnapshot is deleted. Supported values + are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent + and its physical snapshot on underlying storage system are kept. "Delete" + means that the VolumeSnapshotContent and its physical snapshot on + underlying storage system are deleted. In dynamic snapshot creation + case, this field will be filled in with the "DeletionPolicy" field + defined in the VolumeSnapshotClass the VolumeSnapshot refers to. For + pre-existing snapshots, users MUST specify this field when creating + the VolumeSnapshotContent object. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the CSI driver used to create the + physical snapshot on the underlying storage system. This MUST be the + same as the name returned by the CSI GetPluginName() call for that + driver. Required. + type: string + source: + description: source specifies from where a snapshot will be created. + This field is immutable after creation. Required. + properties: + snapshotHandle: + description: snapshotHandle specifies the CSI "snapshot_id" of a + pre-existing snapshot on the underlying storage system. This field + is immutable. + type: string + volumeHandle: + description: volumeHandle specifies the CSI "volume_id" of the volume + from which a snapshot should be dynamically taken from. This field + is immutable. + type: string + type: object + volumeSnapshotClassName: + description: name of the VolumeSnapshotClass to which this snapshot + belongs. + type: string + volumeSnapshotRef: + description: volumeSnapshotRef specifies the VolumeSnapshot object to + which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName + field must reference to this VolumeSnapshotContent's name for the + bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent + object, name and namespace of the VolumeSnapshot object MUST be provided + for binding to happen. This field is immutable after creation. Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an + entire object, this string should contain a valid JSON/Go field + access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen only + to have some well-defined way of referencing a part of an object. + TODO: this design is not final and this field is subject to change + in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is + made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + required: + - deletionPolicy + - driver + - source + - volumeSnapshotRef + type: object + status: + description: status represents the current information of a snapshot. + properties: + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot + is taken by the underlying storage system. In dynamic snapshot creation + case, this field will be filled in with the "creation_time" value + returned from CSI "CreateSnapshotRequest" gRPC call. For a pre-existing + snapshot, this field will be filled with the "creation_time" value + returned from the CSI "ListSnapshots" gRPC call if the driver supports + it. If not specified, it indicates the creation time is unknown. The + format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command `date +%s%N` returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. + format: int64 + type: integer + error: + description: error is the latest observed error during snapshot creation, + if any. + properties: + message: + description: 'message is a string detailing the encountered error + during snapshot creation if specified. NOTE: message may be logged, + and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if a snapshot is ready to be used + to restore a volume. In dynamic snapshot creation case, this field + will be filled in with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" gRPC call. For a pre-existing snapshot, this + field will be filled with the "ready_to_use" value returned from the + CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, + this field will be set to "True". If not specified, it means the readiness + of a snapshot is unknown. + type: boolean + restoreSize: + description: restoreSize represents the complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be filled + in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + gRPC call. For a pre-existing snapshot, this field will be filled + with the "size_bytes" value returned from the CSI "ListSnapshots" + gRPC call if the driver supports it. When restoring a volume from + this snapshot, the size of the volume MUST NOT be smaller than the + restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + format: int64 + minimum: 0 + type: integer + snapshotHandle: + description: snapshotHandle is the CSI "snapshot_id" of a snapshot on + the underlying storage system. If not specified, it indicates that + dynamic snapshot creation has either failed or it is still in progress. + type: string + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml new file mode 100644 index 00000000..483706f1 --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml @@ -0,0 +1,188 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.readyToUse + description: Indicates if a snapshot is ready to be used to restore a volume. + name: ReadyToUse + type: boolean + - JSONPath: .spec.source.persistentVolumeClaimName + description: Name of the source PVC from where a dynamically taken snapshot will + be created. + name: SourcePVC + type: string + - JSONPath: .spec.source.volumeSnapshotContentName + description: Name of the VolumeSnapshotContent which represents a pre-provisioned + snapshot. + name: SourceSnapshotContent + type: string + - JSONPath: .status.restoreSize + description: Represents the complete size of the snapshot. + name: RestoreSize + type: string + - JSONPath: .spec.volumeSnapshotClassName + description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. + name: SnapshotClass + type: string + - JSONPath: .status.boundVolumeSnapshotContentName + description: The name of the VolumeSnapshotContent to which this VolumeSnapshot + is bound. + name: SnapshotContent + type: string + - JSONPath: .status.creationTime + description: Timestamp when the point-in-time snapshot is taken by the underlying + storage system. + name: CreationTime + type: date + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + singular: volumesnapshot + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: VolumeSnapshot is a user's request for either creating a point-in-time + snapshot of a persistent volume, or binding to a pre-existing snapshot. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + spec: + description: 'spec defines the desired characteristics of a snapshot requested + by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots + Required.' + properties: + source: + description: source specifies where a snapshot will be created from. + This field is immutable after creation. Required. + properties: + persistentVolumeClaimName: + description: persistentVolumeClaimName specifies the name of the + PersistentVolumeClaim object in the same namespace as the VolumeSnapshot + object where the snapshot should be dynamically taken from. This + field is immutable. + type: string + volumeSnapshotContentName: + description: volumeSnapshotContentName specifies the name of a pre-existing + VolumeSnapshotContent object. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: 'volumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. If not specified, the default snapshot + class will be used if one exists. If not specified, and there is no + default snapshot class, dynamic snapshot creation will fail. Empty + string is not allowed for this field. TODO(xiangqian): a webhook validation + on empty string. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshot-classes' + type: string + required: + - source + type: object + status: + description: 'status represents the current information of a snapshot. NOTE: + status can be modified by sources other than system controllers, and must + not be depended upon for accuracy. Controllers should only use information + from the VolumeSnapshotContent object after verifying that the binding + is accurate and complete.' + properties: + boundVolumeSnapshotContentName: + description: 'boundVolumeSnapshotContentName represents the name of + the VolumeSnapshotContent object to which the VolumeSnapshot object + is bound. If not specified, it indicates that the VolumeSnapshot object + has not been successfully bound to a VolumeSnapshotContent object + yet. NOTE: Specified boundVolumeSnapshotContentName alone does not + mean binding is valid. Controllers MUST always verify bidirectional + binding between VolumeSnapshot and VolumeSnapshotContent to + avoid possible security issues.' + type: string + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot + is taken by the underlying storage system. In dynamic snapshot creation + case, this field will be filled in with the "creation_time" value + returned from CSI "CreateSnapshotRequest" gRPC call. For a pre-existing + snapshot, this field will be filled with the "creation_time" value + returned from the CSI "ListSnapshots" gRPC call if the driver supports + it. If not specified, it indicates that the creation time of the snapshot + is unknown. + format: date-time + type: string + error: + description: error is the last observed error during snapshot creation, + if any. This field could be helpful to upper level controllers(i.e., + application controller) to decide whether they should continue on + waiting for the snapshot to be created based on the type of error + reported. + properties: + message: + description: 'message is a string detailing the encountered error + during snapshot creation if specified. NOTE: message may be logged, + and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if a snapshot is ready to be used + to restore a volume. In dynamic snapshot creation case, this field + will be filled in with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" gRPC call. For a pre-existing snapshot, this + field will be filled with the "ready_to_use" value returned from the + CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, + this field will be set to "True". If not specified, it means the readiness + of a snapshot is unknown. + type: boolean + restoreSize: + anyOf: + - type: integer + - type: string + description: restoreSize represents the complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be filled + in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + gRPC call. For a pre-existing snapshot, this field will be filled + with the "size_bytes" value returned from the CSI "ListSnapshots" + gRPC call if the driver supports it. When restoring a volume from + this snapshot, the size of the volume MUST NOT be smaller than the + restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/common.sh b/dell-csi-helm-installer/common.sh new file mode 100644 index 00000000..f4b8730e --- /dev/null +++ b/dell-csi-helm-installer/common.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +DRIVERDIR="${SCRIPTDIR}/../helm" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +DARK_GRAY='\033[1;30m' +NC='\033[0m' # No Color + +function log() { + case $1 in + separator) + echo "------------------------------------------------------" + ;; + error) + echo + log separator + printf "${RED}Error: $2\n" + printf "${RED}Installation cannot continue${NC}\n" + exit 1 + ;; + step) + printf "|\n|- %-65s" "$2" + ;; + small_step) + printf "%-61s" "$2" + ;; + section) + log separator + printf "> %s\n" "$2" + log separator + ;; + smart_step) + if [[ $3 == "small" ]]; then + log small_step "$2" + else + log step "$2" + fi + ;; + arrow) + printf " %s\n %s" "|" "|--> " + ;; + step_success) + printf "${GREEN}Success${NC}\n" + ;; + step_failure) + printf "${RED}Failed${NC}\n" + ;; + step_warning) + printf "${YELLOW}Warning${NC}\n" + ;; + info) + printf "${DARK_GRAY}%s${NC}\n" "$2" + ;; + passed) + printf "${GREEN}Success${NC}\n" + ;; + warnings) + printf "${YELLOW}Warnings:${NC}\n" + ;; + errors) + printf "${RED}Errors:${NC}\n" + ;; + *) + echo -n "Unknown" + ;; + esac +} + +function check_error() { + if [[ $1 -ne 0 ]]; then + log step_failure + else + log step_success + fi +} + +# +# get_drivers will populate an array of drivers found by +# enumerating the directories in drivers/ that contain a helm chart +function get_drivers() { + D="${1}" + TTT=$(pwd) + while read -r line; do + DDD=$(echo $line | awk -F '/' '{print $(NF-1)}') + VALIDDRIVERS+=("$DDD") + done < <(find "${D}" -maxdepth 2 -type f -name Chart.yaml | sort) +} + +# +# get_release will determine the helm release name to use +# If ${RELEASE} is set, use that +# Otherwise, use the driver name minus any "csi-" prefix +# argument 1: Driver name +function get_release_name() { + local D="${1}" + if [ ! -z "${RELEASE}" ]; then + echo "${RELEASE}" + return + fi + + local PREFIX="csi-" + R=${D#"$PREFIX"} + echo "${R}" +} diff --git a/dell-csi-helm-installer/csi-install.sh b/dell-csi-helm-installer/csi-install.sh new file mode 100755 index 00000000..5445960c --- /dev/null +++ b/dell-csi-helm-installer/csi-install.sh @@ -0,0 +1,391 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +DRIVERDIR="${SCRIPTDIR}/../helm" +VERIFYSCRIPT="${SCRIPTDIR}/verify.sh" +SNAPCLASSDIR="${SCRIPTDIR}/beta-snapshot-crd" +PROG="${0}" +NODE_VERIFY=1 +VERIFY=1 +MODE="install" +# version of Snapshot CRD to install. Default is none ("") +INSTALL_CRD="" + +declare -a VALIDDRIVERS + +source "$SCRIPTDIR"/common.sh + + +# +# usage will print command execution help and then exit +function usage() { + echo + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace containing the CSI driver" + echo " --values[=] Values file, which defines configuration values" + + echo " Optional" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " --upgrade Perform an upgrade of the specified driver, default is false" + echo " --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root" + echo " --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification" + echo " --skip-verify-node Skip worker node verification checks" + echo " --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes." + echo " -h Help" + echo + + exit 0 +} + +# warning, with an option for users to continue +function warning() { + log separator + printf "${YELLOW}WARNING:${NC}\n" + for N in "$@"; do + echo $N + done + echo + if [ "${ASSUMEYES}" == "true" ]; then + echo "Continuing as '-Y' argument was supplied" + return + fi + read -n 1 -p "Press 'y' to continue or any other key to exit: " CONT + echo + if [ "${CONT}" != "Y" -a "${CONT}" != "y" ]; then + echo "quitting at user request" + exit 2 + fi +} + + +# print header information +function header() { + log section "Installing CSI Driver: ${DRIVER} on ${kMajorVersion}.${kMinorVersion}" +} + +# +# check_for_driver will see if the driver is already installed within the namespace provided +function check_for_driver() { + log section "Checking to see if CSI Driver is already installed" + NUM=$(helm list --namespace "${NS}" | grep "^${RELEASE}\b" | wc -l) + if [ "${1}" == "install" -a "${NUM}" != "0" ]; then + log error "The CSI Driver is already installed" + fi + if [ "${1}" == "upgrade" -a "${NUM}" == "0" ]; then + log error "The CSI Driver is not installed" + fi +} + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + usage + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + usage + exit 1 + fi + # the namespace is required + if [ -z "${NS}" ]; then + echo "No namespace specified" + usage + exit 1 + fi + # values file + if [ -z "${VALUES}" ]; then + echo "No values file was specified" + usage + exit 1 + fi + if [ ! -f "${VALUES}" ]; then + echo "Unable to read values file at: ${VALUES}" + usage + exit 1 + fi +} + +# +# install_driver uses helm to install the driver with a given name +function install_driver() { + if [ "${1}" == "upgrade" ]; then + log step "Upgrading Driver" + else + log step "Installing Driver" + fi + + HELMOUTPUT="/tmp/csi-install.$$.out" + helm ${1} --values "${DRIVERDIR}/${DRIVER}/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml" --values "${DRIVERDIR}/${DRIVER}/driver-image.yaml" --values "${VALUES}" --namespace ${NS} "${RELEASE}" "${DRIVERDIR}/${DRIVER}" >"${HELMOUTPUT}" 2>&1 + if [ $? -ne 0 ]; then + cat "${HELMOUTPUT}" + log error "Helm operation failed, output can be found in ${HELMOUTPUT}. The failure should be examined, before proceeding. Additionally, running csi-uninstall.sh may be needed to clean up partial deployments." + fi + log step_success + # wait for the deployment to finish, use the default timeout + waitOnRunning "${NS}" "statefulset ${RELEASE}-controller,daemonset ${RELEASE}-node" + if [ $? -eq 1 ]; then + warning "Timed out waiting for the operation to complete." \ + "This does not indicate a fatal error, pods may take a while to start." \ + "Progress can be checked by running \"kubectl get pods -n ${NS}\"" + fi +} + +# Print a nice summary at the end +function summary() { + log section "Operation complete" +} + +# waitOnRunning +# will wait, for a timeout period, for a number of pods to go into Running state within a namespace +# arguments: +# $1: required: namespace to watch +# $2: required: comma seperated list of deployment type and name pairs +# for example: "statefulset mystatefulset,daemonset mydaemonset" +# $3: optional: timeout value, 300 seconds is the default. +function waitOnRunning() { + if [ -z "${2}" ]; then + echo "No namespace and/or list of deployments was supplied. This field is required for waitOnRunning" + return 1 + fi + # namespace + local NS="${1}" + # pods + IFS="," read -r -a PODS <<<"${2}" + # timeout value passed in, or 300 seconds as a default + local TIMEOUT="300" + if [ -n "${3}" ]; then + TIMEOUT="${3}" + fi + + error=0 + for D in "${PODS[@]}"; do + log arrow + log smart_step "Waiting for $D to be ready" "small" + kubectl -n "${NS}" rollout status --timeout=${TIMEOUT}s ${D} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + error=1 + log step_failure + else + log step_success + fi + done + + if [ $error -ne 0 ]; then + return 1 + fi + return 0 +} + +function kubectl_safe() { + eval "kubectl $1" + exitcode=$? + if [[ $exitcode != 0 ]]; then + echo "$2" + exit $exitcode + fi +} + +# +# install_snapshot_crds +# Downloads and installs snapshot CRDs +function install_snapshot_crd() { + if [ "${INSTALL_CRD}" == "" ]; then + return + fi + log step "Checking and installing snapshot crds" + + declare -A SNAPCLASSES=( + ["volumesnapshotclasses"]="snapshot.storage.k8s.io_volumesnapshotclasses.yaml" + ["volumesnapshotcontents"]="snapshot.storage.k8s.io_volumesnapshotcontents.yaml" + ["volumesnapshots"]="snapshot.storage.k8s.io_volumesnapshots.yaml" + ) + + for C in "${!SNAPCLASSES[@]}"; do + F="${SNAPCLASSES[$C]}" + # check if custom resource exists + kubectl_safe "get customresourcedefinitions" "Failed to get crds" | grep "${C}" --quiet + + if [[ $? -ne 0 ]]; then + # make sure CRD exists + if [ ! -f "${SNAPCLASSDIR}/${SNAPCLASSES[$C]}" ]; then + echo "Unable to to find Snapshot Classes at ${SNAPCLASSDIR}" + exit 1 + fi + # create the custom resource + kubectl_safe "create -f ${SNAPCLASSDIR}/${SNAPCLASSES[$C]}" "Failed to create Volume Snapshot Beta CRD: ${C}" + fi + done + + sleep 10s + log step_success +} + +# +# verify_kubernetes +# will run a driver specific function to verify environmental requirements +function verify_kubernetes() { + EXTRA_OPTS="" + if [ $VERIFY -eq 0 ]; then + echo "Skipping verification at user request" + else + if [ $NODE_VERIFY -eq 0 ]; then + EXTRA_OPTS="$EXTRA_OPTS --skip-verify-node" + fi + if [ "${INSTALL_CRD}" == "yes" ]; then + EXTRA_OPTS="$EXTRA_OPTS --snapshot-crd" + fi + "${VERIFYSCRIPT}" --namespace "${NS}" --release "${RELEASE}" --values "${VALUES}" --node-verify-user "${NODEUSER}" ${EXTRA_OPTS} + VERIFYRC=$? + case $VERIFYRC in + 0) ;; + + 1) + warning "Kubernetes validation failed but installation can continue. " \ + "This may affect driver installation." + ;; + *) + log error "Kubernetes validation failed." + ;; + esac + fi +} + +# +# main +# +VERIFYOPTS="" +ASSUMEYES="false" + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${DRIVERDIR}" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + skip-verify) + VERIFY=0 + ;; + skip-verify-node) + NODE_VERIFY=0 + ;; + # SNAPSHOT_CRD + snapshot-crd) + INSTALL_CRD="yes" + ;; + upgrade) + MODE="upgrade" + ;; + # NAMESPACE + namespace) + NS="${!OPTIND}" + if [[ -z ${NS} || ${NS} == "--skip-verify" ]]; then + NS=${DEFAULT_NS} + else + OPTIND=$((OPTIND + 1)) + fi + ;; + namespace=*) + NS=${OPTARG#*=} + if [[ -z ${NS} ]]; then NS=${DEFAULT_NS}; fi + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + # VALUES + values) + VALUES="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + values=*) + VALUES=${OPTARG#*=} + ;; + # NODEUSER + node-verify-user) + NODEUSER="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + node-verify-user=*) + HODEUSER=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") +# by default, NODEUSER is root +NODEUSER="${NODEUSER:-root}" + +# make sure kubectl is available +kubectl --help >&/dev/null || { + echo "kubectl required for installation... exiting" + exit 2 +} +# make sure helm is available +helm --help >&/dev/null || { + echo "helm required for installation... exiting" + exit 2 +} + +# Get the kubernetes major and minor version numbers. +kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/[^0-9].*//g') +kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/[^0-9].*//g') + +# validate the parameters passed in +validate_params "${MODE}" + +header +check_for_driver "${MODE}" +verify_kubernetes + +if [[ "${INSTALL_CRD}" != "" ]]; then + install_snapshot_crd +fi + + +# all good, keep processing +install_driver "${MODE}" + +summary diff --git a/dell-csi-helm-installer/csi-uninstall.sh b/dell-csi-helm-installer/csi-uninstall.sh new file mode 100755 index 00000000..e3e8e5cf --- /dev/null +++ b/dell-csi-helm-installer/csi-uninstall.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +DRIVERDIR="${SCRIPTDIR}/../helm" +PROG="${0}" + +declare -a VALIDDRIVERS + +source "$SCRIPTDIR"/common.sh + +# +# usage will print command execution help and then exit +function usage() { + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace to uninstall the CSI driver from" + + echo " Optional" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " -h Help" + echo + + exit 0 +} + + + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + exit 1 + fi + # the namespace is required + if [ -z "${NAMESPACE}" ]; then + echo "No namespace specified" + exit 1 + fi +} + + +# check_for_driver will see if the driver is installed within the namespace provided +function check_for_driver() { + NUM=$(helm list --namespace "${NAMESPACE}" | grep "^${RELEASE}\b" | wc -l) + if [ "${NUM}" == "0" ]; then + echo "The CSI Driver is not installed." + exit 1 + fi +} + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${DRIVERDIR}" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + # NAMESPACE + namespace) + NAMESPACE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + namespace=*) + NAMESPACE=${OPTARG#*=} + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") + +# validate the parameters passed in +validate_params + +check_for_driver +helm delete -n "${NAMESPACE}" "${RELEASE}" +if [ $? -ne 0 ]; then + echo "Removal of the CSI Driver was unsuccessful" + exit 1 +fi + +echo "Removal of the CSI Driver is in progress." +echo "It may take a few minutes for all pods to terminate." + diff --git a/dell-csi-helm-installer/verify.sh b/dell-csi-helm-installer/verify.sh new file mode 100755 index 00000000..4ec05f84 --- /dev/null +++ b/dell-csi-helm-installer/verify.sh @@ -0,0 +1,605 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +PROG="${0}" +source "$SCRIPTDIR"/common.sh + +declare -a VALIDDRIVERS + +# verify-csi-powermax method +function verify-csi-powermax() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_optional_secrets "${RELEASE}-certs" + verify_optional_secrets "csirevproxy-tls-secret" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_iscsi_installation + verify_helm_3 +} + +# +# verify-csi-isilon method +function verify-csi-isilon() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_optional_secrets "${RELEASE}-certs" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# +# verify-csi-vxflexos method +function verify-csi-vxflexos() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_sdc_installation + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# verify-csi-powerstore method +function verify-csi-powerstore() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_powerstore_node_configuration + verify_helm_3 +} + +# verify-csi-unity method +function verify-csi-unity() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_required_secrets "${RELEASE}-certs-0" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# +# verify-driver will call the proper method to verify a specific driver +function verify-driver() { + if [ -z "${1}" ]; then + echo "Expected one argument, the driver name, to verify-driver. Received none." + exit $EXIT_ERROR + fi + local D="${1}" + # check if a verify-$DRIVER function exists + # if not, error and exit + # if yes, check to see if it should be run and run it + FNTYPE=$(type -t verify-$D) + if [ "$FNTYPE" != "function" ]; then + echo "ERROR: verify-$D function does not exist" + exit $EXIT_ERROR + else + header + log step "Driver: ${D}" + echo + verify-$D + summary + fi +} + +# Print usage information +function usage() { + echo + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace to install the CSI driver" + echo " --values[=] Values file, which defines configuration values" + + echo " Optional" + echo " --skip-verify-node Skip worker node verification checks" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root" + echo " --snapshot-crd Signifies that the Snapshot CRDs will be installed as part of installation." + echo " -h Help" + echo + + exit $EXIT_WARNING +} + +# print header information +function header() { + log section "Verifying Kubernetes and driver configuration" + echo "|- Kubernetes Version: ${kMajorVersion}.${kMinorVersion}" +} + +# Check if the SDC is installed and the kernel module loaded +function verify_sdc_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + log step "Verifying the SDC installation" + + error=0 + missing=() + for node in $MINION_NODES; do + # check is the scini kernel module is loaded + ssh ${NODEUSER}@$node "/sbin/lsmod | grep scini" >/dev/null 2>&1 + rv=$? + if [ $rv -ne 0 ]; then + missing+=($node) + error=1 + found_warning "SDC was not found on node: $node" + fi + done + check_error error +} + +function verify_powerstore_node_configuration() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log step "Verifying PowerStore node configuration" + echo + + if ls "${VALUES}" >/dev/null; then + if grep -c "scsiProtocol:[[:blank:]]\+FC" "${VALUES}" >/dev/null; then + log arrow + verify_fc_installation + elif grep -c "scsiProtocol:[[:blank:]]\+ISCSI" "${VALUES}" >/dev/null; then + log arrow + verify_iscsi_installation "small" + elif grep -c "scsiProtocol:[[:blank:]]\+auto" "${VALUES}" >/dev/null; then + log arrow + verify_iscsi_installation "small" + log arrow + verify_fc_installation "small" + elif grep -c "scsiProtocol:[[:blank:]]\+None" "${VALUES}" >/dev/null; then + log step_warning + found_warning "Neither FC nor iSCSI connection is activated, please be sure that NFS settings are correct" + else + log step_failure + found_error "Incorrect scsiProtocol value, must be 'FC', 'ISCSI', 'auto' or 'None'" + fi + else + log step_failure + found_error "${VALUES} doesn't exists" + fi +} + +# Check if the iSCSI client is installed +function verify_iscsi_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log smart_step "Verifying iSCSI installation" "$1" + + error=0 + for node in $MINION_NODES; do + # check if the iSCSI client is installed + ssh ${NODEUSER}@"${node}" "cat /etc/iscsi/initiatorname.iscsi" >/dev/null 2>&1 + rv=$? + if [ $rv -ne 0 ]; then + error=1 + found_warning "iSCSI client was not found on node: $node" + fi + ssh ${NODEUSER}@"${node}" pgrep iscsid &>/dev/null + rv=$? + if [ $rv -ne 0 ]; then + error=1 + found_warning "iscsid is not running on node: $node" + fi + done + + check_error error +} + +# Check if the fc is installed +function verify_fc_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log smart_step "Verifying FC installation" "$1" + + error=0 + for node in $MINION_NODES; do + # check if FC hosts are available + ssh ${NODEUSER}@${node} 'ls --hide=* /sys/class/fc_host/* 1>/dev/null' &>/dev/null + rv=$? + if [[ ${rv} -ne 0 ]]; then + error=1 + found_warning "can't find any FC hosts on node: $node" + fi + done + + check_error error +} + +# verify secrets exist +function verify_required_secrets() { + log step "Verifying that required secrets have been created" + + error=0 + for N in "${@}"; do + # Make sure the secret has already been established + kubectl get secrets -n "${NS}" 2>/dev/null | grep "${N}" --quiet + if [ $? -ne 0 ]; then + error=1 + found_error "Required secret, ${N}, does not exist." + fi + done + check_error error +} + +function verify_optional_secrets() { + log step "Verifying that optional secrets have been created" + + error=0 + for N in "${@}"; do + # Make sure the secret has already been established + kubectl get secrets -n "${NS}" 2>/dev/null | grep "${N}" --quiet + if [ $? -ne 0 ]; then + error=1 + found_warning "Optional secret, ${N}, does not exist." + fi + done + check_error error +} + +# verify minimum and maximum k8s versions +function verify_k8s_versions() { + log step "Verifying Kubernetes versions" + echo + log arrow + verify_min_k8s_version "$1" "$2" "small" + log arrow + verify_max_k8s_version "$3" "$4" "small" +} + +# verify minimum k8s version +function verify_min_k8s_version() { + log smart_step "Verifying minimum Kubernetes version" "$3" + + error=0 + if [[ "${1}" -gt "${kMajorVersion}" ]]; then + error=1 + found_error "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is too old. Minimum required version is: ${1}.${2}" + fi + if [[ "${2}" -gt "${kMinorVersion}" ]]; then + error=1 + found_error "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is too old. Minimum required version is: ${1}.${2}" + fi + + check_error error +} + +# verify maximum k8s version +function verify_max_k8s_version() { + log smart_step "Verifying maximum Kubernetes version" "$3" + + error=0 + if [[ "${1}" -lt "${kMajorVersion}" ]]; then + error=1 + found_warning "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is newer than has been tested. Last tested version is: ${1}.${2}" + fi + if [[ "${2}" -lt "${kMinorVersion}" ]]; then + error=1 + found_warning "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is newer than has been tested. Last tested version is: ${1}.${2}" + fi + + check_error error +} + +# verify namespace +function verify_namespace() { + log step "Verifying that required namespaces have been created" + + error=0 + for N in "${@}"; do + # Make sure the namespace exists + kubectl describe namespace "${N}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + error=1 + found_error "Namespace does not exist: ${N}" + fi + done + + check_error error +} + +# verify that the no alpha version of volume snapshot resource is present on the system +function verify_alpha_snap_resources() { + log step "Verifying alpha snapshot resources" + echo + log arrow + log smart_step "Verifying that alpha snapshot CRDs are not installed" "small" + + error=0 + # check for the alpha snapshot CRDs. These shouldn't be present for installation to proceed with + CRDS=("VolumeSnapshotClasses" "VolumeSnapshotContents" "VolumeSnapshots") + for C in "${CRDS[@]}"; do + # Verify that alpha snapshot related CRDs/CRs are not there on the system. + kubectl explain ${C} 2> /dev/null | grep "^VERSION.*v1alpha1$" --quiet + if [ $? -eq 0 ]; then + error=1 + found_error "The alhpa CRD for ${C} is installed. Please uninstall it" + if [[ $(kubectl get ${C} -A --no-headers 2>/dev/null | wc -l) -ne 0 ]]; then + found_error " Found CR for alpha CRD ${C}. Please delete it" + fi + fi + done + check_error error +} + +# verify that the requirements for beta snapshot support exist +function verify_beta_snap_requirements() { + log step "Verifying beta snapshot support" + echo + log arrow + log smart_step "Verifying that beta snapshot CRDs are available" "small" + + error=0 + # check for the CRDs. These are required for installation + CRDS=("VolumeSnapshotClasses" "VolumeSnapshotContents" "VolumeSnapshots") + for C in "${CRDS[@]}"; do + # Verify if snapshot related CRDs are there on the system. If not install them. + kubectl explain ${C} 2> /dev/null | grep "^VERSION.*v1beta1$" --quiet + if [ $? -ne 0 ]; then + error=1 + if [ "${INSTALL_CRD}" == "yes" ]; then + found_warning "The beta CRD for ${C} is not installed. They will be installed because --snapshot-crd was specified" + else + found_error "The beta CRD for ${C} is not installed. These can be installed by specifying --snapshot-crd during installation" + fi + fi + done + check_error error + + log arrow + log smart_step "Verifying that beta snapshot controller is available" "small" + + error=0 + # check for the snapshot-controller. These are strongly suggested but not required + kubectl get pods -A | grep snapshot-controller --quiet + if [ $? -ne 0 ]; then + error=1 + found_warning "The Snapshot Controller does not seem to be deployed. The Snapshot Controller should be provided by the Kubernetes vendor or administrator." + fi + + check_error error +} + +# verify that helm is v3 or above +function verify_helm_3() { + log step "Verifying helm version" + + error=0 + # Check helm installer version + helm --help >&/dev/null || { + found_error "helm is required for installation" + log step_failure + return + } + + helm version | grep "v3." --quiet + if [ $? -ne 0 ]; then + error=1 + found_error "Driver installation is supported only using helm 3" + fi + + check_error error +} + +# found_error, installation will not continue +function found_error() { + for N in "$@"; do + ERRORS+=("${N}") + done +} + +# found_warning, installation can continue +function found_warning() { + for N in "$@"; do + WARNINGS+=("${N}") + done +} + +# Print a nice summary at the end +function summary() { + echo + log section "Verification Complete" + # print all the WARNINGS + NON_CRD_WARNINGS=0 + if [ "${#WARNINGS[@]}" -ne 0 ]; then + log warnings + for E in "${WARNINGS[@]}"; do + echo "- ${E}" + echo ${E} | grep --quiet "^The beta CRD for VolumeSnapshot" + if [ $? -ne 0 ]; then + NON_CRD_WARNINGS=1 + fi + done + RC=$EXIT_WARNING + if [ "${INSTALL_CRD}" == "yes" -a ${NON_CRD_WARNINGS} -eq 0 ]; then + RC=$EXIT_SUCCESS + fi + fi + + # print all the ERRORS + if [ "${#ERRORS[@]}" -ne 0 ]; then + log errors + for E in "${ERRORS[@]}"; do + echo "- ${E}" + done + RC=$EXIT_ERROR + fi + + return $RC +} + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + usage + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + usage + exit 1 + fi + # the namespace is required + if [ -z "${NS}" ]; then + echo "No namespace specified" + usage + exit 1 + fi + # values file + if [ -z "${VALUES}" ]; then + echo "No values file was specified" + usage + exit 1 + fi + if [ ! -f "${VALUES}" ]; then + echo "Unable to read values file at: ${VALUES}" + usage + exit 1 + fi +} + +# +# main +# +# default values + +NODE_VERIFY=1 + +# exit codes +EXIT_SUCCESS=0 +EXIT_WARNING=1 +EXIT_ERROR=99 + +# arrays of messages +WARNINGS=() +ERRORS=() + +INSTALL_CRD="no" + +# make sure kubectl is available +kubectl --help >&/dev/null || { + echo "kubectl required for verification... exiting" + exit $EXIT_ERROR +} + +# Determine the nodes +MINION_NODES=$(kubectl get nodes -o wide | grep -v -e master -e INTERNAL | awk ' { print $6; }') +MASTER_NODES=$(kubectl get nodes -o wide | awk ' /master/{ print $6; }') +# Get the kubernetes major and minor version numbers. +kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/[^0-9].*//g') +kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/[^0-9].*//g') + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${SCRIPTDIR}/../helm" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + # INSTALL_CRD. Signifies that we were asked to install the CRDs + snapshot-crd) + INSTALL_CRD="yes" + ;; + skip-verify-node) + NODE_VERIFY=0 + ;; + # NAMESPACE + namespace) + NS="${!OPTIND}" + if [[ -z ${NS} || ${NS} == "--skip-verify" ]]; then + NS=${DEFAULT_NS} + else + OPTIND=$((OPTIND + 1)) + fi + ;; + namespace=*) + NS=${OPTARG#*=} + if [[ -z ${NS} ]]; then NS=${DEFAULT_NS}; fi + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + # VALUES + values) + VALUES="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + values=*) + VALUES=${OPTARG#*=} + ;; + # NODEUSER + node-verify-user) + NODEUSER="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + node-verify-user=*) + HODEUSER=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit $EXIT_ERROR + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit $EXIT_ERROR + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") + +#"${RELEASE:-$DRIVER}" +# by default, NODEUSER is root +NODEUSER="${NODEUSER:-root}" + +# validate the parameters passed in +validate_params "${MODE}" + +verify-driver "${DRIVER}" +exit $? diff --git a/docker.mk b/docker.mk index f04477c4..43f2e01b 100644 --- a/docker.mk +++ b/docker.mk @@ -1,15 +1,25 @@ +# docker makefile, included from Makefile, will build/push images with docker or podman +# + # Includes the following generated file to get semantic version information include semver.mk + ifdef NOTES RELNOTE="-$(NOTES)" else RELNOTE= endif +ifeq ($(IMAGETAG),) +IMAGETAG="v$(MAJOR).$(MINOR).$(PATCH)$(RELNOTE)" +endif + + docker: - echo "MAJOR $(MAJOR) MINOR $(MINOR) PATCH $(PATCH) RELNOTE $(RELNOTE) SEMVER $(SEMVER)" - docker build -t "artifactory-sio.isus.emc.com:8129/csi-vxflexos:v$(MAJOR).$(MINOR).$(PATCH)$(RELNOTE)" . + @echo "Base Images is set to: $(BASEIMAGE)" + @echo "Building: $(REGISTRY)/$(IMAGENAME):$(IMAGETAG)" + $(BUILDER) build -t "$(REGISTRY)/$(IMAGENAME):$(IMAGETAG)" --target $(BUILDSTAGE) --build-arg GOPROXY --build-arg BASEIMAGE=$(BASEIMAGE) --build-arg GOVERSION=$(GOVERSION) . push: - echo "MAJOR $(MAJOR) MINOR $(MINOR) PATCH $(PATCH) RELNOTE $(RELNOTE) SEMVER $(SEMVER)" - docker push "artifactory-sio.isus.emc.com:8129/csi-vxflexos:v$(MAJOR).$(MINOR).$(PATCH)$(RELNOTE)" + @echo "Pushing: $(REGISTRY)/$(IMAGENAME):$(IMAGETAG)" + $(BUILDER) push "$(REGISTRY)/$(IMAGENAME):$(IMAGETAG)" diff --git a/go.mod b/go.mod index 3fab8cca..f50cb6c6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,9 @@ module github.com/dell/csi-vxflexos // In order to run unit tests on Windows, you need a stubbed Windows implementation // of the gofsutil package. Use the following replace statements if necessary. +//replace github.com/dell/gofsutil => ./gofsutil +//replace github.com/dell/goscaleio => ./goscaleio go 1.13 @@ -11,8 +13,8 @@ require ( github.com/DATA-DOG/godog v0.7.13 github.com/akutz/memconn v0.1.0 github.com/container-storage-interface/spec v1.1.0 - github.com/dell/gofsutil v1.2.0 - github.com/dell/goscaleio v1.1.0 + github.com/dell/gofsutil v1.3.0 + github.com/dell/goscaleio v1.2.0 github.com/gogo/protobuf v1.2.0 // indirect github.com/golang/protobuf v1.3.1 github.com/gorilla/context v1.1.1 // indirect diff --git a/go.sum b/go.sum index 8bf2b148..e9aac868 100644 --- a/go.sum +++ b/go.sum @@ -27,12 +27,10 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dell/gofsutil v1.2.0 h1:FLvXjNm/mA7y0zpIVgzU61wYIJmNd4VNj8PuY7AR2kw= -github.com/dell/gofsutil v1.2.0/go.mod h1:48eHpMRl0+07uGEnQ7/RE6pTOAVEl74utlGjd0QX/Os= -github.com/dell/goscaleio v1.0.0 h1:YLBcFyK3jQ6wBiFIm6kEE3TsHuTitukAdY14+S7RsBY= -github.com/dell/goscaleio v1.0.0/go.mod h1:gVEFhMQQAwmZsrLNLhcCc8emCMZju9lNcfFVw2H5bss= -github.com/dell/goscaleio v1.1.0 h1:Dk8nGODKnqSO+Qm6fTAgq+izywflH807sWSJ2j+gaQM= -github.com/dell/goscaleio v1.1.0/go.mod h1:gVEFhMQQAwmZsrLNLhcCc8emCMZju9lNcfFVw2H5bss= +github.com/dell/gofsutil v1.3.0 h1:6iDzLAdvrusB5p1yxsW45D2bC9+PUX64tJhH3tgGBN8= +github.com/dell/gofsutil v1.3.0/go.mod h1:48eHpMRl0+07uGEnQ7/RE6pTOAVEl74utlGjd0QX/Os= +github.com/dell/goscaleio v1.2.0 h1:97x2rM0cRlBhy3povQe1OhxF4uI9vCgjRb/o19nP2d0= +github.com/dell/goscaleio v1.2.0/go.mod h1:xrLhA17HgAXG616N7jQOatzVuxeZ5rfYsGSUBaQ7U8I= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= @@ -50,7 +48,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -71,6 +68,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.1/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= @@ -118,7 +116,6 @@ github.com/rexray/gocsi v1.1.0/go.mod h1:kr6L70GxUU6Gu8ehq2dWQmwdILR1tmE05c/OYaT github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/sirupsen/logrus v0.0.0-20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.3/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -128,7 +125,6 @@ github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -146,19 +142,15 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20171023145632-2509b142fb2b h1:vXxKaRjFiMao1tDygYZfT9iEZkE49b7scEND45gopd0= golang.org/x/crypto v0.0.0-20171023145632-2509b142fb2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= @@ -170,10 +162,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20171028101351-661970f62f58/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5 h1:mzjBh+S5frKOsOBobWIMAbXavqjmgO17k/2puhcFR94= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -183,7 +173,6 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b h1:qMK98NmNCRVDIYFycQ5yVRkvgDUFfdP8Ip4KqmDEB7g= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= diff --git a/helm/betasnapshotclass.yaml b/helm/betasnapshotclass.yaml new file mode 100644 index 00000000..a8572875 --- /dev/null +++ b/helm/betasnapshotclass.yaml @@ -0,0 +1,6 @@ +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshotClass +metadata: + name: vxflexos-snapclass +driver: csi-vxflexos.dellemc.com +deletionPolicy: Delete diff --git a/helm/common.bash b/helm/common.bash deleted file mode 100644 index db38813a..00000000 --- a/helm/common.bash +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# Verify kubeadm and kubectl present -kubectl --help >&/dev/null || { - echo "kubectl required for installation... exiting"; exit 2 -} -kubeadm --help >&/dev/null || { - echo "kubeadm required for installation... exiting"; exit 2 -} - -waitOnRunning() { - TARGET=$(kubectl get pods -n ${NS} | grep ${NS} | wc -l) - RUNNING=0 - while [ $RUNNING -ne $TARGET ]; - do - sleep 10 - TARGET=$(kubectl get pods -n ${NS} | grep ${NS} | wc -l) - RUNNING=$(kubectl get pods -n ${NS} | grep "Running" | wc -l) - date - echo running $RUNNING / $TARGET - kubectl get pods -n ${NS} - done -} - -# Get the kubernetes major and minor version numbers. -kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/",.*//') -kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/",.*//') - diff --git a/helm/csi-vxflexos/Chart.yaml b/helm/csi-vxflexos/Chart.yaml index 04646a38..71642f1f 100644 --- a/helm/csi-vxflexos/Chart.yaml +++ b/helm/csi-vxflexos/Chart.yaml @@ -1,6 +1,7 @@ name: csi-vxflexos -version: 1.1.5 -appVersion: 1.1.5 +version: 1.2.0 +appVersion: 1.2.0 +apiVersion: v2 description: | VxFlex OS CSI (Container Storage Interface) driver Kubernetes integration. This chart includes everything required to provision via CSI as diff --git a/helm/csi-vxflexos/driver-image.yaml b/helm/csi-vxflexos/driver-image.yaml new file mode 100644 index 00000000..f317bcd2 --- /dev/null +++ b/helm/csi-vxflexos/driver-image.yaml @@ -0,0 +1,4 @@ +# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. +images: + # "images.driver" defines the container images used for the driver container. + driver: dellemc/csi-vxflexos:v1.2.0.000R diff --git a/helm/csi-vxflexos/k8s-1.14-values.yaml b/helm/csi-vxflexos/k8s-1.17-values.yaml similarity index 62% rename from helm/csi-vxflexos/k8s-1.14-values.yaml rename to helm/csi-vxflexos/k8s-1.17-values.yaml index 1a70f067..4a43ca75 100644 --- a/helm/csi-vxflexos/k8s-1.14-values.yaml +++ b/helm/csi-vxflexos/k8s-1.17-values.yaml @@ -1,20 +1,22 @@ # IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. -kubeversion: "v1.14" +kubeversion: "v1.17" images: # "images.attacher" defines the container images used for the csi attacher # container. - attacher: quay.io/k8scsi/csi-attacher:v1.2.1 + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 # "images.provisioner" defines the container images used for the csi provisioner # container. - #provisioner: quay.io/k8scsi/csi-provisioner:v0.4.2 #for CSI 0.3.0 only (obsolete) - provisioner: quay.io/k8scsi/csi-provisioner:v1.2.1 + provisioner: quay.io/k8scsi/csi-provisioner:v1.5.0 # "images.snapshotter" defines the container image used for the csi snapshotter - snapshotter: quay.io/k8scsi/csi-snapshotter:v1.2.2 + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 # "images.registrar" defines the container images used for the csi registrar # container. registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + # "images.resizer" defines the container images used for the csi resizer + #container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-vxflexos/k8s-1.13-values.yaml b/helm/csi-vxflexos/k8s-1.18-values.yaml similarity index 54% rename from helm/csi-vxflexos/k8s-1.13-values.yaml rename to helm/csi-vxflexos/k8s-1.18-values.yaml index 6e915f1d..77e8cf68 100644 --- a/helm/csi-vxflexos/k8s-1.13-values.yaml +++ b/helm/csi-vxflexos/k8s-1.18-values.yaml @@ -1,19 +1,23 @@ # IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. -kubeversion: "v1.13" +kubeversion: "v1.18" images: # "images.attacher" defines the container images used for the csi attacher # container. - attacher: quay.io/k8scsi/csi-attacher:v1.0.1 + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 # "images.provisioner" defines the container images used for the csi provisioner # container. - provisioner: quay.io/k8scsi/csi-provisioner:v1.0.1 + provisioner: quay.io/k8scsi/csi-provisioner:v1.6.0 # "images.snapshotter" defines the container image used for the csi snapshotter - snapshotter: quay.io/k8scsi/csi-snapshotter:v1.0.1 + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 # "images.registrar" defines the container images used for the csi registrar # container. - registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.0.2 + registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + + # "images.resizer" defines the container images used for the csi resizer + #container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-vxflexos/k8s-1.16-values.yaml b/helm/csi-vxflexos/k8s-1.19-values.yaml similarity index 53% rename from helm/csi-vxflexos/k8s-1.16-values.yaml rename to helm/csi-vxflexos/k8s-1.19-values.yaml index b020b210..25a445a9 100644 --- a/helm/csi-vxflexos/k8s-1.16-values.yaml +++ b/helm/csi-vxflexos/k8s-1.19-values.yaml @@ -1,18 +1,23 @@ -# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DONLOADED. -kubeversion: "v1.16" +# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. +kubeversion: "v1.19" images: # "images.attacher" defines the container images used for the csi attacher # container. - attacher: quay.io/k8scsi/csi-attacher:v1.2.1 + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 # "images.provisioner" defines the container images used for the csi provisioner # container. - provisioner: quay.io/k8scsi/csi-provisioner:v1.4.0 + provisioner: quay.io/k8scsi/csi-provisioner:v1.6.0 # "images.snapshotter" defines the container image used for the csi snapshotter - snapshotter: quay.io/k8scsi/csi-snapshotter:v1.2.0 + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 # "images.registrar" defines the container images used for the csi registrar # container. registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + + # "images.resizer" defines the container images used for the csi resizer + # container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 + diff --git a/helm/csi-vxflexos/templates/controller.yaml b/helm/csi-vxflexos/templates/controller.yaml index 063cd0fc..4aec8cfc 100644 --- a/helm/csi-vxflexos/templates/controller.yaml +++ b/helm/csi-vxflexos/templates/controller.yaml @@ -20,7 +20,10 @@ rules: verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] - apiGroups: [""] resources: ["persistentvolumeclaims"] - verbs: ["get", "list", "watch", "update"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update", "patch"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] @@ -47,8 +50,8 @@ rules: resources: ["volumesnapshots"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["snapshot.storage.k8s.io"] - resources: ["volumesnapshots/status"] - verbs: ["update"] + resources: ["volumesnapshots/status","volumesnapshotcontents/status"] + verbs: ["get", "list", "watch", "update"] - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["create", "list", "watch", "delete", "update"] @@ -75,8 +78,6 @@ spec: selector: matchLabels: app: {{ .Release.Name }}-controller - updateStrategy: - type: RollingUpdate serviceName: {{ .Release.Name }}-controller replicas: {{ required "Must provide the number of controller instances to create." .Values.controllerCount }} template: @@ -106,8 +107,7 @@ spec: {{- if eq .Values.kubeversion "v1.13" }} - "--connection-timeout=300s" - "--provisioner=csi-vxflexos.dellemc.com" - {{- end}} - {{- if eq .Values.kubeversion "v1.14" }} + {{- else }} - "--timeout=120s" {{- end}} - "--v=5" @@ -131,6 +131,17 @@ spec: volumeMounts: - name: socket-dir mountPath: /var/run/csi + - name: resizer + image: {{ required "Must provide the CSI resizer container image." .Values.images.resizer }} + args: + - "--csi-address=$(ADDRESS)" + - "--v=5" + env: + - name: ADDRESS + value: /var/run/csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/run/csi - name: driver image: {{ required "Must provide the VxFlex OS driver container image." .Values.images.driver }} imagePullPolicy: Always diff --git a/helm/csi-vxflexos/templates/node.yaml b/helm/csi-vxflexos/templates/node.yaml index fcc75ea4..ada4b405 100644 --- a/helm/csi-vxflexos/templates/node.yaml +++ b/helm/csi-vxflexos/templates/node.yaml @@ -90,11 +90,16 @@ spec: secretKeyRef: name: {{ .Release.Name }}-creds key: password + - name: X_CSI_VXFLEXOS_ENDPOINT + value: {{ required "Must provide a VxFlex OS REST API gateway HTTPS endpoint." .Values.restGateway }} + - name: X_CSI_VXFLEXOS_INSECURE + value: "true" volumeMounts: - name: driver-path mountPath: /var/lib/kubelet/plugins/vxflexos.emc.dell.com - name: volumedevices-path mountPath: /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices + mountPropagation: "Bidirectional" - name: pods-path mountPath: /var/lib/kubelet/pods mountPropagation: "Bidirectional" diff --git a/helm/csi-vxflexos/templates/snapclass.yaml b/helm/csi-vxflexos/templates/snapclass.yaml new file mode 100644 index 00000000..a8572875 --- /dev/null +++ b/helm/csi-vxflexos/templates/snapclass.yaml @@ -0,0 +1,6 @@ +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshotClass +metadata: + name: vxflexos-snapclass +driver: csi-vxflexos.dellemc.com +deletionPolicy: Delete diff --git a/helm/csi-vxflexos/templates/storageclass-xfs.yaml b/helm/csi-vxflexos/templates/storageclass-xfs.yaml index db0ee3b5..6a34f380 100644 --- a/helm/csi-vxflexos/templates/storageclass-xfs.yaml +++ b/helm/csi-vxflexos/templates/storageclass-xfs.yaml @@ -5,6 +5,15 @@ metadata: annotations: provisioner: csi-vxflexos.dellemc.com reclaimPolicy: {{ required "Must provide a storage class reclaim policy." .Values.storageClass.reclaimPolicy }} +allowVolumeExpansion: true parameters: storagepool: {{ required "Must provide a VxFlex OS storage pool name." .Values.storagePool }} FsType: xfs +volumeBindingMode: WaitForFirstConsumer +allowedTopologies: +- matchLabelExpressions: + - key: csi-vxflexos.dellemc.com/{{ required "Must provide the VxFlex OS system Name." .Values.systemName }} + values: + - csi-vxflexos.dellemc.com + + diff --git a/helm/csi-vxflexos/templates/storageclass.yaml b/helm/csi-vxflexos/templates/storageclass.yaml index 3e1a06c7..81b696e1 100644 --- a/helm/csi-vxflexos/templates/storageclass.yaml +++ b/helm/csi-vxflexos/templates/storageclass.yaml @@ -6,5 +6,12 @@ metadata: storageclass.beta.kubernetes.io/is-default-class: {{ .Values.storageClass.isDefault | quote }} provisioner: csi-vxflexos.dellemc.com reclaimPolicy: {{ required "Must provide a storage class reclaim policy." .Values.storageClass.reclaimPolicy }} +allowVolumeExpansion: true parameters: storagepool: {{ required "Must provide a VxFlex OS storage pool name." .Values.storagePool }} +volumeBindingMode: WaitForFirstConsumer +allowedTopologies: +- matchLabelExpressions: + - key: csi-vxflexos.dellemc.com/{{ required "Must provide the VxFlex OS system Name." .Values.systemName }} + values: + - csi-vxflexos.dellemc.com diff --git a/helm/csi-vxflexos/values.yaml b/helm/csi-vxflexos/values.yaml index 9ab25714..3fc575a4 100644 --- a/helm/csi-vxflexos/values.yaml +++ b/helm/csi-vxflexos/values.yaml @@ -45,27 +45,3 @@ storageClass: # "storageClass.reclaimPolicy" defines what will happen when a volume is # removed from the Kubernetes API. Valid values are "Retain" and "Delete". reclaimPolicy: Delete - -# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DONLOADED. -images: - # "images.driver" defines the container images used for the driver container. - driver: dellemc/csi-vxflexos:v1.1.5.000R - - # "images.attacher" defines the container images used for the csi attacher - # container. - #attacher: quay.io/k8scsi/csi-attacher:v0.4.2 #for CSI 0.3.0 only (obsolete) - attacher: quay.io/k8scsi/csi-attacher:v1.0.1 #doesn't work with CSI 0.3.0 driver - - # "images.provisioner" defines the container images used for the csi provisioner - # container. - #provisioner: quay.io/k8scsi/csi-provisioner:v0.4.2 #for CSI 0.3.0 only (obsolete) - provisioner: quay.io/k8scsi/csi-provisioner:v1.0.1 #doesn't work with CSI 0.3.0 driver - - # "images.snapshotter" defines the container image used for the csi snapshotter - snapshotter: quay.io/k8scsi/csi-snapshotter:v1.0.1 - - # "images.registrar" defines the container images used for the csi registrar - # container. - #registrar: quay.io/k8scsi/driver-registrar:v0.4.2 #for CSI 0.3.0 only (obsolete) - registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.0.2 #doesn't work with CSI 0.3.0 driver - diff --git a/helm/install.vxflexos b/helm/install.vxflexos deleted file mode 100755 index a97f7dd9..00000000 --- a/helm/install.vxflexos +++ /dev/null @@ -1,59 +0,0 @@ -#/bin/bash -# Verify the kubernetes installation has the feature gates needed. -export NS=vxflexos -source ./common.bash - -sh ./verify.kubernetes -rc=$? -if [ $rc -ne 0 ] ; - then echo "*******************************************************************************" - echo "Warning: Kubernetes --feature-gates not correctly configured... it may not work" - echo "*******************************************************************************" - sleep 5 -fi - - -# Make sure the vxflexos-cred has already been established -echo kubectl get secrets -n vxflexos | grep vxflexos-cred --quiet -kubectl get secrets -n vxflexos | grep vxflexos-cred --quiet -if [ $? -ne 0 ]; - then echo "*** YOU MUST PROVIDE VxFlex OS credentials in a Kubernetes secret- see secret.yaml template ***" - exit 2 -fi -# Check for required CustomResourceDefinitions -if [ $kMinorVersion == "13" ]; -then - kubectl get customresourcedefinitions | grep csidrivers --quiet - if [ $? -ne 0 ]; - then echo "installing csidriver CRD"; kubectl create -f csidriver.yaml - fi - kubectl get customresourcedefinitions | grep nodeinfo --quiet - if [ $? -ne 0 ]; - then echo "installing nodeinfo CRD"; kubectl create -f nodeinfo.yaml - fi -fi - - -echo helm install --values myvalues.yaml --values csi-vxflexos/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml --namespace vxflexos vxflexos ./csi-vxflexos -helm install --values myvalues.yaml --values csi-vxflexos/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml --namespace vxflexos vxflexos ./csi-vxflexos - -waitOnRunning - - -echo "CSIDrivers:" -kubectl get csidrivers - -if [ $kMinorVersion == "13" ]; -then - echo "CSINodeInfos:" - kubectl get csinodeinfos -fi - -echo "StorageClasses:" -kubectl get storageclass -kubectl get volumesnapshotclass | grep vxflexos-snapclass --quiet -if [ $? -ne 0 ]; - then echo "installing volumesnapshotclass"; kubectl create -f volumesnapshotclass.yaml -fi -echo "VolumeSnapshotClasses:" -kubectl get volumesnapshotclass diff --git a/helm/uninstall.vxflexos b/helm/uninstall.vxflexos deleted file mode 100755 index 152d0339..00000000 --- a/helm/uninstall.vxflexos +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -helm delete -n vxflexos vxflexos -sleep 10 -kubectl get pods -n vxflexos -kubectl get volumesnapshotclass | grep vxflexos-snapclass --quiet -if [ $? -eq 0 ]; - then kubectl delete volumesnapshotclass vxflexos-snapclass -fi diff --git a/helm/verify.kubernetes b/helm/verify.kubernetes deleted file mode 100755 index a20e9508..00000000 --- a/helm/verify.kubernetes +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -# Determine the kubernetes version -kubeversion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*GitVersion:"//' -e 's/",.*//') -echo Kubernetes version $kubeversion - -# Determine the nodes -MINION_NODES=$(kubectl get nodes -o wide | grep -v -e master -e INTERNAL | awk ' { print $6; }') -MASTER_NODES=$(kubectl get nodes -o wide | awk ' /master/{ print $6; }') -echo Kubernetes master nodes: $MASTER_NODES -echo Kubernetes minion nodes: $MINION_NODES - -echo Verifying the SDC installation. -sdcfail=0 -for node in $MINION_NODES -do - ssh $node /opt/emc/scaleio/sdc/bin/drv_cfg --query_mdm - rv=$? - if [ $rv -ne 0 ]; then - echo "*******************************************************************" - echo "Node $node doees not have the SDC installed"; - echo "*******************************************************************" - sdcfail=1; - fi - -done -if [ $sdcfail -ne 0 ]; then echo "YOU MUST INSTALL THE VXFLEXOS SDC ON ALL MINION (WORKER) NODES"; exit 2; fi - -# Variables used for verification -if [ "${kubeversion}" == "13" ]; then -FEATURE_GATES="VolumeSnapshotDataSource CSINodeInfo CSIDriverRegistry CSIBlockVolume" -else -FEATURE_GATES="VolumeSnapshotDataSource" -fi - -MASTER_PROCS="kubelet kube-apiserver kube-scheduler kube-controller-manager" -MINION_PROCS="kubelet" -fail=0 - -echo Verifying the feature gates. -for node in $MASTER_NODES -do - echo ssh $node ps -ef >.ps.out - ssh $node ps -ef >.ps.out - for gate in $FEATURE_GATES - do - #echo checking $node for $gate ... - for proc in $MASTER_PROCS - do - #echo proc $proc - count=$(grep -e " $proc" -e "/$proc" .ps.out | grep -c $gate) - #echo $node $gate $proc $count - [ $count -ne "1" ] && { echo "node $node proc $proc gate $gate failed"; fail=1; } - done - done -done - -for node in $MINION_NODES -do - echo ssh $node ps -ef >.ps.out - ssh $node ps -ef >.ps.out - for gate in $FEATURE_GATES - do - #echo checking $node for $gate ... - for proc in $MINION_PROCS - do - #echo proc $proc - count=$(grep -e " $proc" -e "/$proc" .ps.out | grep -c $gate) - #echo $node $gate $proc $count - [ $count -ne "1" ] && { echo "node $node proc $proc gate $gate failed"; fail=1; } - done - done -done - -echo fail: $fail -exit $fail diff --git a/helm/volumesnapshotclass.yaml b/helm/volumesnapshotclass.yaml deleted file mode 100644 index ea10263a..00000000 --- a/helm/volumesnapshotclass.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: snapshot.storage.k8s.io/v1alpha1 -kind: VolumeSnapshotClass -metadata: - name: vxflexos-snapclass -snapshotter: csi-vxflexos.dellemc.com diff --git a/licenses/LICENSE b/licenses/LICENSE new file mode 100644 index 00000000..81defdc3 --- /dev/null +++ b/licenses/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + \ No newline at end of file diff --git a/overrides.mk b/overrides.mk new file mode 100644 index 00000000..0bceb6ee --- /dev/null +++ b/overrides.mk @@ -0,0 +1,65 @@ +# overrides file +# this file, included from the Makefile, will overlay default values with environment variables +# + +# DEFAULT values +DEFAULT_BASEIMAGE="registry.access.redhat.com/ubi7/ubi" +DEFAULT_GOVERSION="1.13.12" +DEFAULT_REGISTRY="sample_registry" +DEFAULT_IMAGENAME="csi-vxflexos" +DEFAULT_BUILDSTAGE="final" + +# set the BASEIMAGE if needed +ifeq ($(BASEIMAGE),) +export BASEIMAGE="$(DEFAULT_BASEIMAGE)" +endif + +# set the GOVERSION if needed +ifeq ($(GOVERSION),) +export GOVERSION="$(DEFAULT_GOVERSION)" +endif + +# set the REGISTRY if needed +ifeq ($(REGISTRY),) +export REGISTRY="$(DEFAULT_REGISTRY)" +endif + +# set the IMAGENAME if needed +ifeq ($(IMAGENAME),) +export IMAGENAME="$(DEFAULT_IMAGENAME)" +endif + +# set the BUILDSTAGE if needed +ifeq ($(BUILDSTAGE),) +export BUILDSTAGE="$(DEFAULT_BUILDSTAGE)" +endif + +# figure out if podman or docker should be used (use podman if found) +ifneq (, $(shell which podman 2>/dev/null)) +export BUILDER=podman +else +export BUILDER=docker +endif + +# target to print some help regarding these overrides and how to use them +overrides-help: + @echo + @echo "The following environment variables can be set to control the build" + @echo + @echo "GOVERSION - The version of Go to build with, default is: $(DEFAULT_GOVERSION)" + @echo " Current setting is: $(GOVERSION)" + @echo "BASEIMAGE - The base container image to build from: $(DEFAULT_BASEIMAGE)" + @echo " Current setting is: $(BASEIMAGE)" + @echo "REGISTRY - The registry to push images to, default is: $(DEFAULT_REGISTRY)" + @echo " Current setting is: $(REGISTRY)" + @echo "IMAGENAME - The image name to be built, defaut is: $(DEFAULT_IMAGENAME)" + @echo " Current setting is: $(IMAGENAME)" + @echo "IMAGETAG - The image tag to be built, default is an empty string which will determine the tag by examining annotated tags in the repo." + @echo " Current setting is: $(IMAGETAG)" + @echo "BUILDSTAGE - The Dockerfile build stage to execute, default is: $(DEFAULT_BUILDSTAGE)" + @echo " Stages can be found by looking at the Dockerfile" + @echo " Current setting is: $(BUILDSTAGE)" + @echo + + + diff --git a/service/controller.go b/service/controller.go index 734ecda9..3578001e 100644 --- a/service/controller.go +++ b/service/controller.go @@ -9,6 +9,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" csi "github.com/container-storage-interface/spec/lib/go/csi" @@ -80,10 +81,32 @@ func (s *service) CreateVolume( return nil, err } - // AccessibleTopology not currently supported + // validate AccessibleTopology accessibility := req.GetAccessibilityRequirements() - if accessibility != nil { - return nil, status.Errorf(codes.InvalidArgument, "Volume AccessibilityRequirements is not currently supported") + requestedSystem := "" + + if accessibility != nil && len(accessibility.GetPreferred()) > 0 { + + segments := accessibility.GetPreferred()[0].GetSegments() + for key := range segments { + if strings.HasPrefix(key, Name) { + tokens := strings.Split(key, "/") + constraint := "" + if len(tokens) > 1 { + constraint = tokens[1] + } + log.Printf("Found topology constraint: VxFlex OS system: %s", constraint) + if constraint == s.system.System.ID { + requestedSystem = s.system.System.ID + } + } + } + + // validate that the system name required matches the systemname that we know about + if len(segments) > 0 && requestedSystem == "" { + return nil, status.Errorf(codes.InvalidArgument, + "Requested System %s is unknown to this controller which is managing System %s", requestedSystem, s.system.System.ID) + } } params := req.GetParameters() @@ -251,6 +274,8 @@ func (s *service) createVolumeFromSnapshot(req *csi.CreateVolumeRequest, if vol.Name == name && vol.StoragePoolID == srcVol.StoragePoolID { log.Printf("Requested volume %s already exists", name) csiVolume := s.getCSIVolume(vol) + csiVolume.ContentSource = req.GetVolumeContentSource() + copyInterestingParameters(req.GetParameters(), csiVolume.VolumeContext) log.Printf("Requested volume (from snap) already exists %s (%s) storage pool %s", csiVolume.VolumeContext["Name"], csiVolume.VolumeId, csiVolume.VolumeContext["StoragePoolName"]) return &csi.CreateVolumeResponse{Volume: csiVolume}, nil @@ -1097,6 +1122,13 @@ func (s *service) ControllerGetCapabilities( }, }, }, + { + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_EXPAND_VOLUME, + }, + }, + }, }, }, nil } @@ -1416,7 +1448,79 @@ func (s *service) DeleteSnapshotConsistencyGroup( } func (s *service) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) { - return nil, status.Error(codes.Unimplemented, "") + + var reqID string + var err error + headers, ok := metadata.FromIncomingContext(ctx) + if ok { + if req, ok := headers["csi.requestid"]; ok && len(req) > 0 { + reqID = req[0] + } + } + + if err := s.requireProbe(ctx); err != nil { + return nil, err + } + + volID := req.GetVolumeId() + if volID == "" { + return nil, status.Error(codes.InvalidArgument, + "Volume ID is required") + } + + vol, err := s.getVolByID(volID) + if err != nil { + if strings.EqualFold(err.Error(), sioGatewayVolumeNotFound) || strings.Contains(err.Error(), "must be a hexadecimal number") { + return nil, status.Error(codes.NotFound, "volume not found") + } + return nil, status.Errorf(codes.Internal, "failure to load volume: %s", err.Error()) + } + + volName := vol.Name + cr := req.GetCapacityRange() + log.Printf("cr:%d", cr) + requestedSize, err := validateVolSize(cr) + if err != nil { + return nil, err + } + log.Printf("req.size:%d", requestedSize) + fields := map[string]interface{}{ + "RequestID": reqID, + "VolumeName": volName, + "RequestedSize": requestedSize, + } + log.WithFields(fields).Info("Executing ExpandVolume with following fields") + allocatedSize := int64(vol.SizeInKb) + log.Printf("allocatedsize:%d", allocatedSize) + + if requestedSize < allocatedSize { + return &csi.ControllerExpandVolumeResponse{}, nil + } + + if requestedSize == allocatedSize { + log.Infof("Idempotent call detected for volume (%s) with requested size (%d) SizeInKb and allocated size (%d) SizeInKb", + volName, requestedSize, allocatedSize) + return &csi.ControllerExpandVolumeResponse{ + CapacityBytes: requestedSize * bytesInKiB, + NodeExpansionRequired: true}, nil + } + + reqSize := requestedSize / kiBytesInGiB + tgtVol := goscaleio.NewVolume(s.adminClient) + tgtVol.Volume = vol + err = tgtVol.SetVolumeSize(strconv.Itoa(int(reqSize))) + if err != nil { + log.Errorf("Failed to execute ExpandVolume() with error (%s)", err.Error()) + return nil, status.Error(codes.Internal, err.Error()) + } + + //return the response with NodeExpansionRequired = true, so that CO could call + // NodeExpandVolume subsequently + csiResp := &csi.ControllerExpandVolumeResponse{ + CapacityBytes: requestedSize * bytesInKiB, + NodeExpansionRequired: true, + } + return csiResp, nil } func mergeStringMaps(base map[string]string, additional map[string]string) map[string]string { diff --git a/service/envvars.go b/service/envvars.go index 98ba48f3..bede71de 100644 --- a/service/envvars.go +++ b/service/envvars.go @@ -1,33 +1,34 @@ package service const ( - // EnvEndpoint is the name of the enviroment variable used to set the + // EnvEndpoint is the name of the environment variable used to set the // HTTP endpoint of the ScaleIO Gateway EnvEndpoint = "X_CSI_VXFLEXOS_ENDPOINT" - // EnvUser is the name of the enviroment variable used to set the + // EnvUser is the name of the environment variable used to set the // username when authenticating to the ScaleIO Gateway EnvUser = "X_CSI_VXFLEXOS_USER" - // EnvPassword is the name of the enviroment variable used to set the + // EnvPassword is the name of the environment variable used to set the // user's password when authenticating to the ScaleIO Gateway + /* #nosec G101 */ EnvPassword = "X_CSI_VXFLEXOS_PASSWORD" - // EnvInsecure is the name of the enviroment variable used to specify + // EnvInsecure is the name of the environment variable used to specify // that the ScaleIO Gateway's certificate chain and host name should not // be verified EnvInsecure = "X_CSI_VXFLEXOS_INSECURE" - // EnvSystemName is the name of the enviroment variable used to set the + // EnvSystemName is the name of the environment variable used to set the // name of the ScaleIO system to interact with EnvSystemName = "X_CSI_VXFLEXOS_SYSTEMNAME" - // EnvSDCGUID is the name of the enviroment variable used to set the + // EnvSDCGUID is the name of the environment variable used to set the // GUID of the SDC. This is only used by the Node Service, and removes // a need for calling an external binary to retrieve the GUID EnvSDCGUID = "X_CSI_VXFLEXOS_SDCGUID" - // EnvThick is the name of the enviroment variable used to specify + // EnvThick is the name of the environment variable used to specify // that thick provisioning should be used when creating volumes EnvThick = "X_CSI_VXFLEXOS_THICKPROVISIONING" diff --git a/service/features/authorization_failure.json b/service/features/authorization_failure.json new file mode 100644 index 00000000..5d287e5f --- /dev/null +++ b/service/features/authorization_failure.json @@ -0,0 +1,6 @@ +{ + "message": "Unauthorized", + "httpStatusCode": 401, + "errorCode": 0 +} + diff --git a/service/features/get_system_instances.json b/service/features/get_system_instances.json index 48ab026f..7035d3a6 100644 --- a/service/features/get_system_instances.json +++ b/service/features/get_system_instances.json @@ -2,6 +2,7 @@ { "perfProfile": "Default", "installId": "1c078b073d75512c", + "name": "mocksystem", "systemVersionName": "DellEMC ScaleIO Version: R2_6.0.133", "capacityAlertHighThresholdPercent": 80, "capacityAlertCriticalThresholdPercent": 90, diff --git a/service/features/node_publish_unpublish.feature b/service/features/node_publish_unpublish.feature index 9dac919f..51381a02 100644 --- a/service/features/node_publish_unpublish.feature +++ b/service/features/node_publish_unpublish.feature @@ -13,12 +13,12 @@ Feature: VxFlex OS CSI interface Then the error contains Examples: - | voltype | access | fstype | errormsg | - | "mount" | "single-writer" | "xfs" | "none" | - | "mount" | "single-writer" | "ext4" | "none" | - | "mount" | "multiple-writer" | "ext4" | "Invalid access mode" | - | "block" | "single-writer" | "none" | "none" | - | "block" | "multiple-writer" | "none" | "none" | + | voltype | access | fstype | errormsg | + | "mount" | "single-writer" | "xfs" | "none" | + | "mount" | "single-writer" | "ext4" | "none" | + | "mount" | "multiple-writer" | "ext4" | "Mount volumes do not support AccessMode MULTI_NODE_MULTI_WRITER" | + | "block" | "single-writer" | "none" | "none" | + | "block" | "multiple-writer" | "none" | "none" | Scenario Outline: Node publish block volumes various induced error use cases from examples Given a VxFlexOS service @@ -32,9 +32,10 @@ Feature: VxFlex OS CSI interface Examples: | error | errormsg | + | "NodePublishBlockTargetNotFile" | "existing path is a directory" | | "GOFSMockBindMountError" | "none" | - | "GOFSMockMountError" | "failure bind-mounting block device to private mount" | - | "GOFSMockGetMountsError" | "could not reliably determine existing mount status" | + | "GOFSMockMountError" | "error bind mounting to target path" | + | "GOFSMockGetMountsError" | "Could not getDevMounts" | | "NoSymlinkForNodePublish" | "not published to node" | # may be different for Windows vs. Linux | "NoBlockDevForNodePublish" | "is not a block device@@not published to node" | @@ -42,11 +43,11 @@ Feature: VxFlex OS CSI interface # may be different for Windows vs. Linux | "PrivateDirectoryNotExistForNodePublish"| "cannot find the path specified@@no such file or directory"| | "BlockMkfilePrivateDirectoryNodePublish"| "existing path is not a directory" | - | "NodePublishNoTargetPath" | "target path required" | + | "NodePublishNoTargetPath" | "target path required" | | "NodePublishNoVolumeCapability" | "volume capability required" | - | "NodePublishNoAccessMode" | "volume access mode required" | - | "NodePublishNoAccessType" | "volume access type required" | - | "NodePublishBlockTargetNotFile" | "wrong type (file vs dir)" | + | "NodePublishNoAccessMode" | "Volume Access Mode is required" | + | "NodePublishNoAccessType" | "Volume Access Type is required" | + | "NodePublishBadTargetPath" | "cannot find the path specified@@no such file or directory"| Scenario Outline: Node publish mount volumes various induced error use cases from examples Given a VxFlexOS service @@ -54,28 +55,32 @@ Feature: VxFlex OS CSI interface And a capability with voltype "mount" access "single-writer" fstype "xfs" And get Node Publish Volume Request And I induce error + And I induce error When I call Probe When I call NodePublishVolume "SDC_GUID" Then the error contains Examples: - | error | errormsg | - | "GOFSMockDevMountsError" | "none" | - | "GOFSMockMountError" | "mount induced error" | - | "GOFSMockGetMountsError" | "could not reliably determine existing mount status" | - | "NoSymlinkForNodePublish" | "not published to node" | + | error | errorb | errormsg | + | "GOFSMockDevMountsError" | "none" | "none" | + | "GOFSMockMountError" | "none" | "mount induced error" | + | "GOFSMockGetMountsError" | "none" | "could not reliably determine existing mount status" | + | "NoSymlinkForNodePublish" | "none" | "not published to node" | # may be different for Windows vs. Linux - | "NoBlockDevForNodePublish" | "is not a block device@@not published to node" | - | "TargetNotCreatedForNodePublish" | "none" | + | "NoBlockDevForNodePublish" | "none" | "is not a block device@@not published to node" | + | "TargetNotCreatedForNodePublish" | "none" | "none" | # may be different for Windows vs. Linux - | "PrivateDirectoryNotExistForNodePublish"| "cannot find the path specified@@no such file or directory" | - | "BlockMkfilePrivateDirectoryNodePublish"| "existing path is not a directory" | - | "NodePublishNoTargetPath" | "target path required" | - | "NodePublishNoVolumeCapability" | "volume capability required" | - | "NodePublishNoAccessMode" | "volume access mode required" | - | "NodePublishNoAccessType" | "volume access type required" | - | "NodePublishFileTargetNotDir" | "wrong type (file vs dir)" | - + | "PrivateDirectoryNotExistForNodePublish"| "none" | "cannot find the path specified@@no such file or directory" | + | "BlockMkfilePrivateDirectoryNodePublish"| "none" | "existing path is not a directory" | + | "NodePublishNoTargetPath" | "none" | "target path required" | + | "NodePublishNoVolumeCapability" | "none" | "volume capability required" | + | "NodePublishNoAccessMode" | "none" | "Volume Access Mode is required" | + | "NodePublishNoAccessType" | "none" | "Volume Access Type is required" | + | "NodePublishFileTargetNotDir" | "none" | "existing path is not a directory" | + | "NodePublishPrivateTargetAlreadyCreated"| "none" | "not published to node" | + | "NodePublishPrivateTargetAlreadyMounted"| "none" | "Mount point already in use by device@@none" | + | "NodePublishPrivateTargetAlreadyMounted"| "GOFSMockGetMountsError" | "could not reliably determine existing mount status" | + | "NodePublishBadTargetPath" | "none" | "cannot find the path specified@@no such file or directory"| Scenario Outline: Node publish various use cases from examples when volume already published Given a VxFlexOS service @@ -83,17 +88,18 @@ Feature: VxFlex OS CSI interface And a capability with voltype access fstype When I call Probe And I call NodePublishVolume "SDC_GUID" + And I induce error "NodePublishPathAltDataDir" And I call NodePublishVolume "SDC_GUID" Then the error contains Examples: - | voltype | access | fstype | errormsg | - | "block" | "single-writer" | "none" | "access mode conflicts with existing mounts" | - | "mount" | "single-writer" | "xfs" | "access mode conflicts with existing mounts" | - | "mount" | "single-writer" | "ext4" | "access mode conflicts with existing mounts" | - | "mount" | "multiple-writer" | "ext4" | "Invalid access mode" | -# The following line seems like the wrong behavior; shouldn't this be allowed? - | "block" | "multiple-reader" | "none" | "access mode conflicts with existing mounts" | + | voltype | access | fstype | errormsg | + | "block" | "single-writer" | "none" | "Access mode conflicts with existing mounts" | + | "block" | "multiple-writer" | "none" | "none" | + | "mount" | "single-writer" | "xfs" | "Access mode conflicts with existing mounts" | + | "mount" | "single-writer" | "ext4" | "Access mode conflicts with existing mounts" | + | "mount" | "multiple-writer" | "ext4" | "Mount volumes do not support AccessMode MULTI_NODE_MULTI_WRITER" | + | "block" | "multiple-reader" | "none" | "none" | Scenario Outline: Node publish various use cases from examples when read-only mount volume already published Given a VxFlexOS service @@ -107,15 +113,15 @@ Feature: VxFlex OS CSI interface Then the error contains Examples: - | voltype | access | fstype | errormsg | - | "block" | "multiple-reader" | "none" | "read only not supported for Block Volume" | - | "mount" | "single-reader" | "none" | "none" | - | "mount" | "single-reader" | "xfs" | "none" | - | "mount" | "multiple-reader" | "ext4" | "none" | - | "mount" | "single-writer" | "ext4" | "access mode conflicts with existing mounts" | - | "mount" | "multiple-writer" | "ext4" | "Invalid access mode" | - - Scenario Outline: Node publish various use cases from examples when read-only mount volume already published + | voltype | access | fstype | errormsg | + | "block" | "multiple-reader" | "none" | "read only not supported for Block Volume" | + | "mount" | "single-reader" | "none" | "none" | + | "mount" | "single-reader" | "xfs" | "none" | + | "mount" | "multiple-reader" | "ext4" | "none" | + | "mount" | "single-writer" | "ext4" | "Access mode conflicts with existing mounts" | + | "mount" | "multiple-writer" | "ext4" | "do not support AccessMode MULTI_NODE_MULTI_WRITER" | + + Scenario Outline: Node publish various use cases from examples when read-only mount volume already published and I change the target path Given a VxFlexOS service And a controller published volume And a capability with voltype access fstype @@ -128,14 +134,13 @@ Feature: VxFlex OS CSI interface Then the error contains Examples: - | voltype | access | fstype | errormsg | - | "mount" | "single-reader" | "none" | "none" | - | "mount" | "single-reader" | "xfs" | "none" | - | "block" | "multiple-reader" | "none" | "read only not supported for Block Volume" | - | "mount" | "multiple-reader" | "ext4" | "none" | - | "mount" | "single-writer" | "ext4" | "access mode conflicts with existing mounts" | - | "mount" | "multiple-writer" | "ext4" | "Invalid access mode" | - + | voltype | access | fstype | errormsg | + | "mount" | "single-reader" | "none" | "none" | + | "mount" | "single-reader" | "xfs" | "none" | + | "block" | "multiple-reader" | "none" | "read only not supported for Block Volume" | + | "mount" | "multiple-reader" | "ext4" | "none" | + | "mount" | "single-writer" | "ext4" | "Access mode conflicts with existing mounts" | + | "mount" | "multiple-writer" | "ext4" | "do not support AccessMode MULTI_NODE_MULTI_WRITER" | Scenario: Node publish volume with volume context Given a VxFlexOS service @@ -178,7 +183,7 @@ Feature: VxFlex OS CSI interface | error | errormsg | | "NodeUnpublishBadVolume" | "none" | | "GOFSMockGetMountsError" | "could not reliably determine existing mount status" | - | "NodeUnpublishNoTargetPath" | "target path required" | + | "NodeUnpublishNoTargetPath" | "target path argument is required" | | "GOFSMockUnmountError" | "Error unmounting target" | | "PrivateDirectoryNotExistForNodePublish"| "none" | diff --git a/service/features/service.feature b/service/features/service.feature index 23572347..f2f235b6 100644 --- a/service/features/service.feature +++ b/service/features/service.feature @@ -17,7 +17,6 @@ Feature: VxFlex OS CSI interface When I call Probe Then a valid ProbeResponse is returned -@wip Scenario: Identity Probe call no controller connection Given a VxFlexOS service And the Controller has no connection @@ -57,6 +56,12 @@ Examples: When I call Probe Then the possible error contains "unable to get SDC GUID" + Scenario: Identity Probe call node probe drvCfg error + Given a VxFlexOS service + And there is a Node Probe drvCfg error + When I call Probe + Then the possible error contains "unable to get System Name via config or drv_cfg binary" + Scenario Outline: Create volume good scenario Given a VxFlexOS service When I call Probe @@ -139,12 +144,19 @@ Examples: And I call CreateVolume "volume4" Then the error contains "Couldn't find storage pool" - Scenario: Create volume with Accessibility Requirements + Scenario Outline: Create volume with Accessibility Requirements Given a VxFlexOS service When I call Probe - And I specify AccessibilityRequirements + And I specify AccessibilityRequirements with a SystemID of And I call CreateVolume "accessibility" - Then the error contains "AccessibilityRequirements is not currently supported" + Then the error contains + + Examples: + | sysID | errormsg | + | "f.service.opt.SystemName" | "none" | + | "" | "unknown to this controller" | + | "Unknown" | "unknown to this controller" | + | "badSystem" | "unknown to this controller" | Scenario: Create volume with VolumeContentSource Given a VxFlexOS service @@ -301,6 +313,7 @@ Examples: When I call NodeUnstageVolume Then the error contains "Unimplemented" + Scenario: Call NodeGetCapabilities should return a valid response Given a VxFlexOS service And I call Probe @@ -337,7 +350,7 @@ Examples: And a valid CreateVolumeResponse is returned And I induce error "WrongVolIDError" And I call CreateSnapshot "snap1" - Then the error contains "Failed to create snapshot" + Then the error contains "Failed to create snapshot" Scenario: Snapshot a single block volume but receive error Given a VxFlexOS service @@ -507,6 +520,7 @@ Examples: When I call Probe And I call Create Volume from Snapshot Then the error contains "Failed to create snapshot" + Scenario: Idempotent create a volume from a snapshot Given a VxFlexOS service @@ -519,15 +533,49 @@ Examples: And no error was received And a valid CreateVolumeResponse is returned - Scenario: Call ControllerExpandVolume, should get unimplemented - Given a VxFlexOS service - When I call ControllerExpandVolume - Then the error contains "Unimplemented" - Scenario: Call NodeExpandVolume, should get unimplemented + Scenario Outline: Call ControllerExpandVolume Given a VxFlexOS service - When I call NodeExpandVolume - Then the error contains "Unimplemented" + And I call Probe + And I call CreateVolumeSize "volume10" "32" + And a valid CreateVolumeResponse is returned + And I induce error + Then I call ControllerExpandVolume set to + And the error contains + And I call ControllerExpandVolume set to + Then the error contains + + Examples: + | error | GB | errmsg | + | "none" | 32 | "none" | + | "SetVolumeSizeError" | 64 | "induced error" | + | "none" | 16 | "none" | + | "NoVolumeIDError" | 64 | "Volume ID is required" | + | "none" | 64 | "none" | + | "GetVolByIDError" | 64 | "induced error" | + + Scenario Outline: Call NodeExpandVolume + Given a VxFlexOS service + And I call Probe + And I call CreateVolumeSize "volume4" "32" + And a controller published volume + And a capability with voltype "mount" access "single-writer" fstype "xfs" + And get Node Publish Volume Request + And I call NodePublishVolume "SDC_GUID" + And no error was received + And I induce error + When I call NodeExpandVolume with volumePath as + Then the error contains + + Examples: + | error | volPath | errormsg | + | "none" | "" | "Volume path required" | + | "none" | "test/tmp/datadir" | "none" | + | "GOFSInduceFSTypeError" | "test/tmp/datadir" | "Failed to fetch filesystem" | + | "GOFSInduceResizeFSError" | "test/tmp/datadir" | "Failed to resize device" | + | "NoVolumeIDError" | "test/tmp/datadir" | "Volume ID is required" | + | "none" | "not/a/path/1234" | "Could not stat volume path" | + | "none" | "test/tmp/datafile" | "none" | Scenario: Call NodeGetVolumeStats, should get unimplemented Given a VxFlexOS service @@ -549,7 +597,6 @@ Examples: When i Call getStoragePoolnameByID "123" Then the error contains "cannot find storage pool" -@wip Scenario: Test BeforeServe Given a VxFlexOS service And I invalidate the Probe cache @@ -557,6 +604,26 @@ Examples: # Get different error message on Windows vs. Linux Then the error contains "Unable to initialize cert pool from system@@unable to login to VxFlexOS Gateway@@unable to get SDC GUID" - - - + Scenario: Call Node getAllSystems + Given a VxFlexOS service + And I do not have a gateway connection + When I Call nodeGetAllSystems + + Scenario: Call Node getAllSystems + Given a VxFlexOS service + And I do not have a gateway connection + And I do not have a valid gateway endpoint + When I Call nodeGetAllSystems + Then the error contains "Unable to create ScaleIO client" + + Scenario: Call Node getAllSystems + Given a VxFlexOS service + And I do not have a gateway connection + And I do not have a valid gateway password + When I Call nodeGetAllSystems + Then the error contains "Unable to create ScaleIO client" + + Scenario: Call evalsymlinks + Given a VxFlexOS service + When I call evalsymlink "invalidpath" + Then the error contains "Could not evaluate symlinks for path" diff --git a/service/features/volume.json.template b/service/features/volume.json.template index 8dad6000..a00d7cd8 100644 --- a/service/features/volume.json.template +++ b/service/features/volume.json.template @@ -1,5 +1,5 @@ { - "sizeInKb": 8388608, + "sizeInKb": 33554432, "vtreeId": "c36a59ef00000001", "storagePoolId": "e65f9c2700000000", "isObfuscated": false, diff --git a/service/identity.go b/service/identity.go index b7680e5a..f97613a8 100644 --- a/service/identity.go +++ b/service/identity.go @@ -40,6 +40,13 @@ func (s *service) GetPluginCapabilities( }, }, }, + { + Type: &csi.PluginCapability_VolumeExpansion_{ + VolumeExpansion: &csi.PluginCapability_VolumeExpansion{ + Type: csi.PluginCapability_VolumeExpansion_ONLINE, + }, + }, + }, } } return &rep, nil diff --git a/service/mount.go b/service/mount.go index d34829a7..3cdf2313 100644 --- a/service/mount.go +++ b/service/mount.go @@ -5,14 +5,15 @@ import ( "fmt" "os" "path/filepath" + "strings" + + "time" csi "github.com/container-storage-interface/spec/lib/go/csi" "github.com/dell/gofsutil" log "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "os/exec" - "time" ) // Variables set only for unit testing. @@ -55,8 +56,8 @@ func GetDevice(path string) (*Device, error) { return &Device{ Name: fi.Name(), - FullPath: path, - RealDev: d, + FullPath: replaceBackslashWithSlash(path), + RealDev: replaceBackslashWithSlash(d), }, nil } @@ -85,12 +86,6 @@ func publishVolume( "volume capability required") } - accMode := volCap.GetAccessMode() - if accMode == nil { - return status.Error(codes.InvalidArgument, - "volume access mode required") - } - // make sure device is valid sysDevice, err := GetDevice(device) if err != nil { @@ -99,73 +94,37 @@ func publishVolume( id, err.Error()) } - isBlock := false - typeSet := false - - if blockVol := volCap.GetBlock(); blockVol != nil { - // Read-only is not supported for BlockVolume. Doing a read-only - // bind mount of the device to the target path does not prevent - // the underlying block device from being modified, so don't - // advertise a false sense of security - if ro { - return status.Error(codes.InvalidArgument, - "read only not supported for Block Volume") - } - - isBlock = true - typeSet = true + isBlock, mntVol, accMode, multiAccessFlag, err := validateVolumeCapability(volCap, ro) + if err != nil { + return err } - // make sure target is created - tgtStat, err := os.Stat(target) + // Make sure target is created. The spec says the driver is responsible + // for creating the target, but Kubernetes generallly creates the target. + privTgt := getPrivateMountPoint(privDir, id) + err = createTarget(target, isBlock) if err != nil { - if os.IsNotExist(err) { - if err != nil { - - if isBlock { - _, err = mkfile(target) - if err != nil { - return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) - } - } else { - _, err = mkdir(target) - if err != nil { - return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) - } - } - - } else { - - return status.Errorf(codes.Internal, - "failed to stat target, err: %s", err.Error()) - } - } + // Unmount and remove the private directory for the retry so clean start next time. + // K8S probably removed part of the path. + cleanupPrivateTarget(reqID, privTgt) + return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) } - tgtStat, _ = os.Stat(target) // make sure privDir exists and is a directory if _, err := mkdir(privDir); err != nil { return err } - mntVol := volCap.GetMount() - if mntVol != nil { - typeSet = true - } - if !typeSet { - return status.Error(codes.InvalidArgument, - "volume access type required") + // Handle block as a short cut + if isBlock { + // BLOCK only + mntFlags := mntVol.GetMountFlags() + err = mountBlock(sysDevice, target, mntFlags, singleAccessMode(accMode)) + return err } // check that target is right type for vol type - - if !(tgtStat.IsDir() == !isBlock) { - return status.Errorf(codes.FailedPrecondition, - "target: %s wrong type (file vs dir) Access Type", target) - } - // Path to mount device to - privTgt := getPrivateMountPoint(privDir, id) f := log.Fields{ "id": id, @@ -191,17 +150,13 @@ func publishVolume( log.WithFields(f).Debug("attempting mount to private area") // Make sure private mount point exists - var created bool - if isBlock { - created, err = mkfile(privTgt) - } else { - created, err = mkdir(privTgt) - } + created, err := mkdir(privTgt) if err != nil { return status.Errorf(codes.Internal, "Unable to create private mount point: %s", err.Error()) } + alreadyMounted := false if !created { log.WithFields(f).Debug("private mount target already exists") @@ -222,27 +177,31 @@ func publishVolume( } for _, m := range mnts { if m.Path == privTgt { - log.WithFields(f).WithField("mountedDevice", m.Device).Error( - "mount point already in use by device") - return status.Error(codes.Internal, - "Unable to use private mount point") + log.Debug(fmt.Sprintf("MOUNT: %#v", m)) + resolvedMountDevice := evalSymlinks(m.Device) + if resolvedMountDevice != sysDevice.RealDev { + log.WithFields(f).WithField("mountedDevice", m.Device).Error( + "mount point already in use by device") + return status.Error(codes.Internal, + "Mount point already in use by device") + } + alreadyMounted = true } } } - if !isBlock { + if !alreadyMounted { fs := mntVol.GetFsType() mntFlags := mntVol.GetMountFlags() - + if fs == "xfs" { + mntFlags = append(mntFlags, "nouuid") + } if err := handlePrivFSMount( ctx, accMode, sysDevice, mntFlags, fs, privTgt); err != nil { + // K8S may have removed the desired mount point. Clean up the private target. + cleanupPrivateTarget(reqID, privTgt) return err } - } else { - if err := gofsutil.BindMount(ctx, sysDevice.FullPath, privTgt); err != nil { - return status.Errorf(codes.Internal, - "failure bind-mounting block device to private mount: %s", err.Error()) - } } } else { @@ -250,30 +209,33 @@ func publishVolume( // mounted to the expected private mount, with correct rw/ro perms mounted := false for _, m := range devMnts { - if m.Path == privTgt { + if m.Path == target { + log.Printf("mount %#v already mounted to requested target %s", m, target) + } else if m.Path == privTgt { mounted = true - rwo := "rw" + rwo := multiAccessFlag if ro { rwo = "ro" } - if contains(m.Opts, rwo) { - log.WithFields(f).Debug( - "private mount already in place") - break + if rwo == "" || contains(m.Opts, rwo) { + log.WithFields(f).Debug("private mount already in place") } else { + log.WithFields(f).Printf("mount %#v rwo %s", m, rwo) return status.Error(codes.InvalidArgument, - "access mode conflicts with existing mounts") + "Access mode conflicts with existing mounts") } + } else if singleAccessMode(accMode) { + return status.Error(codes.FailedPrecondition, "Access mode conflicts with existing mounts") } } if !mounted { return status.Error(codes.Internal, - "device already in use and mounted elsewhere") + "Device already in use and mounted elsewhere") } } // Private mount in place, now bind mount to target path - devMnts, err = getDevMounts(sysDevice) + targetMnts, err := getPathMounts(target) if err != nil { return status.Errorf(codes.Internal, "could not reliably determine existing mount status: %s", @@ -282,19 +244,19 @@ func publishVolume( // If mounts already existed for this device, check if mount to // target path was already there - if len(devMnts) > 0 { - for _, m := range devMnts { + if len(targetMnts) > 0 { + for _, m := range targetMnts { if m.Path == target { // volume already published to target // if mount options look good, do nothing - rwo := "rw" - if accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY || accMode.GetMode() == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { + rwo := multiAccessFlag + if ro { rwo = "ro" } - if !contains(m.Opts, rwo) { + if rwo != "" && !contains(m.Opts, rwo) { + log.WithFields(f).Printf("mount %#v rwo %s\n", m, rwo) return status.Error(codes.Internal, "volume previously published with different options") - } // Existing mount satisfies request log.WithFields(f).Debug("volume already published to target") @@ -304,16 +266,29 @@ func publishVolume( } + // Recheck that target is created. k8s has this awful habit of deleting the target if it times out the request. + // This will narrow the window. + err = createTarget(target, isBlock) + if err != nil { + // Unmount and remove the private directory for the retry so clean start next time. + // K8S probably removed part of the path. + cleanupPrivateTarget(reqID, privTgt) + return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) + } + var mntFlags []string - if isBlock { - mntFlags = make([]string, 0) - } else { - mntFlags = mntVol.GetMountFlags() - if accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY || accMode.GetMode() == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { - mntFlags = append(mntFlags, "ro") - } + mntFlags = mntVol.GetMountFlags() + if mntVol.FsType == "xfs" { + mntFlags = append(mntFlags, "nouuid") } + if ro || accMode.GetMode() == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY { + mntFlags = append(mntFlags, "ro") + } + if err := gofsutil.BindMount(ctx, privTgt, target, mntFlags...); err != nil { + // Unmount and remove the private directory for the retry so clean start next time. + // K8S probably removed part of the path. + cleanupPrivateTarget(reqID, privTgt) return status.Errorf(codes.Internal, "error publish volume to target path: %s", err.Error()) @@ -370,13 +345,19 @@ func contains(list []string, item string) bool { func mkfile(path string) (bool, error) { st, err := os.Stat(path) if os.IsNotExist(err) { + /* #nosec G302 */ file, err := os.OpenFile(path, os.O_CREATE, 0755) if err != nil { log.WithField("dir", path).WithError( err).Error("Unable to create dir") return false, err } - file.Close() + err = file.Close() + if err != nil { + // Log the error but keep going + log.WithField("file", path).WithError( + err).Error("Unable to close file") + } log.WithField("path", path).Debug("created file") return true, nil } @@ -391,6 +372,7 @@ func mkfile(path string) (bool, error) { func mkdir(path string) (bool, error) { st, err := os.Stat(path) if os.IsNotExist(err) { + /* #nosec G301 */ if err := os.Mkdir(path, 0755); err != nil { log.WithField("dir", path).WithError( err).Error("Unable to create dir") @@ -450,7 +432,7 @@ func unpublishVolume( tgtMnt := false privMnt := false for _, m := range mnts { - if m.Source == sysDevice.RealDev || m.Device == sysDevice.RealDev { + if m.Source == sysDevice.RealDev || m.Device == sysDevice.RealDev || m.Device == sysDevice.FullPath { if m.Path == privTgt { privMnt = true } else if m.Path == target { @@ -495,7 +477,9 @@ func unmountPrivMount( } log.WithField("directory", target).Debug( "removing directory") - os.Remove(target) + if err := os.Remove(target); err != nil { + log.Errorf("Unable to remove directory: %v", err) + } } return nil } @@ -518,18 +502,37 @@ func getDevMounts( return devMnts, nil } +// For Windows testing, replace any paths with \\ to have / +func replaceBackslashWithSlash(input string) string { + return strings.Replace(input, "\\", "/", -1) +} + +// getPathMounts finds all the mounts for a given path. +func getPathMounts(path string) ([]gofsutil.Info, error) { + ctx := context.Background() + devMnts := make([]gofsutil.Info, 0) + + mnts, err := gofsutil.GetMounts(ctx) + if err != nil { + return devMnts, err + } + for _, m := range mnts { + if m.Path == path { + devMnts = append(devMnts, m) + } + } + return devMnts, nil +} + func removeWithRetry(target string) error { var err error for i := 0; i < 3; i++ { err = os.Remove(target) if err != nil && !os.IsNotExist(err) { log.Error("error removing private mount target: " + err.Error()) - cmd := exec.Command("/usr/bin/rmdir", target) - textBytes, err := cmd.CombinedOutput() + err = os.RemoveAll(target) if err != nil { - log.Error("error calling rmdir: " + err.Error()) - } else { - log.Printf("rmdir output: %s", string(textBytes)) + log.Errorf("Error removing directory: %v", err.Error()) } time.Sleep(3 * time.Second) } else { @@ -539,3 +542,136 @@ func removeWithRetry(target string) error { } return err } + +// Evaulate symlinks to a resolution. In case of an error, +// logs the error but returns the original path. +func evalSymlinks(path string) string { + // eval any symlinks and make sure it points to a device + d, err := filepath.EvalSymlinks(path) + if err != nil { + log.Error("Could not evaluate symlinks for path: " + path) + return path + } + return d +} + +// Given a volume capability, validates it and returns: +// boolean isBlock -- the capability is for a block device +// csi.VolumeCapability_MountVolume - contains FsType and MountFlags +// csi.VolumeCapability_AccessMode accMode gives the access mode +// string multiAccessFlag - "rw" or "ro" or "" as appropriate +// error +func validateVolumeCapability(volCap *csi.VolumeCapability, readOnly bool) (bool, *csi.VolumeCapability_MountVolume, *csi.VolumeCapability_AccessMode, string, error) { + var mntVol *csi.VolumeCapability_MountVolume + isBlock := false + isMount := false + multiAccessFlag := "" + accMode := volCap.GetAccessMode() + if accMode == nil { + return false, mntVol, nil, "", status.Error(codes.InvalidArgument, "Volume Access Mode is required") + } + if blockVol := volCap.GetBlock(); blockVol != nil { + isBlock = true + switch accMode.GetMode() { + case csi.VolumeCapability_AccessMode_UNKNOWN: + return true, mntVol, accMode, "", status.Error(codes.InvalidArgument, "Unknown Access Mode") + case csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER: + case csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY: + case csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY: + multiAccessFlag = "ro" + case csi.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER: + case csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER: + multiAccessFlag = "rw" + } + if readOnly { + return true, mntVol, accMode, "", status.Error(codes.InvalidArgument, "read only not supported for Block Volume") + } + } + mntVol = volCap.GetMount() + if mntVol != nil { + isMount = true + switch accMode.GetMode() { + case csi.VolumeCapability_AccessMode_UNKNOWN: + return false, mntVol, accMode, "", status.Error(codes.InvalidArgument, "Unknown Access Mode") + case csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER: + case csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY: + case csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY: + multiAccessFlag = "ro" + case csi.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER: + case csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER: + return false, mntVol, accMode, "", status.Error(codes.AlreadyExists, "Mount volumes do not support AccessMode MULTI_NODE_MULTI_WRITER") + } + } + + if !isBlock && !isMount { + return false, mntVol, accMode, "", status.Error(codes.InvalidArgument, "Volume Access Type is required") + } + return isBlock, mntVol, accMode, multiAccessFlag, nil +} + +// singleAccessMode returns true if only a single access is allowed SINGLE_NODE_WRITER or SINGLE_NODE_READER_ONLY +func singleAccessMode(accMode *csi.VolumeCapability_AccessMode) bool { + switch accMode.GetMode() { + case csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER: + return true + case csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY: + return true + } + return false +} + +func createTarget(target string, isBlock bool) error { + var err error + // Make sure target is created. The spec says the driver is responsible + // for creating the target, but Kubernetes generallly creates the target. + if isBlock { + _, err = mkfile(target) + if err != nil { + return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) + } + } else { + _, err = mkdir(target) + if err != nil { + return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) + } + } + return nil +} + +// cleanupPrivateTarget unmounts and removes the private directory for the retry so clean start next time. +func cleanupPrivateTarget(reqID, privTgt string) { + log.WithField("CSIRequestID", reqID).WithField("privTgt", privTgt).Info("Cleaning up private target") + if privErr := gofsutil.Unmount(context.Background(), privTgt); privErr != nil { + log.WithField("CSIRequestID", reqID).Printf("Error unmounting privTgt %s: %s", privTgt, privErr) + } + if privErr := removeWithRetry(privTgt); privErr != nil { + log.WithField("CSIRequestID", reqID).Printf("Error removing privTgt %s: %s", privTgt, privErr) + } +} + +// mountBlock bind mounts the device to the required target +func mountBlock(device *Device, target string, mntFlags []string, singleAccess bool) error { + log.Printf("mountBlock called device %#v target %s mntFlags %#v", device, target, mntFlags) + // Check to see if already mounted + mnts, err := getDevMounts(device) + if err != nil { + return status.Errorf(codes.Internal, "Could not getDevMounts for: %s", device.RealDev) + } + for _, mnt := range mnts { + if mnt.Path == target { + log.Info("Block volume target is already mounted") + return nil + } else if singleAccess { + return status.Error(codes.InvalidArgument, "Access mode conflicts with existing mounts") + } + } + err = createTarget(target, true) + if err != nil { + return status.Error(codes.FailedPrecondition, fmt.Sprintf("Could not create %s: %s", target, err.Error())) + } + err = gofsutil.BindMount(context.Background(), device.RealDev, target, mntFlags...) + if err != nil { + return status.Errorf(codes.Internal, "error bind mounting to target path: %s", target) + } + return nil +} diff --git a/service/node.go b/service/node.go index 10d4fd62..656028dc 100644 --- a/service/node.go +++ b/service/node.go @@ -3,12 +3,14 @@ package service import ( "bufio" "bytes" + "fmt" "os" "os/exec" "strings" "time" csi "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/dell/gofsutil" "github.com/dell/goscaleio" log "github.com/sirupsen/logrus" "golang.org/x/net/context" @@ -22,7 +24,8 @@ const ( ) var ( - getMappedVolMaxRetry = 20 + getMappedVolMaxRetry = 30 + connectedSystemID = make([]string, 0) ) func (s *service) NodeStageVolume( @@ -65,21 +68,9 @@ func (s *service) NodePublishVolume( id := req.GetVolumeId() log.Printf("NodePublishVolume id: %s", id) - // If not found immediately, give a little time for controller to - // communicate with SDC that it has volume - var sdcMappedVol *goscaleio.SdcMappedVolume - var err error - for i := 0; i < getMappedVolMaxRetry; i++ { - sdcMappedVol, err = getMappedVol(id) - if sdcMappedVol != nil { - break - } - log.Printf("Node publish getMappedVol retry: %d", i) - time.Sleep(1 * time.Second) - } + sdcMappedVol, err := s.getSDCMappedVol(id) if err != nil { - log.Printf("NodePublishVolume returning not published to node: %s", id) - return nil, err + return nil, status.Error(codes.InvalidArgument, err.Error()) } if err := publishVolume(req, s.privDir, sdcMappedVol.SdcDevice, reqID); err != nil { @@ -102,12 +93,20 @@ func (s *service) NodeUnpublishVolume( } } + targetPath := req.GetTargetPath() + if targetPath == "" { + return nil, status.Error(codes.InvalidArgument, "A target path argument is required") + } + s.logStatistics() id := req.GetVolumeId() log.Printf("NodeUnublishVolume id: %s", id) - sdcMappedVol, err := getMappedVol(id) + sdcMappedVol, err := s.getSDCMappedVol(id) if err != nil { + // fix k8s 19 bug: ControllerUnpublishVolume is called before NodeUnpublishVolume + _ = gofsutil.Unmount(ctx, targetPath) + // Idempotent need to return ok if not published return &csi.NodeUnpublishVolumeResponse{}, nil } @@ -116,15 +115,35 @@ func (s *service) NodeUnpublishVolume( return nil, err } - privTgt := req.GetTargetPath() - if privTgt == "" { - return nil, status.Error(codes.InvalidArgument, "A Staging Target argument is required") + _ = gofsutil.Unmount(ctx, targetPath) + + if err := removeWithRetry(targetPath); err != nil { + log.Errorf("Unable to remove target path: %v", err) } - removeWithRetry(privTgt) return &csi.NodeUnpublishVolumeResponse{}, nil } +func (s *service) getSDCMappedVol(volumeID string) (*goscaleio.SdcMappedVolume, error) { + // If not found immediately, give a little time for controller to + // communicate with SDC that it has volume + var sdcMappedVol *goscaleio.SdcMappedVolume + var err error + for i := 0; i < getMappedVolMaxRetry; i++ { + sdcMappedVol, err = getMappedVol(volumeID) + if sdcMappedVol != nil { + break + } + log.Printf("Node publish getMappedVol retry: %d", i) + time.Sleep(1 * time.Second) + } + if err != nil { + log.Printf("SDC returned volume %s not published to node", volumeID) + return nil, err + } + return sdcMappedVol, err +} + // Get the volumes published to the SDC (given by SdcMappedVolume) and scan for requested vol id func getMappedVol(id string) (*goscaleio.SdcMappedVolume, error) { // get source path of volume/device @@ -148,8 +167,67 @@ func getMappedVol(id string) (*goscaleio.SdcMappedVolume, error) { return sdcMappedVol, nil } +func (s *service) getAllSystems(ctx context.Context, systems []string) error { + // Create our ScaleIO API client, if needed + if s.adminClient == nil { + // create a new client + c, err := goscaleio.NewClientWithArgs( + s.opts.Endpoint, "", s.opts.Insecure, !s.opts.DisableCerts) + if err != nil { + e := fmt.Errorf("Unable to create ScaleIO client: %s", err.Error()) + log.Error(e) + return e + } + // authenticate to this client + _, err = c.Authenticate(&goscaleio.ConfigConnect{ + Endpoint: s.opts.Endpoint, + Username: s.opts.User, + Password: s.opts.Password, + }) + if err != nil { + e := fmt.Errorf("Unable to create ScaleIO client: %s", err.Error()) + log.Error(e) + return e + } + // success! Save the client for later use + s.adminClient = c + } + + // get the systemNames for all of the systemIDs in connectedSystemID + if s.adminClient != nil { + connectedSystemName := make([]string, 0) + for _, i := range systems { + sys, err := s.adminClient.FindSystem(i, i, "") + if err != nil { + // could not find the name for this system. Log a message and keep going + e := fmt.Errorf("Unable to find VxFlex OS system name matching system ID: %s. Error is %v", i, err) + log.Error(e) + } else { + if sys.System == nil || sys.System.Name == "" { + // system does not have a name, this is fine + log.Printf("Found system without a name, system ID: %s", i) + } else { + log.Printf("Found system Name: %s", sys.System.Name) + connectedSystemName = append(connectedSystemName, sys.System.Name) + } + } + } + for _, n := range connectedSystemName { + connectedSystemID = append(connectedSystemID, n) + } + } + return nil +} + func (s *service) nodeProbe(ctx context.Context) error { + // make sure the kernel module is loaded + if !kmodLoaded(s.opts) { + return status.Error(codes.FailedPrecondition, + "scini kernel module not loaded") + } + + // fetch the SDC GUID if s.opts.SdcGUID == "" { // try to get GUID using `drv_cfg` binary if _, err := os.Stat(drvCfg); os.IsNotExist(err) { @@ -167,11 +245,18 @@ func (s *service) nodeProbe(ctx context.Context) error { log.WithField("guid", s.opts.SdcGUID).Info("set SDC GUID") } - if !kmodLoaded(s.opts) { - return status.Error(codes.FailedPrecondition, - "scini kernel module not loaded") + // fetch the systemIDs + var err error + connectedSystemID, err = getSystemsKnownToSDC(s.opts) + if err != nil { + return status.Errorf(codes.FailedPrecondition, "%s", err) } + // get all the system names and IDs. + // ignore the errors here as all the information is supplementary + /* #nosec G104 */ + s.getAllSystems(ctx, connectedSystemID) + // make sure privDir is pre-created if _, err := mkdir(s.privDir); err != nil { return status.Errorf(codes.Internal, @@ -182,6 +267,22 @@ func (s *service) nodeProbe(ctx context.Context) error { return nil } +// getStringInBetween returns empty string if no start or end string found +func getStringInBetween(str string, start string, end string) (result string) { + s := strings.Index(str, start) + if s == -1 { + return + } + s += len(start) + e := strings.Index(str[s:], end) + if e == -1 { + return + } + + contents := str[s : s+e] + return strings.TrimSpace(contents) +} + func kmodLoaded(opts Opts) bool { // opts.Lsmod is introduced solely for unit testing. var out []byte @@ -210,16 +311,66 @@ func kmodLoaded(opts Opts) bool { return false } +func getSystemsKnownToSDC(opts Opts) ([]string, error) { + var out []byte + var err error + systems := make([]string, 0) + + // fetch the systemIDs + if opts.drvCfgQueryMDM == "" { + // try to get system name using `drv_cfg` binary + if _, err := os.Stat(drvCfg); os.IsNotExist(err) { + return systems, status.Error(codes.FailedPrecondition, + "unable to get System Name via config or drv_cfg binary") + } + + out, err = exec.Command(drvCfg, "--query_mdms").CombinedOutput() + if err != nil { + return systems, status.Errorf(codes.FailedPrecondition, + "error getting System ID: %s", err.Error()) + } + } else { + out = []byte(opts.drvCfgQueryMDM) + } + + r := bytes.NewReader(out) + s := bufio.NewScanner(r) + + for s.Scan() { + // the System ID is the field titled "Installation ID" + sysID := getStringInBetween(s.Text(), "MDM-ID", "SDC") + if sysID != "" { + systems = append(systems, sysID) + log.WithField("ID", sysID).Info("Found connected system") + } + } + + return systems, nil +} + func (s *service) NodeGetCapabilities( ctx context.Context, req *csi.NodeGetCapabilitiesRequest) ( *csi.NodeGetCapabilitiesResponse, error) { - return &csi.NodeGetCapabilitiesResponse{}, nil + return &csi.NodeGetCapabilitiesResponse{ + Capabilities: []*csi.NodeServiceCapability{ + { + Type: &csi.NodeServiceCapability_Rpc{ + Rpc: &csi.NodeServiceCapability_RPC{ + Type: csi.NodeServiceCapability_RPC_EXPAND_VOLUME, + }, + }, + }, + }, + }, nil + } -// Minimal version of NodeGetInfo. Returns NodeId -// MaxVolumesPerNode (optional) is left as 0 which means unlimited, and AccessibleTopology is left nil. +// NodeGetInfo returns Node information +// NodeId is the identifier of the node and will match the SDC GUID +// MaxVolumesPerNode (optional) is left as 0 which means unlimited +// AccessibleTopology will be set with the VxFlex OS SystemID func (s *service) NodeGetInfo( ctx context.Context, req *csi.NodeGetInfoRequest) ( @@ -236,7 +387,32 @@ func (s *service) NodeGetInfo( return nil, err } } - return &csi.NodeGetInfoResponse{NodeId: s.opts.SdcGUID}, nil + + // Get the Node ID + if len(connectedSystemID) == 0 { + if !s.opts.AutoProbe { + return nil, status.Error(codes.FailedPrecondition, + "Unable to get Node ID. Either it is not configured, "+ + "or Node Service has not been probed") + } + if err := s.nodeProbe(ctx); err != nil { + return nil, err + } + } + + // Create the topology keys + // csi-vxflexos.dellemc.com/: + topology := map[string]string{} + for _, sysID := range connectedSystemID { + topology[Name+"/"+sysID] = SystemTopologySystemValue + } + + return &csi.NodeGetInfoResponse{ + NodeId: s.opts.SdcGUID, + AccessibleTopology: &csi.Topology{ + Segments: topology, + }, + }, nil } func (s *service) NodeGetVolumeStats( @@ -246,5 +422,80 @@ func (s *service) NodeGetVolumeStats( } func (s *service) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { - return nil, status.Error(codes.Unimplemented, "") + + var reqID string + var err error + headers, ok := metadata.FromIncomingContext(ctx) + if ok { + if req, ok := headers["csi.requestid"]; ok && len(req) > 0 { + reqID = req[0] + } + } + + err = s.nodeProbe(ctx) + if err != nil { + log.Error("nodeProbe failed with error :" + err.Error()) + return nil, err + } + + volumePath := req.GetVolumePath() + if volumePath == "" { + log.Error("Volume path required") + return nil, status.Error(codes.InvalidArgument, + "Volume path required") + } + + // Check if volume path is a directory. + // Mount type volumes are always mounted on a directory. + // If not a directory, assume it's a raw block device mount and return ok. + volumePathInfo, err := os.Lstat(volumePath) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "Could not stat volume path: "+volumePath) + } + if !volumePathInfo.Mode().IsDir() { + log.Infof("Volume path %s is not a directory- assuming a raw block device mount", volumePath) + return &csi.NodeExpandVolumeResponse{}, nil + } + + volID := req.GetVolumeId() + if volID == "" { + return nil, status.Error(codes.InvalidArgument, + "Volume ID is required") + } + + sdcMappedVolume, err := s.getSDCMappedVol(volID) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + log.Infof("sdcMappedVolume %+v", sdcMappedVolume) + sdcDevice := strings.Replace(sdcMappedVolume.SdcDevice, "/dev/", "", 1) + log.Infof("sdcDevice %s", sdcDevice) + devicePath := sdcMappedVolume.SdcDevice + + size := req.GetCapacityRange().GetRequiredBytes() + + f := log.Fields{ + "CSIRequestID": reqID, + "DevicePath": devicePath, + "VolumeID": volID, + "VolumePath": volumePath, + "Size": size, + } + log.WithFields(f).Info("resizing volume") + fsType, err := gofsutil.FindFSType(context.Background(), volumePath) + if err != nil { + log.Errorf("Failed to fetch filesystem type for mount (%s) with error (%s)", volumePath, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) + } + log.Infof("Found %s filesystem mounted on volume %s", fsType, volumePath) + + // Resize the filesystem + err = gofsutil.ResizeFS(context.Background(), volumePath, devicePath, "", fsType) + if err != nil { + log.Errorf("Failed to resize filesystem: mountpoint (%s) device (%s) with error (%s)", + volumePath, devicePath, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) + } + + return &csi.NodeExpandVolumeResponse{}, nil } diff --git a/service/service.go b/service/service.go index c7eb6961..9960cbf4 100644 --- a/service/service.go +++ b/service/service.go @@ -32,6 +32,9 @@ const ( thinProvisioned = "ThinProvisioned" thickProvisioned = "ThickProvisioned" defaultPrivDir = "/dev/disk/csi-vxflexos" + + // SystemTopologySystemValue is the supported topology key + SystemTopologySystemValue string = "csi-vxflexos.dellemc.com" ) // Manifest is the SP's manifest. @@ -62,6 +65,7 @@ type Opts struct { AutoProbe bool DisableCerts bool // used for unit testing only Lsmod string // used for unit testing only + drvCfgQueryMDM string // used for testing only EnableSnapshotCGDelete bool // when snapshot deleted, enable deleting of all snaps in the CG of the snapshot EnableListVolumesSnapshots bool // when listing volumes, include snapshots and volumes } @@ -113,11 +117,8 @@ func (s *service) BeforeServe( if s.opts.Password != "" { fields["password"] = "******" } - - //censor user for logging purposes - fields["user"] = "******" + log.WithFields(fields).Infof("configured %s", Name) - fields["user"] = s.opts.User }() // Get the SP's operating mode. diff --git a/service/service_test.go b/service/service_test.go index a395169d..b020a961 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -21,7 +21,7 @@ func TestMain(m *testing.M) { }, godog.Options{ Format: "pretty", Paths: []string{"features"}, - //Tags: "wip", + //Tags: "wip", }) fmt.Printf("godog finished\n") diff --git a/service/step_defs_test.go b/service/step_defs_test.go index c7cbfef3..d14faf80 100644 --- a/service/step_defs_test.go +++ b/service/step_defs_test.go @@ -32,11 +32,15 @@ const ( altNodeID = "7E012974-3651-4DCB-9954-25975A3C3CDF" datafile = "test/tmp/datafile" datadir = "test/tmp/datadir" + badtarget = "/nonexist/target" + altdatadir = "test/tmp/altdatadir" + altdatafile = "test/tmp/altdatafile" sdcVolume1 = "d0f055a700000000" sdcVolume2 = "d0f055aa00000001" sdcVolume0 = "0000000000000000" mdmID = "0000" nodePublishBlockDevicePath = "test/dev/scinia" + nodePublishAltBlockDevPath = "test/dev/scinib" nodePublishSymlinkDir = "test/dev/disk/by-id" goodSnapID = "444-444" altSnapID = "555-555" @@ -48,7 +52,7 @@ type feature struct { service *service adminClient *goscaleio.Client system *goscaleio.System - err error // return from the preceeding call + err error // return from the preceding call getPluginInfoResponse *csi.GetPluginInfoResponse getPluginCapabilitiesResponse *csi.GetPluginCapabilitiesResponse probeResponse *csi.ProbeResponse @@ -82,6 +86,7 @@ type feature struct { createSnapshotRequest *csi.CreateSnapshotRequest volumeIDList []string snapshotIndex int + volumeID string } func (f *feature) checkGoRoutines(tag string) { @@ -145,6 +150,8 @@ func (f *feature) aVxFlexOSService() error { gofsutil.GOFSMock.InduceFormatError = false gofsutil.GOFSMock.InduceGetDiskFormatError = false gofsutil.GOFSMock.InduceGetDiskFormatType = "" + gofsutil.GOFSMock.InduceFSTypeError = false + gofsutil.GOFSMock.InduceResizeFSError = false gofsutil.GOFSMockMounts = gofsutil.GOFSMockMounts[:0] // configure variables in the driver @@ -196,6 +203,9 @@ Module Size Used by vsock_diag 12610 0 scini 799210 0 ip6t_rpfilter 12595 1 +` + opts.drvCfgQueryMDM = ` +MDM-ID 14dbbf5617523654 SDC ID d0f33bd700000004 INSTALLATION ID 1c078b073d75512c IPs [0]-1.2.3.4 [1]-1.2.3.5 ` svc.opts = opts f.service = svc @@ -277,6 +287,12 @@ func (f *feature) theErrorContains(arg1 string) error { } // We expected an error... if f.err == nil { + possibleMatches := strings.Split(arg1, "@@") + for _, possibleMatch := range possibleMatches { + if possibleMatch == "none" { + return nil + } + } return fmt.Errorf("Expected error to contain %s but no error", arg1) } // Allow for multiple possible matches, separated by @@. This was necessary @@ -315,6 +331,11 @@ func (f *feature) thereIsANodeProbeSdcGUIDError() error { return nil } +func (f *feature) thereIsANodeProbeDrvCfgError() error { + f.service.opts.drvCfgQueryMDM = "" + return nil +} + func getTypicalCreateVolumeRequest() *csi.CreateVolumeRequest { req := new(csi.CreateVolumeRequest) params := make(map[string]string) @@ -322,7 +343,7 @@ func getTypicalCreateVolumeRequest() *csi.CreateVolumeRequest { req.Parameters = params req.Name = "volume1" capacityRange := new(csi.CapacityRange) - capacityRange.RequiredBytes = 8 * 1024 * 1024 * 1024 + capacityRange.RequiredBytes = 32 * 1024 * 1024 * 1024 req.CapacityRange = capacityRange block := new(csi.VolumeCapability_BlockVolume) capability := new(csi.VolumeCapability) @@ -345,7 +366,7 @@ func (f *feature) iSpecifyCreateVolumeMountRequest(fstype string) error { req.Parameters = params req.Name = "mount1" capacityRange := new(csi.CapacityRange) - capacityRange.RequiredBytes = 8 * 1024 * 1024 * 1024 + capacityRange.RequiredBytes = 32 * 1024 * 1024 * 1024 req.CapacityRange = capacityRange capability := new(csi.VolumeCapability) mountVolume := new(csi.VolumeCapability_MountVolume) @@ -400,16 +421,24 @@ func (f *feature) aValidCreateVolumeResponseIsReturned() error { return nil } -func (f *feature) iSpecifyAccessibilityRequirements() error { +func (f *feature) iSpecifyAccessibilityRequirementsWithASystemIDOf(requestedSystem string) error { + if requestedSystem == "f.service.opt.SystemName" { + requestedSystem = f.service.opts.SystemName + } req := new(csi.CreateVolumeRequest) params := make(map[string]string) params["storagepool"] = "viki_pool_HDD_20181031" req.Parameters = params req.Name = "accessability" capacityRange := new(csi.CapacityRange) - capacityRange.RequiredBytes = 8 * 1024 * 1024 * 1024 + capacityRange.RequiredBytes = 32 * 1024 * 1024 * 1024 req.CapacityRange = capacityRange req.AccessibilityRequirements = new(csi.TopologyRequirement) + top := new(csi.Topology) + top.Segments = map[string]string{ + "csi-vxflexos.dellemc.com/" + requestedSystem: "powerflex.dellemc.com", + } + req.AccessibilityRequirements.Preferred = append(req.AccessibilityRequirements.Preferred, top) f.createVolumeRequest = req return nil } @@ -430,7 +459,7 @@ func (f *feature) iSpecifyMULTINODEWRITER() error { req.Parameters = params req.Name = "multinode_writer" capacityRange := new(csi.CapacityRange) - capacityRange.RequiredBytes = 8 * 1024 * 1024 * 1024 + capacityRange.RequiredBytes = 32 * 1024 * 1024 * 1024 req.CapacityRange = capacityRange block := new(csi.VolumeCapability_BlockVolume) capability := new(csi.VolumeCapability) @@ -450,7 +479,7 @@ func (f *feature) iSpecifyMULTINODEWRITER() error { func (f *feature) iSpecifyABadCapacity() error { req := getTypicalCreateVolumeRequest() capacityRange := new(csi.CapacityRange) - capacityRange.RequiredBytes = -8 * 1024 * 1024 * 1024 + capacityRange.RequiredBytes = -32 * 1024 * 1024 * 1024 req.CapacityRange = capacityRange req.Name = "bad capacity" f.createVolumeRequest = req @@ -481,6 +510,7 @@ func (f *feature) iCallCreateVolumeSize(name string, size int64) error { if f.createVolumeResponse != nil { log.Printf("vol id %s\n", f.createVolumeResponse.GetVolume().VolumeId) } + return nil } @@ -534,6 +564,10 @@ func (f *feature) iInduceError(errtype string) error { stepHandlersErrors.RemoveVolumeError = true case "VolumeInstancesError": stepHandlersErrors.VolumeInstancesError = true + case "NoVolumeIDError": + stepHandlersErrors.NoVolumeIDError = true + case "SetVolumeSizeError": + stepHandlersErrors.SetVolumeSizeError = true case "NoSymlinkForNodePublish": cmd := exec.Command("rm", "-rf", nodePublishSymlinkDir) _, err := cmd.CombinedOutput() @@ -567,12 +601,47 @@ func (f *feature) iInduceError(errtype string) error { f.nodePublishVolumeRequest.VolumeCapability.AccessMode = nil case "NodePublishNoAccessType": f.nodePublishVolumeRequest.VolumeCapability.AccessType = nil + case "NodePublishPrivateTargetAlreadyCreated": + err := os.MkdirAll("features/"+sdcVolume1, 0777) + if err != nil { + fmt.Printf("Couldn't make: %s\n", datadir+"/"+sdcVolume1) + } + case "NodePublishPrivateTargetAlreadyMounted": + cmd := exec.Command("mknod", nodePublishAltBlockDevPath, "b", "0", "0") + _, err := cmd.CombinedOutput() + if err != nil { + fmt.Printf("Couldn't create block dev: %s\n", nodePublishAltBlockDevPath) + } + err = os.MkdirAll("features/"+sdcVolume1, 0777) + if err != nil { + fmt.Printf("Couldn't make: %s\n", datadir+"/"+sdcVolume1) + } + err = gofsutil.Mount(context.Background(), nodePublishAltBlockDevPath, "features\\"+sdcVolume1, "none") + if err != nil { + fmt.Printf("Couldn't mount: %s\n", "features\\"+sdcVolume1) + } case "NodePublishNoTargetPath": f.nodePublishVolumeRequest.TargetPath = "" + case "NodePublishBadTargetPath": + f.nodePublishVolumeRequest.TargetPath = badtarget case "NodePublishBlockTargetNotFile": f.nodePublishVolumeRequest.TargetPath = datadir case "NodePublishFileTargetNotDir": f.nodePublishVolumeRequest.TargetPath = datafile + case "NodePublishPathAltDataDir": + if f.nodePublishVolumeRequest.TargetPath == datadir { + err := os.MkdirAll(altdatadir, 0777) + if err != nil { + fmt.Printf("Couldn't make altdatadir: %s\n", altdatadir) + } + f.nodePublishVolumeRequest.TargetPath = altdatadir + } else { + _, err := os.Create(altdatafile) + if err != nil { + fmt.Printf("Couldn't make datafile: %s\n", altdatafile) + } + f.nodePublishVolumeRequest.TargetPath = altdatafile + } case "GOFSMockBindMountError": gofsutil.GOFSMock.InduceBindMountError = true case "GOFSMockDevMountsError": @@ -589,10 +658,16 @@ func (f *feature) iInduceError(errtype string) error { gofsutil.GOFSMock.InduceGetDiskFormatType = "unknown-fs" case "GOFSMockFormatError": gofsutil.GOFSMock.InduceFormatError = true + case "GOFSInduceFSTypeError": + gofsutil.GOFSMock.InduceFSTypeError = true + case "GOFSInduceResizeFSError": + gofsutil.GOFSMock.InduceResizeFSError = true case "NodeUnpublishNoTargetPath": f.nodePublishVolumeRequest.TargetPath = "" case "NodeUnpublishBadVolume": f.nodePublishVolumeRequest.VolumeId = sdcVolume0 + case "none": + return nil default: return fmt.Errorf("Don't know how to induce error %q", errtype) } @@ -840,6 +915,7 @@ func (f *feature) aValidNodeGetInfoResponseIsReturned() error { if f.err != nil { return f.err } + fmt.Printf("node: %s", f.nodeGetInfoResponse) if f.nodeGetInfoResponse.NodeId == "" { return errors.New("expected NodeGetInfoResponse to contain NodeID but it was null") } @@ -1022,11 +1098,13 @@ func (f *feature) aValidControllerGetCapabilitiesResponseIsReturned() error { count = count + 1 case csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS: count = count + 1 + case csi.ControllerServiceCapability_RPC_EXPAND_VOLUME: + count = count + 1 default: return fmt.Errorf("received unexpected capability: %v", typex) } } - if count != 6 { + if count != 7 { return errors.New("Did not retrieve all the expected capabilities") } return nil @@ -1192,9 +1270,9 @@ func (f *feature) aControllerPublishedVolume() error { cmd := exec.Command("rm", "-rf", "features/"+sdcVolume1) _, err = cmd.CombinedOutput() if err != nil { - fmt.Printf("error removing private staging directory") + fmt.Printf("error removing private staging directory\n") } else { - fmt.Printf("removed private staging directory") + fmt.Printf("removed private staging directory\n") } // Make the block device @@ -1203,7 +1281,7 @@ func (f *feature) aControllerPublishedVolume() error { cmd := exec.Command("mknod", nodePublishBlockDevicePath, "b", "0", "0") output, err := cmd.CombinedOutput() if err != nil { - fmt.Printf("scinia: " + err.Error()) + fmt.Printf("scinia: %s\n", err.Error()) } fmt.Printf("mknod output: %s\n", output) @@ -1213,7 +1291,8 @@ func (f *feature) aControllerPublishedVolume() error { output, err = cmd.CombinedOutput() fmt.Printf("symlink output: %s\n", output) if err != nil { - fmt.Printf("link: " + err.Error()) + fmt.Printf("link: %s\n", err.Error()) + err = nil } } @@ -1333,6 +1412,8 @@ func (f *feature) iCallBeforeServe() error { stringSlice = append(stringSlice, EnvPassword+"=password") stringSlice = append(stringSlice, EnvSystemName+"=unknown") stringSlice = append(stringSlice, "X_CSI_PRIVATE_MOUNT_DIR=/csi") + stringSlice = append(stringSlice, "X_CSI_VXFLEXOS_ENABLESNAPSHOTCGDELETE=true") + stringSlice = append(stringSlice, "X_CSI_VXFLEXOS_ENABLELISTVOLUMESNAPSHOTS=true") ctx := context.WithValue(context.Background(), ctxOSEnviron, stringSlice) listener, err := net.Listen("tcp", "127.0.0.1:65000") if err != nil { @@ -1350,17 +1431,33 @@ func (f *feature) iCallNodeStageVolume() error { return nil } -func (f *feature) iCallControllerExpandVolume() error { - ctx := new(context.Context) - req := new(csi.ControllerExpandVolumeRequest) - _, f.err = f.service.ControllerExpandVolume(*ctx, req) +func (f *feature) iCallControllerExpandVolume(size int64) error { + header := metadata.New(map[string]string{"csi.requestid": "1"}) + ctx := metadata.NewIncomingContext(context.Background(), header) + f.volumeID = f.createVolumeResponse.GetVolume().VolumeId + req := &csi.ControllerExpandVolumeRequest{ + VolumeId: f.volumeID, + CapacityRange: &csi.CapacityRange{RequiredBytes: size * bytesInKiB * bytesInKiB * bytesInKiB}, + } + if stepHandlersErrors.NoVolumeIDError { + req.VolumeId = "" + } + _, f.err = f.service.ControllerExpandVolume(ctx, req) return nil } -func (f *feature) iCallNodeExpandVolume() error { - ctx := new(context.Context) - req := new(csi.NodeExpandVolumeRequest) - _, f.err = f.service.NodeExpandVolume(*ctx, req) +func (f *feature) iCallNodeExpandVolume(volPath string) error { + header := metadata.New(map[string]string{"csi.requestid": "1"}) + ctx := metadata.NewIncomingContext(context.Background(), header) + f.volumeID = f.createVolumeResponse.Volume.VolumeId + req := &csi.NodeExpandVolumeRequest{ + VolumeId: sdcVolume1, + VolumePath: volPath, + } + if stepHandlersErrors.NoVolumeIDError { + req.VolumeId = "" + } + _, f.err = f.service.NodeExpandVolume(ctx, req) return nil } @@ -1389,10 +1486,27 @@ func (f *feature) aValidNodeGetCapabilitiesResponseIsReturned() error { if f.err != nil { return f.err } - if len(f.nodeGetCapabilitiesResponse.Capabilities) > 0 { - return errors.New("expected NodeGetCapabilities to return no capabilities") + rep := f.nodeGetCapabilitiesResponse + if rep != nil { + if rep.Capabilities == nil { + return errors.New("no capabilities returned in NodeGetCapabilitiesResponse") + } + count := 0 + for _, cap := range rep.Capabilities { + typex := cap.GetRpc().Type + switch typex { + case csi.NodeServiceCapability_RPC_EXPAND_VOLUME: + count = count + 1 + default: + return fmt.Errorf("received unxexpcted capability: %v", typex) + } + } + if count != 1 { + return errors.New("Did not retrieve all the expected capabilities") + } + return nil } - return nil + return errors.New("expected NodeGetCapabilitiesResponse but didn't get one") } func (f *feature) iCallCreateSnapshot(snapName string) error { @@ -1472,7 +1586,7 @@ func (f *feature) aValidSnapshotConsistencyGroup() error { volumeIDToAncestorID[goodSnapID] = goodVolumeID volumeIDToConsistencyGroupID[goodSnapID] = goodVolumeID - // second snapshot in CG; this looks wierd, but we give same ID to snap + // second snapshot in CG; this looks weird, but we give same ID to snap // as it's ancestor so that we can publish the volume volumeIDToName[altSnapID] = "snap5" volumeNameToID["snap5"] = altSnapID @@ -1661,8 +1775,17 @@ func (f *feature) iInvalidateTheProbeCache() error { return nil } -func (f *feature) iCallGetDevice(invalidPath string) error { - device, err := GetDevice(invalidPath) +func (f *feature) iCallEvalsymlink(path string) error { + + d := evalSymlinks(path) + if d == path { + f.err = errors.New("Could not evaluate symlinks for path") + } + return nil +} + +func (f *feature) iCallGetDevice(Path string) error { + device, err := GetDevice(Path) if device == nil && err != nil { f.err = errors.New("invalid path error") } @@ -1706,6 +1829,31 @@ func (f *feature) iCallGetStoragePoolnameByID(id string) error { return nil } +func (f *feature) iCallNodeGetAllSystems() error { + // lookup the system names for a couple of systems + // This should not generate an error as systems without names are supported + systems := make([]string, 0) + systems = append(systems, "14dbbf5617523654") + systems = append(systems, "9999999999999999") + f.err = f.service.getAllSystems(context.TODO(), systems) + return nil +} + +func (f *feature) iDoNotHaveAGatewayConnection() error { + f.service.adminClient = nil + return nil +} + +func (f *feature) iDoNotHaveAValidGatewayEndpoint() error { + f.service.opts.Endpoint = "" + return nil +} + +func (f *feature) iDoNotHaveAValidGatewayPassword() error { + f.service.opts.Password = "" + return nil +} + func FeatureContext(s *godog.Suite) { f := &feature{} s.Step(`^a VxFlexOS service$`, f.aVxFlexOSService) @@ -1725,9 +1873,10 @@ func FeatureContext(s *godog.Suite) { s.Step(`^the Controller has no connection$`, f.theControllerHasNoConnection) s.Step(`^there is a Node Probe Lsmod error$`, f.thereIsANodeProbeLsmodError) s.Step(`^there is a Node Probe SdcGUID error$`, f.thereIsANodeProbeSdcGUIDError) + s.Step(`^there is a Node Probe drvCfg error$`, f.thereIsANodeProbeDrvCfgError) s.Step(`^I call CreateVolume "([^"]*)"$`, f.iCallCreateVolume) s.Step(`^a valid CreateVolumeResponse is returned$`, f.aValidCreateVolumeResponseIsReturned) - s.Step(`^I specify AccessibilityRequirements$`, f.iSpecifyAccessibilityRequirements) + s.Step(`^I specify AccessibilityRequirements with a SystemID of "([^"]*)"$`, f.iSpecifyAccessibilityRequirementsWithASystemIDOf) s.Step(`^I specify MULTINODE_WRITER$`, f.iSpecifyMULTINODEWRITER) s.Step(`^I specify a BadCapacity$`, f.iSpecifyABadCapacity) s.Step(`^I specify NoStoragePool$`, f.iSpecifyNoStoragePool) @@ -1794,8 +1943,8 @@ func FeatureContext(s *godog.Suite) { s.Step(`^I call ListSnapshots for snapshot "([^"]*)"$`, f.iCallListSnapshotsForSnapshot) s.Step(`^the snapshot ID is "([^"]*)"$`, f.theSnapshotIDIs) s.Step(`^I invalidate the Probe cache$`, f.iInvalidateTheProbeCache) - s.Step(`^I call ControllerExpandVolume$`, f.iCallControllerExpandVolume) - s.Step(`^I call NodeExpandVolume$`, f.iCallNodeExpandVolume) + s.Step(`^I call ControllerExpandVolume set to (\d+)$`, f.iCallControllerExpandVolume) + s.Step(`^I call NodeExpandVolume with volumePath as "([^"]*)"$`, f.iCallNodeExpandVolume) s.Step(`^I call NodeGetVolumeStats$`, f.iCallNodeGetVolumeStats) s.Step(`^I give request volume context$`, f.iGiveRequestVolumeContext) s.Step(`^I call GetDevice "([^"]*)"$`, f.iCallGetDevice) @@ -1803,4 +1952,9 @@ func FeatureContext(s *godog.Suite) { s.Step(`^a new service is returned$`, f.aNewServiceIsReturned) s.Step(`^I call getVolProvisionType with bad params$`, f.iCallGetVolProvisionTypeWithBadParams) s.Step(`^i Call getStoragePoolnameByID "([^"]*)"$`, f.iCallGetStoragePoolnameByID) + s.Step(`^I call evalsymlink "([^"]*)"$`, f.iCallEvalsymlink) + s.Step(`^I Call nodeGetAllSystems$`, f.iCallNodeGetAllSystems) + s.Step(`^I do not have a gateway connection$`, f.iDoNotHaveAGatewayConnection) + s.Step(`^I do not have a valid gateway endpoint$`, f.iDoNotHaveAValidGatewayEndpoint) + s.Step(`^I do not have a valid gateway password$`, f.iDoNotHaveAValidGatewayPassword) } diff --git a/service/step_handlers_test.go b/service/step_handlers_test.go index c12eddbc..2b126cd1 100644 --- a/service/step_handlers_test.go +++ b/service/step_handlers_test.go @@ -40,6 +40,8 @@ var ( NoSysNameError bool NoAdminError bool WrongSysNameError bool + NoVolumeIDError bool + SetVolumeSizeError bool } ) @@ -82,6 +84,8 @@ func getHandler() http.Handler { stepHandlersErrors.NoSysNameError = false stepHandlersErrors.NoAdminError = false stepHandlersErrors.WrongSysNameError = false + stepHandlersErrors.NoVolumeIDError = false + stepHandlersErrors.SetVolumeSizeError = false sdcMappings = sdcMappings[:0] sdcMappingsID = "" @@ -104,6 +108,13 @@ func getRouter() http.Handler { // handleLogin implements GET /api/login func handleLogin(w http.ResponseWriter, r *http.Request) { + u, p, ok := r.BasicAuth() + if !ok || len(strings.TrimSpace(u)) < 1 || len(strings.TrimSpace(p)) < 1 { + w.Header().Set("WWW-Authenticate", "Basic realm=Restricted") + w.WriteHeader(http.StatusUnauthorized) + returnJSONFile("features", "authorization_failure.json", w, nil) + return + } if testControllerHasNoConnection { w.WriteHeader(http.StatusRequestTimeout) return @@ -345,6 +356,11 @@ func handleAction(w http.ResponseWriter, r *http.Request) { if name != "" { volumeNameToID[name] = "" } + case "setVolumeSize": + if stepHandlersErrors.SetVolumeSizeError { + writeError(w, "induced error", http.StatusRequestTimeout, codes.Internal) + return + } } } @@ -408,6 +424,10 @@ func handleInstances(w http.ResponseWriter, r *http.Request) { writeError(w, "induced error", http.StatusRequestTimeout, codes.Internal) return } + if stepHandlersErrors.NoVolumeIDError { + writeError(w, "Volume ID is required", http.StatusRequestTimeout, codes.InvalidArgument) + return + } if stepHandlersErrors.SIOGatewayVolumeNotFoundError { writeError(w, "Could not find the volume", http.StatusRequestTimeout, codes.Internal) diff --git a/test/helm/betasnap1.yaml b/test/helm/betasnap1.yaml new file mode 100644 index 00000000..55078042 --- /dev/null +++ b/test/helm/betasnap1.yaml @@ -0,0 +1,9 @@ +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshot +metadata: + name: pvol0-snap1 + namespace: helmtest-vxflexos +spec: + volumeSnapshotClassName: vxflexos-snapclass + source: + persistentVolumeClaimName: pvol0 diff --git a/test/helm/betasnap2.yaml b/test/helm/betasnap2.yaml new file mode 100644 index 00000000..31484e11 --- /dev/null +++ b/test/helm/betasnap2.yaml @@ -0,0 +1,9 @@ +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshot +metadata: + name: pvol0-snap2 + namespace: helmtest-vxflexos +spec: + volumeSnapshotClassName: vxflexos-snapclass + source: + persistentVolumeClaimName: pvol0 diff --git a/test/helm/unsupported/block1/Chart.yaml b/test/helm/block/block-rwx/Chart.yaml similarity index 88% rename from test/helm/unsupported/block1/Chart.yaml rename to test/helm/block/block-rwx/Chart.yaml index 19136b54..1daee12d 100644 --- a/test/helm/unsupported/block1/Chart.yaml +++ b/test/helm/block/block-rwx/Chart.yaml @@ -1,4 +1,4 @@ -name: vxflex-csi +name: block-rwx version: 0.0.1 appVersion: 2.6.0 description: | diff --git a/test/helm/block/block-rwx/templates/test.yaml b/test/helm/block/block-rwx/templates/test.yaml new file mode 100644 index 00000000..26f36a40 --- /dev/null +++ b/test/helm/block/block-rwx/templates/test.yaml @@ -0,0 +1,47 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vxflextest + namespace: {{ .Values.namespace }} +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvol0 + namespace: {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteMany + volumeMode: Block + resources: + requests: + storage: 8Gi + storageClassName: {{ .Values.storageclass }} +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: vxflextest + namespace: {{ .Values.namespace }} +spec: + replicas: 2 + selector: + matchLabels: + app: vxflextest + template: + metadata: + labels: + app: vxflextest + spec: + serviceAccount: vxflextest + containers: + - name: test + image: docker.io/centos:latest + command: [ "/bin/sleep", "3600" ] + volumeDevices: + - devicePath: "/dev/data0" + name: pvol0 + volumes: + - name: pvol0 + persistentVolumeClaim: + claimName: pvol0 diff --git a/test/helm/block/block-rwx/values.yaml b/test/helm/block/block-rwx/values.yaml new file mode 100644 index 00000000..8b77916c --- /dev/null +++ b/test/helm/block/block-rwx/values.yaml @@ -0,0 +1 @@ +storageclass: vxflexos diff --git a/test/helm/block/block1/Chart.yaml b/test/helm/block/block1/Chart.yaml new file mode 100644 index 00000000..a262edfb --- /dev/null +++ b/test/helm/block/block1/Chart.yaml @@ -0,0 +1,10 @@ +name: block1 +version: 0.0.1 +appVersion: 2.6.0 +description: | + Tests VxFlexOS CSI deployments. +keywords: +- vxflexos-csi +- storage +- block +engine: gotpl diff --git a/test/helm/block/block1/templates/test.yaml b/test/helm/block/block1/templates/test.yaml new file mode 100644 index 00000000..ae766cfc --- /dev/null +++ b/test/helm/block/block1/templates/test.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.name }} + namespace: {{ .Values.namespace }} +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: {{ .Values.name }} + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: {{ .Values.name }} + serviceName: test2vols + template: + metadata: + labels: + app: {{ .Values.name }} + spec: + serviceAccount: {{ .Values.name }} + containers: + - name: test + image: docker.io/centos:latest + command: [ "/bin/sleep", "3600" ] + volumeDevices: + - devicePath: "/dev/data0" + name: pvol0 + volumeClaimTemplates: + - metadata: + name: pvol0 + spec: + accessModes: + - ReadWriteOnce + volumeMode: Block + storageClassName: vxflexos + resources: + requests: + storage: 8Gi + diff --git a/test/helm/block/block1/values.yaml b/test/helm/block/block1/values.yaml new file mode 100644 index 00000000..ae65d217 --- /dev/null +++ b/test/helm/block/block1/values.yaml @@ -0,0 +1,2 @@ +storageclass: vxflexos +name: vxflextest diff --git a/test/helm/unsupported/block2/Chart.yaml b/test/helm/block/block2/Chart.yaml similarity index 88% rename from test/helm/unsupported/block2/Chart.yaml rename to test/helm/block/block2/Chart.yaml index 19136b54..037af4dd 100644 --- a/test/helm/unsupported/block2/Chart.yaml +++ b/test/helm/block/block2/Chart.yaml @@ -1,4 +1,4 @@ -name: vxflex-csi +name: block2 version: 0.0.1 appVersion: 2.6.0 description: | diff --git a/test/helm/block/block2/templates/test.yaml b/test/helm/block/block2/templates/test.yaml new file mode 100644 index 00000000..64386df2 --- /dev/null +++ b/test/helm/block/block2/templates/test.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.name }} + namespace: {{ .Values.namespace }} +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: {{ .Values.name }} + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: {{ .Values.name }} + serviceName: test2vols + template: + metadata: + labels: + app: {{ .Values.name }} + spec: + serviceAccount: {{ .Values.name }} + containers: + - name: test + image: docker.io/centos:latest + command: [ "/bin/sleep", "3600" ] + volumeDevices: + - devicePath: "/dev/data0" + name: pvol0 + - devicePath: "/dev/data1" + name: pvol1 + volumeClaimTemplates: + - metadata: + name: pvol0 + spec: + accessModes: + - ReadWriteOnce + volumeMode: Block + storageClassName: {{ .Values.storageclass }} + resources: + requests: + storage: 8Gi + - metadata: + name: pvol1 + spec: + accessModes: + - ReadWriteOnce + volumeMode: Block + storageClassName: {{ .Values.storageclass }} + resources: + requests: + storage: 12Gi + diff --git a/test/helm/block/block2/values.yaml b/test/helm/block/block2/values.yaml new file mode 100644 index 00000000..38dc52c9 --- /dev/null +++ b/test/helm/block/block2/values.yaml @@ -0,0 +1,2 @@ +name: vxflextest +storageclass: vxflexos diff --git a/test/helm/blocksnap/1snap/Chart.yaml b/test/helm/blocksnap/1snap/Chart.yaml new file mode 100644 index 00000000..20fcf7f7 --- /dev/null +++ b/test/helm/blocksnap/1snap/Chart.yaml @@ -0,0 +1,11 @@ +name: 1snap +version: 1.0.0 +apiVersion: v1 +appVersion: 1.0.0 +description: | + Tests VxFlexOS CSI deployments. +icon: https://avatars1.githubusercontent.com/u/20958494?s=200&v=4 +keywords: +- vxflexos-csi +- storage +engine: gotpl diff --git a/test/helm/blocksnap/1snap/templates/snap1.yaml b/test/helm/blocksnap/1snap/templates/snap1.yaml new file mode 100644 index 00000000..f2c03f28 --- /dev/null +++ b/test/helm/blocksnap/1snap/templates/snap1.yaml @@ -0,0 +1,9 @@ +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshot +metadata: + name: pvol0-snap1 + namespace: {{ .Values.namespace }} +spec: + source: + persistentVolumeClaimName: pvol0 + volumeSnapshotClassName: {{ .Values.snapclass }} diff --git a/test/helm/blocksnap/1vol/Chart.yaml b/test/helm/blocksnap/1vol/Chart.yaml new file mode 100644 index 00000000..6b2bdd51 --- /dev/null +++ b/test/helm/blocksnap/1vol/Chart.yaml @@ -0,0 +1,11 @@ +name: 1vol +version: 1.0.0 +apiVersion: v1 +appVersion: 1.0.0 +description: | + Tests VxFlexOS CSI deployments. +icon: https://avatars1.githubusercontent.com/u/20958494?s=200&v=4 +keywords: +- vxflexos-csi +- storage +engine: gotpl diff --git a/test/helm/blocksnap/1vol/templates/test.yaml b/test/helm/blocksnap/1vol/templates/test.yaml new file mode 100644 index 00000000..fab8cc97 --- /dev/null +++ b/test/helm/blocksnap/1vol/templates/test.yaml @@ -0,0 +1,47 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvol0 + namespace: {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: {{ .Values.storageclass }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vol + namespace: {{ .Values.namespace }} +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: vol + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: vol + serviceName: 1vol + template: + metadata: + labels: + app: vol + spec: + serviceAccount: vol + containers: + - name: test + image: docker.io/centos:latest + command: [ "/bin/sleep", "3600" ] + volumeMounts: + - mountPath: "/data0" + name: pvol0 + volumes: + - name: pvol0 + persistentVolumeClaim: + claimName: pvol0 diff --git a/test/helm/blocksnap/1volfromsnap/Chart.yaml b/test/helm/blocksnap/1volfromsnap/Chart.yaml new file mode 100644 index 00000000..e8de7ccc --- /dev/null +++ b/test/helm/blocksnap/1volfromsnap/Chart.yaml @@ -0,0 +1,11 @@ +name: 1volfromsnap +version: 1.0.0 +apiVersion: v1 +appVersion: 1.0.0 +description: | + Tests VxFlexOS CSI deployments. +icon: https://avatars1.githubusercontent.com/u/20958494?s=200&v=4 +keywords: +- vxflexos-csi +- storage +engine: gotpl diff --git a/test/helm/blocksnap/1volfromsnap/templates/test.yaml b/test/helm/blocksnap/1volfromsnap/templates/test.yaml new file mode 100644 index 00000000..b63c78cc --- /dev/null +++ b/test/helm/blocksnap/1volfromsnap/templates/test.yaml @@ -0,0 +1,49 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvol0-copy1 + namespace: {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteOnce + dataSource: + apiGroup: snapshot.storage.k8s.io + kind: VolumeSnapshot + name: pvol0-snap1 + resources: + requests: + storage: 8Gi + storageClassName: {{ .Values.storageclass }} + volumeMode: Block +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: copy + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: copy + serviceName: copy + template: + metadata: + labels: + app: copy + spec: + serviceAccount: vol + containers: + - name: copy + image: docker.io/centos:latest + command: [ "/bin/sleep", "3600" ] + securityContext: + capabilities: + add: + - SYS_ADMIN + volumeDevices: + - devicePath: "/data0" + name: pvol0-copy1 + volumes: + - name: pvol0-copy1 + persistentVolumeClaim: + claimName: pvol0-copy1 diff --git a/test/helm/blocksnap/README.md b/test/helm/blocksnap/README.md new file mode 100644 index 00000000..12755da2 --- /dev/null +++ b/test/helm/blocksnap/README.md @@ -0,0 +1,26 @@ +Blocksnap Test +============== + +This is a real use case that arises in data protection. The idea is to make a mounted file system from a volume for a first pod, +have that pod write some data to the file system, and then take a snap of the volume, and then to make a second pod which +uses the snap as a volume source for a block mounted volume. + +The block volume created from the snapshot can then be used to transmit the volume efficiently by the 2nd pod to remote storage. + +The test mounts the block volume in the 2nd pod in a local directory, and compares the data written by the 1st pod (which is a tar .tgz file) +with the data from mounting the snap contents in the 2nd pod, which should always be identical. + +Running the Test +---------------- + +Execute "sh run.sh" to run the test in a kubernetes environment that supports beta block snapshots. The test is preconfigured to use +the vxflexos CSI torage system in run.sh. You can edit run.sh and change the storageclass, snapclass (the volumesnapshotclass name), +and namespace parameters to run the test for a different type of CSI storage. + +The test is constructed from three helm charts that are deployed in the following sequence: +1. 1vol creates one volume and deploys it in a pod +2. 1snap creates a snapshot from the volume in step 1. +3. 1volfromsnap creates a volume from the snapshot and deploys it in a second pod. + +If the test runs succssfully, it compares the data generated in the first pod with the data from the snap in the second pod +to make sure they match. Then it deletes the helm deployments and waits until the pvcs in the namespace are deleted. diff --git a/test/helm/blocksnap/run.sh b/test/helm/blocksnap/run.sh new file mode 100644 index 00000000..2d6fe0f9 --- /dev/null +++ b/test/helm/blocksnap/run.sh @@ -0,0 +1,89 @@ +#!/bin/sh +namespace=test +helmsettings="storageclass=vxflexos,snapclass=vxflexos-snapclass" +alias k=kubectl + +# arg1=pod name +waitOnRunning() { + echo "waiting on $1 to reach running" + running=0 + while [ $running -ne 1 ] ; + do + k get pods -n $namespace | grep $1 + running=$(k get pods -n $namespace | grep $1 | grep Running | wc -l) + sleep 5 + done +} + +# arg1=volumesnapshot name +waitOnSnapshotReady() { + echo "waiting on $1 to reach ready" + ready="false" + while [ "$ready" != "true" ] ; + do + name=$(k get volumesnapshot -n $namespace | grep $1 | awk ' { print $1; }') + ready=$(k get volumesnapshot -n $namespace | grep $1 | awk ' { print $2; }') + echo $name ready: $ready + sleep 5 + done +} + +# waitOnNoPvc() +waitOnNoPvc() { + echo "waiting on all pvcs to be deleted from namespace" + pvcs=$(k get pvc -n $namespace | grep -v NAME | wc -l) + while [ $pvcs -gt 0 ] ; + do + pvcs=$(k get pvc -n $namespace | grep -v NAME | wc -l) + k get pvc -n $namespace + sleep 5 + done +} + +helm install --set $helmsettings -n $namespace 1vol 1vol +waitOnRunning vol-0 + +# Write some data into the file system. +echo "k exec -it -n test vxflextest-0 -- tar czvf /data0/data.tgz /usr" +k exec -it -n test vol-0 -- tar czvf /data0/data.tgz /usr +# Sync the data onto the file system +k exec -it -n test vol-0 -- sync +k exec -it -n test vol-0 -- ls -l /data0/data.tgz +sumA=$(k exec -it -n test vol-0 -- md5sum /data0/data.tgz | awk ' {print $1}') +echo sumA $sumA +k exec -it -n test vol-0 -- sync + +helm install --set $helmsettings -n $namespace 1snap 1snap +waitOnSnapshotReady vol0-snap1 + +helm install --set $helmsettings -n test 1volfromsnap 1volfromsnap +waitOnRunning copy-0 +k get pods -n test + +echo "Checking the data" +echo "k exec -it -n test copy-0 -- mkdir /tmp/foo" +k exec -it -n test copy-0 -- mkdir /tmp/foo +echo "k exec -it -n test copy-0 -- mount /data0 /tmp/foo" +k exec -it -n test copy-0 -- mount /data0 /tmp/foo +echo "k exec -it -n test copy-0 -- ls -l /tmp/foo/data.tgz" +k exec -it -n test copy-0 -- ls -l /tmp/foo/data.tgz +echo "k exec -it -n test copy-0 -- tar tzvf /tmp/foo/data.tgz | tail -20" +k exec -it -n test copy-0 -- tar tzvf /tmp/foo/data.tgz | tail -20 +sumB=$(k exec -it -n test copy-0 -- md5sum /tmp/foo/data.tgz | awk ' {print $1}') + +echo sumA $sumA sumB $sumB +if [ "$sumA" != "$sumB" ] ; then + echo "Different checksums- test failed" + exit 2 +fi + +sleep 30 +helm delete -n $namespace 1volfromsnap + +sleep 30 +helm delete -n $namespace 1snap + +sleep 30 +helm delete -n $namespace 1vol + +waitOnNoPvc diff --git a/test/helm/common.bash b/test/helm/common.bash old mode 100644 new mode 100755 index 711f1ade..7bb5eaf8 --- a/test/helm/common.bash +++ b/test/helm/common.bash @@ -14,3 +14,5 @@ waitOnRunning() { done } +kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/[^0-9].*//g') +kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/[^0-9].*//g') diff --git a/test/helm/deletepvcs.sh b/test/helm/deletepvcs.sh old mode 100644 new mode 100755 index dfb017a0..c4f7631d --- a/test/helm/deletepvcs.sh +++ b/test/helm/deletepvcs.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash force=no if [ "$1" == "--force" ]; then diff --git a/test/helm/get.volume.ids b/test/helm/get.volume.ids index c91af44b..aedcab40 100644 --- a/test/helm/get.volume.ids +++ b/test/helm/get.volume.ids @@ -1,4 +1,4 @@ -#/bin/bash +#!/bin/bash ids=$(kubectl describe persistentvolume -n helmtest-vxflexos | grep VolumeHandle | awk ' { print $2; }') echo ids $ids ids=$(echo $ids | tr ' ' ',' ) diff --git a/test/helm/postgres.sh b/test/helm/postgres.sh old mode 100644 new mode 100755 index c8777457..c3b4fd17 --- a/test/helm/postgres.sh +++ b/test/helm/postgres.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash DBSQL=/root/dbsamples-0.1/world/world.sql helm install -n postgres postgres echo "Waiting for pods to come up..." diff --git a/test/helm/snap1.yaml b/test/helm/snap1.yaml deleted file mode 100644 index f6e0f5cf..00000000 --- a/test/helm/snap1.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: snapshot.storage.k8s.io/v1alpha1 -kind: VolumeSnapshot -metadata: - name: pvol0-snap1 - namespace: helmtest-vxflexos -spec: - snapshotClassName: vxflexos-snapclass - source: - name: pvol0 - kind: PersistentVolumeClaim diff --git a/test/helm/snap2.yaml b/test/helm/snap2.yaml deleted file mode 100644 index b21936fa..00000000 --- a/test/helm/snap2.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: snapshot.storage.k8s.io/v1alpha1 -kind: VolumeSnapshot -metadata: - name: pvol0-snap2 - namespace: helmtest-vxflexos -spec: - snapshotClassName: vxflexos-snapclass - source: - name: pvol0 - kind: PersistentVolumeClaim diff --git a/test/helm/snapcg.yaml b/test/helm/snapcg.yaml deleted file mode 100644 index 0dc9d993..00000000 --- a/test/helm/snapcg.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: snapshot.storage.k8s.io/v1alpha1 -kind: VolumeSnapshot -metadata: - name: pvol0-snap1 - namespace: helmtest-vxflexos -spec: - snapshotClassName: vxflexos-cgsnap - source: - name: pvol0 - kind: PersistentVolumeClaim diff --git a/test/helm/snapcgtest.sh b/test/helm/snapcgtest.sh deleted file mode 100644 index 63ecde5f..00000000 --- a/test/helm/snapcgtest.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -rm -f .volsnapclass.yaml -kubectl delete volumesnapshotclass vxflexos-cgsnap -n helmtest-vxflexos - -# Collect the list of "Bound" volumes and translate them to VxFlex OS ids -vols=$( kubectl get pv | grep Bound | awk ' { print $1; }' ) -ids="" -for avol in $vols; -do - echo $avol - ids="${ids} $(kubectl describe persistentvolume $avol | grep VolumeHandle | awk ' { print $2; }')" -done -ids=$(echo $ids | tr ' ' ',' ) -echo ids $ids - -# Edit the snapshotclass to have a valid VOLUME_ID_LIST -sed .volsnapclass.yaml -cat .volsnapclass.yaml - -echo "creating volume snapshot class..." -kubectl create -f .volsnapclass.yaml -sleep 3 -echo "creating volume snapshot" -kubectl create -f snapcg.yaml -sleep 20 -echo "snapshot created:" -kubectl get volumesnapshot -n helmtest-vxflexos -sleep 60 -echo "deleting volume snapshot" -kubectl delete -f snapcg.yaml -sleep 20 -echo "snapshot deleted:" -kubectl get volumesnapshot -n helmtest-vxflexos -kubectl delete volumesnapshotclass vxflexos-cgsnap -n helmtest-vxflexos diff --git a/test/helm/snaprestoretest.sh b/test/helm/snaprestoretest.sh old mode 100644 new mode 100755 index ecbfd4fa..244f67f1 --- a/test/helm/snaprestoretest.sh +++ b/test/helm/snaprestoretest.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash NS=helmtest-vxflexos source ./common.bash @@ -11,11 +11,11 @@ kubectl exec -n ${NS} vxflextest-0 -- ls -l /data0 kubectl exec -n ${NS} vxflextest-0 -- sync kubectl exec -n ${NS} vxflextest-0 -- sync echo "creating snap1 of pvol0" -kubectl create -f snap1.yaml +kubectl create -f betasnap1.yaml sleep 10 kubectl get volumesnapshot -n ${NS} echo "updating container to add a volume sourced from snapshot" -helm upgrade -n helmtest-vxflexos 2vols 2vols+restore +helm upgrade -n helmtest-vxflexos 2vols 2vols+restore echo "waiting for container to upgrade/stabalize" sleep 20 waitOnRunning diff --git a/test/helm/snaptest.sh b/test/helm/snaptest.sh old mode 100644 new mode 100755 index 805261c3..6a3c8936 --- a/test/helm/snaptest.sh +++ b/test/helm/snaptest.sh @@ -1,19 +1,22 @@ -#!/bin/sh +#!/bin/bash +NS=helmtest-vxflexos +source ./common.bash + echo "creating snap1 of pvol0" -kubectl create -f snap1.yaml +kubectl create -f betasnap1.yaml sleep 10 -kubectl get volumesnapshot -n helmtest-vxflexos -kubectl describe volumesnapshot -n helmtest-vxflexos +kubectl get volumesnapshot -n ${NS} +kubectl describe volumesnapshot -n ${NS} sleep 10 echo "creating snap2 of pvol0" -kubectl create -f snap2.yaml +kubectl create -f betasnap2.yaml sleep 10 -kubectl describe volumesnapshot -n helmtest-vxflexos +kubectl describe volumesnapshot -n ${NS} sleep 10 echo "deleting snapshots..." -kubectl delete volumesnapshot pvol0-snap1 -n helmtest-vxflexos +kubectl delete volumesnapshot pvol0-snap1 -n ${NS} sleep 10 -kubectl delete volumesnapshot pvol0-snap2 -n helmtest-vxflexos +kubectl delete volumesnapshot pvol0-snap2 -n ${NS} sleep 10 -kubectl get volumesnapshot -n helmtest-vxflexos +kubectl get volumesnapshot -n ${NS} diff --git a/test/helm/starttest.sh b/test/helm/starttest.sh index 63e1ed6c..91401084 100755 --- a/test/helm/starttest.sh +++ b/test/helm/starttest.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash [ "$1" = "" ] && { echo "requires test name as argument" exit 2 diff --git a/test/helm/stoptest.sh b/test/helm/stoptest.sh index c86b83d3..6517424b 100755 --- a/test/helm/stoptest.sh +++ b/test/helm/stoptest.sh @@ -1,4 +1,4 @@ -#/bin/sh +#!/bin/bash helm delete -n helmtest-vxflexos $1 sleep 10 kubectl get pods -n helmtest-vxflexos diff --git a/test/helm/unsupported/block1/templates/block-pvc.yaml b/test/helm/unsupported/block1/templates/block-pvc.yaml deleted file mode 100644 index 9f36aff2..00000000 --- a/test/helm/unsupported/block1/templates/block-pvc.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: block-pvc - namespace: helmtest-vxflexos -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: vxflexos - volumeMode: Block - #volumeName: block-pv diff --git a/test/helm/unsupported/block1/templates/test.yaml b/test/helm/unsupported/block1/templates/test.yaml deleted file mode 100644 index 85d22e1a..00000000 --- a/test/helm/unsupported/block1/templates/test.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: vxflextest - namespace: helmtest-vxflexos ---- -kind: StatefulSet -apiVersion: apps/v1 -metadata: - name: vxflextest - namespace: helmtest-vxflexos -spec: - selector: - matchLabels: - app: vxflextest - template: - metadata: - labels: - app: vxflextest - spec: - serviceAccount: vxflextest - containers: - - name: test - image: docker.io/centos:latest - command: [ "/bin/sleep", "3600" ] - deviceMounts: - - devicePath: "/data2" - name: block - volumes: - - name: block - persistentVolumeClaim: - claimName: block-pvc - diff --git a/test/helm/unsupported/block2/templates/block-pv.yaml b/test/helm/unsupported/block2/templates/block-pv.yaml deleted file mode 100644 index a9cbb9e7..00000000 --- a/test/helm/unsupported/block2/templates/block-pv.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: block-pv - namespace: helmtest-vxflexos -spec: - accessModes: - - ReadWriteOnce - capacity: - storage: 8Gi - csi: - driver: vxflexos.emc.dell.com - volumeHandle: 72cf800900000004 - persistentVolumeReclaimPolicy: Delete - storageClassName: vxflexos - volumeMode: Block diff --git a/test/helm/unsupported/block2/templates/block-pvc.yaml b/test/helm/unsupported/block2/templates/block-pvc.yaml deleted file mode 100644 index 9ae1c4bf..00000000 --- a/test/helm/unsupported/block2/templates/block-pvc.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: block-pvc - namespace: helmtest-vxflexos -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 8Gi - storageClassName: vxflexos - volumeMode: Block - volumeName: block-pv diff --git a/test/helm/unsupported/block2/templates/test.yaml b/test/helm/unsupported/block2/templates/test.yaml deleted file mode 100644 index b10d45b0..00000000 --- a/test/helm/unsupported/block2/templates/test.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: vxflextest - namespace: helmtest-vxflexos ---- -kind: StatefulSet -apiVersion: apps/v1 -metadata: - name: vxflextest - namespace: helmtest-vxflexos -spec: - serviceName: test - selector: - matchLabels: - app: vxflextest - template: - metadata: - labels: - app: vxflextest - spec: - serviceAccount: vxflextest - containers: - - name: test - image: docker.io/centos:latest - command: [ "/bin/sleep", "3600" ] - volumeDevices: - - devicePath: "/data2" - name: block - volumes: - - name: block - persistentVolumeClaim: - claimName: block-pvc - diff --git a/test/helm/volumesnapshotclass.yaml b/test/helm/volumesnapshotclass.yaml index b75948a2..6d168f1c 100644 --- a/test/helm/volumesnapshotclass.yaml +++ b/test/helm/volumesnapshotclass.yaml @@ -1,8 +1,5 @@ -apiVersion: snapshot.storage.k8s.io/v1alpha1 +apiVersion: snapshot.storage.k8s.io/v1beta1 kind: VolumeSnapshotClass metadata: - name: vxflexos-cgsnap - namespace: helmtest-vxflexos -snapshotter: csi-vxflexos.dellemc.com -parameters: - VolumeIDList: "__VOLUME_ID_LIST__" + name: vxflexos-snapclass +driver: csi-vxflexos.dellemc.com diff --git a/test/integration/features/integration.feature b/test/integration/features/integration.feature index 550ca141..a7e75ad5 100644 --- a/test/integration/features/integration.feature +++ b/test/integration/features/integration.feature @@ -40,6 +40,35 @@ Feature: VxFlex OS CSI interface And when I call DeleteVolume Then there are no errors +@long + Scenario Outline: Create volume, create snapshot, delete snapshot, delete volume for multiple sizes + Given a VxFlexOS service + And a capability with voltype "block" access "single-writer" fstype "xfs" + And a basic block volume request "integration1" + When I call CreateVolume + And when I call PublishVolume "SDC_GUID" + And when I call NodePublishVolume "SDC_GUID" + And verify published volume with voltype "block" access "single-writer" fstype "xfs" + And when I call NodePublishVolume "SDC_GUID" + And I write block data + And I call CreateSnapshot + And there are no errors + And I call DeleteSnapshot + And there are no errors + And when I call NodeUnpublishVolume "SDC_GUID" + And when I call UnpublishVolume "SDC_GUID" + And when I call DeleteVolume + And there are no errors + And when I call DeleteAllVolumes + And there are no errors + + Examples: + | size | + | "8" | + | "16" | + | "32" | + | "64" | + Scenario: Create volume, create snapshot, create volume from snapshot, delete original volume, delete new volume Given a VxFlexOS service And a basic block volume request "integration1" "8" @@ -106,6 +135,7 @@ Feature: VxFlex OS CSI interface And when I call DeleteAllVolumes And there are no errors +@xwip Scenario Outline: Create publish, node-publish, node-unpublish, unpublish, and delete basic volume Given a VxFlexOS service And a capability with voltype access fstype @@ -129,10 +159,7 @@ Feature: VxFlex OS CSI interface | "block" | "single-writer" | "none" | "none" | | "block" | "multi-writer" | "none" | "none" | | "block" | "single-writer" | "none" | "none" | - - - Scenario: Create volume with access mode read only many Given a VxFlexOS service And a capability with voltype "mount" access "single-writer" fstype "xfs" @@ -153,6 +180,27 @@ Feature: VxFlex OS CSI interface And when I call DeleteVolume Then there are no errors + Scenario: Create block volume with access mode read write many + Given a VxFlexOS service + And a capability with voltype "block" access "multi-writer" fstype "" + And a volume request "block-multi-writer-test" "8" + When I call CreateVolume + And there are no errors + And when I call PublishVolume "SDC_GUID" + And when I call PublishVolume "ALT_GUID" + And when I call NodePublishVolumeWithPoint "SDC_GUID" "/tmp/tempdev1" + And there are no errors + And when I call NodePublishVolumeWithPoint "SDC_GUID" "/tmp/tempdev2" + And there are no errors + And when I call NodePublishVolume "ALT_GUID" + And there are no errors + And when I call NodeUnpublishVolume "ALT_GUID" + And when I call NodeUnpublishVolumeWithPoint "SDC_GUID" "/tmp/tempdev1" + And when I call NodeUnpublishVolumeWithPoint "SDC_GUID" "/tmp/tempdev2" + And when I call UnpublishVolume "SDC_GUID" + And when I call UnpublishVolume "ALT_GUID" + And when I call DeleteVolume + Then there are no errors Scenario: Create publish, unpublish, and delete basic volume Given a VxFlexOS service @@ -219,11 +267,6 @@ Feature: VxFlex OS CSI interface | 1 | | 2 | | 5 | - | 10 | - | 20 | - | 50 | - | 100 | - | 200 | Scenario Outline: Idempotent create volumes, publish, node publish, node unpublish, unpublish, delete volumes in parallel Given a VxFlexOS service @@ -251,9 +294,63 @@ Feature: VxFlex OS CSI interface And there are no errors And when I delete volumes in parallel Then there are no errors - + Examples: + | numberOfVolumes | | 1 | + | 10 | + + + + Scenario: Expand Volume Mount + Given a VxFlexOS service + And a capability with voltype "mount" access "single-writer" fstype "xfs" + And a volume request "integration30" "16" + When I call CreateVolume + And there are no errors + And when I call PublishVolume "SDC_GUID" + And there are no errors + And when I call NodePublishVolume "SDC_GUID" + And there are no errors + And when I call ExpandVolume to "20" + And there are no errors + And when I call NodeExpandVolume + And there are no errors + And I call ListVolume + And a valid ListVolumeResponse is returned + And when I call NodeUnpublishVolume "SDC_GUID" + And there are no errors + And when I call UnpublishVolume "SDC_GUID" + And there are no errors + And when I call DeleteVolume + Then there are no errors + + + Scenario: Expand Volume Block + Given a VxFlexOS service + And a capability with voltype "block" access "single-writer" fstype "none" + And a volume request "integration33" "8" + When I call CreateVolume + And there are no errors + And when I call PublishVolume "SDC_GUID" + And there are no errors + And when I call NodePublishVolume "SDC_GUID" + And there are no errors + And when I call ExpandVolume to "10" + And there are no errors + And when I call NodeExpandVolume + And there are no errors + And I call ListVolume + And a valid ListVolumeResponse is returned + And when I call NodeUnpublishVolume "SDC_GUID" + And there are no errors + And when I call UnpublishVolume "SDC_GUID" + And there are no errors + And when I call DeleteVolume + Then there are no errors + + | numberOfVolumes | + | 1 | | 10 | | 20 | diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index e08a88c7..7dce8e6e 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -55,7 +55,7 @@ func TestMain(m *testing.M) { }, godog.Options{ Format: "pretty", Paths: []string{"features"}, - // Tags: "wip", + //Tags: "wip", }) if st := m.Run(); st > exitVal { exitVal = st diff --git a/test/integration/run.sh b/test/integration/run.sh index e4670ca2..1c5a5007 100644 --- a/test/integration/run.sh +++ b/test/integration/run.sh @@ -11,7 +11,7 @@ if [ $rc -ne 0 ]; then echo "failed http unauthorized test"; exit $rc; fi rm -f unix.sock source ../../env.sh echo $SDC_GUID -GOOS=linux CGO_ENABLED=0 GO111MODULE=on go test -v -coverprofile=c.linux.out -timeout 30m -coverpkg=github.com/dell/csi-vxflexos/service *test.go & +GOOS=linux CGO_ENABLED=0 GO111MODULE=on go test -v -coverprofile=c.linux.out -timeout 60m -coverpkg=github.com/dell/csi-vxflexos/service *test.go & if [ -f ./csi-sanity ] ; then sleep 5 ./csi-sanity --csi.endpoint=./unix_sock --csi.testvolumeparameters=./pool.yml --csi.testvolumesize 8589934592 diff --git a/test/integration/step_defs_test.go b/test/integration/step_defs_test.go index c96c66f2..4f22b8c4 100644 --- a/test/integration/step_defs_test.go +++ b/test/integration/step_defs_test.go @@ -33,6 +33,9 @@ type feature struct { snapshotID string volIDList []string maxRetryCount int + expandVolumeResponse *csi.ControllerExpandVolumeResponse + nodeExpandVolumeRequest *csi.NodeExpandVolumeRequest + nodeExpandVolumeResponse *csi.NodeExpandVolumeResponse } func (f *feature) addError(err error) { @@ -50,6 +53,8 @@ func (f *feature) aVxFlexOSService() error { f.snapshotID = "" f.volIDList = f.volIDList[:0] f.maxRetryCount = MaxRetries + f.expandVolumeResponse = nil + f.nodeExpandVolumeResponse = nil return nil } @@ -342,15 +347,19 @@ func (f *feature) getNodePublishVolumeRequest() *csi.NodePublishVolumeRequest { } func (f *feature) whenICallNodePublishVolumeWithPoint(arg1 string, arg2 string) error { - _, err := os.Stat(arg2) - if err != nil && os.IsNotExist(err) { - err = os.Mkdir(arg2, 0777) - if err != nil { - return err - } + block := f.capability.GetBlock() + if block != nil { + } else { + _, err := os.Stat(arg2) + if err != nil && os.IsNotExist(err) { + err = os.Mkdir(arg2, 0777) + if err != nil { + return err + } + } } - err = f.nodePublishVolume(f.volID, arg2) + err := f.nodePublishVolume(f.volID, arg2) if err != nil { fmt.Printf("NodePublishVolume failed: %s\n", err.Error()) f.addError(err) @@ -405,7 +414,6 @@ func (f *feature) whenICallNodeUnpublishVolume(arg1 string) error { } func (f *feature) whenICallNodeUnpublishVolumeWithPoint(arg1, arg2 string) error { - err := f.nodeUnpublishVolume(f.volID, arg2) if err != nil { fmt.Printf("NodeUnpublishVolume failed: %s\n", err.Error()) @@ -918,6 +926,111 @@ func (f *feature) whenIDeleteVolumesInParallel(nVols int) error { return nil } +// Writes a fixed pattern of block data (0x57 bytes) in 1 MB chunks to raw block mounted at /tmp/datafile. +// Used to make sure the data has changed when taking a snapshot +func (f *feature) iWriteBlockData() error { + buf := make([]byte, 1024*1024) + for i := 0; i < 1024*1024; i++ { + buf[i] = 0x57 + } + fp, err := os.OpenFile("/tmp/datafile", os.O_RDWR, 0666) + if err != nil { + return nil + } + var nrecords int + for err == nil { + var n int + n, err = fp.Write(buf) + if n == len(buf) { + nrecords++ + } + if (nrecords % 256) == 0 { + fmt.Printf("%d records\r", nrecords) + } + } + fp.Close() + fmt.Printf("\rWrote %d MB\n", nrecords) + return nil + +} + +func (f *feature) whenICallExpandVolumeTo(size int64) error { + + err := f.controllerExpandVolume(f.volID, size) + if err != nil { + fmt.Printf("ControllerExpandVolume %s:\n", err.Error()) + f.addError(err) + } else { + fmt.Printf("ControllerExpandVolume completed successfully\n") + } + time.Sleep(SleepTime) + return nil +} + +func (f *feature) controllerExpandVolume(volID string, size int64) error { + + const bytesInKiB = 1024 + var resp *csi.ControllerExpandVolumeResponse + var err error + req := &csi.ControllerExpandVolumeRequest{ + VolumeId: volID, + CapacityRange: &csi.CapacityRange{RequiredBytes: size * bytesInKiB * bytesInKiB * bytesInKiB}, + } + ctx := context.Background() + client := csi.NewControllerClient(grpcClient) + for i := 0; i < f.maxRetryCount; i++ { + resp, err = client.ControllerExpandVolume(ctx, req) + if err == nil { + break + } + fmt.Printf("Controller ExpandVolume retry: %s\n", err.Error()) + time.Sleep(RetrySleepTime) + } + f.expandVolumeResponse = resp + return err +} + +func (f *feature) whenICallNodeExpandVolume() error { + + nodePublishReq := f.nodePublishVolumeRequest + if nodePublishReq == nil { + err := fmt.Errorf("Volume is not stage, nodePublishVolumeRequest not found") + return err + } + err := f.nodeExpandVolume(f.volID, nodePublishReq.TargetPath) + if err != nil { + fmt.Printf("NodeExpandVolume %s:\n", err.Error()) + f.addError(err) + } else { + fmt.Printf("NodeExpandVolume completed successfully\n") + } + time.Sleep(SleepTime) + return nil + +} + +func (f *feature) nodeExpandVolume(volID, volPath string) error { + var resp *csi.NodeExpandVolumeResponse + var err error + req := &csi.NodeExpandVolumeRequest{ + VolumeId: volID, + VolumePath: volPath, + } + ctx := context.Background() + client := csi.NewNodeClient(grpcClient) + // Retry loop to deal with API being overwhelmed + for i := 0; i < f.maxRetryCount; i++ { + resp, err = client.NodeExpandVolume(ctx, req) + if err == nil { + break + } + fmt.Printf("Node ExpandVolume retry: %s\n", err.Error()) + time.Sleep(RetrySleepTime) + } + f.nodeExpandVolumeResponse = resp + return err +} + func FeatureContext(s *godog.Suite) { f := &feature{} s.Step(`^a VxFlexOS service$`, f.aVxFlexOSService) @@ -956,4 +1069,7 @@ func FeatureContext(s *godog.Suite) { s.Step(`^I node unpublish (\d+) volumes in parallel$`, f.iNodeUnpublishVolumesInParallel) s.Step(`^I unpublish (\d+) volumes in parallel$`, f.iUnpublishVolumesInParallel) s.Step(`^when I delete (\d+) volumes in parallel$`, f.whenIDeleteVolumesInParallel) + s.Step(`^I write block data$`, f.iWriteBlockData) + s.Step(`^when I call ExpandVolume to "([^"]*)"$`, f.whenICallExpandVolumeTo) + s.Step(`^when I call NodeExpandVolume$`, f.whenICallNodeExpandVolume) } diff --git a/test/sanity/run.sh b/test/sanity/run.sh index 0a888e7d..d3391185 100644 --- a/test/sanity/run.sh +++ b/test/sanity/run.sh @@ -1,4 +1,4 @@ #!/bin/sh rm -rf /tmp/csi-staging rm -rf /tmp/csi-mount -csi-sanity --ginkgo.v --csi.endpoint=/root/csi-vxflexos/test/sanity/unix_sock --csi.testvolumesize 17179869184 --csi.testvolumeparameters=volParams.yaml --csi.secrets=secrets.yaml --ginkgo.skip "pagination should detect volumes added between pages and accept tokens when the last volume from a page is deleted|check the presence of new volumes and absence of deleted ones in the volume list|should fail when the volume is missing" +csi-sanity --ginkgo.v --csi.endpoint=/root/csi-vxflexos/test/sanity/unix_sock --csi.testvolumeexpandsize 25769803776 --csi.testvolumesize 17179869184 --csi.testvolumeparameters=volParams.yaml --csi.secrets=secrets.yaml --ginkgo.skip "pagination should detect volumes added between pages and accept tokens when the last volume from a page is deleted|check the presence of new volumes and absence of deleted ones in the volume list|should fail when the volume is missing"