@@ -65,6 +65,7 @@ func NewControllerServer(ephemeral bool) *controllerServer {
6565 csi .ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME ,
6666 csi .ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT ,
6767 csi .ControllerServiceCapability_RPC_LIST_SNAPSHOTS ,
68+ csi .ControllerServiceCapability_RPC_CLONE_VOLUME ,
6869 }),
6970 }
7071}
@@ -178,19 +179,47 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
178179 snapshotId := contentSource .GetSnapshot ().GetSnapshotId ()
179180 snapshot , ok := hostPathVolumeSnapshots [snapshotId ]
180181 if ! ok {
182+ deleteHostpathVolume (volumeID )
181183 return nil , status .Errorf (codes .NotFound , "cannot find snapshot %v" , snapshotId )
182184 }
183185 if snapshot .ReadyToUse != true {
186+ deleteHostpathVolume (volumeID )
184187 return nil , status .Errorf (codes .Internal , "Snapshot %v is not yet ready to use." , snapshotId )
185188 }
186189 snapshotPath := snapshot .Path
187190 args := []string {"zxvf" , snapshotPath , "-C" , path }
188191 executor := utilexec .New ()
189192 out , err := executor .Command ("tar" , args ... ).CombinedOutput ()
190193 if err != nil {
194+ deleteHostpathVolume (volumeID )
191195 return nil , status .Error (codes .Internal , fmt .Sprintf ("failed pre-populate data for volume: %v: %s" , err , out ))
192196 }
193197 }
198+ if srcVolume := contentSource .GetVolume (); srcVolume != nil {
199+ srcVolumeID := srcVolume .GetVolumeId ()
200+ hostPathVolume , ok := hostPathVolumes [srcVolumeID ]
201+ if ! ok {
202+ deleteHostpathVolume (volumeID )
203+ return nil , status .Error (codes .NotFound , "source volumeID does not exist, are source/destination in the same storage class?" )
204+ }
205+ srcPath := hostPathVolume .VolPath
206+ isEmpty , err := hostPathIsEmpty (srcPath )
207+ if err != nil {
208+ deleteHostpathVolume (volumeID )
209+ return nil , status .Error (codes .Internal , fmt .Sprintf ("failed verification check of source hostpath volume: %s: %v" , srcVolumeID , err ))
210+ }
211+
212+ // If the source hostpath volume is empty it's a noop and we just move along, otherwise the cp call will fail with a a file stat error DNE
213+ if ! isEmpty {
214+ args := []string {"-a" , srcPath + "/*" , path + "/" }
215+ executor := utilexec .New ()
216+ out , err := executor .Command ("cp" , args ... ).CombinedOutput ()
217+ if err != nil {
218+ deleteHostpathVolume (volumeID )
219+ return nil , status .Error (codes .Internal , fmt .Sprintf ("failed pre-populate data (clone) for volume: %s: %s" , volumeID , out ))
220+ }
221+ }
222+ }
194223 }
195224
196225 createVolumeResponse := & csi.CreateVolumeResponse {}
0 commit comments