Skip to content

Commit 5362bad

Browse files
authored
Storage Management (#7949)
1 parent 288f066 commit 5362bad

File tree

93 files changed

+5436
-93
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+5436
-93
lines changed

api/src/main/java/com/cloud/agent/api/Command.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public int getWait() {
4747
return wait;
4848
}
4949

50+
/**
51+
* This is the time in seconds that the agent will wait before waiting for an answer from the endpoint.
52+
* The actual wait time is twice the value of this variable.
53+
* See {@link com.cloud.agent.manager.AgentAttache#send(com.cloud.agent.transport.Request, int) AgentAttache#send} implementation for more details.
54+
*
55+
* @param wait
56+
**/
5057
public void setWait(int wait) {
5158
this.wait = wait;
5259
}

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ public class EventTypes {
395395
public static final String EVENT_STORAGE_IP_RANGE_UPDATE = "STORAGE.IP.RANGE.UPDATE";
396396

397397
public static final String EVENT_IMAGE_STORE_DATA_MIGRATE = "IMAGE.STORE.MIGRATE.DATA";
398+
public static final String EVENT_IMAGE_STORE_RESOURCES_MIGRATE = "IMAGE.STORE.MIGRATE.RESOURCES";
399+
public static final String EVENT_IMAGE_STORE_OBJECT_DOWNLOAD = "IMAGE.STORE.OBJECT.DOWNLOAD";
398400

399401
// Configuration Table
400402
public static final String EVENT_CONFIGURATION_VALUE_EDIT = "CONFIGURATION.VALUE.EDIT";
@@ -1147,6 +1149,7 @@ public class EventTypes {
11471149
entityEventDetails.put(EVENT_IMPORT_VCENTER_STORAGE_POLICIES, "StoragePolicies");
11481150

11491151
entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class);
1152+
entityEventDetails.put(EVENT_IMAGE_STORE_OBJECT_DOWNLOAD, ImageStore.class);
11501153
entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs");
11511154
}
11521155

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,7 @@ public class ApiConstants {
972972
public static final String TARGET_ID = "targetid";
973973
public static final String FILES = "files";
974974
public static final String SRC_POOL = "srcpool";
975+
public static final String DEST_POOL = "destpool";
975976
public static final String DEST_POOLS = "destpools";
976977
public static final String VOLUME_IDS = "volumeids";
977978

api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,33 @@
1717
package org.apache.cloudstack.api.command.admin.iso;
1818

1919
import org.apache.cloudstack.api.APICommand;
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.Parameter;
2022
import org.apache.cloudstack.api.ResponseObject.ResponseView;
2123
import org.apache.cloudstack.api.command.admin.AdminCmd;
2224
import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
25+
import org.apache.cloudstack.api.response.ImageStoreResponse;
26+
import org.apache.cloudstack.api.response.StoragePoolResponse;
2327
import org.apache.cloudstack.api.response.TemplateResponse;
2428

2529
@APICommand(name = "listIsos", description = "Lists all available ISO files.", responseObject = TemplateResponse.class, responseView = ResponseView.Full,
2630
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
2731
public class ListIsosCmdByAdmin extends ListIsosCmd implements AdminCmd {
32+
@Parameter(name = ApiConstants.IMAGE_STORE_ID, type = CommandType.UUID, entityType = ImageStoreResponse.class,
33+
description = "ID of the image or image cache store", since = "4.19")
34+
private Long imageStoreId;
35+
36+
@Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class,
37+
description = "ID of the storage pool", since = "4.19")
38+
private Long storagePoolId;
39+
40+
@Override
41+
public Long getImageStoreId() {
42+
return imageStoreId;
43+
}
44+
45+
@Override
46+
public Long getStoragePoolId() {
47+
return storagePoolId;
48+
}
2849
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.snapshot;
18+
19+
import com.cloud.storage.Snapshot;
20+
import org.apache.cloudstack.api.APICommand;
21+
import org.apache.cloudstack.api.ApiConstants;
22+
import org.apache.cloudstack.api.Parameter;
23+
import org.apache.cloudstack.api.ResponseObject;
24+
import org.apache.cloudstack.api.command.admin.AdminCmd;
25+
import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
26+
import org.apache.cloudstack.api.response.ImageStoreResponse;
27+
import org.apache.cloudstack.api.response.SnapshotResponse;
28+
import org.apache.cloudstack.api.response.StoragePoolResponse;
29+
30+
@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = {
31+
Snapshot.class }, responseView = ResponseObject.ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
32+
public class ListSnapshotsCmdByAdmin extends ListSnapshotsCmd implements AdminCmd {
33+
@Parameter(name = ApiConstants.IMAGE_STORE_ID, type = CommandType.UUID, entityType = ImageStoreResponse.class,
34+
description = "ID of the image or image cache store", since = "4.19")
35+
private Long imageStoreId;
36+
37+
@Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class,
38+
description = "ID of the storage pool", since = "4.19")
39+
private Long storagePoolId;
40+
41+
@Override
42+
public Long getImageStoreId() {
43+
return imageStoreId;
44+
}
45+
46+
@Override
47+
public Long getStoragePoolId() {
48+
return storagePoolId;
49+
}
50+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.storage;
18+
19+
import com.cloud.event.EventTypes;
20+
import org.apache.cloudstack.api.APICommand;
21+
import org.apache.cloudstack.api.ApiConstants;
22+
import org.apache.cloudstack.api.BaseAsyncCmd;
23+
import org.apache.cloudstack.api.Parameter;
24+
import org.apache.cloudstack.api.response.ExtractResponse;
25+
import org.apache.cloudstack.api.response.ImageStoreResponse;
26+
import org.apache.cloudstack.context.CallContext;
27+
import org.apache.cloudstack.storage.browser.StorageBrowser;
28+
29+
import javax.inject.Inject;
30+
import java.nio.file.Path;
31+
32+
@APICommand(name = "downloadImageStoreObject", description = "Download object at a specified path on an image store.",
33+
responseObject = ExtractResponse.class, since = "4.19.0", requestHasSensitiveInfo = false,
34+
responseHasSensitiveInfo = false)
35+
public class DownloadImageStoreObjectCmd extends BaseAsyncCmd {
36+
37+
@Inject
38+
StorageBrowser storageBrowser;
39+
40+
/////////////////////////////////////////////////////
41+
//////////////// API parameters /////////////////////
42+
/////////////////////////////////////////////////////
43+
44+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, required = true,
45+
description = "id of the image store")
46+
private Long storeId;
47+
48+
@Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to download on image store")
49+
private String path;
50+
51+
/////////////////////////////////////////////////////
52+
/////////////////// Accessors ///////////////////////
53+
/////////////////////////////////////////////////////
54+
55+
public Long getStoreId() {
56+
return storeId;
57+
}
58+
59+
public String getPath() {
60+
if (path == null) {
61+
path = "/";
62+
}
63+
// We prepend "/" to path and normalize to prevent path traversal attacks
64+
return Path.of(String.format("/%s", path)).normalize().toString().substring(1);
65+
}
66+
67+
/////////////////////////////////////////////////////
68+
/////////////// API Implementation///////////////////
69+
/////////////////////////////////////////////////////
70+
71+
@Override
72+
public void execute() {
73+
ExtractResponse response = storageBrowser.downloadImageStoreObject(this);
74+
response.setResponseName(getCommandName());
75+
response.setObjectName(getCommandName());
76+
this.setResponseObject(response);
77+
}
78+
79+
/**
80+
* For commands the API framework needs to know the owner of the object being acted upon. This method is
81+
* used to determine that information.
82+
*
83+
* @return the id of the account that owns the object being acted upon
84+
*/
85+
@Override
86+
public long getEntityOwnerId() {
87+
return CallContext.current().getCallingAccount().getId();
88+
}
89+
90+
@Override
91+
public String getEventType() {
92+
return EventTypes.EVENT_IMAGE_STORE_OBJECT_DOWNLOAD;
93+
}
94+
95+
@Override
96+
public String getEventDescription() {
97+
return "Downloading object at path " + getPath() + " on image store " + getStoreId();
98+
}
99+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.storage;
18+
19+
import org.apache.cloudstack.api.APICommand;
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.BaseListCmd;
22+
import org.apache.cloudstack.api.Parameter;
23+
import org.apache.cloudstack.api.response.ImageStoreResponse;
24+
import org.apache.cloudstack.api.response.ListResponse;
25+
import org.apache.cloudstack.storage.browser.DataStoreObjectResponse;
26+
import org.apache.cloudstack.storage.browser.StorageBrowser;
27+
28+
import javax.inject.Inject;
29+
import java.nio.file.Path;
30+
31+
@APICommand(name = "listImageStoreObjects", description = "Lists objects at specified path on an image store.",
32+
responseObject = DataStoreObjectResponse.class, since = "4.19.0", requestHasSensitiveInfo = false,
33+
responseHasSensitiveInfo = false)
34+
public class ListImageStoreObjectsCmd extends BaseListCmd {
35+
36+
@Inject
37+
StorageBrowser storageBrowser;
38+
39+
/////////////////////////////////////////////////////
40+
//////////////// API parameters /////////////////////
41+
/////////////////////////////////////////////////////
42+
43+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, required = true,
44+
description = "id of the image store")
45+
private Long storeId;
46+
47+
@Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to list on image store")
48+
private String path;
49+
50+
/////////////////////////////////////////////////////
51+
/////////////////// Accessors ///////////////////////
52+
/////////////////////////////////////////////////////
53+
54+
public Long getStoreId() {
55+
return storeId;
56+
}
57+
58+
public String getPath() {
59+
if (path == null) {
60+
path = "/";
61+
}
62+
// We prepend "/" to path and normalize to prevent path traversal attacks
63+
return Path.of(String.format("/%s", path)).normalize().toString().substring(1);
64+
}
65+
66+
/////////////////////////////////////////////////////
67+
/////////////// API Implementation///////////////////
68+
/////////////////////////////////////////////////////
69+
70+
@Override
71+
public void execute() {
72+
ListResponse<DataStoreObjectResponse> response = storageBrowser.listImageStoreObjects(this);
73+
response.setResponseName(getCommandName());
74+
response.setObjectName(getCommandName());
75+
this.setResponseObject(response);
76+
}
77+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.storage;
18+
19+
import org.apache.cloudstack.api.APICommand;
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.BaseListCmd;
22+
import org.apache.cloudstack.api.Parameter;
23+
import org.apache.cloudstack.api.response.ListResponse;
24+
import org.apache.cloudstack.api.response.StoragePoolResponse;
25+
import org.apache.cloudstack.storage.browser.DataStoreObjectResponse;
26+
import org.apache.cloudstack.storage.browser.StorageBrowser;
27+
28+
import javax.inject.Inject;
29+
import java.nio.file.Path;
30+
31+
32+
@APICommand(name = "listStoragePoolObjects", description = "Lists objects at specified path on a storage pool.",
33+
responseObject = DataStoreObjectResponse.class, since = "4.19.0", requestHasSensitiveInfo = false,
34+
responseHasSensitiveInfo = false)
35+
public class ListStoragePoolObjectsCmd extends BaseListCmd {
36+
37+
@Inject
38+
StorageBrowser storageBrowser;
39+
40+
/////////////////////////////////////////////////////
41+
//////////////// API parameters /////////////////////
42+
/////////////////////////////////////////////////////
43+
44+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, required = true,
45+
description = "id of the storage pool")
46+
private Long storeId;
47+
48+
@Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to list on storage pool")
49+
private String path;
50+
51+
/////////////////////////////////////////////////////
52+
/////////////////// Accessors ///////////////////////
53+
/////////////////////////////////////////////////////
54+
55+
public Long getStoreId() {
56+
return storeId;
57+
}
58+
59+
public String getPath() {
60+
if (path == null) {
61+
path = "/";
62+
}
63+
// We prepend "/" to path and normalize to prevent path traversal attacks
64+
return Path.of(String.format("/%s", path)).normalize().toString().substring(1);
65+
}
66+
67+
/////////////////////////////////////////////////////
68+
/////////////// API Implementation///////////////////
69+
/////////////////////////////////////////////////////
70+
71+
@Override
72+
public void execute() {
73+
ListResponse<DataStoreObjectResponse> response = storageBrowser.listPrimaryStoreObjects(this);
74+
response.setResponseName(getCommandName());
75+
response.setObjectName(getCommandName());
76+
this.setResponseObject(response);
77+
}
78+
}

0 commit comments

Comments
 (0)