You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2013/10/28 07:05:11 UTC
[45/54] git commit: updated refs/heads/hyperv to a27899a
Implemented commands that are required for VR to bootup and Vm deployment to work
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/16422cbc
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/16422cbc
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/16422cbc
Branch: refs/heads/hyperv
Commit: 16422cbc0eaa9c0bb4e65e526dd341ec6e6c6a64
Parents: 33e19bf
Author: Rajesh Battala <ra...@citrix.com>
Authored: Fri Oct 11 13:42:42 2013 +0530
Committer: Rajesh Battala <ra...@citrix.com>
Committed: Fri Oct 11 16:43:32 2013 +0530
----------------------------------------------------------------------
.../resource/HypervDirectConnectResource.java | 690 ++++++++++++++++++-
1 file changed, 689 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/16422cbc/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
index e22f284..57a9dfd 100644
--- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
+++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java
@@ -16,11 +16,18 @@
// under the License.
package com.cloud.hypervisor.hyperv.resource;
+import java.io.File;
import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.channels.SocketChannel;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.UUID;
import javax.naming.ConfigurationException;
@@ -36,6 +43,10 @@ import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.GetDomRVersionAnswer;
+import com.cloud.agent.api.GetDomRVersionCmd;
+import com.cloud.agent.api.NetworkUsageAnswer;
+import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.StartupCommand;
@@ -43,12 +54,31 @@ import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.UnsupportedAnswer;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
+import com.cloud.agent.api.check.CheckSshAnswer;
+import com.cloud.agent.api.check.CheckSshCommand;
+import com.cloud.agent.api.routing.CreateIpAliasCommand;
+import com.cloud.agent.api.routing.DhcpEntryCommand;
+import com.cloud.agent.api.routing.DnsMasqConfigCommand;
+import com.cloud.agent.api.routing.IpAliasTO;
+import com.cloud.agent.api.routing.IpAssocAnswer;
+import com.cloud.agent.api.routing.IpAssocCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.routing.SavePasswordCommand;
+import com.cloud.agent.api.routing.VmDataCommand;
+import com.cloud.agent.api.to.DhcpTO;
+import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.Networks.RouterPrivateIpStrategy;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.serializer.GsonHelper;
+import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.utils.ssh.SshHelper;
+import com.cloud.vm.VirtualMachineName;
import com.google.gson.Gson;
/**
@@ -68,6 +98,11 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
private String _guid;
private String _agentIp;
private int _port = DEFAULT_AGENT_PORT;
+ protected final long _ops_timeout = 900000; // 15 minutes time out to time
+
+ protected final int _retry = 24;
+ protected final int _sleep = 10000;
+ protected final int DEFAULT_DOMR_SSHPORT = 3922;
private String _clusterGuid;
@@ -296,6 +331,8 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
// Using java.net.URI, see
// http://docs.oracle.com/javase/1.5.0/docs/api/java/net/URI.html
URI agentUri = null;
+ Class<? extends Command> clazz = cmd.getClass();
+ Answer answer = null;
try {
String cmdName = cmd.getClass().getName();
agentUri =
@@ -307,10 +344,36 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
s_logger.error(errMsg, e);
return null;
}
+
+ if (clazz == CheckSshCommand.class) {
+ answer = execute((CheckSshCommand) cmd);
+ } else if (clazz == GetDomRVersionCmd.class) {
+ answer = execute((GetDomRVersionCmd)cmd);
+ } else if (cmd instanceof NetworkUsageCommand) {
+ answer = execute((NetworkUsageCommand) cmd);
+ } else if (clazz == IpAssocCommand.class) {
+ answer = execute((IpAssocCommand) cmd);
+ } else if (clazz == DnsMasqConfigCommand.class) {
+ return execute((DnsMasqConfigCommand) cmd);
+ } else if (clazz == CreateIpAliasCommand.class) {
+ return execute((CreateIpAliasCommand) cmd);
+ } else if (clazz == DhcpEntryCommand.class) {
+ answer = execute((DhcpEntryCommand) cmd);
+ } else if (clazz == VmDataCommand.class) {
+ answer = execute((VmDataCommand) cmd);
+ } else if (clazz == SavePasswordCommand.class) {
+ answer = execute((SavePasswordCommand) cmd);
+ }
+
+ else {
+
+ // Else send the cmd to hyperv agent.
+
String ansStr = postHttpRequest(s_gson.toJson(cmd), agentUri);
if (ansStr == null) {
- return null;
+ // return null;
+ return Answer.createUnsupportedCommandAnswer(cmd);
}
// Only Answer instances are returned by remote agents.
// E.g. see Response.getAnswers()
@@ -320,9 +383,586 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
if (result.length > 0) {
return result[0];
}
+ }
+ return answer;
+ }
+
+ protected Answer execute(SavePasswordCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+
+ s_logger.info("Executing resource SavePasswordCommand. vmName: " + cmd.getVmName() + ", vmIp: " + cmd.getVmIpAddress() + ", password: "
+ + StringUtils.getMaskedPasswordForDisplay(cmd.getPassword()));
+ }
+
+ String controlIp = getRouterSshControlIp(cmd);
+ final String password = cmd.getPassword();
+ final String vmIpAddress = cmd.getVmIpAddress();
+
+ // Run save_password_to_domr.sh
+ String args = " -v " + vmIpAddress;
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + controlIp + ", /root/savepassword.sh " + args + " -p " + StringUtils.getMaskedPasswordForDisplay(cmd.getPassword()));
+ }
+
+ args += " -p " + password;
+
+
+ try {
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/root/savepassword.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("savepassword command on domain router " + controlIp + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "SavePassword failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("savepassword command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "SavePasswordCommand failed due to " + e;
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ return new Answer(cmd);
+ }
+
+
+
+ protected Answer execute(VmDataCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource VmDataCommand: " + s_gson.toJson(cmd));
+ }
+
+ String routerPrivateIpAddress = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ String controlIp = getRouterSshControlIp(cmd);
+
+ String vmIpAddress = cmd.getVmIpAddress();
+ List<String[]> vmData = cmd.getVmData();
+ String[] vmDataArgs = new String[vmData.size() * 2 + 4];
+ vmDataArgs[0] = "routerIP";
+ vmDataArgs[1] = routerPrivateIpAddress;
+ vmDataArgs[2] = "vmIP";
+ vmDataArgs[3] = vmIpAddress;
+ int i = 4;
+ for (String[] vmDataEntry : vmData) {
+ String folder = vmDataEntry[0];
+ String file = vmDataEntry[1];
+ String contents = (vmDataEntry[2] != null) ? vmDataEntry[2] : "none";
+
+ vmDataArgs[i] = folder + "," + file;
+ vmDataArgs[i + 1] = contents;
+ i += 2;
+ }
+
+ String content = encodeDataArgs(vmDataArgs);
+ String tmpFileName = UUID.randomUUID().toString();
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run vm_data command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", data: " + content);
+ }
+
+ try {
+ SshHelper.scpTo(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/tmp", content.getBytes(), tmpFileName, null);
+
+ try {
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
+ "/root/userdata.py " + tmpFileName);
+
+ if (!result.first()) {
+ s_logger.error("vm_data command on domain router " + controlIp + " failed. messge: " + result.second());
+ return new Answer(cmd, false, "VmDataCommand failed due to " + result.second());
+ }
+ } finally {
+
+ SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "rm /tmp/" + tmpFileName);
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("vm_data command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "VmDataCommand failed due to " + e;
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ return new Answer(cmd);
+ }
+
+
+ private String encodeDataArgs(String[] dataArgs) {
+ StringBuilder sb = new StringBuilder();
+
+ for (String arg : dataArgs) {
+ sb.append(arg);
+ sb.append("\n");
+ }
+
+ return sb.toString();
+ }
+
+
+ protected Answer execute(DhcpEntryCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource DhcpEntryCommand: " + s_gson.toJson(cmd));
+ }
+
+ // ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domr "/root/edithosts.sh $mac $ip $vm $dfltrt $ns $staticrt" >/dev/null
+
+ String args = " -m " + cmd.getVmMac();
+ if (cmd.getVmIpAddress() != null) {
+ args += " -4 " + cmd.getVmIpAddress();
+ }
+ args += " -h " + cmd.getVmName();
+
+ if (cmd.getDefaultRouter() != null) {
+ args += " -d " + cmd.getDefaultRouter();
+ }
+
+ if (cmd.getDefaultDns() != null) {
+ args += " -n " + cmd.getDefaultDns();
+ }
+
+ if (cmd.getStaticRoutes() != null) {
+ args += " -s " + cmd.getStaticRoutes();
+ }
+
+ if (cmd.getVmIp6Address() != null) {
+ args += " -6 " + cmd.getVmIp6Address();
+ args += " -u " + cmd.getDuid();
+ }
+
+ if (!cmd.isDefault()) {
+ args += " -N";
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args);
+ }
+
+ try {
+ String controlIp = getRouterSshControlIp(cmd);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
+ "/root/edithosts.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("dhcp_entry command on domR " + controlIp + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "DhcpEntry failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("dhcp_entry command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "DhcpEntryCommand failed due to " + e;
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ return new Answer(cmd);
+ }
+
+
+
+
+
+ protected Answer execute(final CreateIpAliasCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing createIpAlias command: " + s_gson.toJson(cmd));
+ }
+ cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ List<IpAliasTO> ipAliasTOs = cmd.getIpAliasList();
+ String args="";
+ for (IpAliasTO ipaliasto : ipAliasTOs) {
+ args = args + ipaliasto.getAlias_count()+":"+ipaliasto.getRouterip()+":"+ipaliasto.getNetmask()+"-";
+ }
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/createIpAlias " + args);
+ }
+
+ try {
+ String controlIp = getRouterSshControlIp(cmd);
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
+ "/root/createIpAlias.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("CreateIpAlias command on domr " + controlIp + " failed, message: " + result.second());
+
+ return new Answer(cmd, false, "createipAlias failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("createIpAlias command on domain router " + controlIp + " completed");
+ }
+
+ } catch (Throwable e) {
+ String msg = "createIpAlias failed due to " + e;
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ return new Answer(cmd);
+ }
+
+
+ protected Answer execute(final DnsMasqConfigCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing dnsmasqConfig command: " + s_gson.toJson(cmd));
+ }
+ String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ String controlIp = getRouterSshControlIp(cmd);
+
+ assert(controlIp != null);
+
+ List<DhcpTO> dhcpTos = cmd.getIps();
+ String args ="";
+ for(DhcpTO dhcpTo : dhcpTos) {
+ args = args + dhcpTo.getRouterIp()+":"+dhcpTo.getGateway()+":"+dhcpTo.getNetmask()+":"+dhcpTo.getStartIpOfSubnet()+"-";
+ }
+ //File keyFile = mgr.getSystemVMKeyFile();
+
+ try {
+ Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/root/dnsmasq.sh " + args);
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + routerIp + ", /root/dnsmasq.sh");
+ }
+
+ if (!result.first()) {
+ s_logger.error("Unable update dnsmasq config file");
+ return new Answer(cmd, false, "dnsmasq config update failed due to: " + result.second());
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("dnsmasq config command on domain router " + routerIp + " completed");
+ }
+ }catch (Throwable e) {
+ String msg = "Dnsmasqconfig command failed due to " + e.getMessage();
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ return new Answer(cmd);
+ }
+
+
+
+ protected Answer execute(IpAssocCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource IPAssocCommand: " + s_gson.toJson(cmd));
+ }
+
+ int i = 0;
+ String[] results = new String[cmd.getIpAddresses().length];
+
+ try {
+
+ IpAddressTO[] ips = cmd.getIpAddresses();
+ String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
+ String controlIp = getRouterSshControlIp(cmd);
+ for (IpAddressTO ip : ips) {
+ assignPublicIpAddress(routerName, controlIp, ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getBroadcastUri(), ip.getVlanGateway(), ip.getVlanNetmask(),ip.getVifMacAddress());
+ results[i++] = ip.getPublicIp() + " - success";
+ }
+
+ for (; i < cmd.getIpAddresses().length; i++) {
+ results[i++] = IpAssocAnswer.errorResult;
+ }
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: " + e.toString() + " will shortcut rest of IPAssoc commands", e);
+
+ for (; i < cmd.getIpAddresses().length; i++) {
+ results[i++] = IpAssocAnswer.errorResult;
+ }
+ }
+
+ return new IpAssocAnswer(cmd, results);
+ }
+
+ protected void assignPublicIpAddress(final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
+ final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress) throws Exception {
+
+ //String publicNeworkName = HypervisorHostHelper.getPublicNetworkNamePrefix(vlanId);
+ //Pair<Integer, VirtualDevice> publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
+
+ if (s_logger.isDebugEnabled()) {
+ //s_logger.debug("Find public NIC index, public network name: " + publicNeworkName + ", index: " + publicNicInfo.first());
+ }
+
+ boolean addVif = false;
+ boolean removeVif = false;
+ if (add ) { // && publicNicInfo.first().intValue() == -1) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Plug new NIC to associate" + privateIpAddress + " to " + publicIpAddress);
+ }
+
+ addVif = true;
+ } else if (!add && firstIP) {
+ removeVif = true;
+
+ if (s_logger.isDebugEnabled()) {
+ //s_logger.debug("Unplug NIC " + publicNicInfo.first());
+ }
+ }
+
+/* if (addVif) {
+ plugPublicNic(vmMo, vlanId, vifMacAddress);
+ publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
+ if (publicNicInfo.first().intValue() >= 0) {
+ networkUsage(privateIpAddress, "addVif", "eth" + publicNicInfo.first());
+ }
+ }
+*/
+/* if (publicNicInfo.first().intValue() < 0) {
+ String msg = "Failed to find DomR VIF to associate/disassociate IP with.";
+ s_logger.error(msg);
+ throw new InternalErrorException(msg);
+ }
+*/
+ String args = null;
+
+ if (add) {
+ args = " -A ";
+ } else {
+ args = " -D ";
+ }
+
+ if (sourceNat) {
+ args += " -s ";
+ }
+ if (firstIP) {
+ args += " -f ";
+ }
+ String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask));
+ args += " -l ";
+ args += publicIpAddress + "/" + cidrSize;
+
+ args += " -c ";
+ args += "eth" +"2"; // currently hardcoding to eth 2 (which is default public ipd)//publicNicInfo.first();
+
+ args += " -g ";
+ args += vlanGateway;
+
+ if (addVif) {
+ args += " -n ";
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Run command on domain router " + privateIpAddress + ", /opt/cloud/bin/ipassoc.sh " + args);
+ }
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(privateIpAddress, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/opt/cloud/bin/ipassoc.sh " + args);
+
+ if (!result.first()) {
+ s_logger.error("ipassoc command on domain router " + privateIpAddress + " failed. message: " + result.second());
+ throw new Exception("ipassoc failed due to " + result.second());
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("ipassoc command on domain router " + privateIpAddress + " completed");
+ }
+ }
+
+
+ protected Answer execute(GetDomRVersionCmd cmd) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Executing resource GetDomRVersionCmd: " + s_gson.toJson(cmd));
+ s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /opt/cloud/bin/get_template_version.sh ");
+ }
+
+ Pair<Boolean, String> result;
+ try {
+ String controlIp = getRouterSshControlIp(cmd);
+ result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
+ "/opt/cloud/bin/get_template_version.sh ");
+
+ if (!result.first()) {
+ s_logger.error("GetDomRVersionCmd on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " failed, message: " + result.second());
+
+ return new GetDomRVersionAnswer(cmd, "GetDomRVersionCmd failed due to " + result.second());
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("GetDomRVersionCmd on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
+ }
+ } catch (Throwable e) {
+ String msg = "GetDomRVersionCmd failed due to " + e;
+ s_logger.error(msg, e);
+ return new GetDomRVersionAnswer(cmd, msg);
+ }
+ String[] lines = result.second().split("&");
+ if (lines.length != 2) {
+ return new GetDomRVersionAnswer(cmd, result.second());
+ }
+ return new GetDomRVersionAnswer(cmd, result.second(), lines[0], lines[1]);
+ }
+
+
+ private static String getRouterSshControlIp(NetworkElementCommand cmd) {
+ String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+ String routerGuestIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP);
+ String zoneNetworkType = cmd.getAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE);
+
+ if(routerGuestIp != null && zoneNetworkType != null && NetworkType.valueOf(zoneNetworkType) == NetworkType.Basic) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("In Basic zone mode, use router's guest IP for SSH control. guest IP : " + routerGuestIp);
+
+ return routerGuestIp;
+ }
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Use router's private IP for SSH control. IP : " + routerIp);
+ return routerIp;
+ }
+
+ protected Answer execute(NetworkUsageCommand cmd) {
+/* if ( cmd.isForVpc() ) {
+ return VPCNetworkUsage(cmd);
+ }
+*/ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource NetworkUsageCommand "+ s_gson.toJson(cmd));
+ }
+ if(cmd.getOption()!=null && cmd.getOption().equals("create") ){
+ String result = networkUsage(cmd.getPrivateIP(), "create", null);
+ NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "true", 0L, 0L);
+ return answer;
+ }
+ long[] stats = getNetworkStats(cmd.getPrivateIP());
+
+ NetworkUsageAnswer answer = new NetworkUsageAnswer(cmd, "", stats[0], stats[1]);
+ return answer;
+ }
+ private long[] getNetworkStats(String privateIP) {
+ String result = networkUsage(privateIP, "get", null);
+ long[] stats = new long[2];
+ if (result != null) {
+ try {
+ String[] splitResult = result.split(":");
+ int i = 0;
+ while (i < splitResult.length - 1) {
+ stats[0] += (new Long(splitResult[i++])).longValue();
+ stats[1] += (new Long(splitResult[i++])).longValue();
+ }
+ } catch (Throwable e) {
+ s_logger.warn("Unable to parse return from script return of network usage command: " + e.toString(), e);
+ }
+ }
+ return stats;
+ }
+
+
+ protected CheckSshAnswer execute(CheckSshCommand cmd) {
+ String vmName = cmd.getName();
+ String privateIp = cmd.getIp();
+ int cmdPort = cmd.getPort();
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort);
+ }
+
+ try {
+ String result = connect(cmd.getName(), privateIp, cmdPort);
+ if (result != null) {
+ s_logger.error("Can not ping System vm " + vmName + "due to:" + result);
+ return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result);
+ }
+ } catch (Exception e) {
+ s_logger.error("Can not ping System vm " + vmName + "due to exception");
+ return new CheckSshAnswer(cmd, e);
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Ping command port succeeded for vm " + vmName);
+ }
+
+ if (VirtualMachineName.isValidRouterName(vmName)) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Execute network usage setup command on " + vmName);
+ }
+ networkUsage(privateIp, "create", null);
+ }
+
+ return new CheckSshAnswer(cmd);
+ }
+
+
+ protected String networkUsage(final String privateIpAddress, final String option, final String ethName) {
+ String args = null;
+ if (option.equals("get")) {
+ args = "-g";
+ } else if (option.equals("create")) {
+ args = "-c";
+ } else if (option.equals("reset")) {
+ args = "-r";
+ } else if (option.equals("addVif")) {
+ args = "-a";
+ args += ethName;
+ } else if (option.equals("deleteVif")) {
+ args = "-d";
+ args += ethName;
+ }
+
+ try {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Executing /opt/cloud/bin/netusage.sh " + args + " on DomR " + privateIpAddress);
+ }
+
+ Pair<Boolean, String> result = SshHelper.sshExecute(privateIpAddress, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/opt/cloud/bin/netusage.sh " + args);
+
+ if (!result.first()) {
+ return null;
+ }
+
+ return result.second();
+ } catch (Throwable e) {
+ s_logger.error("Unable to execute NetworkUsage command on DomR (" + privateIpAddress + "), domR may not be ready yet. failure due to "
+ + e);
+ }
+
return null;
}
+ private File getSystemVMPatchIsoFile() {
+ // locate systemvm.iso
+ URL url = this.getClass().getClassLoader().getResource("vms/systemvm.iso");
+ File isoFile = null;
+ if (url != null) {
+ isoFile = new File(url.getPath());
+ }
+
+ if(isoFile == null || !isoFile.exists()) {
+ isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso");
+ }
+
+ assert(isoFile != null);
+ if(!isoFile.exists()) {
+ s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString());
+ }
+ return isoFile;
+ }
+
+ public File getSystemVMKeyFile() {
+ URL url = this.getClass().getClassLoader().getResource("scripts/vm/systemvm/id_rsa.cloud");
+ File keyFile = null;
+ if ( url != null ){
+ keyFile = new File(url.getPath());
+ }
+ if (keyFile == null || !keyFile.exists()) {
+ keyFile = new File("/usr/share/cloudstack-common/scripts/vm/systemvm/id_rsa.cloud");
+ }
+ assert(keyFile != null);
+ if(!keyFile.exists()) {
+ s_logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString());
+ }
+ return keyFile;
+ }
+
+
public static String postHttpRequest(final String jsonCmd,
final URI agentUri) {
// Using Apache's HttpClient for HTTP POST
@@ -450,5 +1090,53 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
public void setRunLevel(final int level) {
// TODO Auto-generated method stub
}
+ protected String connect(final String vmName, final String ipAddress, final int port) {
+ long startTick = System.currentTimeMillis();
+
+ // wait until we have at least been waiting for _ops_timeout time or
+ // at least have tried _retry times, this is to coordinate with system
+ // VM patching/rebooting time that may need
+ int retry = _retry;
+ while (System.currentTimeMillis() - startTick <= _ops_timeout || --retry > 0) {
+ SocketChannel sch = null;
+ try {
+ s_logger.info("Trying to connect to " + ipAddress);
+ sch = SocketChannel.open();
+ sch.configureBlocking(true);
+ sch.socket().setSoTimeout(5000);
+
+ InetSocketAddress addr = new InetSocketAddress(ipAddress, port);
+ sch.connect(addr);
+ return null;
+ } catch (IOException e) {
+ s_logger.info("Could not connect to " + ipAddress + " due to " + e.toString());
+ if (e instanceof ConnectException) {
+ // if connection is refused because of VM is being started,
+ // we give it more sleep time
+ // to avoid running out of retry quota too quickly
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException ex) {
+ }
+ }
+ } finally {
+ if (sch != null) {
+ try {
+ sch.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ s_logger.info("Unable to logon to " + ipAddress);
+
+ return "Unable to connect";
+ }
}