You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/05/24 11:36:51 UTC

[GitHub] dhlaluku closed pull request #2675: Remote Diganosis api

dhlaluku closed pull request #2675: Remote Diganosis api
URL: https://github.com/apache/cloudstack/pull/2675
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 504b2149837..d78e46f9e65 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -719,6 +719,8 @@
     public static final String LAST_ANNOTATED = "lastannotated";
     public static final String LDAP_DOMAIN = "ldapdomain";
 
+    public static final String DIAGNOSIS_TYPE = "diagnosistype";
+
     public enum HostDetails {
         all, capacity, events, stats, min;
     }
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmd.java
new file mode 100644
index 00000000000..84dc57da7e1
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmd.java
@@ -0,0 +1,114 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.api.command.admin.diagnosis;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.vm.VirtualMachine;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.RemoteDiagnosisResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.diangosis.RemoteDiagnosisService;
+
+import javax.inject.Inject;
+
+@APICommand(name = RemoteDiagnosisCmd.APINAME,
+        since = "4.11",
+        description = "Execute network utility command (ping/arping/tracert from a remote host",
+        responseHasSensitiveInfo = false,
+        requestHasSensitiveInfo = false,
+        responseObject = RemoteDiagnosisResponse.class,
+        entityType = VirtualMachine.class,
+        authorized = RoleType.Admin)
+public class RemoteDiagnosisCmd extends BaseCmd {
+
+    public static final String APINAME = "remoteDiganosis";
+
+    @Inject
+    private RemoteDiagnosisService diagnosisService;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name = ApiConstants.ID,
+            description = "The ID of the System VM instance",
+            required = true,
+            type = CommandType.UUID,
+            entityType = RemoteDiagnosisResponse.class)
+    private Long id;
+
+    @Parameter(name = ApiConstants.IP_ADDRESS,
+            description = "Destination IP address to ping",
+            required = true,
+            type = CommandType.STRING)
+    private String ipaddress;
+
+    @Parameter(name = ApiConstants.DIAGNOSIS_TYPE,
+            description = "The type of command to be executed inside the System VM instance, e.g. ping, tracert or arping",
+            type = CommandType.STRING)
+    private String diagnosisType;
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+    public Long getId() {
+        return id;
+    }
+
+    public String getIpaddress() {
+        return ipaddress;
+    }
+
+    public String getDiagnosisType() {
+        return diagnosisType;
+    }
+    /////////////////////////////////////////////////////
+    /////////////////// Implementation //////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = CallContext.current().getCallingAccount();
+        if (account != null){
+            return account.getId();
+        }
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+        RemoteDiagnosisResponse diagnosisResponse = diagnosisService.pingAddress(this);
+        diagnosisResponse.setObjectName("diagnosis");
+        diagnosisResponse.setResponseName(getCommandName());
+        this.setResponseObject(diagnosisResponse);
+    }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/RemoteDiagnosisResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/RemoteDiagnosisResponse.java
new file mode 100644
index 00000000000..1d6297c94b2
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/response/RemoteDiagnosisResponse.java
@@ -0,0 +1,53 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.cloud.vm.VirtualMachine;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+@EntityReference(value = VirtualMachine.class)
+public class RemoteDiagnosisResponse extends BaseResponse {
+    @SerializedName("details")
+    @Param(description = "Script executing result")
+    private String details;
+
+    @SerializedName("success")
+    @Param(description = "true if operation is executed successfully")
+    private Boolean success;
+
+    public String getDetails() {
+        return details;
+    }
+
+    public void setDetails(String details) {
+        this.details = details;
+    }
+
+    public Boolean getResult() {
+        return success;
+    }
+
+    public void setResult(Boolean success) {
+        this.success = success;
+    }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/diangosis/RemoteDiagnosisService.java b/api/src/main/java/org/apache/cloudstack/diangosis/RemoteDiagnosisService.java
new file mode 100644
index 00000000000..87ca312d2dc
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/diangosis/RemoteDiagnosisService.java
@@ -0,0 +1,30 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.diangosis;
+
+import com.cloud.exception.AgentUnavailableException;
+import org.apache.cloudstack.api.command.admin.diagnosis.RemoteDiagnosisCmd;
+import org.apache.cloudstack.api.response.RemoteDiagnosisResponse;
+
+public interface RemoteDiagnosisService {
+    RemoteDiagnosisResponse pingAddress(RemoteDiagnosisCmd cmd) throws AgentUnavailableException;
+
+
+}
diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmdTest.java
new file mode 100644
index 00000000000..5f2d421b93a
--- /dev/null
+++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/diagnosis/RemoteDiagnosisCmdTest.java
@@ -0,0 +1,34 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.api.command.admin.diagnosis;
+
+import org.junit.After;
+import org.junit.Before;
+
+public class RemoteDiagnosisCmdTest {
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java
index 838f0877918..39a2a04fab3 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java
@@ -69,4 +69,7 @@
 
     public static final String VR_CFG = "vr_cfg.sh";
 
+    // New script for use by remoteDiagnosis API
+    public static final String PING_REMOTELY = "ping_remotely.sh";
+
 }
\ No newline at end of file
diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index 0ffe8cc0ea2..e4b37e84dbf 100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@ -19,29 +19,6 @@
 
 package com.cloud.agent.resource.virtualnetwork;
 
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.channels.SocketChannel;
-import org.joda.time.Duration;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.UUID;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.ca.SetupCertificateAnswer;
-import org.apache.cloudstack.ca.SetupCertificateCommand;
-import org.apache.cloudstack.ca.SetupKeyStoreCommand;
-import org.apache.cloudstack.ca.SetupKeystoreAnswer;
-import org.apache.cloudstack.utils.security.KeyStoreUtils;
-import org.apache.log4j.Logger;
-
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.CheckRouterAnswer;
 import com.cloud.agent.api.CheckRouterCommand;
@@ -59,6 +36,29 @@
 import com.cloud.utils.ExecutionResult;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.cloudstack.ca.SetupCertificateAnswer;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+import org.apache.cloudstack.ca.SetupKeystoreAnswer;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisAnswer;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisCommand;
+import org.apache.cloudstack.utils.security.KeyStoreUtils;
+import org.apache.log4j.Logger;
+import org.joda.time.Duration;
+
+import javax.naming.ConfigurationException;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SocketChannel;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.UUID;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * VirtualNetworkResource controls and configures virtual networking
@@ -191,7 +191,9 @@ private Answer executeQueryCommand(NetworkElementCommand cmd) {
         } else if (cmd instanceof CheckS2SVpnConnectionsCommand) {
             return execute((CheckS2SVpnConnectionsCommand) cmd);
         } else if (cmd instanceof GetRouterAlertsCommand) {
-            return execute((GetRouterAlertsCommand)cmd);
+            return execute((GetRouterAlertsCommand) cmd);
+        } else if (cmd instanceof ExecuteDiagnosisCommand){
+            return execute((ExecuteDiagnosisCommand) cmd);
         } else {
             s_logger.error("Unknown query command in VirtualRoutingResource!");
             return Answer.createUnsupportedCommandAnswer(cmd);
@@ -292,6 +294,14 @@ private Answer execute(CheckRouterCommand cmd) {
         return new CheckRouterAnswer(cmd, result.getDetails(), true);
     }
 
+    private Answer execute(ExecuteDiagnosisCommand cmd){
+        final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.PING_REMOTELY, cmd.getArgs());
+        if (!result.isSuccess()){
+            return new ExecuteDiagnosisAnswer(cmd, false, "ExecuteDiagnosisCommand failed");
+        }
+        return new ExecuteDiagnosisAnswer(cmd, result.isSuccess(), result.getDetails());
+    }
+
     private Answer execute(GetDomRVersionCmd cmd) {
         final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VERSION, null);
         if (!result.isSuccess()) {
diff --git a/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisAnswer.java b/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisAnswer.java
new file mode 100644
index 00000000000..aba37ddf83b
--- /dev/null
+++ b/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisAnswer.java
@@ -0,0 +1,29 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.diagnosis;
+
+import com.cloud.agent.api.Answer;
+
+public class ExecuteDiagnosisAnswer extends Answer {
+    public ExecuteDiagnosisAnswer(ExecuteDiagnosisCommand cmd, boolean result, String details){
+        super(cmd, result, details);
+    }
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisCommand.java b/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisCommand.java
new file mode 100644
index 00000000000..ef0a4620004
--- /dev/null
+++ b/core/src/main/java/org/apache/cloudstack/diagnosis/ExecuteDiagnosisCommand.java
@@ -0,0 +1,43 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.diagnosis;
+
+import com.cloud.agent.api.routing.NetworkElementCommand;
+
+public class ExecuteDiagnosisCommand extends NetworkElementCommand {
+    private final Long ssvmId;
+    private final String pingDestination ;
+    private final String diagnosisType;
+
+    public ExecuteDiagnosisCommand(Long ssvmId, String pingDestination, String diagnosisType) {
+        this.ssvmId = ssvmId;
+        this.pingDestination = pingDestination;
+        this.diagnosisType = diagnosisType;
+    }
+
+    public String getArgs(){
+        return diagnosisType + " " + pingDestination;
+    }
+
+    @Override
+    public boolean isQuery() {
+        return true;
+    }
+}
diff --git a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManager.java b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManager.java
index df2703d0b08..8e1748d2f28 100644
--- a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManager.java
+++ b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManager.java
@@ -16,9 +16,6 @@
 // under the License.
 package com.cloud.agent.manager;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.CheckRouterAnswer;
 import com.cloud.agent.api.CheckRouterCommand;
@@ -56,6 +53,11 @@
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.Manager;
 import com.cloud.vm.VirtualMachine.PowerState;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisAnswer;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisCommand;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public interface MockVmManager extends Manager {
 
@@ -97,6 +99,8 @@
 
     CheckRouterAnswer checkRouter(CheckRouterCommand cmd);
 
+    ExecuteDiagnosisAnswer executeDiagnosis(ExecuteDiagnosisCommand cmd);
+
     Answer cleanupNetworkRules(CleanupNetworkRulesCmd cmd, SimulatorInfo info);
 
     Answer scaleVm(ScaleVmCommand cmd);
diff --git a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManagerImpl.java b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManagerImpl.java
index 6eaf09cad85..4b9edde23ce 100644
--- a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManagerImpl.java
@@ -16,19 +16,6 @@
 // under the License.
 package com.cloud.agent.manager;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.CheckRouterAnswer;
 import com.cloud.agent.api.CheckRouterCommand;
@@ -89,6 +76,19 @@
 import com.cloud.utils.db.TransactionLegacy;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.VirtualMachine.PowerState;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisAnswer;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisCommand;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 
 @Component
 public class MockVmManagerImpl extends ManagerBase implements MockVmManager {
@@ -273,6 +273,14 @@ public CheckRouterAnswer checkRouter(final CheckRouterCommand cmd) {
         }
     }
 
+    @Override
+    public ExecuteDiagnosisAnswer executeDiagnosis(ExecuteDiagnosisCommand cmd) {
+        final String router_name = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
+        final MockVm vm = _mockVmDao.findByVmName(router_name);
+
+        return new ExecuteDiagnosisAnswer(cmd, true, null);
+    }
+
     @Override
     public Map<String, PowerState> getVmStates(final String hostGuid) {
         TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
diff --git a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/SimulatorManagerImpl.java b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/SimulatorManagerImpl.java
index 729777312fb..88185fe7efa 100644
--- a/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/SimulatorManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/SimulatorManagerImpl.java
@@ -16,30 +16,6 @@
 // under the License.
 package com.cloud.agent.manager;
 
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import com.google.gson.Gson;
-import com.google.gson.stream.JsonReader;
-
-import org.apache.cloudstack.ca.SetupCertificateCommand;
-import org.apache.cloudstack.ca.SetupKeyStoreCommand;
-import org.apache.cloudstack.storage.command.DeleteCommand;
-import org.apache.cloudstack.storage.command.DownloadCommand;
-import org.apache.cloudstack.storage.command.DownloadProgressCommand;
-import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
-import org.apache.cloudstack.storage.command.UploadStatusCommand;
-
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.AttachIsoCommand;
 import com.cloud.agent.api.BackupSnapshotCommand;
@@ -138,6 +114,27 @@
 import com.cloud.utils.db.TransactionLegacy;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.VirtualMachine.PowerState;
+import com.google.gson.Gson;
+import com.google.gson.stream.JsonReader;
+import org.apache.cloudstack.ca.SetupCertificateCommand;
+import org.apache.cloudstack.ca.SetupKeyStoreCommand;
+import org.apache.cloudstack.diagnosis.ExecuteDiagnosisCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DownloadCommand;
+import org.apache.cloudstack.storage.command.DownloadProgressCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.command.UploadStatusCommand;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @Component
 public class SimulatorManagerImpl extends ManagerBase implements SimulatorManager, PluggableService {
@@ -363,7 +360,7 @@ public Answer simulate(final Command cmd, final String hostGuid) {
                 } else if (cmd instanceof DownloadProgressCommand) {
                     answer = _mockStorageMgr.DownloadProcess((DownloadProgressCommand)cmd);
                 } else if (cmd instanceof DownloadCommand) {
-                    answer = _mockStorageMgr.Download((DownloadCommand)cmd);
+                    answer = _mockStorageMgr.Download((DownloadCommand) cmd);
                 } else if (cmd instanceof GetStorageStatsCommand) {
                     answer = _mockStorageMgr.GetStorageStats((GetStorageStatsCommand)cmd);
                 } else if (cmd instanceof GetVolumeStatsCommand) {
@@ -391,7 +388,9 @@ public Answer simulate(final Command cmd, final String hostGuid) {
                 } else if (cmd instanceof GetVmStatsCommand) {
                     answer = _mockVmMgr.getVmStats((GetVmStatsCommand)cmd);
                 } else if (cmd instanceof CheckRouterCommand) {
-                    answer = _mockVmMgr.checkRouter((CheckRouterCommand)cmd);
+                    answer = _mockVmMgr.checkRouter((CheckRouterCommand) cmd);
+                }else if (cmd instanceof ExecuteDiagnosisCommand) {
+                    answer = _mockVmMgr.executeDiagnosis((ExecuteDiagnosisCommand)cmd);
                 } else if (cmd instanceof GetDomRVersionCmd) {
                     answer = _mockVmMgr.getDomRVersion((GetDomRVersionCmd)cmd);
                 } else if (cmd instanceof CopyVolumeCommand) {
diff --git a/server/src/main/java/org/apache/cloudstack/diagnosis/RemoteDiagnosisServiceImpl.java b/server/src/main/java/org/apache/cloudstack/diagnosis/RemoteDiagnosisServiceImpl.java
new file mode 100644
index 00000000000..cddac541c52
--- /dev/null
+++ b/server/src/main/java/org/apache/cloudstack/diagnosis/RemoteDiagnosisServiceImpl.java
@@ -0,0 +1,115 @@
+/*
+ * // Licensed to the Apache Software Foundation (ASF) under one
+ * // or more contributor license agreements.  See the NOTICE file
+ * // distributed with this work for additional information
+ * // regarding copyright ownership.  The ASF licenses this file
+ * // to you under the Apache License, Version 2.0 (the
+ * // "License"); you may not use this file except in compliance
+ * // with the License.  You may obtain a copy of the License at
+ * //
+ * //   http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing,
+ * // software distributed under the License is distributed on an
+ * // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * // KIND, either express or implied.  See the License for the
+ * // specific language governing permissions and limitations
+ * // under the License.
+ */
+
+package org.apache.cloudstack.diagnosis;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.network.router.RouterControlHelper;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.component.PluggableService;
+import com.cloud.vm.DomainRouterVO;
+import com.cloud.vm.dao.DomainRouterDao;
+import org.apache.cloudstack.api.command.admin.diagnosis.RemoteDiagnosisCmd;
+import org.apache.cloudstack.api.response.RemoteDiagnosisResponse;
+import org.apache.cloudstack.diangosis.RemoteDiagnosisService;
+import org.apache.log4j.Logger;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RemoteDiagnosisServiceImpl extends ManagerBase implements PluggableService, RemoteDiagnosisService {
+    private static final Logger s_logger = Logger.getLogger(RemoteDiagnosisServiceImpl.class);
+
+    @Inject
+    private DomainRouterDao domainRouterDao;
+    @Inject
+    private RouterControlHelper routerControlHelper;
+    @Inject
+    private AgentManager agentManager;
+    @Inject
+    private VirtualRouterDeployer vrDeployer;
+
+    @Override
+    public RemoteDiagnosisResponse pingAddress(final RemoteDiagnosisCmd cmd) throws AgentUnavailableException {
+        final Long routerId = cmd.getId();
+        final DomainRouterVO router = domainRouterDao.findById(routerId);
+
+        final Long hostId = router.getHostId();
+
+        // Verify parameter
+        if (router == null) {
+            throw new InvalidParameterValueException("Unable to find router by id " + routerId + ".");
+        }
+
+        final ExecuteDiagnosisCommand command = new ExecuteDiagnosisCommand(routerId,
+                cmd.getIpaddress(), cmd.getDiagnosisType());
+        command.setAccessDetail(NetworkElementCommand.ROUTER_IP, routerControlHelper.getRouterControlIp(router.getId()));
+        command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
+
+//        String routerAccessIP = command.getRouterAccessIp();
+//        String routerIp = command.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+//
+//        final ExecutionResult result = vrDeployer.executeInVR(routerIp, VRScripts.PING_REMOTELY, command.getArgs());
+//        ExecuteDiagnosisAnswer answer = new ExecuteDiagnosisAnswer(command, result.isSuccess(), result.getDetails());
+
+
+//        Answer origAnswer = agentManager.easySend(hostId, command);
+//        ExecuteDiagnosisAnswer answer = ((ExecuteDiagnosisAnswer) origAnswer);
+        Answer origAnswer;
+
+        try{
+            origAnswer = agentManager.send(hostId,command);
+        } catch (final OperationTimedoutException e) {
+            s_logger.warn("Timed Out", e);
+            throw new AgentUnavailableException("Unable to send commands to virtual router ", hostId, e);
+        }
+
+        ExecuteDiagnosisAnswer answer = null;
+        if (origAnswer instanceof ExecuteDiagnosisAnswer) {
+            answer = (ExecuteDiagnosisAnswer) origAnswer;
+        } else {
+            s_logger.warn("Unable to update router " + router.getHostName() + "status");
+        }
+
+        return createRemoteDiagnosisResponse(answer);
+    }
+
+    private static RemoteDiagnosisResponse createRemoteDiagnosisResponse(ExecuteDiagnosisAnswer answer){
+        RemoteDiagnosisResponse response = new RemoteDiagnosisResponse();
+        response.setResult(answer.getResult());
+        response.setDetails(answer.getDetails());
+        return response;
+    }
+
+    @Override
+    public List<Class<?>> getCommands() {
+        List<Class<?>> cmdList = new ArrayList<>();
+        cmdList.add(RemoteDiagnosisCmd.class);
+        return cmdList;
+    }
+
+
+}
diff --git a/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
index c7715a866c4..402c944d7cc 100644
--- a/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
+++ b/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml
@@ -298,4 +298,5 @@
     <bean id="indirectAgentLBService" class="org.apache.cloudstack.agent.lb.IndirectAgentLBServiceImpl" />
 
     <bean id="directDownloadManager" class="org.apache.cloudstack.direct.download.DirectDownloadManagerImpl" />
+    <bean id="remoteDiagnosisService" class="org.apache.cloudstack.diagnosis.RemoteDiagnosisServiceImpl" />
 </beans>
diff --git a/systemvm/debian/opt/cloud/bin/ping_remotely.sh b/systemvm/debian/opt/cloud/bin/ping_remotely.sh
new file mode 100755
index 00000000000..6c988b50649
--- /dev/null
+++ b/systemvm/debian/opt/cloud/bin/ping_remotely.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+$1 $2 -c 5
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index a025efefcbc..5ef7db27c86 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -190,7 +190,8 @@
     'CA': 'Certificate',
     'listElastistorInterface': 'Misc',
     'cloudian': 'Cloudian',
-    'Sioc' : 'Sioc'
+    'Sioc' : 'Sioc',
+    'remoteDiganosis': 'Virtual Machine'
     }
 
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services