1616// under the License.
1717package org .apache .cloudstack .storage .template ;
1818
19+ import static com .cloud .utils .NumbersUtil .toHumanReadableSize ;
20+
1921import java .io .File ;
22+ import java .io .IOException ;
2023import java .net .URI ;
2124import java .net .URISyntaxException ;
2225import java .nio .file .Path ;
3033
3134import javax .naming .ConfigurationException ;
3235
33- import com .cloud .agent .api .Answer ;
34-
3536import org .apache .cloudstack .storage .resource .SecondaryStorageResource ;
37+ import org .apache .commons .lang3 .StringUtils ;
3638
39+ import com .cloud .agent .api .Answer ;
3740import com .cloud .agent .api .storage .CreateEntityDownloadURLAnswer ;
3841import com .cloud .agent .api .storage .CreateEntityDownloadURLCommand ;
3942import com .cloud .agent .api .storage .DeleteEntityDownloadURLCommand ;
4851import com .cloud .storage .template .TemplateUploader ;
4952import com .cloud .storage .template .TemplateUploader .Status ;
5053import com .cloud .storage .template .TemplateUploader .UploadCompleteCallback ;
54+ import com .cloud .utils .FileUtil ;
5155import com .cloud .utils .NumbersUtil ;
56+ import com .cloud .utils .UuidUtils ;
5257import com .cloud .utils .component .ManagerBase ;
5358import com .cloud .utils .exception .CloudRuntimeException ;
5459import com .cloud .utils .script .Script ;
5560
56- import static com .cloud .utils .NumbersUtil .toHumanReadableSize ;
57-
5861public class UploadManagerImpl extends ManagerBase implements UploadManager {
5962
63+ protected static final String EXTRACT_USERDATA_DIR = "userdata" ;
64+ protected static final String BASE_EXTRACT_PATH = String .format ("/var/www/html/%s/" , EXTRACT_USERDATA_DIR );
65+
6066 public class Completion implements UploadCompleteCallback {
6167 private final String jobId ;
6268
@@ -266,7 +272,7 @@ public CreateEntityDownloadURLAnswer handleCreateEntityURLCommand(CreateEntityDo
266272 return new CreateEntityDownloadURLAnswer (errorString , CreateEntityDownloadURLAnswer .RESULT_FAILURE );
267273 }
268274 // Create the directory structure so that its visible under apache server root
269- String extractDir = "/var/www/html/userdata/" ;
275+ String extractDir = BASE_EXTRACT_PATH ;
270276 extractDir = extractDir + cmd .getFilepathInExtractURL () + File .separator ;
271277 Script command = new Script ("/bin/su" , logger );
272278 command .add ("-s" );
@@ -330,12 +336,20 @@ public Answer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLComman
330336 String extractUrl = cmd .getExtractUrl ();
331337 String result ;
332338 if (extractUrl != null ) {
333- command .add ("unlink /var/www/html/userdata/" + extractUrl .substring (extractUrl .lastIndexOf (File .separator ) + 1 ));
339+ URI uri = URI .create (extractUrl );
340+ String uriPath = uri .getPath ();
341+ String marker = String .format ("/%s/" , EXTRACT_USERDATA_DIR );
342+ String linkPath = uriPath .startsWith (marker )
343+ ? uriPath .substring (marker .length ())
344+ : uriPath .substring (uriPath .indexOf (marker ) + marker .length ());
345+ command .add ("unlink " + BASE_EXTRACT_PATH + linkPath );
334346 result = command .execute ();
335347 if (result != null ) {
336348 // FIXME - Ideally should bail out if you can't delete symlink. Not doing it right now.
337349 // This is because the ssvm might already be destroyed and the symlinks do not exist.
338350 logger .warn ("Error in deleting symlink :" + result );
351+ } else {
352+ deleteEntitySymlinkRootDirectoryIfNeeded (cmd , linkPath );
339353 }
340354 }
341355
@@ -356,6 +370,30 @@ public Answer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLComman
356370 return new Answer (cmd , true , "" );
357371 }
358372
373+ protected void deleteEntitySymlinkRootDirectoryIfNeeded (DeleteEntityDownloadURLCommand cmd , String linkPath ) {
374+ if (StringUtils .isEmpty (linkPath )) {
375+ return ;
376+ }
377+ String [] parts = linkPath .split ("/" );
378+ if (parts .length == 0 ) {
379+ return ;
380+ }
381+ String rootDir = parts [0 ];
382+ if (StringUtils .isEmpty (rootDir ) || !UuidUtils .isUuid (rootDir )) {
383+ return ;
384+ }
385+ logger .info ("Deleting symlink root directory: {} for {}" , rootDir , cmd .getExtractUrl ());
386+ Path rootDirPath = Path .of (BASE_EXTRACT_PATH , rootDir );
387+ String failMsg = "Failed to delete symlink root directory: {} for {}" ;
388+ try {
389+ if (!FileUtil .deleteRecursively (rootDirPath )) {
390+ logger .warn (failMsg , rootDir , cmd .getExtractUrl ());
391+ }
392+ } catch (IOException e ) {
393+ logger .warn (failMsg , rootDir , cmd .getExtractUrl (), e );
394+ }
395+ }
396+
359397 private String getInstallPath (String jobId ) {
360398 // TODO Auto-generated method stub
361399 return null ;
0 commit comments