Skip to content

Instantly share code, notes, and snippets.

@wallnerryan
Created February 21, 2020 02:19
Show Gist options
  • Save wallnerryan/a20d929499eb37ddfedc22a67c9fc01b to your computer and use it in GitHub Desktop.
Save wallnerryan/a20d929499eb37ddfedc22a67c9fc01b to your computer and use it in GitHub Desktop.
packageportworximport("fmt""os"volumeclient"github.com/libopenstorage/openstorage/api/client/volume""k8s.io/klog""k8s.io/utils/mount"utilstrings"k8s.io/utils/strings"v1"k8s.io/api/core/v1""k8s.io/apimachinery/pkg/api/resource"metav1"k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/types""k8s.io/kubernetes/pkg/volume""k8s.io/kubernetes/pkg/volume/util")const(attachContextKey="context"attachHostKey="host")//ProbeVolumePluginsistheprimaryentrypointforvolumeplugins.funcProbeVolumePlugins()[]volume.VolumePlugin{return[]volume.VolumePlugin{&portworxVolumePlugin{nil,nil}}}typeportworxVolumePluginstruct{hostvolume.VolumeHostutil*portworxVolumeUtil}var_volume.VolumePlugin=&portworxVolumePlugin{}var_volume.PersistentVolumePlugin=&portworxVolumePlugin{}var_volume.DeletableVolumePlugin=&portworxVolumePlugin{}var_volume.ProvisionableVolumePlugin=&portworxVolumePlugin{}var_volume.ExpandableVolumePlugin=&portworxVolumePlugin{}const(portworxVolumePluginName="kubernetes.io/portworx-volume")funcgetPath(uidtypes.UID,volNamestring,hostvolume.VolumeHost)string{returnhost.GetPodVolumeDir(uid,utilstrings.EscapeQualifiedName(portworxVolumePluginName),volName)}func(plugin*portworxVolumePlugin)Init(hostvolume.VolumeHost)error{client,err:=volumeclient.NewDriverClient(fmt.Sprintf("http://%s:%d",host.GetHostName(),osdMgmtDefaultPort),pxdDriverName,osdDriverVersion,pxDriverName)iferr!=nil{returnerr}plugin.host=hostplugin.util=&portworxVolumeUtil{portworxClient:client,}returnnil}func(plugin*portworxVolumePlugin)GetPluginName()string{returnportworxVolumePluginName}func(plugin*portworxVolumePlugin)GetVolumeName(spec*volume.Spec)(string,error){volumeSource,_,err:=getVolumeSource(spec)iferr!=nil{return"",err}returnvolumeSource.VolumeID,nil}func(plugin*portworxVolumePlugin)CanSupport(spec*volume.Spec)bool{return(spec.PersistentVolume!=nil&&spec.PersistentVolume.Spec.PortworxVolume!=nil)||(spec.Volume!=nil&&spec.Volume.PortworxVolume!=nil)}func(plugin*portworxVolumePlugin)RequiresRemount()bool{returnfalse}func(plugin*portworxVolumePlugin)GetAccessModes()[]v1.PersistentVolumeAccessMode{return[]v1.PersistentVolumeAccessMode{v1.ReadWriteOnce,v1.ReadWriteMany,}}func(plugin*portworxVolumePlugin)NewMounter(spec*volume.Spec,pod*v1.Pod,_volume.VolumeOptions)(volume.Mounter,error){returnplugin.newMounterInternal(spec,pod.UID,plugin.util,plugin.host.GetMounter(plugin.GetPluginName()))}func(plugin*portworxVolumePlugin)newMounterInternal(spec*volume.Spec,podUIDtypes.UID,managerportworxManager,mountermount.Interface)(volume.Mounter,error){pwx,readOnly,err:=getVolumeSource(spec)iferr!=nil{returnnil,err}volumeID:=pwx.VolumeIDfsType:=pwx.FSTypereturn&portworxVolumeMounter{portworxVolume:&portworxVolume{podUID:podUID,volName:spec.Name(),volumeID:volumeID,manager:manager,mounter:mounter,plugin:plugin,MetricsProvider:volume.NewMetricsStatFS(getPath(podUID,spec.Name(),plugin.host)),},fsType:fsType,readOnly:readOnly,diskMounter:util.NewSafeFormatAndMountFromHost(plugin.GetPluginName(),plugin.host)},nil}func(plugin*portworxVolumePlugin)NewUnmounter(volNamestring,podUIDtypes.UID)(volume.Unmounter,error){returnplugin.newUnmounterInternal(volName,podUID,plugin.util,plugin.host.GetMounter(plugin.GetPluginName()))}func(plugin*portworxVolumePlugin)newUnmounterInternal(volNamestring,podUIDtypes.UID,managerportworxManager,mountermount.Interface)(volume.Unmounter,error){return&portworxVolumeUnmounter{&portworxVolume{podUID:podUID,volName:volName,manager:manager,mounter:mounter,plugin:plugin,MetricsProvider:volume.NewMetricsStatFS(getPath(podUID,volName,plugin.host)),}},nil}func(plugin*portworxVolumePlugin)NewDeleter(spec*volume.Spec)(volume.Deleter,error){returnplugin.newDeleterInternal(spec,plugin.util)}func(plugin*portworxVolumePlugin)newDeleterInternal(spec*volume.Spec,managerportworxManager)(volume.Deleter,error){ifspec.PersistentVolume!=nil&&spec.PersistentVolume.Spec.PortworxVolume==nil{returnnil,fmt.Errorf("spec.PersistentVolumeSource.PortworxVolumeisnil")}return&portworxVolumeDeleter{portworxVolume:&portworxVolume{volName:spec.Name(),volumeID:spec.PersistentVolume.Spec.PortworxVolume.VolumeID,manager:manager,plugin:plugin,}},nil}func(plugin*portworxVolumePlugin)NewProvisioner(optionsvolume.VolumeOptions)(volume.Provisioner,error){returnplugin.newProvisionerInternal(options,plugin.util)}func(plugin*portworxVolumePlugin)newProvisionerInternal(optionsvolume.VolumeOptions,managerportworxManager)(volume.Provisioner,error){return&portworxVolumeProvisioner{portworxVolume:&portworxVolume{manager:manager,plugin:plugin,},options:options,},nil}func(plugin*portworxVolumePlugin)RequiresFSResize()bool{returnfalse}func(plugin*portworxVolumePlugin)ExpandVolumeDevice(spec*volume.Spec,newSizeresource.Quantity,oldSizeresource.Quantity)(resource.Quantity,error){klog.V(4).Infof("Expanding:%sfrom%vto%v",spec.Name(),oldSize,newSize)err:=plugin.util.ResizeVolume(spec,newSize,plugin.host)iferr!=nil{returnoldSize,err}klog.V(4).Infof("Successfullyresized%sto%v",spec.Name(),newSize)returnnewSize,nil}func(plugin*portworxVolumePlugin)ConstructVolumeSpec(volumeName,mountPathstring)(*volume.Spec,error){portworxVolume:=&v1.Volume{Name:volumeName,VolumeSource:v1.VolumeSource{PortworxVolume:&v1.PortworxVolumeSource{VolumeID:volumeName,},},}returnvolume.NewSpecFromVolume(portworxVolume),nil}func(plugin*portworxVolumePlugin)SupportsMountOption()bool{returnfalse}func(plugin*portworxVolumePlugin)SupportsBulkVolumeVerification()bool{returnfalse}funcgetVolumeSource(spec*volume.Spec)(*v1.PortworxVolumeSource,bool,error){ifspec.Volume!=nil&&spec.Volume.PortworxVolume!=nil{returnspec.Volume.PortworxVolume,spec.Volume.PortworxVolume.ReadOnly,nil}elseifspec.PersistentVolume!=nil&&spec.PersistentVolume.Spec.PortworxVolume!=nil{returnspec.PersistentVolume.Spec.PortworxVolume,spec.ReadOnly,nil}returnnil,false,fmt.Errorf("SpecdoesnotreferenceaPortworxVolumetype")}//AbstractinterfacetoPDoperations.typeportworxManagerinterface{//CreatesavolumeCreateVolume(provisioner*portworxVolumeProvisioner)(volumeIDstring,volumeSizeGBint64,labelsmap[string]string,errerror)//DeletesavolumeDeleteVolume(deleter*portworxVolumeDeleter)error//AttachavolumeAttachVolume(mounter*portworxVolumeMounter,attachOptionsmap[string]string)(string,error)//DetachavolumeDetachVolume(unmounter*portworxVolumeUnmounter)error//MountavolumeMountVolume(mounter*portworxVolumeMounter,mountDirstring)error//UnmountavolumeUnmountVolume(unmounter*portworxVolumeUnmounter,mountDirstring)error//ResizeavolumeResizeVolume(spec*volume.Spec,newSizeresource.Quantity,hostvolume.VolumeHost)error}//portworxVolumevolumesareportworxblockdevices//thatareattachedtothekubelet'shostmachineandexposedtothepod.typeportworxVolumestruct{volNamestringpodUIDtypes.UID//UniqueidofthePD,usedtofindthediskresourceintheprovider.volumeIDstring//UtilityinterfacethatprovidesAPIcallstotheprovidertoattach/detachdisks.managerportworxManager//Mounterinterfacethatprovidessystemcallstomounttheglobalpathtothepodlocalpath.mountermount.Interfaceplugin*portworxVolumePluginvolume.MetricsProvider}typeportworxVolumeMounterstruct{*portworxVolume//Filesystemtype,optional.fsTypestring//Specifieswhetherthediskwillbeattachedasread-only.readOnlybool//diskMounterprovidestheinterfacethatisusedtomounttheactualblockdevice.diskMounter*mount.SafeFormatAndMount}var_volume.Mounter=&portworxVolumeMounter{}func(b*portworxVolumeMounter)GetAttributes()volume.Attributes{returnvolume.Attributes{ReadOnly:b.readOnly,Managed:!b.readOnly,SupportsSELinux:false,}}//Checkspriortomountoperationstoverifythattherequiredcomponents(binaries,etc.)//tomountthevolumeareavailableontheunderlyingnode.//Ifnot,itreturnsanerrorfunc(b*portworxVolumeMounter)CanMount()error{returnnil}//SetUpattachesthediskandbindmountstothevolumepath.func(b*portworxVolumeMounter)SetUp(mounterArgsvolume.MounterArgs)error{returnb.SetUpAt(b.GetPath(),mounterArgs)}//SetUpAtattachesthediskandbindmountstothevolumepath.func(b*portworxVolumeMounter)SetUpAt(dirstring,mounterArgsvolume.MounterArgs)error{notMnt,err:=b.mounter.IsLikelyNotMountPoint(dir)klog.Infof("PortworxVolumesetup.Dir:%s%v%v",dir,!notMnt,err)iferr!=nil&&!os.IsNotExist(err){klog.Errorf("Cannotvalidatemountpoint:%s",dir)returnerr}if!notMnt{returnnil}attachOptions:=make(map[string]string)attachOptions[attachContextKey]=dirattachOptions[attachHostKey]=b.plugin.host.GetHostName()if_,err:=b.manager.AttachVolume(b,attachOptions);err!=nil{returnerr}klog.V(4).Infof("PortworxVolume%sattached",b.volumeID)iferr:=os.MkdirAll(dir,0750);err!=nil{returnerr}iferr:=b.manager.MountVolume(b,dir);err!=nil{returnerr}if!b.readOnly{volume.SetVolumeOwnership(b,mounterArgs.FsGroup)}klog.Infof("PortworxVolume%ssetupat%s",b.volumeID,dir)returnnil}func(pwx*portworxVolume)GetPath()string{returngetPath(pwx.podUID,pwx.volName,pwx.plugin.host)}typeportworxVolumeUnmounterstruct{*portworxVolume}var_volume.Unmounter=&portworxVolumeUnmounter{}//Unmountsthebindmount,anddetachesthediskonlyifthePD//resourcewasthelastreferencetothatdiskonthekubelet.func(c*portworxVolumeUnmounter)TearDown()error{returnc.TearDownAt(c.GetPath())}//Unmountsthebindmount,anddetachesthediskonlyifthePD//resourcewasthelastreferencetothatdiskonthekubelet.func(c*portworxVolumeUnmounter)TearDownAt(dirstring)error{klog.Infof("PortworxVolumeTearDownof%s",dir)iferr:=c.manager.UnmountVolume(c,dir);err!=nil{returnerr}//CallPortworxDetachVolume.iferr:=c.manager.DetachVolume(c);err!=nil{returnerr}returnnil}typeportworxVolumeDeleterstruct{*portworxVolume}var_volume.Deleter=&portworxVolumeDeleter{}func(d*portworxVolumeDeleter)GetPath()string{returngetPath(d.podUID,d.volName,d.plugin.host)}func(d*portworxVolumeDeleter)Delete()error{returnd.manager.DeleteVolume(d)}typeportworxVolumeProvisionerstruct{*portworxVolumeoptionsvolume.VolumeOptions}var_volume.Provisioner=&portworxVolumeProvisioner{}func(c*portworxVolumeProvisioner)Provision(selectedNode*v1.Node,allowedTopologies[]v1.TopologySelectorTerm)(*v1.PersistentVolume,error){if!util.AccessModesContainedInAll(c.plugin.GetAccessModes(),c.options.PVC.Spec.AccessModes){returnnil,fmt.Errorf("invalidAccessModes%v:onlyAccessModes%varesupported",c.options.PVC.Spec.AccessModes,c.plugin.GetAccessModes())}ifutil.CheckPersistentVolumeClaimModeBlock(c.options.PVC){returnnil,fmt.Errorf("%sdoesnotsupportblockvolumeprovisioning",c.plugin.GetPluginName())}volumeID,sizeGiB,labels,err:=c.manager.CreateVolume(c)iferr!=nil{returnnil,err}pv:=&v1.PersistentVolume{ObjectMeta:metav1.ObjectMeta{Name:c.options.PVName,Labels:map[string]string{},Annotations:map[string]string{util.VolumeDynamicallyCreatedByKey:"portworx-volume-dynamic-provisioner",},},Spec:v1.PersistentVolumeSpec{PersistentVolumeReclaimPolicy:c.options.PersistentVolumeReclaimPolicy,AccessModes:c.options.PVC.Spec.AccessModes,Capacity:v1.ResourceList{v1.ResourceName(v1.ResourceStorage):resource.MustParse(fmt.Sprintf("%dGi",sizeGiB)),},PersistentVolumeSource:v1.PersistentVolumeSource{PortworxVolume:&v1.PortworxVolumeSource{VolumeID:volumeID,},},},}iflen(labels)!=0{ifpv.Labels==nil{pv.Labels=make(map[string]string)}fork,v:=rangelabels{pv.Labels[k]=v}}iflen(c.options.PVC.Spec.AccessModes)==0{pv.Spec.AccessModes=c.plugin.GetAccessModes()}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment