Skip to content

Commit 0b247be

Browse files
author
Dingane Hlaluku
committed
* Complete API implementation
* Complete UI integration * Complete marvin test * Complete Secondary storage GC background task
1 parent a6f4d6d commit 0b247be

File tree

38 files changed

+2453
-61
lines changed

38 files changed

+2453
-61
lines changed

api/src/main/java/com/cloud/agent/api/to/DataObjectType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
package com.cloud.agent.api.to;
2020

2121
public enum DataObjectType {
22-
VOLUME, SNAPSHOT, TEMPLATE
22+
VOLUME, SNAPSHOT, TEMPLATE, TAR
2323
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ public class ApiConstants {
722722
public static final String STDERR = "stderr";
723723
public static final String EXITCODE = "exitcode";
724724
public static final String TARGET_ID = "targetid";
725+
public static final String FILES = "files";
725726
public static final String VOLUME_IDS = "volumeids";
726727

727728
public enum HostDetails {
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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.diagnostics;
18+
19+
import java.util.List;
20+
21+
import javax.inject.Inject;
22+
23+
import org.apache.cloudstack.acl.RoleType;
24+
import org.apache.cloudstack.api.APICommand;
25+
import org.apache.cloudstack.api.ApiArgValidator;
26+
import org.apache.cloudstack.api.ApiCommandJobType;
27+
import org.apache.cloudstack.api.ApiConstants;
28+
import org.apache.cloudstack.api.BaseAsyncCmd;
29+
import org.apache.cloudstack.api.BaseCmd;
30+
import org.apache.cloudstack.api.Parameter;
31+
import org.apache.cloudstack.api.ServerApiException;
32+
import org.apache.cloudstack.api.response.SystemVmResponse;
33+
import org.apache.cloudstack.api.response.diagnostics.GetDiagnosticsDataResponse;
34+
import org.apache.cloudstack.context.CallContext;
35+
import org.apache.cloudstack.diagnostics.DiagnosticsService;
36+
import org.apache.commons.lang3.StringUtils;
37+
import org.apache.commons.validator.routines.UrlValidator;
38+
import org.apache.log4j.Logger;
39+
40+
import com.cloud.event.EventTypes;
41+
import com.cloud.exception.InsufficientCapacityException;
42+
import com.cloud.exception.ResourceUnavailableException;
43+
import com.cloud.user.Account;
44+
import com.cloud.utils.exception.CloudRuntimeException;
45+
import com.cloud.vm.VirtualMachine;
46+
47+
@APICommand(name = GetDiagnosticsDataCmd.APINAME,
48+
responseObject = GetDiagnosticsDataResponse.class,
49+
entityType = {VirtualMachine.class},
50+
responseHasSensitiveInfo = false,
51+
requestHasSensitiveInfo = false,
52+
description = "Get diagnostics data files from system VMs",
53+
since = "4.12.0.0",
54+
authorized = {RoleType.Admin})
55+
public class GetDiagnosticsDataCmd extends BaseAsyncCmd {
56+
private static final Logger LOGGER = Logger.getLogger(GetDiagnosticsDataCmd.class);
57+
public static final String APINAME = "getDiagnosticsData";
58+
@Inject
59+
private DiagnosticsService diagnosticsService;
60+
/////////////////////////////////////////////////////
61+
//////////////// API parameters /////////////////////
62+
/////////////////////////////////////////////////////
63+
@Parameter(name = ApiConstants.TARGET_ID,
64+
type = BaseCmd.CommandType.UUID,
65+
entityType = SystemVmResponse.class,
66+
required = true,
67+
validations = {ApiArgValidator.PositiveNumber},
68+
description = "The ID of the system VM instance to retrieve diagnostics data files from")
69+
private Long id;
70+
71+
@Parameter(name = ApiConstants.FILES,
72+
type = BaseCmd.CommandType.LIST,
73+
collectionType = BaseCmd.CommandType.STRING,
74+
description = "A comma separated list of diagnostics data files to be retrieved. Defaults are taken from global settings if none has been provided.")
75+
private List<String> filesList;
76+
77+
78+
/////////////////////////////////////////////////////
79+
/////////////////// Accessors ///////////////////////
80+
/////////////////////////////////////////////////////
81+
public Long getId() {
82+
return id;
83+
}
84+
85+
public List<String> getFilesList() {
86+
return filesList;
87+
}
88+
89+
/////////////////////////////////////////////////////
90+
/////////////////// Implementation //////////////////
91+
/////////////////////////////////////////////////////
92+
@Override
93+
public String getCommandName() {
94+
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
95+
}
96+
97+
@Override
98+
public long getEntityOwnerId() {
99+
Account account = CallContext.current().getCallingAccount();
100+
if (account != null) {
101+
return account.getId();
102+
}
103+
return Account.ACCOUNT_ID_SYSTEM;
104+
}
105+
106+
@Override
107+
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException {
108+
try {
109+
String downloadUrl = diagnosticsService.getDiagnosticsDataCommand(this);
110+
UrlValidator urlValidator = new UrlValidator();
111+
if (StringUtils.isEmpty(downloadUrl)) {
112+
throw new CloudRuntimeException("Failed to retrieve diagnostics files");
113+
}
114+
GetDiagnosticsDataResponse response = new GetDiagnosticsDataResponse();
115+
if (urlValidator.isValid(downloadUrl)){
116+
response.setUrl(downloadUrl);
117+
response.setObjectName("diagnostics");
118+
response.setResponseName(getCommandName());
119+
this.setResponseObject(response);
120+
} else {
121+
throw new CloudRuntimeException("failed to generate valid download url: " + downloadUrl);
122+
}
123+
} catch (ServerApiException e) {
124+
throw new CloudRuntimeException("Internal exception caught while retrieving diagnostics files: ", e);
125+
}
126+
}
127+
128+
@Override
129+
public String getEventType() {
130+
VirtualMachine.Type vmType = _entityMgr.findById(VirtualMachine.class, getId()).getType();
131+
String eventType = "";
132+
switch (vmType) {
133+
case ConsoleProxy:
134+
eventType = EventTypes.EVENT_PROXY_DIAGNOSTICS;
135+
break;
136+
case SecondaryStorageVm:
137+
eventType = EventTypes.EVENT_SSVM_DIAGNOSTICS;
138+
break;
139+
case DomainRouter:
140+
eventType = EventTypes.EVENT_ROUTER_DIAGNOSTICS;
141+
break;
142+
}
143+
return eventType;
144+
}
145+
146+
@Override
147+
public String getEventDescription() {
148+
return "Getting diagnostics data files from system vm: " + this._uuidMgr.getUuid(VirtualMachine.class, getId());
149+
}
150+
151+
@Override
152+
public ApiCommandJobType getInstanceType() {
153+
return ApiCommandJobType.SystemVm;
154+
}
155+
156+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.response.diagnostics;
18+
19+
import com.cloud.serializer.Param;
20+
import com.cloud.vm.VirtualMachine;
21+
import com.google.gson.annotations.SerializedName;
22+
23+
import org.apache.cloudstack.api.ApiConstants;
24+
import org.apache.cloudstack.api.BaseResponse;
25+
import org.apache.cloudstack.api.EntityReference;
26+
27+
@EntityReference(value = VirtualMachine.class)
28+
public class GetDiagnosticsDataResponse extends BaseResponse {
29+
@SerializedName(ApiConstants.URL)
30+
@Param(description = "Storage URL to download retrieve diagnostics data files")
31+
private String url;
32+
33+
public String getUrl() {
34+
return url;
35+
}
36+
37+
public void setUrl(String url) {
38+
this.url = url;
39+
}
40+
}

api/src/main/java/org/apache/cloudstack/diagnostics/DiagnosticsService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
//
1919
package org.apache.cloudstack.diagnostics;
2020

21-
import org.apache.cloudstack.api.command.admin.diagnostics.RunDiagnosticsCmd;
22-
2321
import java.util.Map;
2422

23+
import org.apache.cloudstack.api.command.admin.diagnostics.GetDiagnosticsDataCmd;
24+
import org.apache.cloudstack.api.command.admin.diagnostics.RunDiagnosticsCmd;
25+
2526
public interface DiagnosticsService {
2627

2728
Map<String, String> runDiagnosticsCommand(RunDiagnosticsCmd cmd);
2829

30+
String getDiagnosticsDataCommand(GetDiagnosticsDataCmd getDiagnosticsDataCmd);
2931
}

core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,6 @@ public class VRScripts {
7070
public static final String VR_CFG = "vr_cfg.sh";
7171

7272
public static final String DIAGNOSTICS = "diagnostics.py";
73+
public static final String RETRIEVE_DIAGNOSTICS = "get_diagnostics_files.py";
74+
public static final String VR_FILE_CLEANUP = "cleanup.sh";
7375
}

core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
import java.net.InetSocketAddress;
2424
import java.nio.channels.SocketChannel;
2525

26+
import org.apache.cloudstack.diagnostics.DeleteFileInVrCommand;
2627
import org.apache.cloudstack.diagnostics.DiagnosticsAnswer;
2728
import org.apache.cloudstack.diagnostics.DiagnosticsCommand;
29+
import org.apache.cloudstack.diagnostics.PrepareFilesAnswer;
30+
import org.apache.cloudstack.diagnostics.PrepareFilesCommand;
2831
import org.joda.time.Duration;
2932
import java.util.ArrayList;
3033
import java.util.HashMap;
@@ -196,7 +199,11 @@ private Answer executeQueryCommand(NetworkElementCommand cmd) {
196199
} else if (cmd instanceof GetRouterAlertsCommand) {
197200
return execute((GetRouterAlertsCommand)cmd);
198201
} else if (cmd instanceof DiagnosticsCommand) {
199-
return execute((DiagnosticsCommand)cmd);
202+
return execute((DiagnosticsCommand) cmd);
203+
} else if (cmd instanceof PrepareFilesCommand) {
204+
return execute((PrepareFilesCommand) cmd);
205+
} else if (cmd instanceof DeleteFileInVrCommand) {
206+
return execute((DeleteFileInVrCommand)cmd);
200207
} else {
201208
s_logger.error("Unknown query command in VirtualRoutingResource!");
202209
return Answer.createUnsupportedCommandAnswer(cmd);
@@ -306,6 +313,24 @@ private Answer execute(DiagnosticsCommand cmd) {
306313
return new DiagnosticsAnswer(cmd, result.isSuccess(), result.getDetails());
307314
}
308315

316+
private Answer execute(PrepareFilesCommand cmd) {
317+
String fileList = String.join(" ", cmd.getFilesToRetrieveList());
318+
_eachTimeout = Duration.standardSeconds(cmd.getTimeout());
319+
final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.RETRIEVE_DIAGNOSTICS, fileList, _eachTimeout);
320+
if (result.isSuccess()) {
321+
return new PrepareFilesAnswer(cmd, true, result.getDetails());
322+
}
323+
return new PrepareFilesAnswer(cmd, false, result.getDetails());
324+
}
325+
326+
private Answer execute(DeleteFileInVrCommand cmd) {
327+
ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VR_FILE_CLEANUP, cmd.getFileName());
328+
if (result.isSuccess()) {
329+
return new Answer(cmd, result.isSuccess(), result.getDetails());
330+
}
331+
return new Answer(cmd, result.isSuccess(), result.getDetails());
332+
}
333+
309334
private Answer execute(GetDomRVersionCmd cmd) {
310335
final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VERSION, null);
311336
if (!result.isSuccess()) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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.diagnostics;
18+
19+
import com.cloud.agent.api.Answer;
20+
21+
public class CopyToSecondaryStorageAnswer extends Answer {
22+
23+
public CopyToSecondaryStorageAnswer(CopyToSecondaryStorageCommand command, boolean success, String details) {
24+
super(command, success, details);
25+
}
26+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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.diagnostics;
18+
19+
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
20+
21+
public class CopyToSecondaryStorageCommand extends StorageSubSystemCommand {
22+
private String secondaryStorageUrl;
23+
private String systemVmIp;
24+
private String fileName;
25+
26+
public CopyToSecondaryStorageCommand(String secondaryStorageUrl, String systemVmIp, String fileName) {
27+
this.secondaryStorageUrl = secondaryStorageUrl;
28+
this.systemVmIp = systemVmIp;
29+
this.fileName = fileName;
30+
}
31+
32+
public String getSecondaryStorageUrl() {
33+
return secondaryStorageUrl;
34+
}
35+
36+
public String getSystemVmIp() {
37+
return systemVmIp;
38+
}
39+
40+
public String getFileName() {
41+
return fileName;
42+
}
43+
44+
@Override
45+
public boolean executeInSequence() {
46+
return false;
47+
}
48+
49+
@Override
50+
public void setExecuteInSequence(boolean inSeq) {
51+
52+
}
53+
}

0 commit comments

Comments
 (0)