PageRenderTime 285ms CodeModel.GetById 30ms RepoModel.GetById 2ms app.codeStats 2ms

/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java

https://github.com/jlk/CloudStack
Java | 6818 lines | 5779 code | 736 blank | 303 comment | 1444 complexity | 8c0408e176a7c9d46a5757d68f4fe9cc MD5 | raw file
Possible License(s): Apache-2.0
  1. // Copyright 2012 Citrix Systems, Inc. Licensed under the
  2. // Apache License, Version 2.0 (the "License"); you may not use this
  3. // file except in compliance with the License. Citrix Systems, Inc.
  4. // reserves all rights not expressly granted by the License.
  5. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. // Unless required by applicable law or agreed to in writing, software
  7. // distributed under the License is distributed on an "AS IS" BASIS,
  8. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. // See the License for the specific language governing permissions and
  10. // limitations under the License.
  11. //
  12. // Automatically generated by addcopyright.py at 04/03/2012
  13. package com.cloud.hypervisor.xen.resource;
  14. import java.io.BufferedReader;
  15. import java.io.File;
  16. import java.io.FileInputStream;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.io.InputStreamReader;
  20. import java.io.StringReader;
  21. import java.net.URI;
  22. import java.net.URISyntaxException;
  23. import java.net.URL;
  24. import java.net.URLConnection;
  25. import java.util.ArrayList;
  26. import java.util.Collections;
  27. import java.util.Date;
  28. import java.util.HashMap;
  29. import java.util.HashSet;
  30. import java.util.Iterator;
  31. import java.util.LinkedList;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Properties;
  35. import java.util.Queue;
  36. import java.util.Random;
  37. import java.util.Set;
  38. import java.util.UUID;
  39. import javax.ejb.Local;
  40. import javax.naming.ConfigurationException;
  41. import javax.xml.parsers.DocumentBuilderFactory;
  42. import org.apache.log4j.Logger;
  43. import org.apache.xmlrpc.XmlRpcException;
  44. import org.w3c.dom.Document;
  45. import org.w3c.dom.Node;
  46. import org.w3c.dom.NodeList;
  47. import org.xml.sax.InputSource;
  48. import com.cloud.agent.IAgentControl;
  49. import com.cloud.agent.api.Answer;
  50. import com.cloud.agent.api.AttachIsoCommand;
  51. import com.cloud.agent.api.AttachVolumeAnswer;
  52. import com.cloud.agent.api.AttachVolumeCommand;
  53. import com.cloud.agent.api.BackupSnapshotAnswer;
  54. import com.cloud.agent.api.BackupSnapshotCommand;
  55. import com.cloud.agent.api.BumpUpPriorityCommand;
  56. import com.cloud.agent.api.CheckHealthAnswer;
  57. import com.cloud.agent.api.CheckHealthCommand;
  58. import com.cloud.agent.api.CheckNetworkAnswer;
  59. import com.cloud.agent.api.CheckNetworkCommand;
  60. import com.cloud.agent.api.CheckOnHostAnswer;
  61. import com.cloud.agent.api.CheckOnHostCommand;
  62. import com.cloud.agent.api.CheckRouterAnswer;
  63. import com.cloud.agent.api.CheckRouterCommand;
  64. import com.cloud.agent.api.CheckVirtualMachineAnswer;
  65. import com.cloud.agent.api.CheckVirtualMachineCommand;
  66. import com.cloud.agent.api.CleanupNetworkRulesCmd;
  67. import com.cloud.agent.api.ClusterSyncAnswer;
  68. import com.cloud.agent.api.ClusterSyncCommand;
  69. import com.cloud.agent.api.Command;
  70. import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
  71. import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
  72. import com.cloud.agent.api.CreateStoragePoolCommand;
  73. import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
  74. import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
  75. import com.cloud.agent.api.DeleteStoragePoolCommand;
  76. import com.cloud.agent.api.GetDomRVersionAnswer;
  77. import com.cloud.agent.api.GetDomRVersionCmd;
  78. import com.cloud.agent.api.GetHostStatsAnswer;
  79. import com.cloud.agent.api.GetHostStatsCommand;
  80. import com.cloud.agent.api.GetStorageStatsAnswer;
  81. import com.cloud.agent.api.GetStorageStatsCommand;
  82. import com.cloud.agent.api.GetVmStatsAnswer;
  83. import com.cloud.agent.api.GetVmStatsCommand;
  84. import com.cloud.agent.api.GetVncPortAnswer;
  85. import com.cloud.agent.api.GetVncPortCommand;
  86. import com.cloud.agent.api.HostStatsEntry;
  87. import com.cloud.agent.api.MaintainAnswer;
  88. import com.cloud.agent.api.MaintainCommand;
  89. import com.cloud.agent.api.ManageSnapshotAnswer;
  90. import com.cloud.agent.api.ManageSnapshotCommand;
  91. import com.cloud.agent.api.MigrateAnswer;
  92. import com.cloud.agent.api.MigrateCommand;
  93. import com.cloud.agent.api.ModifySshKeysCommand;
  94. import com.cloud.agent.api.ModifyStoragePoolAnswer;
  95. import com.cloud.agent.api.ModifyStoragePoolCommand;
  96. import com.cloud.agent.api.NetworkRulesSystemVmCommand;
  97. import com.cloud.agent.api.PingCommand;
  98. import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
  99. import com.cloud.agent.api.PingRoutingWithOvsCommand;
  100. import com.cloud.agent.api.PingTestCommand;
  101. import com.cloud.agent.api.PoolEjectCommand;
  102. import com.cloud.agent.api.PrepareForMigrationAnswer;
  103. import com.cloud.agent.api.PrepareForMigrationCommand;
  104. import com.cloud.agent.api.ReadyAnswer;
  105. import com.cloud.agent.api.ReadyCommand;
  106. import com.cloud.agent.api.RebootAnswer;
  107. import com.cloud.agent.api.RebootCommand;
  108. import com.cloud.agent.api.RebootRouterCommand;
  109. import com.cloud.agent.api.SecurityGroupRuleAnswer;
  110. import com.cloud.agent.api.SecurityGroupRulesCmd;
  111. import com.cloud.agent.api.SetupAnswer;
  112. import com.cloud.agent.api.SetupCommand;
  113. import com.cloud.agent.api.StartAnswer;
  114. import com.cloud.agent.api.StartCommand;
  115. import com.cloud.agent.api.StartupCommand;
  116. import com.cloud.agent.api.StartupRoutingCommand;
  117. import com.cloud.agent.api.StartupStorageCommand;
  118. import com.cloud.agent.api.StopAnswer;
  119. import com.cloud.agent.api.StopCommand;
  120. import com.cloud.agent.api.StoragePoolInfo;
  121. import com.cloud.agent.api.UpdateHostPasswordCommand;
  122. import com.cloud.agent.api.UpgradeSnapshotCommand;
  123. import com.cloud.agent.api.VmStatsEntry;
  124. import com.cloud.agent.api.check.CheckSshAnswer;
  125. import com.cloud.agent.api.check.CheckSshCommand;
  126. import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
  127. import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
  128. import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
  129. import com.cloud.agent.api.routing.DhcpEntryCommand;
  130. import com.cloud.agent.api.routing.IpAssocAnswer;
  131. import com.cloud.agent.api.routing.IpAssocCommand;
  132. import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
  133. import com.cloud.agent.api.routing.NetworkElementCommand;
  134. import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
  135. import com.cloud.agent.api.routing.SavePasswordCommand;
  136. import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
  137. import com.cloud.agent.api.routing.SetFirewallRulesCommand;
  138. import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
  139. import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
  140. import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
  141. import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
  142. import com.cloud.agent.api.routing.VmDataCommand;
  143. import com.cloud.agent.api.routing.VpnUsersCfgCommand;
  144. import com.cloud.agent.api.storage.CopyVolumeAnswer;
  145. import com.cloud.agent.api.storage.CopyVolumeCommand;
  146. import com.cloud.agent.api.storage.CreateAnswer;
  147. import com.cloud.agent.api.storage.CreateCommand;
  148. import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
  149. import com.cloud.agent.api.storage.DestroyCommand;
  150. import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
  151. import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
  152. import com.cloud.agent.api.to.IpAddressTO;
  153. import com.cloud.agent.api.to.NicTO;
  154. import com.cloud.agent.api.to.PortForwardingRuleTO;
  155. import com.cloud.agent.api.to.StaticNatRuleTO;
  156. import com.cloud.agent.api.to.StorageFilerTO;
  157. import com.cloud.agent.api.to.SwiftTO;
  158. import com.cloud.agent.api.to.VirtualMachineTO;
  159. import com.cloud.agent.api.to.VolumeTO;
  160. import com.cloud.exception.InternalErrorException;
  161. import com.cloud.host.Host.Type;
  162. import com.cloud.hypervisor.Hypervisor.HypervisorType;
  163. import com.cloud.network.HAProxyConfigurator;
  164. import com.cloud.network.LoadBalancerConfigurator;
  165. import com.cloud.network.Networks;
  166. import com.cloud.network.Networks.BroadcastDomainType;
  167. import com.cloud.network.Networks.IsolationType;
  168. import com.cloud.network.Networks.TrafficType;
  169. import com.cloud.network.PhysicalNetworkSetupInfo;
  170. import com.cloud.network.ovs.OvsCreateGreTunnelAnswer;
  171. import com.cloud.network.ovs.OvsCreateGreTunnelCommand;
  172. import com.cloud.network.ovs.OvsCreateTunnelAnswer;
  173. import com.cloud.network.ovs.OvsCreateTunnelCommand;
  174. import com.cloud.network.ovs.OvsDeleteFlowCommand;
  175. import com.cloud.network.ovs.OvsDestroyTunnelCommand;
  176. import com.cloud.network.ovs.OvsSetTagAndFlowAnswer;
  177. import com.cloud.network.ovs.OvsSetTagAndFlowCommand;
  178. import com.cloud.resource.ServerResource;
  179. import com.cloud.resource.hypervisor.HypervisorResource;
  180. import com.cloud.storage.Storage;
  181. import com.cloud.storage.Storage.ImageFormat;
  182. import com.cloud.storage.Storage.StoragePoolType;
  183. import com.cloud.storage.Volume;
  184. import com.cloud.storage.VolumeVO;
  185. import com.cloud.storage.template.TemplateInfo;
  186. import com.cloud.template.VirtualMachineTemplate.BootloaderType;
  187. import com.cloud.utils.NumbersUtil;
  188. import com.cloud.utils.Pair;
  189. import com.cloud.utils.Ternary;
  190. import com.cloud.utils.exception.CloudRuntimeException;
  191. import com.cloud.utils.net.NetUtils;
  192. import com.cloud.vm.DiskProfile;
  193. import com.cloud.vm.VirtualMachine;
  194. import com.cloud.vm.VirtualMachine.State;
  195. import com.cloud.vm.VirtualMachineName;
  196. import com.trilead.ssh2.SCPClient;
  197. import com.xensource.xenapi.Bond;
  198. import com.xensource.xenapi.Connection;
  199. import com.xensource.xenapi.Console;
  200. import com.xensource.xenapi.Host;
  201. import com.xensource.xenapi.HostCpu;
  202. import com.xensource.xenapi.HostMetrics;
  203. import com.xensource.xenapi.Network;
  204. import com.xensource.xenapi.PBD;
  205. import com.xensource.xenapi.PIF;
  206. import com.xensource.xenapi.Pool;
  207. import com.xensource.xenapi.SR;
  208. import com.xensource.xenapi.Session;
  209. import com.xensource.xenapi.Task;
  210. import com.xensource.xenapi.Types;
  211. import com.xensource.xenapi.Types.BadServerResponse;
  212. import com.xensource.xenapi.Types.IpConfigurationMode;
  213. import com.xensource.xenapi.Types.VmPowerState;
  214. import com.xensource.xenapi.Types.XenAPIException;
  215. import com.xensource.xenapi.VBD;
  216. import com.xensource.xenapi.VDI;
  217. import com.xensource.xenapi.VIF;
  218. import com.xensource.xenapi.VLAN;
  219. import com.xensource.xenapi.VM;
  220. import com.xensource.xenapi.VMGuestMetrics;
  221. import com.xensource.xenapi.XenAPIObject;
  222. /**
  223. * CitrixResourceBase encapsulates the calls to the XenServer Xapi process
  224. * to perform the required functionalities for CloudStack.
  225. *
  226. * ==============> READ THIS <==============
  227. * Because the XenServer objects can expire when the session expires, we cannot
  228. * keep any of the actual XenServer objects in this class. The only
  229. * thing that is constant is the UUID of the XenServer objects but not the
  230. * objects themselves! This is very important before you do any changes in
  231. * this code here.
  232. *
  233. */
  234. @Local(value = ServerResource.class)
  235. public abstract class CitrixResourceBase implements ServerResource, HypervisorResource {
  236. private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class);
  237. protected static final XenServerConnectionPool _connPool = XenServerConnectionPool.getInstance();
  238. protected String _name;
  239. protected String _username;
  240. protected Queue<String> _password=new LinkedList<String>();
  241. protected final int _retry = 100;
  242. protected final int _sleep = 10000;
  243. protected long _dcId;
  244. protected String _pod;
  245. protected String _cluster;
  246. protected static final XenServerPoolVms s_vms = new XenServerPoolVms();
  247. protected String _privateNetworkName;
  248. protected String _linkLocalPrivateNetworkName;
  249. protected String _publicNetworkName;
  250. protected String _storageNetworkName1;
  251. protected String _storageNetworkName2;
  252. protected String _guestNetworkName;
  253. protected int _wait;
  254. protected int _migratewait;
  255. protected String _instance; //instance name (default is usually "VM")
  256. static final Random _rand = new Random(System.currentTimeMillis());
  257. protected IAgentControl _agentControl;
  258. final int _maxWeight = 256;
  259. protected int _heartbeatInterval = 60;
  260. protected final XsHost _host = new XsHost();
  261. // Guest and Host Performance Statistics
  262. protected String _consolidationFunction = "AVERAGE";
  263. protected int _pollingIntervalInSeconds = 60;
  264. //Hypervisor specific params with generic value, may need to be overridden for specific versions
  265. long _xs_memory_used = 128 * 1024 * 1024L; // xen hypervisor used 128 M
  266. double _xs_virtualization_factor = 63.0/64.0; // 1 - virtualization overhead
  267. protected boolean _canBridgeFirewall = false;
  268. protected boolean _isOvs = false;
  269. protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
  270. protected String _localGateway;
  271. public enum SRType {
  272. NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA, EXT;
  273. String _str;
  274. private SRType() {
  275. _str = super.toString().toLowerCase();
  276. }
  277. @Override
  278. public String toString() {
  279. return _str;
  280. }
  281. public boolean equals(String type) {
  282. return _str.equalsIgnoreCase(type);
  283. }
  284. }
  285. protected static HashMap<Types.VmPowerState, State> s_statesTable;
  286. static {
  287. s_statesTable = new HashMap<Types.VmPowerState, State>();
  288. s_statesTable.put(Types.VmPowerState.HALTED, State.Stopped);
  289. s_statesTable.put(Types.VmPowerState.PAUSED, State.Running);
  290. s_statesTable.put(Types.VmPowerState.RUNNING, State.Running);
  291. s_statesTable.put(Types.VmPowerState.SUSPENDED, State.Running);
  292. s_statesTable.put(Types.VmPowerState.UNRECOGNIZED, State.Unknown);
  293. }
  294. protected boolean cleanupHaltedVms(Connection conn) throws XenAPIException, XmlRpcException {
  295. Host host = Host.getByUuid(conn, _host.uuid);
  296. Map<VM, VM.Record> vms = VM.getAllRecords(conn);
  297. boolean success = true;
  298. for (Map.Entry<VM, VM.Record> entry : vms.entrySet()) {
  299. VM vm = entry.getKey();
  300. VM.Record vmRec = entry.getValue();
  301. if ( vmRec.isATemplate || vmRec.isControlDomain ) {
  302. continue;
  303. }
  304. if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host)) {
  305. try {
  306. vm.destroy(conn);
  307. } catch (Exception e) {
  308. s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to ", e);
  309. success = false;
  310. }
  311. }
  312. }
  313. return success;
  314. }
  315. protected boolean isRefNull(XenAPIObject object) {
  316. return (object == null || object.toWireString().equals("OpaqueRef:NULL") || object.toWireString().equals("<not in database>"));
  317. }
  318. @Override
  319. public void disconnected() {
  320. }
  321. protected boolean pingdomr(Connection conn, String host, String port) {
  322. String status;
  323. status = callHostPlugin(conn, "vmops", "pingdomr", "host", host, "port", port);
  324. if (status == null || status.isEmpty()) {
  325. return false;
  326. }
  327. return true;
  328. }
  329. protected boolean pingXenServer() {
  330. Session slaveSession = null;
  331. Connection slaveConn = null;
  332. try {
  333. URL slaveUrl = null;
  334. slaveUrl = _connPool.getURL(_host.ip);
  335. slaveConn = new Connection(slaveUrl, 10);
  336. slaveSession = _connPool.slaveLocalLoginWithPassword(slaveConn, _username, _password);
  337. return true;
  338. } catch (Exception e) {
  339. } finally {
  340. if( slaveSession != null ){
  341. try{
  342. Session.localLogout(slaveConn);
  343. } catch (Exception e) {
  344. }
  345. slaveConn.dispose();
  346. }
  347. }
  348. return false;
  349. }
  350. protected String logX(XenAPIObject obj, String msg) {
  351. return new StringBuilder("Host ").append(_host.ip).append(" ").append(obj.toWireString()).append(": ").append(msg).toString();
  352. }
  353. @Override
  354. public Answer executeRequest(Command cmd) {
  355. Class<? extends Command> clazz = cmd.getClass();
  356. if (clazz == CreateCommand.class) {
  357. return execute((CreateCommand) cmd);
  358. } else if (clazz == SetPortForwardingRulesCommand.class) {
  359. return execute((SetPortForwardingRulesCommand) cmd);
  360. } else if (clazz == SetStaticNatRulesCommand.class) {
  361. return execute((SetStaticNatRulesCommand) cmd);
  362. } else if (clazz == LoadBalancerConfigCommand.class) {
  363. return execute((LoadBalancerConfigCommand) cmd);
  364. } else if (clazz == IpAssocCommand.class) {
  365. return execute((IpAssocCommand) cmd);
  366. } else if (clazz == CheckConsoleProxyLoadCommand.class) {
  367. return execute((CheckConsoleProxyLoadCommand) cmd);
  368. } else if (clazz == WatchConsoleProxyLoadCommand.class) {
  369. return execute((WatchConsoleProxyLoadCommand) cmd);
  370. } else if (clazz == SavePasswordCommand.class) {
  371. return execute((SavePasswordCommand) cmd);
  372. } else if (clazz == DhcpEntryCommand.class) {
  373. return execute((DhcpEntryCommand) cmd);
  374. } else if (clazz == VmDataCommand.class) {
  375. return execute((VmDataCommand) cmd);
  376. } else if (clazz == ReadyCommand.class) {
  377. return execute((ReadyCommand) cmd);
  378. } else if (clazz == GetHostStatsCommand.class) {
  379. return execute((GetHostStatsCommand) cmd);
  380. } else if (clazz == GetVmStatsCommand.class) {
  381. return execute((GetVmStatsCommand) cmd);
  382. } else if (clazz == CheckHealthCommand.class) {
  383. return execute((CheckHealthCommand) cmd);
  384. } else if (clazz == StopCommand.class) {
  385. return execute((StopCommand) cmd);
  386. } else if (clazz == RebootRouterCommand.class) {
  387. return execute((RebootRouterCommand) cmd);
  388. } else if (clazz == RebootCommand.class) {
  389. return execute((RebootCommand) cmd);
  390. } else if (clazz == CheckVirtualMachineCommand.class) {
  391. return execute((CheckVirtualMachineCommand) cmd);
  392. } else if (clazz == PrepareForMigrationCommand.class) {
  393. return execute((PrepareForMigrationCommand) cmd);
  394. } else if (clazz == MigrateCommand.class) {
  395. return execute((MigrateCommand) cmd);
  396. } else if (clazz == DestroyCommand.class) {
  397. return execute((DestroyCommand) cmd);
  398. } else if (clazz == CreateStoragePoolCommand.class) {
  399. return execute((CreateStoragePoolCommand) cmd);
  400. } else if (clazz == ModifyStoragePoolCommand.class) {
  401. return execute((ModifyStoragePoolCommand) cmd);
  402. } else if (clazz == DeleteStoragePoolCommand.class) {
  403. return execute((DeleteStoragePoolCommand) cmd);
  404. } else if (clazz == CopyVolumeCommand.class) {
  405. return execute((CopyVolumeCommand) cmd);
  406. } else if (clazz == AttachVolumeCommand.class) {
  407. return execute((AttachVolumeCommand) cmd);
  408. } else if (clazz == AttachIsoCommand.class) {
  409. return execute((AttachIsoCommand) cmd);
  410. } else if (clazz == ManageSnapshotCommand.class) {
  411. return execute((ManageSnapshotCommand) cmd);
  412. } else if (clazz == BackupSnapshotCommand.class) {
  413. return execute((BackupSnapshotCommand) cmd);
  414. } else if (clazz == CreateVolumeFromSnapshotCommand.class) {
  415. return execute((CreateVolumeFromSnapshotCommand) cmd);
  416. } else if (clazz == CreatePrivateTemplateFromVolumeCommand.class) {
  417. return execute((CreatePrivateTemplateFromVolumeCommand) cmd);
  418. } else if (clazz == CreatePrivateTemplateFromSnapshotCommand.class) {
  419. return execute((CreatePrivateTemplateFromSnapshotCommand) cmd);
  420. } else if (clazz == UpgradeSnapshotCommand.class) {
  421. return execute((UpgradeSnapshotCommand) cmd);
  422. } else if (clazz == GetStorageStatsCommand.class) {
  423. return execute((GetStorageStatsCommand) cmd);
  424. } else if (clazz == PrimaryStorageDownloadCommand.class) {
  425. return execute((PrimaryStorageDownloadCommand) cmd);
  426. } else if (clazz == GetVncPortCommand.class) {
  427. return execute((GetVncPortCommand) cmd);
  428. } else if (clazz == SetupCommand.class) {
  429. return execute((SetupCommand) cmd);
  430. } else if (clazz == MaintainCommand.class) {
  431. return execute((MaintainCommand) cmd);
  432. } else if (clazz == PingTestCommand.class) {
  433. return execute((PingTestCommand) cmd);
  434. } else if (clazz == CheckOnHostCommand.class) {
  435. return execute((CheckOnHostCommand) cmd);
  436. } else if (clazz == ModifySshKeysCommand.class) {
  437. return execute((ModifySshKeysCommand) cmd);
  438. } else if (clazz == PoolEjectCommand.class) {
  439. return execute((PoolEjectCommand) cmd);
  440. } else if (clazz == StartCommand.class) {
  441. return execute((StartCommand)cmd);
  442. } else if (clazz == RemoteAccessVpnCfgCommand.class) {
  443. return execute((RemoteAccessVpnCfgCommand)cmd);
  444. } else if (clazz == VpnUsersCfgCommand.class) {
  445. return execute((VpnUsersCfgCommand)cmd);
  446. } else if (clazz == CheckSshCommand.class) {
  447. return execute((CheckSshCommand)cmd);
  448. } else if (clazz == SecurityGroupRulesCmd.class) {
  449. return execute((SecurityGroupRulesCmd) cmd);
  450. } else if (clazz == OvsCreateGreTunnelCommand.class) {
  451. return execute((OvsCreateGreTunnelCommand)cmd);
  452. } else if (clazz == OvsSetTagAndFlowCommand.class) {
  453. return execute((OvsSetTagAndFlowCommand)cmd);
  454. } else if (clazz == OvsDeleteFlowCommand.class) {
  455. return execute((OvsDeleteFlowCommand)cmd);
  456. } else if (clazz == CleanupNetworkRulesCmd.class){
  457. return execute((CleanupNetworkRulesCmd)cmd);
  458. } else if (clazz == NetworkRulesSystemVmCommand.class) {
  459. return execute((NetworkRulesSystemVmCommand)cmd);
  460. } else if (clazz == OvsCreateTunnelCommand.class) {
  461. return execute((OvsCreateTunnelCommand)cmd);
  462. } else if (clazz == OvsDestroyTunnelCommand.class) {
  463. return execute((OvsDestroyTunnelCommand)cmd);
  464. } else if (clazz == UpdateHostPasswordCommand.class) {
  465. return execute((UpdateHostPasswordCommand)cmd);
  466. } else if (cmd instanceof CheckRouterCommand) {
  467. return execute((CheckRouterCommand)cmd);
  468. } else if (cmd instanceof SetFirewallRulesCommand) {
  469. return execute((SetFirewallRulesCommand)cmd);
  470. } else if (cmd instanceof BumpUpPriorityCommand) {
  471. return execute((BumpUpPriorityCommand)cmd);
  472. } else if (cmd instanceof ClusterSyncCommand) {
  473. return execute((ClusterSyncCommand)cmd);
  474. } else if (cmd instanceof GetDomRVersionCmd) {
  475. return execute((GetDomRVersionCmd)cmd);
  476. } else if (clazz == CheckNetworkCommand.class) {
  477. return execute((CheckNetworkCommand) cmd);
  478. } else {
  479. return Answer.createUnsupportedCommandAnswer(cmd);
  480. }
  481. }
  482. protected XsLocalNetwork getNativeNetworkForTraffic(Connection conn, TrafficType type, String name) throws XenAPIException, XmlRpcException {
  483. if (name != null) {
  484. if (s_logger.isDebugEnabled()) {
  485. s_logger.debug("Looking for network named " + name);
  486. }
  487. return getNetworkByName(conn, name);
  488. }
  489. if (type == TrafficType.Guest) {
  490. return new XsLocalNetwork(Network.getByUuid(conn, _host.guestNetwork), null, PIF.getByUuid(conn, _host.guestPif), null);
  491. } else if (type == TrafficType.Control) {
  492. setupLinkLocalNetwork(conn);
  493. return new XsLocalNetwork(Network.getByUuid(conn, _host.linkLocalNetwork));
  494. } else if (type == TrafficType.Management) {
  495. return new XsLocalNetwork(Network.getByUuid(conn, _host.privateNetwork), null, PIF.getByUuid(conn, _host.privatePif), null);
  496. } else if (type == TrafficType.Public) {
  497. return new XsLocalNetwork(Network.getByUuid(conn, _host.publicNetwork), null, PIF.getByUuid(conn, _host.publicPif), null);
  498. } else if (type == TrafficType.Storage) {
  499. return new XsLocalNetwork(Network.getByUuid(conn, _host.storageNetwork1), null, PIF.getByUuid(conn, _host.storagePif1), null);
  500. }
  501. throw new CloudRuntimeException("Unsupported network type: " + type);
  502. }
  503. /**
  504. * This is a tricky to create network in xenserver.
  505. * if you create a network then create bridge by brctl or openvswitch yourself,
  506. * then you will get an expection that is "REQUIRED_NETWROK" when you start a
  507. * vm with this network. The soultion is, create a vif of dom0 and plug it in
  508. * network, xenserver will create the bridge on behalf of you
  509. * @throws XmlRpcException
  510. * @throws XenAPIException
  511. */
  512. private void enableXenServerNetwork(Connection conn, Network nw,
  513. String vifNameLabel, String networkDesc) throws XenAPIException, XmlRpcException {
  514. /* Make sure there is a physical bridge on this network */
  515. VIF dom0vif = null;
  516. Pair<VM, VM.Record> vm = getControlDomain(conn);
  517. VM dom0 = vm.first();
  518. s_logger.debug("Create a vif on dom0 for " + networkDesc);
  519. VIF.Record vifr = new VIF.Record();
  520. vifr.VM = dom0;
  521. vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0);
  522. if (vifr.device == null) {
  523. s_logger.debug("Failed to create " + networkDesc + ", no vif available");
  524. return;
  525. }
  526. Map<String, String> config = new HashMap<String, String>();
  527. config.put("nameLabel", vifNameLabel);
  528. vifr.otherConfig = config;
  529. vifr.MAC = "FE:FF:FF:FF:FF:FF";
  530. vifr.network = nw;
  531. dom0vif = VIF.create(conn, vifr);
  532. dom0vif.plug(conn);
  533. dom0vif.unplug(conn);
  534. synchronized(_tmpDom0Vif) {
  535. _tmpDom0Vif.add(dom0vif);
  536. }
  537. }
  538. private synchronized Network setupvSwitchNetwork(Connection conn) {
  539. try {
  540. if (_host.vswitchNetwork == null) {
  541. Network vswitchNw = null;
  542. Network.Record rec = new Network.Record();
  543. String nwName = Networks.BroadcastScheme.VSwitch.toString();
  544. Set<Network> networks = Network.getByNameLabel(conn, nwName);
  545. if (networks.size() == 0) {
  546. rec.nameDescription = "vswitch network for " + nwName;
  547. rec.nameLabel = nwName;
  548. vswitchNw = Network.create(conn, rec);
  549. } else {
  550. vswitchNw = networks.iterator().next();
  551. }
  552. enableXenServerNetwork(conn, vswitchNw, "vswitch", "vswicth network");
  553. _host.vswitchNetwork = vswitchNw;
  554. }
  555. return _host.vswitchNetwork;
  556. } catch (Exception e) {
  557. e.printStackTrace();
  558. }
  559. return null;
  560. }
  561. private synchronized Network createTunnelNetwork(Connection conn, long account) {
  562. try {
  563. String nwName = "OVSTunnel" + account;
  564. Network nw = null;
  565. Network.Record rec = new Network.Record();
  566. Set<Network> networks = Network.getByNameLabel(conn, nwName);
  567. if (networks.size() == 0) {
  568. rec.nameDescription = "tunnel network for account " + account;
  569. rec.nameLabel = nwName;
  570. nw = Network.create(conn, rec);
  571. } else {
  572. nw = networks.iterator().next();
  573. }
  574. enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + account);
  575. return nw;
  576. } catch (Exception e) {
  577. s_logger.warn("create tunnel network failed", e);
  578. return null;
  579. }
  580. }
  581. protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException {
  582. String name = nic.getName();
  583. XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name);
  584. if (network == null) {
  585. s_logger.error("Network is not configured on the backend for nic " + nic.toString());
  586. throw new CloudRuntimeException("Network for the backend is not configured correctly for network broadcast domain: " + nic.getBroadcastUri());
  587. }
  588. if (nic.getBroadcastUri() != null && nic.getBroadcastUri().toString().contains("untagged")) {
  589. return network.getNetwork();
  590. } else if (nic.getBroadcastType() == BroadcastDomainType.Vlan) {
  591. URI broadcastUri = nic.getBroadcastUri();
  592. assert broadcastUri.getScheme().equals(BroadcastDomainType.Vlan.scheme());
  593. long vlan = Long.parseLong(broadcastUri.getHost());
  594. return enableVlanNetwork(conn, vlan, network);
  595. } else if (nic.getBroadcastType() == BroadcastDomainType.Native || nic.getBroadcastType() == BroadcastDomainType.LinkLocal) {
  596. return network.getNetwork();
  597. } else if (nic.getBroadcastType() == BroadcastDomainType.Vswitch) {
  598. String broadcastUri = nic.getBroadcastUri().toString();
  599. String header = broadcastUri.substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length());
  600. if (header.startsWith("vlan")) {
  601. _isOvs = true;
  602. return setupvSwitchNetwork(conn);
  603. } else {
  604. long account = Long.parseLong(nic.getBroadcastUri().getHost());
  605. return createTunnelNetwork(conn, account);
  606. }
  607. } else if (nic.getBroadcastType() == BroadcastDomainType.Storage) {
  608. URI broadcastUri = nic.getBroadcastUri();
  609. if (broadcastUri == null) {
  610. return network.getNetwork();
  611. } else {
  612. long vlan = Long.parseLong(broadcastUri.getHost());
  613. return enableVlanNetwork(conn, vlan, network);
  614. }
  615. }
  616. throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri());
  617. }
  618. protected VIF createVif(Connection conn, String vmName, VM vm, NicTO nic) throws XmlRpcException, XenAPIException {
  619. if (s_logger.isDebugEnabled()) {
  620. s_logger.debug("Creating VIF for " + vmName + " on nic " + nic);
  621. }
  622. VIF.Record vifr = new VIF.Record();
  623. vifr.VM = vm;
  624. vifr.device = Integer.toString(nic.getDeviceId());
  625. vifr.MAC = nic.getMac();
  626. vifr.network = getNetwork(conn, nic);
  627. if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) {
  628. vifr.qosAlgorithmType = "ratelimit";
  629. vifr.qosAlgorithmParams = new HashMap<String, String>();
  630. // convert mbs to kilobyte per second
  631. vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 128));
  632. }
  633. VIF vif = VIF.create(conn, vifr);
  634. if (s_logger.isDebugEnabled()) {
  635. vifr = vif.getRecord(conn);
  636. s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId());
  637. }
  638. return vif;
  639. }
  640. protected void prepareISO(Connection conn, String vmName) throws XmlRpcException, XenAPIException {
  641. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  642. if( vms == null || vms.size() != 1) {
  643. throw new CloudRuntimeException("There are " + ((vms == null) ? "0" : vms.size()) + " VMs named " + vmName);
  644. }
  645. VM vm = vms.iterator().next();
  646. Set<VBD> vbds = vm.getVBDs(conn);
  647. for ( VBD vbd : vbds ) {
  648. VBD.Record vbdr = vbd.getRecord(conn);
  649. if ( vbdr.type == Types.VbdType.CD && vbdr.empty == false ) {
  650. VDI vdi = vbdr.VDI;
  651. SR sr = vdi.getSR(conn);
  652. Set<PBD> pbds = sr.getPBDs(conn);
  653. if( pbds == null ) {
  654. throw new CloudRuntimeException("There is no pbd for sr " + sr);
  655. }
  656. for ( PBD pbd : pbds ) {
  657. PBD.Record pbdr = pbd.getRecord(conn);
  658. if ( pbdr.host.getUuid(conn).equals(_host.uuid)) {
  659. return;
  660. }
  661. }
  662. sr.setShared(conn, true);
  663. Host host = Host.getByUuid(conn, _host.uuid);
  664. PBD.Record pbdr = pbds.iterator().next().getRecord(conn);
  665. pbdr.host = host;
  666. pbdr.uuid = "";
  667. PBD pbd = PBD.create(conn, pbdr);
  668. pbdPlug(conn, pbd, pbd.getUuid(conn));
  669. break;
  670. }
  671. }
  672. }
  673. protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException {
  674. if (volume.getType() == Volume.Type.ISO) {
  675. String isopath = volume.getPath();
  676. if (isopath == null) {
  677. return null;
  678. }
  679. int index = isopath.lastIndexOf("/");
  680. String mountpoint = isopath.substring(0, index);
  681. URI uri;
  682. try {
  683. uri = new URI(mountpoint);
  684. } catch (URISyntaxException e) {
  685. throw new CloudRuntimeException("Incorrect uri " + mountpoint, e);
  686. }
  687. SR isoSr = createIsoSRbyURI(conn, uri, vmName, false);
  688. String isoname = isopath.substring(index + 1);
  689. VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr);
  690. if (isoVdi == null) {
  691. throw new CloudRuntimeException("Unable to find ISO " + volume.getPath());
  692. }
  693. return isoVdi;
  694. } else {
  695. return VDI.getByUuid(conn, volume.getPath());
  696. }
  697. }
  698. protected VBD createVbd(Connection conn, VolumeTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
  699. Volume.Type type = volume.getType();
  700. VDI vdi = mount(conn, vmName, volume);
  701. VBD.Record vbdr = new VBD.Record();
  702. vbdr.VM = vm;
  703. if (vdi != null) {
  704. vbdr.VDI = vdi;
  705. } else {
  706. vbdr.empty = true;
  707. }
  708. if (type == Volume.Type.ROOT && bootLoaderType == BootloaderType.PyGrub) {
  709. vbdr.bootable = true;
  710. }else if(type == Volume.Type.ISO && bootLoaderType == BootloaderType.CD) {
  711. vbdr.bootable = true;
  712. }
  713. vbdr.userdevice = Long.toString(volume.getDeviceId());
  714. if (volume.getType() == Volume.Type.ISO) {
  715. vbdr.mode = Types.VbdMode.RO;
  716. vbdr.type = Types.VbdType.CD;
  717. } else if (volume.getType() == Volume.Type.ROOT) {
  718. vbdr.mode = Types.VbdMode.RW;
  719. vbdr.type = Types.VbdType.DISK;
  720. vbdr.unpluggable = false;
  721. } else {
  722. vbdr.mode = Types.VbdMode.RW;
  723. vbdr.type = Types.VbdType.DISK;
  724. vbdr.unpluggable = true;
  725. }
  726. VBD vbd = VBD.create(conn, vbdr);
  727. if (s_logger.isDebugEnabled()) {
  728. s_logger.debug("VBD " + vbd.getUuid(conn) + " created for " + volume);
  729. }
  730. return vbd;
  731. }
  732. protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException {
  733. String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD);
  734. if ( guestOsTypeName == null ) {
  735. String msg = " Hypervisor " + this.getClass().getName() + " doesn't support guest OS type " + vmSpec.getOs()
  736. + ". you can choose 'Other install media' to run it as HVM";
  737. s_logger.warn(msg);
  738. throw new CloudRuntimeException(msg);
  739. }
  740. Set<VM> templates = VM.getByNameLabel(conn, guestOsTypeName);
  741. assert templates.size() == 1 : "Should only have 1 template but found " + templates.size();
  742. VM template = templates.iterator().next();
  743. VM vm = template.createClone(conn, vmSpec.getName());
  744. VM.Record vmr = vm.getRecord(conn);
  745. if (s_logger.isDebugEnabled()) {
  746. s_logger.debug("Created VM " + vmr.uuid + " for " + vmSpec.getName());
  747. }
  748. for (Console console : vmr.consoles) {
  749. console.destroy(conn);
  750. }
  751. vm.setIsATemplate(conn, false);
  752. vm.setAffinity(conn, host);
  753. vm.removeFromOtherConfig(conn, "disks");
  754. vm.setNameLabel(conn, vmSpec.getName());
  755. setMemory(conn, vm, vmSpec.getMinRam());
  756. vm.setVCPUsMax(conn, (long)vmSpec.getCpus());
  757. vm.setVCPUsAtStartup(conn, (long)vmSpec.getCpus());
  758. Map<String, String> vcpuParams = new HashMap<String, String>();
  759. Integer speed = vmSpec.getSpeed();
  760. if (speed != null) {
  761. int cpuWeight = _maxWeight; //cpu_weight
  762. int utilization = 0; // max CPU cap, default is unlimited
  763. // weight based allocation
  764. cpuWeight = (int)((speed*0.99) / _host.speed * _maxWeight);
  765. if (cpuWeight > _maxWeight) {
  766. cpuWeight = _maxWeight;
  767. }
  768. if (vmSpec.getLimitCpuUse()) {
  769. utilization = (int)((speed*0.99) / _host.speed * 100);
  770. }
  771. vcpuParams.put("weight", Integer.toString(cpuWeight));
  772. vcpuParams.put("cap", Integer.toString(utilization));
  773. }
  774. if (vcpuParams.size() > 0) {
  775. vm.setVCPUsParams(conn, vcpuParams);
  776. }
  777. vm.setActionsAfterCrash(conn, Types.OnCrashBehaviour.DESTROY);
  778. vm.setActionsAfterShutdown(conn, Types.OnNormalExit.DESTROY);
  779. String bootArgs = vmSpec.getBootArgs();
  780. if (bootArgs != null && bootArgs.length() > 0) {
  781. String pvargs = vm.getPVArgs(conn);
  782. pvargs = pvargs + vmSpec.getBootArgs().replaceAll(" ", "%");
  783. if (s_logger.isDebugEnabled()) {
  784. s_logger.debug("PV args are " + pvargs);
  785. }
  786. vm.setPVArgs(conn, pvargs);
  787. }
  788. if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
  789. if (vmSpec.getBootloader() == BootloaderType.CD) {
  790. VolumeTO [] disks = vmSpec.getDisks();
  791. for (VolumeTO disk : disks) {
  792. if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
  793. String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
  794. if (!isoGuestOsName.equals(guestOsTypeName)) {
  795. vmSpec.setBootloader(BootloaderType.PyGrub);
  796. }
  797. }
  798. }
  799. }
  800. if (vmSpec.getBootloader() == BootloaderType.CD) {
  801. vm.setPVBootloader(conn, "eliloader");
  802. Map<String, String> otherConfig = vm.getOtherConfig(conn);
  803. if ( ! vm.getOtherConfig(conn).containsKey("install-repository") ) {
  804. otherConfig.put( "install-repository", "cdrom");
  805. }
  806. vm.setOtherConfig(conn, otherConfig);
  807. } else if (vmSpec.getBootloader() == BootloaderType.PyGrub ){
  808. vm.setPVBootloader(conn, "pygrub");
  809. } else {
  810. vm.destroy(conn);
  811. throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader());
  812. }
  813. }
  814. return vm;
  815. }
  816. protected String handleVmStartFailure(Connection conn, String vmName, VM vm, String message, Throwable th) {
  817. String msg = "Unable to start " + vmName + " due to " + message;
  818. s_logger.warn(msg, th);
  819. if (vm == null) {
  820. return msg;
  821. }
  822. try {
  823. VM.Record vmr = vm.getRecord(conn);
  824. List<Network> networks = new ArrayList<Network>();
  825. for (VIF vif : vmr.VIFs) {
  826. try {
  827. VIF.Record rec = vif.getRecord(conn);
  828. networks.add(rec.network);
  829. } catch (Exception e) {
  830. s_logger.warn("Unable to cleanup VIF", e);
  831. }
  832. }
  833. if (vmr.powerState == VmPowerState.RUNNING) {
  834. try {
  835. vm.hardShutdown(conn);
  836. } catch (Exception e) {
  837. s_logger.warn("VM hardshutdown failed due to ", e);
  838. }
  839. }
  840. if (vm.getPowerState(conn) == VmPowerState.HALTED) {
  841. try {
  842. vm.destroy(conn);
  843. } catch (Exception e) {
  844. s_logger.warn("VM destroy failed due to ", e);
  845. }
  846. }
  847. for (VBD vbd : vmr.VBDs) {
  848. try {
  849. vbd.unplug(conn);
  850. vbd.destroy(conn);
  851. } catch (Exception e) {
  852. s_logger.warn("Unable to clean up VBD due to ", e);
  853. }
  854. }
  855. for (VIF vif : vmr.VIFs) {
  856. try {
  857. vif.unplug(conn);
  858. vif.destroy(conn);
  859. } catch (Exception e) {
  860. s_logger.warn("Unable to cleanup VIF", e);
  861. }
  862. }
  863. for (Network network : networks) {
  864. if (network.getNameLabel(conn).startsWith("VLAN")) {
  865. disableVlanNetwork(conn, network);
  866. }
  867. }
  868. } catch (Exception e) {
  869. s_logger.warn("VM getRecord failed due to ", e);
  870. }
  871. return msg;
  872. }
  873. protected VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException {
  874. if( _host.systemvmisouuid == null ) {
  875. Set<SR> srs = SR.getByNameLabel(conn, "XenServer Tools");
  876. if( srs.size() != 1 ) {
  877. throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools");
  878. }
  879. SR sr = srs.iterator().next();
  880. sr.scan(conn);
  881. SR.Record srr = sr.getRecord(conn);
  882. if( _host.systemvmisouuid == null ) {
  883. for( VDI vdi : srr.VDIs ) {
  884. VDI.Record vdir = vdi.getRecord(conn);
  885. if(vdir.nameLabel.contains("systemvm.iso")){
  886. _host.systemvmisouuid = vdir.uuid;
  887. break;
  888. }
  889. }
  890. }
  891. if( _host.systemvmisouuid == null ) {
  892. throw new CloudRuntimeException("can not find systemvmiso");
  893. }
  894. }
  895. VBD.Record cdromVBDR = new VBD.Record();
  896. cdromVBDR.VM = vm;
  897. cdromVBDR.empty = true;
  898. cdromVBDR.bootable = false;
  899. cdromVBDR.userdevice = "3";
  900. cdromVBDR.mode = Types.VbdMode.RO;
  901. cdromVBDR.type = Types.VbdType.CD;
  902. VBD cdromVBD = VBD.create(conn, cdromVBDR);
  903. cdromVBD.insert(conn, VDI.getByUuid(conn, _host.systemvmisouuid));
  904. return cdromVBD;
  905. }
  906. protected CheckSshAnswer execute(CheckSshCommand cmd) {
  907. Connection conn = getConnection();
  908. String vmName = cmd.getName();
  909. String privateIp = cmd.getIp();
  910. int cmdPort = cmd.getPort();
  911. if (s_logger.isDebugEnabled()) {
  912. s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort);
  913. }
  914. try {
  915. String result = connect(conn, cmd.getName(), privateIp, cmdPort);
  916. if (result != null) {
  917. return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result);
  918. }
  919. } catch (Exception e) {
  920. return new CheckSshAnswer(cmd, e);
  921. }
  922. if (s_logger.isDebugEnabled()) {
  923. s_logger.debug("Ping command port succeeded for vm " + vmName);
  924. }
  925. return new CheckSshAnswer(cmd);
  926. }
  927. private HashMap<String, String> parseDefaultOvsRuleComamnd(String str) {
  928. HashMap<String, String> cmd = new HashMap<String, String>();
  929. String[] sarr = str.split("/");
  930. for (int i = 0; i < sarr.length; i++) {
  931. String c = sarr[i];
  932. c = c.startsWith("/") ? c.substring(1) : c;
  933. c = c.endsWith("/") ? c.substring(0, c.length() - 1) : c;
  934. String[] p = c.split(";");
  935. if (p.length != 2) {
  936. continue;
  937. }
  938. if (p[0].equalsIgnoreCase("vlans")) {
  939. p[1] = p[1].replace("@", "[");
  940. p[1] = p[1].replace("#", "]");
  941. }
  942. cmd.put(p[0], p[1]);
  943. }
  944. return cmd;
  945. }
  946. private void cleanUpTmpDomVif(Connection conn) {
  947. List<VIF> vifs;
  948. synchronized(_tmpDom0Vif) {
  949. vifs = _tmpDom0Vif;
  950. _tmpDom0Vif = new ArrayList<VIF>();
  951. }
  952. for (VIF v : vifs) {
  953. String vifName = "unkown";
  954. try {
  955. VIF.Record vifr = v.getRecord(conn);
  956. Map<String, String> config = vifr.otherConfig;
  957. vifName = config.get("nameLabel");
  958. v.destroy(conn);
  959. s_logger.debug("Destroy temp dom0 vif" + vifName + " success");
  960. } catch (Exception e) {
  961. s_logger.warn("Destroy temp dom0 vif " + vifName + "failed", e);
  962. }
  963. }
  964. }
  965. @Override
  966. public StartAnswer execute(StartCommand cmd) {
  967. Connection conn = getConnection();
  968. VirtualMachineTO vmSpec = cmd.getVirtualMachine();
  969. String vmName = vmSpec.getName();
  970. State state = State.Stopped;
  971. VM vm = null;
  972. try {
  973. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  974. if ( vms != null ) {
  975. for ( VM v : vms ) {
  976. VM.Record vRec = v.getRecord(conn);
  977. if ( vRec.powerState == VmPowerState.HALTED ) {
  978. v.destroy(conn);
  979. } else if ( vRec.powerState == VmPowerState.RUNNING ) {
  980. String host = vRec.residentOn.getUuid(conn);
  981. String msg = "VM " + vmName + " is runing on host " + host;
  982. s_logger.debug(msg);
  983. return new StartAnswer(cmd, msg, host);
  984. } else {
  985. String msg = "There is already a VM having the same name " + vmName + " vm record " + vRec.toString();
  986. s_logger.warn(msg);
  987. return new StartAnswer(cmd, msg);
  988. }
  989. }
  990. }
  991. synchronized (_cluster.intern()) {
  992. s_vms.put(_cluster, _name, vmName, State.Starting);
  993. }
  994. s_logger.debug("1. The VM " + vmName + " is in Starting state.");
  995. Host host = Host.getByUuid(conn, _host.uuid);
  996. vm = createVmFromTemplate(conn, vmSpec, host);
  997. for (VolumeTO disk : vmSpec.getDisks()) {
  998. createVbd(conn, disk, vmName, vm, vmSpec.getBootloader());
  999. }
  1000. if (vmSpec.getType() != VirtualMachine.Type.User) {
  1001. createPatchVbd(conn, vmName, vm);
  1002. }
  1003. for (NicTO nic : vmSpec.getNics()) {
  1004. createVif(conn, vmName, vm, nic);
  1005. }
  1006. startVM(conn, host, vm, vmName);
  1007. if (_isOvs) {
  1008. for (NicTO nic : vmSpec.getNics()) {
  1009. if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) {
  1010. HashMap<String, String> args = parseDefaultOvsRuleComamnd(nic.getBroadcastUri().toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()));
  1011. OvsSetTagAndFlowCommand flowCmd = new OvsSetTagAndFlowCommand(args.get("vmName"), args.get("tag"), args.get("vlans"),
  1012. args.get("seqno"), Long.parseLong(args.get("vmId")));
  1013. OvsSetTagAndFlowAnswer r = execute(flowCmd);
  1014. if (!r.getResult()) {
  1015. s_logger.warn("Failed to set flow for VM " + r.getVmId());
  1016. } else {
  1017. s_logger.info("Success to set flow for VM " + r.getVmId());
  1018. }
  1019. }
  1020. }
  1021. }
  1022. cleanUpTmpDomVif(conn);
  1023. if (_canBridgeFirewall) {
  1024. String result = null;
  1025. if (vmSpec.getType() != VirtualMachine.Type.User) {
  1026. NicTO[] nics = vmSpec.getNics();
  1027. boolean secGrpEnabled = false;
  1028. for (NicTO nic : nics) {
  1029. if (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) {
  1030. secGrpEnabled = true;
  1031. break;
  1032. }
  1033. }
  1034. if (secGrpEnabled) {
  1035. result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", vmName);
  1036. if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
  1037. s_logger.warn("Failed to program default network rules for " + vmName);
  1038. } else {
  1039. s_logger.info("Programmed default network rules for " + vmName);
  1040. }
  1041. }
  1042. } else {
  1043. //For user vm, program the rules for each nic if the isolation uri scheme is ec2
  1044. NicTO[] nics = vmSpec.getNics();
  1045. for (NicTO nic : nics) {
  1046. if (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) {
  1047. result = callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), "vmID", Long.toString(vmSpec.getId()));
  1048. if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
  1049. s_logger.warn("Failed to program default network rules for " + vmName+" on nic with ip:"+nic.getIp()+" mac:"+nic.getMac());
  1050. } else {
  1051. s_logger.info("Programmed default network rules for " + vmName+" on nic with ip:"+nic.getIp()+" mac:"+nic.getMac());
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. state = State.Running;
  1058. return new StartAnswer(cmd);
  1059. } catch (Exception e) {
  1060. s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e);
  1061. String msg = handleVmStartFailure(conn, vmName, vm, "", e);
  1062. return new StartAnswer(cmd, msg);
  1063. } finally {
  1064. synchronized (_cluster.intern()) {
  1065. if (state != State.Stopped) {
  1066. s_vms.put(_cluster, _name, vmName, state);
  1067. s_logger.debug("2. The VM " + vmName + " is in " + state + " state.");
  1068. } else {
  1069. s_vms.remove(_cluster, _name, vmName);
  1070. s_logger.debug("The VM is in stopped state, detected problem during startup : " + vmName);
  1071. }
  1072. }
  1073. }
  1074. }
  1075. protected Answer execute(ModifySshKeysCommand cmd) {
  1076. return new Answer(cmd);
  1077. }
  1078. private boolean doPingTest(Connection conn, final String computingHostIp) {
  1079. String args = "-h " + computingHostIp;
  1080. String result = callHostPlugin(conn, "vmops", "pingtest", "args", args);
  1081. if (result == null || result.isEmpty()) {
  1082. return false;
  1083. }
  1084. return true;
  1085. }
  1086. protected CheckOnHostAnswer execute(CheckOnHostCommand cmd) {
  1087. return new CheckOnHostAnswer(cmd, null, "Not Implmeneted");
  1088. }
  1089. private boolean doPingTest(Connection conn, final String domRIp, final String vmIp) {
  1090. String args = "-i " + domRIp + " -p " + vmIp;
  1091. String result = callHostPlugin(conn, "vmops", "pingtest", "args", args);
  1092. if (result == null || result.isEmpty()) {
  1093. return false;
  1094. }
  1095. return true;
  1096. }
  1097. private Answer execute(PingTestCommand cmd) {
  1098. Connection conn = getConnection();
  1099. boolean result = false;
  1100. final String computingHostIp = cmd.getComputingHostIp();
  1101. if (computingHostIp != null) {
  1102. result = doPingTest(conn, computingHostIp);
  1103. } else {
  1104. result = doPingTest(conn, cmd.getRouterIp(), cmd.getPrivateIp());
  1105. }
  1106. if (!result) {
  1107. return new Answer(cmd, false, "PingTestCommand failed");
  1108. }
  1109. return new Answer(cmd);
  1110. }
  1111. private CheckRouterAnswer execute(CheckRouterCommand cmd) {
  1112. Connection conn = getConnection();
  1113. String args = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1114. String result = callHostPlugin(conn, "vmops", "checkRouter", "args", args);
  1115. if (result == null || result.isEmpty()) {
  1116. return new CheckRouterAnswer(cmd, "CheckRouterCommand failed");
  1117. }
  1118. return new CheckRouterAnswer(cmd, result, true);
  1119. }
  1120. private GetDomRVersionAnswer execute(GetDomRVersionCmd cmd) {
  1121. Connection conn = getConnection();
  1122. String args = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1123. String result = callHostPlugin(conn, "vmops", "getDomRVersion", "args", args);
  1124. if (result == null || result.isEmpty()) {
  1125. return new GetDomRVersionAnswer(cmd, "getDomRVersionCmd failed");
  1126. }
  1127. String[] lines = result.split("&");
  1128. if (lines.length != 2) {
  1129. return new GetDomRVersionAnswer(cmd, result);
  1130. }
  1131. return new GetDomRVersionAnswer(cmd, result, lines[0], lines[1]);
  1132. }
  1133. private Answer execute(BumpUpPriorityCommand cmd) {
  1134. Connection conn = getConnection();
  1135. String args = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1136. String result = callHostPlugin(conn, "vmops", "bumpUpPriority", "args", args);
  1137. if (result == null || result.isEmpty()) {
  1138. return new Answer(cmd, false, "BumpUpPriorityCommand failed");
  1139. }
  1140. return new Answer(cmd, true, result);
  1141. }
  1142. protected MaintainAnswer execute(MaintainCommand cmd) {
  1143. Connection conn = getConnection();
  1144. try {
  1145. Pool pool = Pool.getByUuid(conn, _host.pool);
  1146. Pool.Record poolr = pool.getRecord(conn);
  1147. Host.Record hostr = poolr.master.getRecord(conn);
  1148. if (!_host.uuid.equals(hostr.uuid)) {
  1149. s_logger.debug("Not the master node so just return ok: " + _host.ip);
  1150. return new MaintainAnswer(cmd);
  1151. }
  1152. Map<Host, Host.Record> hostMap = Host.getAllRecords(conn);
  1153. if (hostMap.size() == 1) {
  1154. s_logger.debug("There is the last host in pool " + poolr.uuid );
  1155. return new MaintainAnswer(cmd);
  1156. }
  1157. Host newMaster = null;
  1158. Host.Record newMasterRecord = null;
  1159. for (Map.Entry<Host, Host.Record> entry : hostMap.entrySet()) {
  1160. if (!_host.uuid.equals(entry.getValue().uuid)) {
  1161. newMaster = entry.getKey();
  1162. newMasterRecord = entry.getValue();
  1163. s_logger.debug("New master for the XenPool is " + newMasterRecord.uuid + " : " + newMasterRecord.address);
  1164. try {
  1165. _connPool.switchMaster(_host.ip, _host.pool, conn, newMaster, _username, _password, _wait);
  1166. return new MaintainAnswer(cmd, "New Master is " + newMasterRecord.address);
  1167. } catch (XenAPIException e) {
  1168. s_logger.warn("Unable to switch the new master to " + newMasterRecord.uuid + ": " + newMasterRecord.address + " Trying again...");
  1169. } catch (XmlRpcException e) {
  1170. s_logger.warn("Unable to switch the new master to " + newMasterRecord.uuid + ": " + newMasterRecord.address + " Trying again...");
  1171. }
  1172. }
  1173. }
  1174. return new MaintainAnswer(cmd, false, "Unable to find an appropriate host to set as the new master");
  1175. } catch (XenAPIException e) {
  1176. s_logger.warn("Unable to put server in maintainence mode", e);
  1177. return new MaintainAnswer(cmd, false, e.getMessage());
  1178. } catch (XmlRpcException e) {
  1179. s_logger.warn("Unable to put server in maintainence mode", e);
  1180. return new MaintainAnswer(cmd, false, e.getMessage());
  1181. }
  1182. }
  1183. protected SetPortForwardingRulesAnswer execute(SetPortForwardingRulesCommand cmd) {
  1184. Connection conn = getConnection();
  1185. String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1186. String[] results = new String[cmd.getRules().length];
  1187. int i = 0;
  1188. boolean endResult = true;
  1189. for (PortForwardingRuleTO rule : cmd.getRules()) {
  1190. StringBuilder args = new StringBuilder();
  1191. args.append(routerIp);
  1192. args.append(rule.revoked() ? " -D " : " -A ");
  1193. args.append(" -P ").append(rule.getProtocol().toLowerCase());
  1194. args.append(" -l ").append(rule.getSrcIp());
  1195. args.append(" -p ").append(rule.getStringSrcPortRange());
  1196. args.append(" -r ").append(rule.getDstIp());
  1197. args.append(" -d ").append(rule.getStringDstPortRange());
  1198. String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args.toString());
  1199. if (result == null || result.isEmpty()) {
  1200. results[i++] = "Failed";
  1201. endResult = false;
  1202. } else {
  1203. results[i++] = null;
  1204. }
  1205. }
  1206. return new SetPortForwardingRulesAnswer(cmd, results, endResult);
  1207. }
  1208. protected SetStaticNatRulesAnswer execute(SetStaticNatRulesCommand cmd) {
  1209. Connection conn = getConnection();
  1210. String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1211. //String args = routerIp;
  1212. String[] results = new String[cmd.getRules().length];
  1213. int i = 0;
  1214. boolean endResult = true;
  1215. for (StaticNatRuleTO rule : cmd.getRules()) {
  1216. //1:1 NAT needs instanceip;publicip;domrip;op
  1217. StringBuilder args = new StringBuilder();
  1218. args.append(routerIp);
  1219. args.append(rule.revoked() ? " -D " : " -A ");
  1220. args.append(" -l ").append(rule.getSrcIp());
  1221. args.append(" -r ").append(rule.getDstIp());
  1222. if (rule.getProtocol() != null) {
  1223. args.append(" -P ").append(rule.getProtocol().toLowerCase());
  1224. }
  1225. args.append(" -d ").append(rule.getStringSrcPortRange());
  1226. args.append(" -G ");
  1227. String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args.toString());
  1228. if (result == null || result.isEmpty()) {
  1229. results[i++] = "Failed";
  1230. endResult = false;
  1231. } else {
  1232. results[i++] = null;
  1233. }
  1234. }
  1235. return new SetStaticNatRulesAnswer(cmd, results, endResult);
  1236. }
  1237. protected Answer execute(final LoadBalancerConfigCommand cmd) {
  1238. Connection conn = getConnection();
  1239. String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1240. if (routerIp == null) {
  1241. return new Answer(cmd);
  1242. }
  1243. LoadBalancerConfigurator cfgtr = new HAProxyConfigurator();
  1244. String[] config = cfgtr.generateConfiguration(cmd);
  1245. String[][] rules = cfgtr.generateFwRules(cmd);
  1246. String tmpCfgFilePath = "/tmp/" + routerIp.replace('.', '_') + ".cfg";
  1247. String tmpCfgFileContents = "";
  1248. for (int i = 0; i < config.length; i++) {
  1249. tmpCfgFileContents += config[i];
  1250. tmpCfgFileContents += "\n";
  1251. }
  1252. String result = callHostPlugin(conn, "vmops", "createFile", "filepath", tmpCfgFilePath, "filecontents", tmpCfgFileContents);
  1253. if (result == null || result.isEmpty()) {
  1254. return new Answer(cmd, false, "LoadBalancerConfigCommand failed to create HA proxy cfg file.");
  1255. }
  1256. String[] addRules = rules[LoadBalancerConfigurator.ADD];
  1257. String[] removeRules = rules[LoadBalancerConfigurator.REMOVE];
  1258. String[] statRules = rules[LoadBalancerConfigurator.STATS];
  1259. String args = "";
  1260. args += "-i " + routerIp;
  1261. args += " -f " + tmpCfgFilePath;
  1262. StringBuilder sb = new StringBuilder();
  1263. if (addRules.length > 0) {
  1264. for (int i = 0; i < addRules.length; i++) {
  1265. sb.append(addRules[i]).append(',');
  1266. }
  1267. args += " -a " + sb.toString();
  1268. }
  1269. sb = new StringBuilder();
  1270. if (removeRules.length > 0) {
  1271. for (int i = 0; i < removeRules.length; i++) {
  1272. sb.append(removeRules[i]).append(',');
  1273. }
  1274. args += " -d " + sb.toString();
  1275. }
  1276. sb = new StringBuilder();
  1277. if (statRules.length > 0) {
  1278. for (int i = 0; i < statRules.length; i++) {
  1279. sb.append(statRules[i]).append(',');
  1280. }
  1281. args += " -s " + sb.toString();
  1282. }
  1283. result = callHostPlugin(conn, "vmops", "setLoadBalancerRule", "args", args);
  1284. if (result == null || result.isEmpty()) {
  1285. return new Answer(cmd, false, "LoadBalancerConfigCommand failed");
  1286. }
  1287. callHostPlugin(conn, "vmops", "deleteFile", "filepath", tmpCfgFilePath);
  1288. return new Answer(cmd);
  1289. }
  1290. protected synchronized Answer execute(final DhcpEntryCommand cmd) {
  1291. Connection conn = getConnection();
  1292. String args = "-r " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1293. args += " -v " + cmd.getVmIpAddress();
  1294. args += " -m " + cmd.getVmMac();
  1295. args += " -n " + cmd.getVmName();
  1296. if (cmd.getDefaultRouter() != null) {
  1297. args += " -d " + cmd.getDefaultRouter();
  1298. }
  1299. if (cmd.getStaticRoutes() != null) {
  1300. args += " -s " + cmd.getStaticRoutes();
  1301. }
  1302. if (cmd.getDefaultDns() != null) {
  1303. args += " -N " + cmd.getDefaultDns();
  1304. }
  1305. String result = callHostPlugin(conn, "vmops", "saveDhcpEntry", "args", args);
  1306. if (result == null || result.isEmpty()) {
  1307. return new Answer(cmd, false, "DhcpEntry failed");
  1308. }
  1309. return new Answer(cmd);
  1310. }
  1311. protected synchronized Answer execute(final RemoteAccessVpnCfgCommand cmd) {
  1312. Connection conn = getConnection();
  1313. String args = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1314. if (cmd.isCreate()) {
  1315. args += " -r " + cmd.getIpRange();
  1316. args += " -p " + cmd.getPresharedKey();
  1317. args += " -s " + cmd.getVpnServerIp();
  1318. args += " -l " + cmd.getLocalIp();
  1319. args += " -c ";
  1320. } else {
  1321. args += " -d ";
  1322. args += " -s " + cmd.getVpnServerIp();
  1323. }
  1324. String result = callHostPlugin(conn, "vmops", "lt2p_vpn", "args", args);
  1325. if (result == null || result.isEmpty()) {
  1326. return new Answer(cmd, false, "Configure VPN failed");
  1327. }
  1328. return new Answer(cmd);
  1329. }
  1330. protected synchronized Answer execute(final VpnUsersCfgCommand cmd) {
  1331. Connection conn = getConnection();
  1332. for (VpnUsersCfgCommand.UsernamePassword userpwd: cmd.getUserpwds()) {
  1333. String args = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1334. if (!userpwd.isAdd()) {
  1335. args += " -U " + userpwd.getUsername();
  1336. } else {
  1337. args += " -u " + userpwd.getUsernamePassword();
  1338. }
  1339. String result = callHostPlugin(conn, "vmops", "lt2p_vpn", "args", args);
  1340. if (result == null || result.isEmpty()) {
  1341. return new Answer(cmd, false, "Configure VPN user failed for user " + userpwd.getUsername());
  1342. }
  1343. }
  1344. return new Answer(cmd);
  1345. }
  1346. protected Answer execute(final VmDataCommand cmd) {
  1347. Connection conn = getConnection();
  1348. String routerPrivateIpAddress = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1349. String vmIpAddress = cmd.getVmIpAddress();
  1350. List<String[]> vmData = cmd.getVmData();
  1351. String[] vmDataArgs = new String[vmData.size() * 2 + 4];
  1352. vmDataArgs[0] = "routerIP";
  1353. vmDataArgs[1] = routerPrivateIpAddress;
  1354. vmDataArgs[2] = "vmIP";
  1355. vmDataArgs[3] = vmIpAddress;
  1356. int i = 4;
  1357. for (String[] vmDataEntry : vmData) {
  1358. String folder = vmDataEntry[0];
  1359. String file = vmDataEntry[1];
  1360. String contents = (vmDataEntry[2] != null) ? vmDataEntry[2] : "none";
  1361. vmDataArgs[i] = folder + "," + file;
  1362. vmDataArgs[i + 1] = contents;
  1363. i += 2;
  1364. }
  1365. String result = callHostPlugin(conn, "vmops", "vm_data", vmDataArgs);
  1366. if (result == null || result.isEmpty()) {
  1367. return new Answer(cmd, false, "vm_data failed");
  1368. } else {
  1369. return new Answer(cmd);
  1370. }
  1371. }
  1372. protected Answer execute(final SavePasswordCommand cmd) {
  1373. Connection conn = getConnection();
  1374. final String password = cmd.getPassword();
  1375. final String routerPrivateIPAddress = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1376. final String vmName = cmd.getVmName();
  1377. final String vmIpAddress = cmd.getVmIpAddress();
  1378. final String local = vmName;
  1379. // Run save_password_to_domr.sh
  1380. String args = "-r " + routerPrivateIPAddress;
  1381. args += " -v " + vmIpAddress;
  1382. args += " -p " + password;
  1383. args += " " + local;
  1384. String result = callHostPlugin(conn, "vmops", "savePassword", "args", args);
  1385. if (result == null || result.isEmpty()) {
  1386. return new Answer(cmd, false, "savePassword failed");
  1387. }
  1388. return new Answer(cmd);
  1389. }
  1390. protected void assignPublicIpAddress(Connection conn, String vmName, String privateIpAddress, String publicIpAddress, boolean add, boolean firstIP,
  1391. boolean sourceNat, String vlanId, String vlanGateway, String vlanNetmask, String vifMacAddress, String guestIp, Integer networkRate, TrafficType trafficType, String name) throws InternalErrorException {
  1392. try {
  1393. VM router = getVM(conn, vmName);
  1394. NicTO nic = new NicTO();
  1395. nic.setMac(vifMacAddress);
  1396. nic.setType(trafficType);
  1397. if (vlanId == null) {
  1398. nic.setBroadcastType(BroadcastDomainType.Native);
  1399. } else {
  1400. nic.setBroadcastType(BroadcastDomainType.Vlan);
  1401. nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vlanId));
  1402. }
  1403. nic.setDeviceId(0);
  1404. nic.setNetworkRateMbps(networkRate);
  1405. nic.setName(name);
  1406. Network network = getNetwork(conn, nic);
  1407. // Determine the correct VIF on DomR to associate/disassociate the
  1408. // IP address with
  1409. VIF correctVif = getCorrectVif(conn, router, network);
  1410. // If we are associating an IP address and DomR doesn't have a VIF
  1411. // for the specified vlan ID, we need to add a VIF
  1412. // If we are disassociating the last IP address in the VLAN, we need
  1413. // to remove a VIF
  1414. boolean addVif = false;
  1415. boolean removeVif = false;
  1416. if (add && correctVif == null) {
  1417. addVif = true;
  1418. } else if (!add && firstIP) {
  1419. /* FIXME: This is incorrect. Because you can only tell if it's the first IP in this bundle of ip address which send to the router,
  1420. * but don't know if it's the only IP left in the router - because we didn't send all the related vlan's IPs to the router now. */
  1421. removeVif = true;
  1422. }
  1423. if (addVif) {
  1424. // Add a new VIF to DomR
  1425. String vifDeviceNum = getLowestAvailableVIFDeviceNum(conn, router);
  1426. if (vifDeviceNum == null) {
  1427. throw new InternalErrorException("There were no more available slots for a new VIF on router: " + router.getNameLabel(conn));
  1428. }
  1429. nic.setDeviceId(Integer.parseInt(vifDeviceNum));
  1430. correctVif = createVif(conn, vmName, router, nic);
  1431. correctVif.plug(conn);
  1432. // Add iptables rule for network usage
  1433. networkUsage(conn, privateIpAddress, "addVif", "eth" + correctVif.getDevice(conn));
  1434. }
  1435. if (correctVif == null) {
  1436. throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with.");
  1437. }
  1438. String args = privateIpAddress;
  1439. if (add) {
  1440. args += " -A ";
  1441. } else {
  1442. args += " -D ";
  1443. }
  1444. String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask));
  1445. if (sourceNat) {
  1446. args += " -s";
  1447. }
  1448. if (firstIP) {
  1449. args += " -f";
  1450. args += " -l ";
  1451. args += publicIpAddress + "/" + cidrSize;
  1452. } else {
  1453. args += " -l ";
  1454. args += publicIpAddress;
  1455. }
  1456. args += " -c ";
  1457. args += "eth" + correctVif.getDevice(conn);
  1458. args += " -g ";
  1459. args += vlanGateway;
  1460. String result = callHostPlugin(conn, "vmops", "ipassoc", "args", args);
  1461. if (result == null || result.isEmpty()) {
  1462. throw new InternalErrorException("Xen plugin \"ipassoc\" failed.");
  1463. }
  1464. if (removeVif) {
  1465. network = correctVif.getNetwork(conn);
  1466. // Mark this vif to be removed from network usage
  1467. networkUsage(conn, privateIpAddress, "deleteVif", "eth" + correctVif.getDevice(conn));
  1468. // Remove the VIF from DomR
  1469. correctVif.unplug(conn);
  1470. correctVif.destroy(conn);
  1471. // Disable the VLAN network if necessary
  1472. disableVlanNetwork(conn, network);
  1473. }
  1474. } catch (XenAPIException e) {
  1475. String msg = "Unable to assign public IP address due to " + e.toString();
  1476. s_logger.warn(msg, e);
  1477. throw new InternalErrorException(msg);
  1478. } catch (final XmlRpcException e) {
  1479. String msg = "Unable to assign public IP address due to " + e.getMessage();
  1480. s_logger.warn(msg, e);
  1481. throw new InternalErrorException(msg);
  1482. }
  1483. }
  1484. protected String networkUsage(Connection conn, final String privateIpAddress, final String option, final String vif) {
  1485. if (option.equals("get")) {
  1486. return "0:0";
  1487. }
  1488. return null;
  1489. }
  1490. protected Answer execute(IpAssocCommand cmd) {
  1491. Connection conn = getConnection();
  1492. String[] results = new String[cmd.getIpAddresses().length];
  1493. int i = 0;
  1494. String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
  1495. String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  1496. try {
  1497. IpAddressTO[] ips = cmd.getIpAddresses();
  1498. for (IpAddressTO ip : ips) {
  1499. assignPublicIpAddress(conn, routerName, routerIp, ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getVlanId(),
  1500. ip.getVlanGateway(), ip.getVlanNetmask(), ip.getVifMacAddress(), ip.getGuestIp(), ip.getNetworkRate(), ip.getTrafficType(), ip.getNetworkName());
  1501. results[i++] = ip.getPublicIp() + " - success";
  1502. }
  1503. } catch (InternalErrorException e) {
  1504. s_logger.error(
  1505. "Ip Assoc failure on applying one ip due to exception: ", e);
  1506. results[i++] = IpAssocAnswer.errorResult;
  1507. }
  1508. return new IpAssocAnswer(cmd, results);
  1509. }
  1510. protected GetVncPortAnswer execute(GetVncPortCommand cmd) {
  1511. Connection conn = getConnection();
  1512. try {
  1513. Set<VM> vms = VM.getByNameLabel(conn, cmd.getName());
  1514. if(vms.size() == 1) {
  1515. int vncport = getVncPort(conn, vms.iterator().next());
  1516. String consoleurl;
  1517. consoleurl = "consoleurl=" +getVncUrl(conn, vms.iterator().next()) + "&" +"sessionref="+ conn.getSessionReference();
  1518. return new GetVncPortAnswer(cmd, consoleurl, vncport);
  1519. } else {
  1520. return new GetVncPortAnswer(cmd, "There are " + vms.size() + " VMs named " + cmd.getName());
  1521. }
  1522. } catch (Exception e) {
  1523. String msg = "Unable to get vnc port due to " + e.toString();
  1524. s_logger.warn(msg, e);
  1525. return new GetVncPortAnswer(cmd, msg);
  1526. }
  1527. }
  1528. protected Storage.StorageResourceType getStorageResourceType() {
  1529. return Storage.StorageResourceType.STORAGE_POOL;
  1530. }
  1531. protected CheckHealthAnswer execute(CheckHealthCommand cmd) {
  1532. boolean result = pingXenServer();
  1533. return new CheckHealthAnswer(cmd, result);
  1534. }
  1535. protected long[] getNetworkStats(Connection conn, String privateIP) {
  1536. String result = networkUsage(conn, privateIP, "get", null);
  1537. long[] stats = new long[2];
  1538. if (result != null) {
  1539. String[] splitResult = result.split(":");
  1540. int i = 0;
  1541. while (i < splitResult.length - 1) {
  1542. stats[0] += (new Long(splitResult[i++])).longValue();
  1543. stats[1] += (new Long(splitResult[i++])).longValue();
  1544. }
  1545. }
  1546. return stats;
  1547. }
  1548. /**
  1549. * This is the method called for getting the HOST stats
  1550. *
  1551. * @param cmd
  1552. * @return
  1553. */
  1554. protected GetHostStatsAnswer execute(GetHostStatsCommand cmd) {
  1555. Connection conn = getConnection();
  1556. try {
  1557. HostStatsEntry hostStats = getHostStats(conn, cmd, cmd.getHostGuid(), cmd.getHostId());
  1558. return new GetHostStatsAnswer(cmd, hostStats);
  1559. } catch (Exception e) {
  1560. String msg = "Unable to get Host stats" + e.toString();
  1561. s_logger.warn(msg, e);
  1562. return new GetHostStatsAnswer(cmd, null);
  1563. }
  1564. }
  1565. protected HostStatsEntry getHostStats(Connection conn, GetHostStatsCommand cmd, String hostGuid, long hostId) {
  1566. HostStatsEntry hostStats = new HostStatsEntry(hostId, 0, 0, 0, "host", 0, 0, 0, 0);
  1567. Object[] rrdData = getRRDData(conn, 1); // call rrd method with 1 for host
  1568. if (rrdData == null) {
  1569. return null;
  1570. }
  1571. Integer numRows = (Integer) rrdData[0];
  1572. Integer numColumns = (Integer) rrdData[1];
  1573. Node legend = (Node) rrdData[2];
  1574. Node dataNode = (Node) rrdData[3];
  1575. NodeList legendChildren = legend.getChildNodes();
  1576. for (int col = 0; col < numColumns; col++) {
  1577. if (legendChildren == null || legendChildren.item(col) == null) {
  1578. continue;
  1579. }
  1580. String columnMetadata = getXMLNodeValue(legendChildren.item(col));
  1581. if (columnMetadata == null) {
  1582. continue;
  1583. }
  1584. String[] columnMetadataList = columnMetadata.split(":");
  1585. if (columnMetadataList.length != 4) {
  1586. continue;
  1587. }
  1588. String type = columnMetadataList[1];
  1589. String param = columnMetadataList[3];
  1590. if (type.equalsIgnoreCase("host")) {
  1591. if (param.contains("pif_eth0_rx")) {
  1592. hostStats.setNetworkReadKBs(getDataAverage(dataNode, col, numRows));
  1593. }
  1594. if (param.contains("pif_eth0_tx")) {
  1595. hostStats.setNetworkWriteKBs(getDataAverage(dataNode, col, numRows));
  1596. }
  1597. if (param.contains("memory_total_kib")) {
  1598. hostStats.setTotalMemoryKBs(getDataAverage(dataNode, col, numRows));
  1599. }
  1600. if (param.contains("memory_free_kib")) {
  1601. hostStats.setFreeMemoryKBs(getDataAverage(dataNode, col, numRows));
  1602. }
  1603. if (param.contains("cpu")) {
  1604. // hostStats.setNumCpus(hostStats.getNumCpus() + 1);
  1605. hostStats.setCpuUtilization(hostStats.getCpuUtilization() + getDataAverage(dataNode, col, numRows));
  1606. }
  1607. /*
  1608. if (param.contains("loadavg")) {
  1609. hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows)));
  1610. }
  1611. */
  1612. }
  1613. }
  1614. // add the host cpu utilization
  1615. /*
  1616. if (hostStats.getNumCpus() != 0) {
  1617. hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus());
  1618. s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization());
  1619. }
  1620. */
  1621. return hostStats;
  1622. }
  1623. protected GetVmStatsAnswer execute( GetVmStatsCommand cmd) {
  1624. Connection conn = getConnection();
  1625. List<String> vmNames = cmd.getVmNames();
  1626. HashMap<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>();
  1627. if( vmNames.size() == 0 ) {
  1628. return new GetVmStatsAnswer(cmd, vmStatsNameMap);
  1629. }
  1630. try {
  1631. // Determine the UUIDs of the requested VMs
  1632. List<String> vmUUIDs = new ArrayList<String>();
  1633. for (String vmName : vmNames) {
  1634. VM vm = getVM(conn, vmName);
  1635. vmUUIDs.add(vm.getUuid(conn));
  1636. }
  1637. HashMap<String, VmStatsEntry> vmStatsUUIDMap = getVmStats(conn, cmd, vmUUIDs, cmd.getHostGuid());
  1638. if( vmStatsUUIDMap == null ) {
  1639. return new GetVmStatsAnswer(cmd, vmStatsNameMap);
  1640. }
  1641. for (String vmUUID : vmStatsUUIDMap.keySet()) {
  1642. vmStatsNameMap.put(vmNames.get(vmUUIDs.indexOf(vmUUID)), vmStatsUUIDMap.get(vmUUID));
  1643. }
  1644. return new GetVmStatsAnswer(cmd, vmStatsNameMap);
  1645. } catch (XenAPIException e) {
  1646. String msg = "Unable to get VM stats" + e.toString();
  1647. s_logger.warn(msg, e);
  1648. return new GetVmStatsAnswer(cmd, vmStatsNameMap);
  1649. } catch (XmlRpcException e) {
  1650. String msg = "Unable to get VM stats" + e.getMessage();
  1651. s_logger.warn(msg, e);
  1652. return new GetVmStatsAnswer(cmd, vmStatsNameMap);
  1653. }
  1654. }
  1655. protected HashMap<String, VmStatsEntry> getVmStats(Connection conn, GetVmStatsCommand cmd, List<String> vmUUIDs, String hostGuid) {
  1656. HashMap<String, VmStatsEntry> vmResponseMap = new HashMap<String, VmStatsEntry>();
  1657. for (String vmUUID : vmUUIDs) {
  1658. vmResponseMap.put(vmUUID, new VmStatsEntry(0, 0, 0, 0, "vm"));
  1659. }
  1660. Object[] rrdData = getRRDData(conn, 2); // call rrddata with 2 for vm
  1661. if (rrdData == null) {
  1662. return null;
  1663. }
  1664. Integer numRows = (Integer) rrdData[0];
  1665. Integer numColumns = (Integer) rrdData[1];
  1666. Node legend = (Node) rrdData[2];
  1667. Node dataNode = (Node) rrdData[3];
  1668. NodeList legendChildren = legend.getChildNodes();
  1669. for (int col = 0; col < numColumns; col++) {
  1670. if (legendChildren == null || legendChildren.item(col) == null) {
  1671. continue;
  1672. }
  1673. String columnMetadata = getXMLNodeValue(legendChildren.item(col));
  1674. if (columnMetadata == null) {
  1675. continue;
  1676. }
  1677. String[] columnMetadataList = columnMetadata.split(":");
  1678. if (columnMetadataList.length != 4) {
  1679. continue;
  1680. }
  1681. String type = columnMetadataList[1];
  1682. String uuid = columnMetadataList[2];
  1683. String param = columnMetadataList[3];
  1684. if (type.equals("vm") && vmResponseMap.keySet().contains(uuid)) {
  1685. VmStatsEntry vmStatsAnswer = vmResponseMap.get(uuid);
  1686. vmStatsAnswer.setEntityType("vm");
  1687. if (param.contains("cpu")) {
  1688. vmStatsAnswer.setNumCPUs(vmStatsAnswer.getNumCPUs() + 1);
  1689. vmStatsAnswer.setCPUUtilization(((vmStatsAnswer.getCPUUtilization() + getDataAverage(dataNode, col, numRows))));
  1690. } else if (param.matches("vif_\\d_rx")) {
  1691. vmStatsAnswer.setNetworkReadKBs(vmStatsAnswer.getNetworkReadKBs() + (getDataAverage(dataNode, col, numRows)/(8*2)));
  1692. } else if (param.matches("vif_\\d_tx")) {
  1693. vmStatsAnswer.setNetworkWriteKBs(vmStatsAnswer.getNetworkWriteKBs() + (getDataAverage(dataNode, col, numRows)/(8*2)));
  1694. }
  1695. }
  1696. }
  1697. for (String vmUUID : vmResponseMap.keySet()) {
  1698. VmStatsEntry vmStatsAnswer = vmResponseMap.get(vmUUID);
  1699. if (vmStatsAnswer.getNumCPUs() != 0) {
  1700. vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization() / vmStatsAnswer.getNumCPUs());
  1701. }
  1702. vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization()*100);
  1703. if(s_logger.isDebugEnabled()) {
  1704. s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization());
  1705. }
  1706. }
  1707. return vmResponseMap;
  1708. }
  1709. protected Object[] getRRDData(Connection conn, int flag) {
  1710. /*
  1711. * Note: 1 => called from host, hence host stats 2 => called from vm, hence vm stats
  1712. */
  1713. String stats = "";
  1714. try {
  1715. if (flag == 1) {
  1716. stats = getHostStatsRawXML(conn);
  1717. }
  1718. if (flag == 2) {
  1719. stats = getVmStatsRawXML(conn);
  1720. }
  1721. } catch (Exception e1) {
  1722. s_logger.warn("Error whilst collecting raw stats from plugin: ", e1);
  1723. return null;
  1724. }
  1725. // s_logger.debug("The raw xml stream is:"+stats);
  1726. // s_logger.debug("Length of raw xml is:"+stats.length());
  1727. //stats are null when the host plugin call fails (host down state)
  1728. if(stats == null) {
  1729. return null;
  1730. }
  1731. StringReader statsReader = new StringReader(stats);
  1732. InputSource statsSource = new InputSource(statsReader);
  1733. Document doc = null;
  1734. try {
  1735. doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(statsSource);
  1736. } catch (Exception e) {
  1737. s_logger.warn("Exception caught whilst processing the document via document factory:", e);
  1738. return null;
  1739. }
  1740. if(doc==null){
  1741. s_logger.warn("Null document found after tryinh to parse the stats source");
  1742. return null;
  1743. }
  1744. NodeList firstLevelChildren = doc.getChildNodes();
  1745. NodeList secondLevelChildren = (firstLevelChildren.item(0)).getChildNodes();
  1746. Node metaNode = secondLevelChildren.item(0);
  1747. Node dataNode = secondLevelChildren.item(1);
  1748. Integer numRows = 0;
  1749. Integer numColumns = 0;
  1750. Node legend = null;
  1751. NodeList metaNodeChildren = metaNode.getChildNodes();
  1752. for (int i = 0; i < metaNodeChildren.getLength(); i++) {
  1753. Node n = metaNodeChildren.item(i);
  1754. if (n.getNodeName().equals("rows")) {
  1755. numRows = Integer.valueOf(getXMLNodeValue(n));
  1756. } else if (n.getNodeName().equals("columns")) {
  1757. numColumns = Integer.valueOf(getXMLNodeValue(n));
  1758. } else if (n.getNodeName().equals("legend")) {
  1759. legend = n;
  1760. }
  1761. }
  1762. return new Object[] { numRows, numColumns, legend, dataNode };
  1763. }
  1764. protected String getXMLNodeValue(Node n) {
  1765. return n.getChildNodes().item(0).getNodeValue();
  1766. }
  1767. protected double getDataAverage(Node dataNode, int col, int numRows) {
  1768. double value = 0;
  1769. double dummy = 0;
  1770. int numRowsUsed = 0;
  1771. for (int row = 0; row < numRows; row++) {
  1772. Node data = dataNode.getChildNodes().item(numRows - 1 - row).getChildNodes().item(col + 1);
  1773. Double currentDataAsDouble = Double.valueOf(getXMLNodeValue(data));
  1774. if (!currentDataAsDouble.equals(Double.NaN)) {
  1775. numRowsUsed += 1;
  1776. value += currentDataAsDouble;
  1777. }
  1778. }
  1779. if(numRowsUsed == 0)
  1780. {
  1781. if((!Double.isInfinite(value))&&(!Double.isNaN(value)))
  1782. {
  1783. return value;
  1784. }
  1785. else
  1786. {
  1787. s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows=0");
  1788. return dummy;
  1789. }
  1790. }
  1791. else
  1792. {
  1793. if((!Double.isInfinite(value/numRowsUsed))&&(!Double.isNaN(value/numRowsUsed)))
  1794. {
  1795. return (value/numRowsUsed);
  1796. }
  1797. else
  1798. {
  1799. s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows>0");
  1800. return dummy;
  1801. }
  1802. }
  1803. }
  1804. protected String getHostStatsRawXML(Connection conn) {
  1805. Date currentDate = new Date();
  1806. String startTime = String.valueOf(currentDate.getTime() / 1000 - 1000);
  1807. return callHostPlugin(conn, "vmops", "gethostvmstats", "collectHostStats", String.valueOf("true"), "consolidationFunction", _consolidationFunction, "interval", String
  1808. .valueOf(_pollingIntervalInSeconds), "startTime", startTime);
  1809. }
  1810. protected String getVmStatsRawXML(Connection conn) {
  1811. Date currentDate = new Date();
  1812. String startTime = String.valueOf(currentDate.getTime() / 1000 - 1000);
  1813. return callHostPlugin(conn, "vmops", "gethostvmstats", "collectHostStats", String.valueOf("false"), "consolidationFunction", _consolidationFunction, "interval", String
  1814. .valueOf(_pollingIntervalInSeconds), "startTime", startTime);
  1815. }
  1816. protected State convertToState(Types.VmPowerState ps) {
  1817. final State state = s_statesTable.get(ps);
  1818. return state == null ? State.Unknown : state;
  1819. }
  1820. protected HashMap<String, Pair<String, State>> getAllVms(Connection conn) {
  1821. final HashMap<String, Pair<String, State>> vmStates = new HashMap<String, Pair<String, State>>();
  1822. Map<VM, VM.Record> vm_map = null;
  1823. for (int i = 0; i < 2; i++) {
  1824. try {
  1825. vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER
  1826. break;
  1827. } catch (final Throwable e) {
  1828. s_logger.warn("Unable to get vms", e);
  1829. }
  1830. try {
  1831. Thread.sleep(1000);
  1832. } catch (final InterruptedException ex) {
  1833. }
  1834. }
  1835. if (vm_map == null) {
  1836. return null;
  1837. }
  1838. for (VM.Record record: vm_map.values()) {
  1839. if (record.isControlDomain || record.isASnapshot || record.isATemplate) {
  1840. continue; // Skip DOM0
  1841. }
  1842. VmPowerState ps = record.powerState;
  1843. final State state = convertToState(ps);
  1844. if (s_logger.isTraceEnabled()) {
  1845. s_logger.trace("VM " + record.nameLabel + ": powerstate = " + ps + "; vm state=" + state.toString());
  1846. }
  1847. Host host = record.residentOn;
  1848. String host_uuid = null;
  1849. if( ! isRefNull(host) ) {
  1850. try {
  1851. host_uuid = host.getUuid(conn);
  1852. } catch (BadServerResponse e) {
  1853. // TODO Auto-generated catch block
  1854. e.printStackTrace();
  1855. } catch (XenAPIException e) {
  1856. // TODO Auto-generated catch block
  1857. e.printStackTrace();
  1858. } catch (XmlRpcException e) {
  1859. // TODO Auto-generated catch block
  1860. e.printStackTrace();
  1861. }
  1862. vmStates.put(record.nameLabel, new Pair<String, State>(host_uuid, state));
  1863. }
  1864. }
  1865. return vmStates;
  1866. }
  1867. protected State getVmState(Connection conn, final String vmName) {
  1868. int retry = 3;
  1869. while (retry-- > 0) {
  1870. try {
  1871. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  1872. for (final VM vm : vms) {
  1873. return convertToState(vm.getPowerState(conn));
  1874. }
  1875. } catch (final BadServerResponse e) {
  1876. // There is a race condition within xen such that if a vm is
  1877. // deleted and we
  1878. // happen to ask for it, it throws this stupid response. So
  1879. // if this happens,
  1880. // we take a nap and try again which then avoids the race
  1881. // condition because
  1882. // the vm's information is now cleaned up by xen. The error
  1883. // is as follows
  1884. // com.xensource.xenapi.Types$BadServerResponse
  1885. // [HANDLE_INVALID, VM,
  1886. // 3dde93f9-c1df-55a7-2cde-55e1dce431ab]
  1887. s_logger.info("Unable to get a vm PowerState due to " + e.toString() + ". We are retrying. Count: " + retry);
  1888. try {
  1889. Thread.sleep(3000);
  1890. } catch (final InterruptedException ex) {
  1891. }
  1892. } catch (XenAPIException e) {
  1893. String msg = "Unable to get a vm PowerState due to " + e.toString();
  1894. s_logger.warn(msg, e);
  1895. break;
  1896. } catch (final XmlRpcException e) {
  1897. String msg = "Unable to get a vm PowerState due to " + e.getMessage();
  1898. s_logger.warn(msg, e);
  1899. break;
  1900. }
  1901. }
  1902. return State.Stopped;
  1903. }
  1904. protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
  1905. Connection conn = getConnection();
  1906. final String vmName = cmd.getVmName();
  1907. final State state = getVmState(conn, vmName);
  1908. Integer vncPort = null;
  1909. if (state == State.Running) {
  1910. synchronized (_cluster.intern()) {
  1911. s_vms.put(_cluster, _name, vmName, State.Running);
  1912. }
  1913. s_logger.debug("3. The VM " + vmName + " is in Running state");
  1914. }
  1915. return new CheckVirtualMachineAnswer(cmd, state, vncPort);
  1916. }
  1917. protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
  1918. Connection conn = getConnection();
  1919. VirtualMachineTO vm = cmd.getVirtualMachine();
  1920. if (s_logger.isDebugEnabled()) {
  1921. s_logger.debug("Preparing host for migrating " + vm);
  1922. }
  1923. NicTO[] nics = vm.getNics();
  1924. try {
  1925. prepareISO(conn, vm.getName());
  1926. for (NicTO nic : nics) {
  1927. getNetwork(conn, nic);
  1928. }
  1929. synchronized (_cluster.intern()) {
  1930. s_vms.put(_cluster, _name, vm.getName(), State.Migrating);
  1931. }
  1932. s_logger.debug("4. The VM " + vm.getName() + " is in Migrating state");
  1933. return new PrepareForMigrationAnswer(cmd);
  1934. } catch (Exception e) {
  1935. s_logger.warn("Catch Exception " + e.getClass().getName() + " prepare for migration failed due to " + e.toString(), e);
  1936. return new PrepareForMigrationAnswer(cmd, e);
  1937. }
  1938. }
  1939. private String copy_vhd_to_secondarystorage(Connection conn, String mountpoint, String vdiuuid, String sruuid, int wait) {
  1940. String results = callHostPluginAsync(conn, "vmopspremium", "copy_vhd_to_secondarystorage",
  1941. wait, "mountpoint", mountpoint, "vdiuuid", vdiuuid, "sruuid", sruuid);
  1942. String errMsg = null;
  1943. if (results == null || results.isEmpty()) {
  1944. errMsg = "copy_vhd_to_secondarystorage return null";
  1945. } else {
  1946. String[] tmp = results.split("#");
  1947. String status = tmp[0];
  1948. if (status.equals("0")) {
  1949. return tmp[1];
  1950. } else {
  1951. errMsg = tmp[1];
  1952. }
  1953. }
  1954. String source = vdiuuid + ".vhd";
  1955. killCopyProcess(conn, source);
  1956. s_logger.warn(errMsg);
  1957. throw new CloudRuntimeException(errMsg);
  1958. }
  1959. String upgradeSnapshot(Connection conn, String templatePath, String snapshotPath) {
  1960. String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot",
  1961. 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath);
  1962. if (results == null || results.isEmpty()) {
  1963. String msg = "upgrade_snapshot return null";
  1964. s_logger.warn(msg);
  1965. throw new CloudRuntimeException(msg);
  1966. }
  1967. String[] tmp = results.split("#");
  1968. String status = tmp[0];
  1969. if (status.equals("0")) {
  1970. return results;
  1971. } else {
  1972. s_logger.warn(results);
  1973. throw new CloudRuntimeException(results);
  1974. }
  1975. }
  1976. String createTemplateFromSnapshot(Connection conn, String templatePath, String snapshotPath, int wait) {
  1977. String tmpltLocalDir = UUID.randomUUID().toString();
  1978. String results = callHostPluginAsync(conn, "vmopspremium", "create_privatetemplate_from_snapshot",
  1979. wait, "templatePath", templatePath, "snapshotPath", snapshotPath, "tmpltLocalDir", tmpltLocalDir);
  1980. String errMsg = null;
  1981. if (results == null || results.isEmpty()) {
  1982. errMsg = "create_privatetemplate_from_snapshot return null";
  1983. } else {
  1984. String[] tmp = results.split("#");
  1985. String status = tmp[0];
  1986. if (status.equals("0")) {
  1987. return results;
  1988. } else {
  1989. errMsg = "create_privatetemplate_from_snapshot failed due to " + tmp[1];
  1990. }
  1991. }
  1992. String source = "cloud_mount/" + tmpltLocalDir;
  1993. killCopyProcess(conn, source);
  1994. s_logger.warn(errMsg);
  1995. throw new CloudRuntimeException(errMsg);
  1996. }
  1997. boolean killCopyProcess(Connection conn, String nameLabel) {
  1998. String results = callHostPluginAsync(conn, "vmops", "kill_copy_process",
  1999. 60, "namelabel", nameLabel);
  2000. String errMsg = null;
  2001. if (results == null || results.equals("false")) {
  2002. errMsg = "kill_copy_process failed";
  2003. s_logger.warn(errMsg);
  2004. return false;
  2005. } else {
  2006. return true;
  2007. }
  2008. }
  2009. void destroyVDIbyNameLabel(Connection conn, String nameLabel) {
  2010. try {
  2011. Set<VDI> vdis = VDI.getByNameLabel(conn, nameLabel);
  2012. if ( vdis.size() != 1 ) {
  2013. s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel);
  2014. return;
  2015. }
  2016. for (VDI vdi : vdis) {
  2017. try {
  2018. vdi.destroy(conn);
  2019. } catch (Exception e) {
  2020. }
  2021. }
  2022. } catch (Exception e){
  2023. }
  2024. }
  2025. String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) {
  2026. String nameLabel = "cloud-" + UUID.randomUUID().toString();
  2027. String results = callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage",
  2028. wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel);
  2029. String errMsg = null;
  2030. if (results == null || results.isEmpty()) {
  2031. errMsg = "copy_vhd_from_secondarystorage return null";
  2032. } else {
  2033. String[] tmp = results.split("#");
  2034. String status = tmp[0];
  2035. if (status.equals("0")) {
  2036. return tmp[1];
  2037. } else {
  2038. errMsg = tmp[1];
  2039. }
  2040. }
  2041. String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1);
  2042. if( killCopyProcess(conn, source) ) {
  2043. destroyVDIbyNameLabel(conn, nameLabel);
  2044. }
  2045. s_logger.warn(errMsg);
  2046. throw new CloudRuntimeException(errMsg);
  2047. }
  2048. public PrimaryStorageDownloadAnswer execute(final PrimaryStorageDownloadCommand cmd) {
  2049. String tmplturl = cmd.getUrl();
  2050. String poolName = cmd.getPoolUuid();
  2051. int wait = cmd.getWait();
  2052. try {
  2053. URI uri = new URI(tmplturl);
  2054. String tmplpath = uri.getHost() + ":" + uri.getPath();
  2055. Connection conn = getConnection();
  2056. SR poolsr = null;
  2057. Set<SR> srs = SR.getByNameLabel(conn, poolName);
  2058. if (srs.size() != 1) {
  2059. String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
  2060. s_logger.warn(msg);
  2061. return new PrimaryStorageDownloadAnswer(msg);
  2062. } else {
  2063. poolsr = srs.iterator().next();
  2064. }
  2065. String pUuid = poolsr.getUuid(conn);
  2066. boolean isISCSI = IsISCSI(poolsr.getType(conn));
  2067. String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait);
  2068. VDI tmpl = getVDIbyUuid(conn, uuid);
  2069. VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
  2070. String snapshotUuid = snapshotvdi.getUuid(conn);
  2071. snapshotvdi.setNameLabel(conn, "Template " + cmd.getName());
  2072. String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
  2073. VDI parent = getVDIbyUuid(conn, parentuuid);
  2074. Long phySize = parent.getPhysicalUtilisation(conn);
  2075. tmpl.destroy(conn);
  2076. poolsr.scan(conn);
  2077. try{
  2078. Thread.sleep(5000);
  2079. } catch (Exception e) {
  2080. }
  2081. return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize);
  2082. } catch (Exception e) {
  2083. String msg = "Catch Exception " + e.getClass().getName() + " on host:" + _host.uuid + " for template: "
  2084. + tmplturl + " due to " + e.toString();
  2085. s_logger.warn(msg, e);
  2086. return new PrimaryStorageDownloadAnswer(msg);
  2087. }
  2088. }
  2089. protected String removeSRSync(Connection conn, SR sr) {
  2090. if (sr == null) {
  2091. return null;
  2092. }
  2093. if (s_logger.isDebugEnabled()) {
  2094. s_logger.debug(logX(sr, "Removing SR"));
  2095. }
  2096. long waittime = 0;
  2097. try {
  2098. Set<VDI> vdis = sr.getVDIs(conn);
  2099. for (VDI vdi : vdis) {
  2100. Map<java.lang.String, Types.VdiOperations> currentOperation = vdi.getCurrentOperations(conn);
  2101. if (currentOperation == null || currentOperation.size() == 0) {
  2102. continue;
  2103. }
  2104. if (waittime >= 1800000) {
  2105. String msg = "This template is being used, try late time";
  2106. s_logger.warn(msg);
  2107. return msg;
  2108. }
  2109. waittime += 30000;
  2110. try {
  2111. Thread.sleep(30000);
  2112. } catch (final InterruptedException ex) {
  2113. }
  2114. }
  2115. removeSR(conn, sr);
  2116. return null;
  2117. } catch (XenAPIException e) {
  2118. s_logger.warn(logX(sr, "Unable to get current opertions " + e.toString()), e);
  2119. } catch (XmlRpcException e) {
  2120. s_logger.warn(logX(sr, "Unable to get current opertions " + e.getMessage()), e);
  2121. }
  2122. String msg = "Remove SR failed";
  2123. s_logger.warn(msg);
  2124. return msg;
  2125. }
  2126. protected void removeSR(Connection conn, SR sr) {
  2127. if (sr == null) {
  2128. return;
  2129. }
  2130. if (s_logger.isDebugEnabled()) {
  2131. s_logger.debug(logX(sr, "Removing SR"));
  2132. }
  2133. for (int i = 0; i < 2; i++) {
  2134. try {
  2135. Set<VDI> vdis = sr.getVDIs(conn);
  2136. for (VDI vdi : vdis) {
  2137. vdi.forget(conn);
  2138. }
  2139. Set<PBD> pbds = sr.getPBDs(conn);
  2140. for (PBD pbd : pbds) {
  2141. if (s_logger.isDebugEnabled()) {
  2142. s_logger.debug(logX(pbd, "Unplugging pbd"));
  2143. }
  2144. if (pbd.getCurrentlyAttached(conn)) {
  2145. pbd.unplug(conn);
  2146. }
  2147. pbd.destroy(conn);
  2148. }
  2149. pbds = sr.getPBDs(conn);
  2150. if (pbds.size() == 0) {
  2151. if (s_logger.isDebugEnabled()) {
  2152. s_logger.debug(logX(sr, "Forgetting"));
  2153. }
  2154. sr.forget(conn);
  2155. return;
  2156. }
  2157. if (s_logger.isDebugEnabled()) {
  2158. s_logger.debug(logX(sr, "There are still pbd attached"));
  2159. if (s_logger.isTraceEnabled()) {
  2160. for (PBD pbd : pbds) {
  2161. s_logger.trace(logX(pbd, " Still attached"));
  2162. }
  2163. }
  2164. }
  2165. } catch (XenAPIException e) {
  2166. s_logger.debug(logX(sr, "Catch XenAPIException: " + e.toString()));
  2167. } catch (XmlRpcException e) {
  2168. s_logger.debug(logX(sr, "Catch Exception: " + e.getMessage()));
  2169. }
  2170. }
  2171. s_logger.warn(logX(sr, "Unable to remove SR"));
  2172. }
  2173. protected MigrateAnswer execute(final MigrateCommand cmd) {
  2174. Connection conn = getConnection();
  2175. final String vmName = cmd.getVmName();
  2176. State state = null;
  2177. state = s_vms.getState(_cluster, vmName);
  2178. synchronized (_cluster.intern()) {
  2179. s_vms.put(_cluster, _name, vmName, State.Stopping);
  2180. }
  2181. s_logger.debug("5. The VM " + vmName + " is in Stopping state");
  2182. try {
  2183. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  2184. String ipaddr = cmd.getDestinationIp();
  2185. Set<Host> hosts = Host.getAll(conn);
  2186. Host dsthost = null;
  2187. for (Host host : hosts) {
  2188. if (host.getAddress(conn).equals(ipaddr)) {
  2189. dsthost = host;
  2190. break;
  2191. }
  2192. }
  2193. if ( dsthost == null ) {
  2194. String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.pool;
  2195. s_logger.warn(msg);
  2196. return new MigrateAnswer(cmd, false, msg, null);
  2197. }
  2198. for (VM vm : vms) {
  2199. Set<VBD> vbds = vm.getVBDs(conn);
  2200. for( VBD vbd : vbds) {
  2201. VBD.Record vbdRec = vbd.getRecord(conn);
  2202. if( vbdRec.type.equals(Types.VbdType.CD.toString()) && !vbdRec.empty ) {
  2203. vbd.eject(conn);
  2204. break;
  2205. }
  2206. }
  2207. migrateVM(conn, dsthost, vm, vmName);
  2208. vm.setAffinity(conn, dsthost);
  2209. state = State.Stopping;
  2210. }
  2211. return new MigrateAnswer(cmd, true, "migration succeeded", null);
  2212. } catch (Exception e) {
  2213. String msg = "Catch Exception " + e.getClass().getName() + ": Migration failed due to " + e.toString();
  2214. s_logger.warn(msg, e);
  2215. return new MigrateAnswer(cmd, false, msg, null);
  2216. } finally {
  2217. synchronized (_cluster.intern()) {
  2218. s_vms.put(_cluster, _name, vmName, state);
  2219. }
  2220. s_logger.debug("6. The VM " + vmName + " is in " + state + " state");
  2221. }
  2222. }
  2223. protected State getRealPowerState(Connection conn, String label) {
  2224. int i = 0;
  2225. s_logger.trace("Checking on the HALTED State");
  2226. for (; i < 20; i++) {
  2227. try {
  2228. Set<VM> vms = VM.getByNameLabel(conn, label);
  2229. if (vms == null || vms.size() == 0) {
  2230. continue;
  2231. }
  2232. VM vm = vms.iterator().next();
  2233. VmPowerState vps = vm.getPowerState(conn);
  2234. if (vps != null && vps != VmPowerState.HALTED && vps != VmPowerState.UNRECOGNIZED) {
  2235. return convertToState(vps);
  2236. }
  2237. } catch (XenAPIException e) {
  2238. String msg = "Unable to get real power state due to " + e.toString();
  2239. s_logger.warn(msg, e);
  2240. } catch (XmlRpcException e) {
  2241. String msg = "Unable to get real power state due to " + e.getMessage();
  2242. s_logger.warn(msg, e);
  2243. }
  2244. try {
  2245. Thread.sleep(1000);
  2246. } catch (InterruptedException e) {
  2247. }
  2248. }
  2249. return State.Stopped;
  2250. }
  2251. protected Pair<VM, VM.Record> getControlDomain(Connection conn) throws XenAPIException, XmlRpcException {
  2252. Host host = Host.getByUuid(conn, _host.uuid);
  2253. Set<VM> vms = null;
  2254. vms = host.getResidentVMs(conn);
  2255. for (VM vm : vms) {
  2256. if (vm.getIsControlDomain(conn)) {
  2257. return new Pair<VM, VM.Record>(vm, vm.getRecord(conn));
  2258. }
  2259. }
  2260. throw new CloudRuntimeException("Com'on no control domain? What the crap?!#@!##$@");
  2261. }
  2262. protected ReadyAnswer execute(ReadyCommand cmd) {
  2263. Connection conn = getConnection();
  2264. Long dcId = cmd.getDataCenterId();
  2265. // Ignore the result of the callHostPlugin. Even if unmounting the
  2266. // snapshots dir fails, let Ready command
  2267. // succeed.
  2268. callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString());
  2269. setupLinkLocalNetwork(conn);
  2270. _localGateway = callHostPlugin(conn, "vmops", "getgateway", "mgmtIP", _host.ip);
  2271. if (_localGateway == null || _localGateway.isEmpty()) {
  2272. String msg = "can not get gateway for host :" + _host.uuid;
  2273. s_logger.warn(msg);
  2274. return new ReadyAnswer(cmd, msg);
  2275. }
  2276. try {
  2277. boolean result = cleanupHaltedVms(conn);
  2278. if (!result) {
  2279. return new ReadyAnswer(cmd, "Unable to cleanup halted vms");
  2280. }
  2281. } catch (XenAPIException e) {
  2282. s_logger.warn("Unable to cleanup halted vms", e);
  2283. return new ReadyAnswer(cmd, "Unable to cleanup halted vms");
  2284. } catch (XmlRpcException e) {
  2285. s_logger.warn("Unable to cleanup halted vms", e);
  2286. return new ReadyAnswer(cmd, "Unable to cleanup halted vms");
  2287. }
  2288. return new ReadyAnswer(cmd);
  2289. }
  2290. //
  2291. // using synchronized on VM name in the caller does not prevent multiple
  2292. // commands being sent against
  2293. // the same VM, there will be a race condition here in finally clause and
  2294. // the main block if
  2295. // there are multiple requests going on
  2296. //
  2297. // Therefore, a lazy solution is to add a synchronized guard here
  2298. protected int getVncPort(Connection conn, VM vm) {
  2299. VM.Record record;
  2300. try {
  2301. record = vm.getRecord(conn);
  2302. Set<Console> consoles = record.consoles;
  2303. if (consoles.isEmpty()) {
  2304. s_logger.warn("There are no Consoles available to the vm : " + record.nameDescription);
  2305. return -1;
  2306. }
  2307. Iterator<Console> i = consoles.iterator();
  2308. } catch (XenAPIException e) {
  2309. String msg = "Unable to get vnc-port due to " + e.toString();
  2310. s_logger.warn(msg, e);
  2311. return -1;
  2312. } catch (XmlRpcException e) {
  2313. String msg = "Unable to get vnc-port due to " + e.getMessage();
  2314. s_logger.warn(msg, e);
  2315. return -1;
  2316. }
  2317. String hvm = "true";
  2318. if (record.HVMBootPolicy.isEmpty()) {
  2319. hvm = "false";
  2320. }
  2321. String vncport = callHostPlugin(conn, "vmops", "getvncport", "domID", record.domid.toString(), "hvm", hvm, "version", _host.product_version);
  2322. if (vncport == null || vncport.isEmpty()) {
  2323. return -1;
  2324. }
  2325. vncport = vncport.replace("\n", "");
  2326. return NumbersUtil.parseInt(vncport, -1);
  2327. }
  2328. protected String getVncUrl(Connection conn, VM vm) {
  2329. VM.Record record;
  2330. Console c;
  2331. String consoleurl;
  2332. try {
  2333. record = vm.getRecord(conn);
  2334. Set<Console> consoles = record.consoles;
  2335. if (consoles.isEmpty()) {
  2336. s_logger.warn("There are no Consoles available to the vm : " + record.nameDescription);
  2337. return null;
  2338. }
  2339. Iterator<Console> i = consoles.iterator();
  2340. c = i.next();
  2341. consoleurl = c.getLocation(conn);
  2342. } catch (XenAPIException e) {
  2343. String msg = "Unable to get console url due to " + e.toString();
  2344. s_logger.warn(msg, e);
  2345. return null;
  2346. } catch (XmlRpcException e) {
  2347. String msg = "Unable to get console url due to " + e.getMessage();
  2348. s_logger.warn(msg, e);
  2349. return null;
  2350. }
  2351. if (consoleurl.isEmpty())
  2352. return null;
  2353. else
  2354. return consoleurl;
  2355. }
  2356. @Override
  2357. public RebootAnswer execute(RebootCommand cmd) {
  2358. Connection conn = getConnection();
  2359. synchronized (_cluster.intern()) {
  2360. s_vms.put(_cluster, _name, cmd.getVmName(), State.Starting);
  2361. }
  2362. s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state");
  2363. try {
  2364. Set<VM> vms = null;
  2365. try {
  2366. vms = VM.getByNameLabel(conn, cmd.getVmName());
  2367. } catch (XenAPIException e0) {
  2368. s_logger.debug("getByNameLabel failed " + e0.toString());
  2369. return new RebootAnswer(cmd, "getByNameLabel failed " + e0.toString());
  2370. } catch (Exception e0) {
  2371. s_logger.debug("getByNameLabel failed " + e0.getMessage());
  2372. return new RebootAnswer(cmd, "getByNameLabel failed");
  2373. }
  2374. for (VM vm : vms) {
  2375. try {
  2376. rebootVM(conn, vm, vm.getNameLabel(conn));
  2377. } catch (Exception e) {
  2378. String msg = e.toString();
  2379. s_logger.warn(msg, e);
  2380. return new RebootAnswer(cmd, msg);
  2381. }
  2382. }
  2383. return new RebootAnswer(cmd, "reboot succeeded", null, null);
  2384. } finally {
  2385. synchronized (_cluster.intern()) {
  2386. s_vms.put(_cluster, _name, cmd.getVmName(), State.Running);
  2387. }
  2388. s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state");
  2389. }
  2390. }
  2391. protected Answer execute(RebootRouterCommand cmd) {
  2392. Connection conn = getConnection();
  2393. Long bytesSent = 0L;
  2394. Long bytesRcvd = 0L;
  2395. if (VirtualMachineName.isValidRouterName(cmd.getVmName())) {
  2396. long[] stats = getNetworkStats(conn, cmd.getPrivateIpAddress());
  2397. bytesSent = stats[0];
  2398. bytesRcvd = stats[1];
  2399. }
  2400. RebootAnswer answer = execute((RebootCommand) cmd);
  2401. answer.setBytesSent(bytesSent);
  2402. answer.setBytesReceived(bytesRcvd);
  2403. if (answer.getResult()) {
  2404. String cnct = connect(conn, cmd.getVmName(), cmd.getPrivateIpAddress());
  2405. networkUsage(conn, cmd.getPrivateIpAddress(), "create", null);
  2406. if (cnct == null) {
  2407. return answer;
  2408. } else {
  2409. return new Answer(cmd, false, cnct);
  2410. }
  2411. }
  2412. return answer;
  2413. }
  2414. protected void startvmfailhandle(Connection conn, VM vm, List<Ternary<SR, VDI, VolumeVO>> mounts) {
  2415. if (vm != null) {
  2416. try {
  2417. if (vm.getPowerState(conn) == VmPowerState.RUNNING) {
  2418. try {
  2419. vm.hardShutdown(conn);
  2420. } catch (Exception e) {
  2421. String msg = "VM hardshutdown failed due to " + e.toString();
  2422. s_logger.warn(msg, e);
  2423. }
  2424. }
  2425. if (vm.getPowerState(conn) == VmPowerState.HALTED) {
  2426. try {
  2427. vm.destroy(conn);
  2428. } catch (Exception e) {
  2429. String msg = "VM destroy failed due to " + e.toString();
  2430. s_logger.warn(msg, e);
  2431. }
  2432. }
  2433. } catch (Exception e) {
  2434. String msg = "VM getPowerState failed due to " + e.toString();
  2435. s_logger.warn(msg, e);
  2436. }
  2437. }
  2438. if (mounts != null) {
  2439. for (Ternary<SR, VDI, VolumeVO> mount : mounts) {
  2440. VDI vdi = mount.second();
  2441. Set<VBD> vbds = null;
  2442. try {
  2443. vbds = vdi.getVBDs(conn);
  2444. } catch (Exception e) {
  2445. String msg = "VDI getVBDS failed due to " + e.toString();
  2446. s_logger.warn(msg, e);
  2447. continue;
  2448. }
  2449. for (VBD vbd : vbds) {
  2450. try {
  2451. vbd.unplug(conn);
  2452. vbd.destroy(conn);
  2453. } catch (Exception e) {
  2454. String msg = "VBD destroy failed due to " + e.toString();
  2455. s_logger.warn(msg, e);
  2456. }
  2457. }
  2458. }
  2459. }
  2460. }
  2461. protected void setMemory(Connection conn, VM vm, long memsize) throws XmlRpcException, XenAPIException {
  2462. vm.setMemoryStaticMin(conn, memsize);
  2463. vm.setMemoryDynamicMin(conn, memsize);
  2464. vm.setMemoryDynamicMax(conn, memsize);
  2465. vm.setMemoryStaticMax(conn, memsize);
  2466. }
  2467. private void waitForTask(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException {
  2468. long beginTime = System.currentTimeMillis();
  2469. while (task.getStatus(c) == Types.TaskStatusType.PENDING) {
  2470. try {
  2471. Thread.sleep(pollInterval);
  2472. } catch (InterruptedException e) {
  2473. }
  2474. if( System.currentTimeMillis() - beginTime > timeout){
  2475. String msg = "Async " + timeout/1000 + " seconds timeout for task " + task.toString();
  2476. s_logger.warn(msg);
  2477. task.cancel(c);
  2478. throw new Types.BadAsyncResult(msg);
  2479. }
  2480. }
  2481. }
  2482. private void checkForSuccess(Connection c, Task task) throws XenAPIException, XmlRpcException {
  2483. if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) {
  2484. return;
  2485. } else {
  2486. String msg = "Task failed! Task record: " + task.getRecord(c);
  2487. s_logger.warn(msg);
  2488. task.cancel(c);
  2489. throw new Types.BadAsyncResult(msg);
  2490. }
  2491. }
  2492. void rebootVM(Connection conn, VM vm, String vmName) throws XmlRpcException {
  2493. Task task = null;
  2494. try {
  2495. task = vm.cleanRebootAsync(conn);
  2496. try {
  2497. //poll every 1 seconds , timeout after 10 minutes
  2498. waitForTask(conn, task, 1000, 10 * 60 * 1000);
  2499. checkForSuccess(conn, task);
  2500. } catch (Types.HandleInvalid e) {
  2501. if (vm.getPowerState(conn) == Types.VmPowerState.RUNNING) {
  2502. task = null;
  2503. return;
  2504. }
  2505. throw new CloudRuntimeException("Reboot VM catch HandleInvalid and VM is not in RUNNING state");
  2506. }
  2507. } catch (XenAPIException e) {
  2508. s_logger.debug("Unable to Clean Reboot VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString() + ", try hard reboot");
  2509. try {
  2510. vm.hardReboot(conn);
  2511. } catch (Exception e1) {
  2512. String msg = "Unable to hard Reboot VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString();
  2513. s_logger.warn(msg, e1);
  2514. throw new CloudRuntimeException(msg);
  2515. }
  2516. }finally {
  2517. if( task != null) {
  2518. try {
  2519. task.destroy(conn);
  2520. } catch (Exception e1) {
  2521. s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString());
  2522. }
  2523. }
  2524. }
  2525. }
  2526. void forceShutdownVM(Connection conn, VM vm) {
  2527. try {
  2528. Long domId = vm.getDomid(conn);
  2529. callHostPlugin(conn, "vmopspremium", "forceShutdownVM", "domId", domId.toString());
  2530. vm.powerStateReset(conn);
  2531. vm.destroy(conn);
  2532. } catch (Exception e) {
  2533. String msg = "forceShutdown failed due to " + e.toString();
  2534. s_logger.warn(msg, e);
  2535. throw new CloudRuntimeException(msg);
  2536. }
  2537. }
  2538. void shutdownVM(Connection conn, VM vm, String vmName) throws XmlRpcException {
  2539. Task task = null;
  2540. try {
  2541. task = vm.cleanShutdownAsync(conn);
  2542. try {
  2543. //poll every 1 seconds , timeout after 10 minutes
  2544. waitForTask(conn, task, 1000, 10 * 60 * 1000);
  2545. checkForSuccess(conn, task);
  2546. } catch (Types.HandleInvalid e) {
  2547. if (vm.getPowerState(conn) == Types.VmPowerState.HALTED) {
  2548. task = null;
  2549. return;
  2550. }
  2551. throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in HALTED state");
  2552. }
  2553. } catch (XenAPIException e) {
  2554. s_logger.debug("Unable to cleanShutdown VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString());
  2555. try {
  2556. Types.VmPowerState state = vm.getPowerState(conn);
  2557. if (state == Types.VmPowerState.RUNNING ) {
  2558. try {
  2559. vm.hardShutdown(conn);
  2560. } catch (Exception e1) {
  2561. s_logger.debug("Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString());
  2562. state = vm.getPowerState(conn);
  2563. if (state == Types.VmPowerState.RUNNING ) {
  2564. forceShutdownVM(conn, vm);
  2565. }
  2566. return;
  2567. }
  2568. } else if (state == Types.VmPowerState.HALTED ) {
  2569. return;
  2570. } else {
  2571. String msg = "After cleanShutdown the VM status is " + state.toString() + ", that is not expected";
  2572. s_logger.warn(msg);
  2573. throw new CloudRuntimeException(msg);
  2574. }
  2575. } catch (Exception e1) {
  2576. String msg = "Unable to hardShutdown VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString();
  2577. s_logger.warn(msg, e1);
  2578. throw new CloudRuntimeException(msg);
  2579. }
  2580. }finally {
  2581. if( task != null) {
  2582. try {
  2583. task.destroy(conn);
  2584. } catch (Exception e1) {
  2585. s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString());
  2586. }
  2587. }
  2588. }
  2589. }
  2590. void startVM(Connection conn, Host host, VM vm, String vmName) throws XmlRpcException {
  2591. Task task = null;
  2592. try {
  2593. task = vm.startOnAsync(conn, host, false, true);
  2594. try {
  2595. //poll every 1 seconds , timeout after 10 minutes
  2596. waitForTask(conn, task, 1000, 10 * 60 * 1000);
  2597. checkForSuccess(conn, task);
  2598. } catch (Types.HandleInvalid e) {
  2599. if (vm.getPowerState(conn) == Types.VmPowerState.RUNNING) {
  2600. task = null;
  2601. return;
  2602. }
  2603. throw new CloudRuntimeException("Shutdown VM catch HandleInvalid and VM is not in RUNNING state");
  2604. }
  2605. } catch (XenAPIException e) {
  2606. String msg = "Unable to start VM(" + vmName + ") on host(" + _host.uuid +") due to " + e.toString();
  2607. s_logger.warn(msg, e);
  2608. throw new CloudRuntimeException(msg);
  2609. }finally {
  2610. if( task != null) {
  2611. try {
  2612. task.destroy(conn);
  2613. } catch (Exception e1) {
  2614. s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString());
  2615. }
  2616. }
  2617. }
  2618. }
  2619. private
  2620. void migrateVM(Connection conn, Host destHost, VM vm, String vmName) throws XmlRpcException {
  2621. Task task = null;
  2622. try {
  2623. Map<String, String> other = new HashMap<String, String>();
  2624. other.put("live", "true");
  2625. task = vm.poolMigrateAsync(conn, destHost, other);
  2626. try {
  2627. // poll every 1 seconds
  2628. long timeout = (_migratewait) * 1000L;
  2629. waitForTask(conn, task, 1000, timeout);
  2630. checkForSuccess(conn, task);
  2631. } catch (Types.HandleInvalid e) {
  2632. if (vm.getResidentOn(conn).equals(destHost)) {
  2633. task = null;
  2634. return;
  2635. }
  2636. throw new CloudRuntimeException("migrate VM catch HandleInvalid and VM is not running on dest host");
  2637. }
  2638. } catch (XenAPIException e) {
  2639. String msg = "Unable to migrate VM(" + vmName + ") from host(" + _host.uuid +") due to " + e.toString();
  2640. s_logger.warn(msg, e);
  2641. throw new CloudRuntimeException(msg);
  2642. }finally {
  2643. if( task != null) {
  2644. try {
  2645. task.destroy(conn);
  2646. } catch (Exception e1) {
  2647. s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString());
  2648. }
  2649. }
  2650. }
  2651. }
  2652. protected VDI cloudVDIcopy(Connection conn, VDI vdi, SR sr, int wait) throws XenAPIException, XmlRpcException {
  2653. Task task = null;
  2654. if ( wait == 0 ) {
  2655. wait = 2 * 60 * 60;
  2656. }
  2657. try {
  2658. task = vdi.copyAsync(conn, sr);
  2659. // poll every 1 seconds , timeout after 2 hours
  2660. waitForTask(conn, task, 1000, wait * 1000);
  2661. checkForSuccess(conn, task);
  2662. VDI dvdi = Types.toVDI(task, conn);
  2663. return dvdi;
  2664. } finally {
  2665. if (task != null) {
  2666. try {
  2667. task.destroy(conn);
  2668. } catch (Exception e1) {
  2669. s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1);
  2670. }
  2671. }
  2672. }
  2673. }
  2674. boolean swiftDownload(Connection conn, SwiftTO swift, String container, String rfilename, String dir, String lfilename, Boolean remote) {
  2675. String result = null;
  2676. try {
  2677. result = callHostPluginAsync(conn, "swiftxen", "swift", 60 * 60,
  2678. "op", "download", "url", swift.getUrl(), "account", swift.getAccount(),
  2679. "username", swift.getUserName(), "key", swift.getKey(), "rfilename", rfilename,
  2680. "dir", dir, "lfilename", lfilename, "remote", remote.toString());
  2681. if( result != null && result.equals("true")) {
  2682. return true;
  2683. }
  2684. } catch (Exception e) {
  2685. s_logger.warn("swift download failed due to ", e);
  2686. }
  2687. return false;
  2688. }
  2689. boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) {
  2690. String result = null;
  2691. try {
  2692. result = callHostPluginAsync(conn, "swiftxen", "swift", wait,
  2693. "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(),
  2694. "username", swift.getUserName(), "key", swift.getKey(), "container", container,
  2695. "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString());
  2696. if( result != null && result.equals("true")) {
  2697. return true;
  2698. }
  2699. } catch (Exception e) {
  2700. s_logger.warn("swift upload failed due to " + e.toString(), e);
  2701. }
  2702. return false;
  2703. }
  2704. boolean swiftDelete(Connection conn, SwiftTO swift, String rfilename) {
  2705. String result = null;
  2706. try {
  2707. result = callHostPlugin(conn, "swiftxen", "swift",
  2708. "op", "delete", "url", swift.getUrl(), "account", swift.getAccount(),
  2709. "username", swift.getUserName(), "key", swift.getKey(), "rfilename", rfilename);
  2710. if( result != null && result.equals("true")) {
  2711. return true;
  2712. }
  2713. } catch (Exception e) {
  2714. s_logger.warn("swift download failed due to ", e);
  2715. }
  2716. return false;
  2717. }
  2718. private void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) {
  2719. String lfilename;
  2720. String ldir;
  2721. if ( isISCSI ) {
  2722. ldir = "/dev/VG_XenStorage-" + srUuid;
  2723. lfilename = "VHD-" + snapshotUuid;
  2724. } else {
  2725. ldir = "/var/run/sr-mount/" + srUuid;
  2726. lfilename = snapshotUuid + ".vhd";
  2727. }
  2728. swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait);
  2729. }
  2730. protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, Long dcId, Long accountId,
  2731. Long volumeId, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) {
  2732. String backupSnapshotUuid = null;
  2733. if (prevBackupUuid == null) {
  2734. prevBackupUuid = "";
  2735. }
  2736. // Each argument is put in a separate line for readability.
  2737. // Using more lines does not harm the environment.
  2738. String backupUuid = UUID.randomUUID().toString();
  2739. String results = callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait,
  2740. "primaryStorageSRUuid", primaryStorageSRUuid, "dcId", dcId.toString(), "accountId", accountId.toString(),
  2741. "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath,
  2742. "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString());
  2743. String errMsg = null;
  2744. if (results == null || results.isEmpty()) {
  2745. errMsg = "Could not copy backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId
  2746. + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
  2747. + secondaryStorageMountPath + " due to null";
  2748. } else {
  2749. String[] tmp = results.split("#");
  2750. String status = tmp[0];
  2751. backupSnapshotUuid = tmp[1];
  2752. // status == "1" if and only if backupSnapshotUuid != null
  2753. // So we don't rely on status value but return backupSnapshotUuid as an
  2754. // indicator of success.
  2755. if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) {
  2756. s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId
  2757. + " to secondary storage");
  2758. return backupSnapshotUuid;
  2759. } else {
  2760. errMsg = "Could not copy backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId
  2761. + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
  2762. + secondaryStorageMountPath + " due to " + tmp[1];
  2763. }
  2764. }
  2765. String source = backupUuid + ".vhd";
  2766. killCopyProcess(conn, source);
  2767. s_logger.warn(errMsg);
  2768. return null;
  2769. }
  2770. protected String callHostPluginAsync(Connection conn, String plugin, String cmd, int wait, String... params) {
  2771. int timeout = wait * 1000;
  2772. Map<String, String> args = new HashMap<String, String>();
  2773. Task task = null;
  2774. try {
  2775. for (int i = 0; i < params.length; i += 2) {
  2776. args.put(params[i], params[i + 1]);
  2777. }
  2778. if (s_logger.isTraceEnabled()) {
  2779. s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
  2780. }
  2781. Host host = Host.getByUuid(conn, _host.uuid);
  2782. task = host.callPluginAsync(conn, plugin, cmd, args);
  2783. // poll every 1 seconds
  2784. waitForTask(conn, task, 1000, timeout);
  2785. checkForSuccess(conn, task);
  2786. String result = task.getResult(conn);
  2787. if (s_logger.isTraceEnabled()) {
  2788. s_logger.trace("callHostPlugin Result: " + result);
  2789. }
  2790. return result.replace("<value>", "").replace("</value>", "").replace("\n", "");
  2791. } catch (Types.HandleInvalid e) {
  2792. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args)
  2793. + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + e.handle);
  2794. } catch (XenAPIException e) {
  2795. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to "
  2796. + e.toString(), e);
  2797. } catch (XmlRpcException e) {
  2798. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to "
  2799. + e.getMessage(), e);
  2800. } finally {
  2801. if (task != null) {
  2802. try {
  2803. task.destroy(conn);
  2804. } catch (Exception e1) {
  2805. s_logger.warn("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid + ") due to ", e1);
  2806. }
  2807. }
  2808. }
  2809. return null;
  2810. }
  2811. @Override
  2812. public StopAnswer execute(StopCommand cmd) {
  2813. String vmName = cmd.getVmName();
  2814. try {
  2815. Connection conn = getConnection();
  2816. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  2817. // stop vm which is running on this host or is in halted state
  2818. Iterator<VM> iter = vms.iterator();
  2819. while ( iter.hasNext() ) {
  2820. VM vm = iter.next();
  2821. VM.Record vmr = vm.getRecord(conn);
  2822. if (vmr.powerState != VmPowerState.RUNNING) {
  2823. continue;
  2824. }
  2825. if (isRefNull(vmr.residentOn)) {
  2826. continue;
  2827. }
  2828. if (vmr.residentOn.getUuid(conn).equals(_host.uuid)) {
  2829. continue;
  2830. }
  2831. iter.remove();
  2832. }
  2833. if (vms.size() == 0) {
  2834. synchronized (_cluster.intern()) {
  2835. s_logger.info("VM does not exist on XenServer" + _host.uuid);
  2836. s_vms.remove(_cluster, _name, vmName);
  2837. }
  2838. return new StopAnswer(cmd, "VM does not exist", 0 , 0L, 0L);
  2839. }
  2840. Long bytesSent = 0L;
  2841. Long bytesRcvd = 0L;
  2842. for (VM vm : vms) {
  2843. VM.Record vmr = vm.getRecord(conn);
  2844. if (vmr.isControlDomain) {
  2845. String msg = "Tring to Shutdown control domain";
  2846. s_logger.warn(msg);
  2847. return new StopAnswer(cmd, msg);
  2848. }
  2849. if (vmr.powerState == VmPowerState.RUNNING && !isRefNull(vmr.residentOn) && !vmr.residentOn.getUuid(conn).equals(_host.uuid)) {
  2850. String msg = "Stop Vm " + vmName + " failed due to this vm is not running on this host: " + _host.uuid + " but host:" + vmr.residentOn.getUuid(conn);
  2851. s_logger.warn(msg);
  2852. return new StopAnswer(cmd, msg);
  2853. }
  2854. State state = s_vms.getState(_cluster, vmName);
  2855. synchronized (_cluster.intern()) {
  2856. s_vms.put(_cluster, _name, vmName, State.Stopping);
  2857. }
  2858. s_logger.debug("9. The VM " + vmName + " is in Stopping state");
  2859. try {
  2860. if (vmr.powerState == VmPowerState.RUNNING) {
  2861. /* when stop a vm, set affinity to current xenserver */
  2862. vm.setAffinity(conn, vm.getResidentOn(conn));
  2863. if (VirtualMachineName.isValidRouterName(vmName)) {
  2864. if (cmd.getPrivateRouterIpAddress() != null) {
  2865. long[] stats = getNetworkStats(conn, cmd.getPrivateRouterIpAddress());
  2866. bytesSent = stats[0];
  2867. bytesRcvd = stats[1];
  2868. }
  2869. }
  2870. if (_canBridgeFirewall) {
  2871. String result = callHostPlugin(conn, "vmops", "destroy_network_rules_for_vm", "vmName", cmd
  2872. .getVmName());
  2873. if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
  2874. s_logger.warn("Failed to remove network rules for vm " + cmd.getVmName());
  2875. } else {
  2876. s_logger.info("Removed network rules for vm " + cmd.getVmName());
  2877. }
  2878. }
  2879. shutdownVM(conn, vm, vmName);
  2880. }
  2881. } catch (Exception e) {
  2882. String msg = "Catch exception " + e.getClass().getName() + " when stop VM:" + cmd.getVmName() + " due to " + e.toString();
  2883. s_logger.debug(msg);
  2884. return new StopAnswer(cmd, msg);
  2885. } finally {
  2886. try {
  2887. if (vm.getPowerState(conn) == VmPowerState.HALTED) {
  2888. Set<VIF> vifs = vm.getVIFs(conn);
  2889. List<Network> networks = new ArrayList<Network>();
  2890. for (VIF vif : vifs) {
  2891. networks.add(vif.getNetwork(conn));
  2892. }
  2893. List<VDI> vdis = getVdis(conn, vm);
  2894. vm.destroy(conn);
  2895. for( VDI vdi : vdis ){
  2896. umount(conn, vdi);
  2897. }
  2898. state = State.Stopped;
  2899. SR sr = getISOSRbyVmName(conn, cmd.getVmName());
  2900. removeSR(conn, sr);
  2901. // Disable any VLAN networks that aren't used
  2902. // anymore
  2903. for (Network network : networks) {
  2904. if (network.getNameLabel(conn).startsWith("VLAN")) {
  2905. disableVlanNetwork(conn, network);
  2906. }
  2907. }
  2908. return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, bytesSent, bytesRcvd);
  2909. }
  2910. } catch (XenAPIException e) {
  2911. String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString();
  2912. s_logger.warn(msg, e);
  2913. } catch (Exception e) {
  2914. String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.getMessage();
  2915. s_logger.warn(msg, e);
  2916. } finally {
  2917. synchronized (_cluster.intern()) {
  2918. s_vms.put(_cluster, _name, vmName, state);
  2919. }
  2920. s_logger.debug("10. The VM " + vmName + " is in " + state + " state");
  2921. }
  2922. }
  2923. }
  2924. } catch (XenAPIException e) {
  2925. String msg = "Stop Vm " + vmName + " fail due to " + e.toString();
  2926. s_logger.warn(msg, e);
  2927. return new StopAnswer(cmd, msg);
  2928. } catch (XmlRpcException e) {
  2929. String msg = "Stop Vm " + vmName + " fail due to " + e.getMessage();
  2930. s_logger.warn(msg, e);
  2931. return new StopAnswer(cmd, msg);
  2932. } catch (Exception e) {
  2933. s_logger.warn("Unable to stop " + vmName + " due to ", e);
  2934. return new StopAnswer(cmd, e);
  2935. }
  2936. return new StopAnswer(cmd, "Stop VM failed");
  2937. }
  2938. private List<VDI> getVdis(Connection conn, VM vm) {
  2939. List<VDI> vdis = new ArrayList<VDI>();
  2940. try {
  2941. Set<VBD> vbds =vm.getVBDs(conn);
  2942. for( VBD vbd : vbds ) {
  2943. vdis.add(vbd.getVDI(conn));
  2944. }
  2945. } catch (XenAPIException e) {
  2946. String msg = "getVdis can not get VPD due to " + e.toString();
  2947. s_logger.warn(msg, e);
  2948. } catch (XmlRpcException e) {
  2949. String msg = "getVdis can not get VPD due to " + e.getMessage();
  2950. s_logger.warn(msg, e);
  2951. }
  2952. return vdis;
  2953. }
  2954. protected String connect(Connection conn, final String vmName, final String ipAddress, final int port) {
  2955. for (int i = 0; i <= _retry; i++) {
  2956. try {
  2957. Set<VM> vms = VM.getByNameLabel(conn, vmName);
  2958. if (vms.size() < 1) {
  2959. String msg = "VM " + vmName + " is not running";
  2960. s_logger.warn(msg);
  2961. return msg;
  2962. }
  2963. } catch (Exception e) {
  2964. String msg = "VM.getByNameLabel " + vmName + " failed due to " + e.toString();
  2965. s_logger.warn(msg, e);
  2966. return msg;
  2967. }
  2968. if (s_logger.isDebugEnabled()) {
  2969. s_logger.debug("Trying to connect to " + ipAddress);
  2970. }
  2971. if (pingdomr(conn, ipAddress, Integer.toString(port))) {
  2972. return null;
  2973. }
  2974. try {
  2975. Thread.sleep(_sleep);
  2976. } catch (final InterruptedException e) {
  2977. }
  2978. }
  2979. String msg = "Timeout, Unable to logon to " + ipAddress;
  2980. s_logger.debug(msg);
  2981. return msg;
  2982. }
  2983. protected String connect(Connection conn, final String vmname, final String ipAddress) {
  2984. return connect(conn, vmname, ipAddress, 3922);
  2985. }
  2986. protected boolean isDeviceUsed(Connection conn, VM vm, Long deviceId) {
  2987. // Figure out the disk number to attach the VM to
  2988. String msg = null;
  2989. try {
  2990. Set<String> allowedVBDDevices = vm.getAllowedVBDDevices(conn);
  2991. if (allowedVBDDevices.contains(deviceId.toString())) {
  2992. return false;
  2993. }
  2994. return true;
  2995. } catch (XmlRpcException e) {
  2996. msg = "Catch XmlRpcException due to: " + e.getMessage();
  2997. s_logger.warn(msg, e);
  2998. } catch (XenAPIException e) {
  2999. msg = "Catch XenAPIException due to: " + e.toString();
  3000. s_logger.warn(msg, e);
  3001. }
  3002. throw new CloudRuntimeException("When check deviceId " + msg);
  3003. }
  3004. protected String getUnusedDeviceNum(Connection conn, VM vm) {
  3005. // Figure out the disk number to attach the VM to
  3006. try {
  3007. Set<String> allowedVBDDevices = vm.getAllowedVBDDevices(conn);
  3008. if (allowedVBDDevices.size() == 0) {
  3009. throw new CloudRuntimeException("Could not find an available slot in VM with name: " + vm.getNameLabel(conn) + " to attach a new disk.");
  3010. }
  3011. return allowedVBDDevices.iterator().next();
  3012. } catch (XmlRpcException e) {
  3013. String msg = "Catch XmlRpcException due to: " + e.getMessage();
  3014. s_logger.warn(msg, e);
  3015. } catch (XenAPIException e) {
  3016. String msg = "Catch XenAPIException due to: " + e.toString();
  3017. s_logger.warn(msg, e);
  3018. }
  3019. throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk.");
  3020. }
  3021. protected String callHostPlugin(Connection conn, String plugin, String cmd, String... params) {
  3022. Map<String, String> args = new HashMap<String, String>();
  3023. String msg;
  3024. try {
  3025. for (int i = 0; i < params.length; i += 2) {
  3026. args.put(params[i], params[i + 1]);
  3027. }
  3028. if (s_logger.isTraceEnabled()) {
  3029. s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
  3030. }
  3031. Host host = Host.getByUuid(conn, _host.uuid);
  3032. String result = host.callPlugin(conn, plugin, cmd, args);
  3033. if (s_logger.isTraceEnabled()) {
  3034. s_logger.trace("callHostPlugin Result: " + result);
  3035. }
  3036. return result.replace("\n", "");
  3037. } catch (XenAPIException e) {
  3038. msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString();
  3039. s_logger.warn(msg);
  3040. } catch (XmlRpcException e) {
  3041. msg = "callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage();
  3042. s_logger.debug(msg);
  3043. }
  3044. throw new CloudRuntimeException(msg);
  3045. }
  3046. protected String getArgsString(Map<String, String> args) {
  3047. StringBuilder argString = new StringBuilder();
  3048. for (Map.Entry<String, String> arg : args.entrySet()) {
  3049. argString.append(arg.getKey() + ": " + arg.getValue() + ", ");
  3050. }
  3051. return argString.toString();
  3052. }
  3053. protected boolean setIptables(Connection conn) {
  3054. String result = callHostPlugin(conn, "vmops", "setIptables");
  3055. if (result == null || result.isEmpty()) {
  3056. return false;
  3057. }
  3058. return true;
  3059. }
  3060. protected XsLocalNetwork getManagementNetwork(Connection conn) throws XmlRpcException, XenAPIException {
  3061. PIF mgmtPif = null;
  3062. PIF.Record mgmtPifRec = null;
  3063. Host host = Host.getByUuid(conn, _host.uuid);
  3064. Set<PIF> hostPifs = host.getPIFs(conn);
  3065. for (PIF pif : hostPifs) {
  3066. PIF.Record rec = pif.getRecord(conn);
  3067. if (rec.management) {
  3068. if (rec.VLAN != null && rec.VLAN != -1) {
  3069. String msg = new StringBuilder("Unsupported configuration. Management network is on a VLAN. host=").append(_host.uuid).append("; pif=").append(rec.uuid)
  3070. .append("; vlan=").append(rec.VLAN).toString();
  3071. s_logger.warn(msg);
  3072. throw new CloudRuntimeException(msg);
  3073. }
  3074. if (s_logger.isDebugEnabled()) {
  3075. s_logger.debug("Management network is on pif=" + rec.uuid);
  3076. }
  3077. mgmtPif = pif;
  3078. mgmtPifRec = rec;
  3079. break;
  3080. }
  3081. }
  3082. if (mgmtPif == null) {
  3083. String msg = "Unable to find management network for " + _host.uuid;
  3084. s_logger.warn(msg);
  3085. throw new CloudRuntimeException(msg);
  3086. }
  3087. Bond bond = mgmtPifRec.bondSlaveOf;
  3088. if ( !isRefNull(bond) ) {
  3089. String msg = "Management interface is on slave(" +mgmtPifRec.uuid + ") of bond("
  3090. + bond.getUuid(conn) + ") on host(" +_host.uuid + "), please move management interface to bond!";
  3091. s_logger.warn(msg);
  3092. throw new CloudRuntimeException(msg);
  3093. }
  3094. Network nk = mgmtPifRec.network;
  3095. Network.Record nkRec = nk.getRecord(conn);
  3096. return new XsLocalNetwork(nk, nkRec, mgmtPif, mgmtPifRec);
  3097. }
  3098. protected VIF getCorrectVif(Connection conn, VM router, Network network) throws XmlRpcException, XenAPIException {
  3099. Set<VIF> routerVIFs = router.getVIFs(conn);
  3100. for (VIF vif : routerVIFs) {
  3101. Network vifNetwork = vif.getNetwork(conn);
  3102. if (vifNetwork.getUuid(conn).equals(network.getUuid(conn))) {
  3103. return vif;
  3104. }
  3105. }
  3106. return null;
  3107. }
  3108. protected String getLowestAvailableVIFDeviceNum(Connection conn, VM vm) {
  3109. try {
  3110. Set<String> availableDeviceNums = vm.getAllowedVIFDevices(conn);
  3111. Iterator<String> deviceNumsIterator = availableDeviceNums.iterator();
  3112. List<Integer> sortedDeviceNums = new ArrayList<Integer>();
  3113. while (deviceNumsIterator.hasNext()) {
  3114. try {
  3115. sortedDeviceNums.add(Integer.valueOf(deviceNumsIterator.next()));
  3116. } catch (NumberFormatException e) {
  3117. s_logger.debug("Obtained an invalid value for an available VIF device number for VM: " + vm.getNameLabel(conn));
  3118. return null;
  3119. }
  3120. }
  3121. Collections.sort(sortedDeviceNums);
  3122. return String.valueOf(sortedDeviceNums.get(0));
  3123. } catch (XmlRpcException e) {
  3124. String msg = "Caught XmlRpcException: " + e.getMessage();
  3125. s_logger.warn(msg, e);
  3126. } catch (XenAPIException e) {
  3127. String msg = "Caught XenAPIException: " + e.toString();
  3128. s_logger.warn(msg, e);
  3129. }
  3130. return null;
  3131. }
  3132. protected VDI mount(Connection conn, StoragePoolType pooltype, String volumeFolder, String volumePath) {
  3133. return getVDIbyUuid(conn, volumePath);
  3134. }
  3135. /**
  3136. * getNetworkByName() retrieves what the server thinks is the actual
  3137. * network used by the XenServer host. This method should always be
  3138. * used to talk to retrieve a network by the name. The reason is
  3139. * because of the problems in using the name label as the way to find
  3140. * the Network.
  3141. *
  3142. * To see how we are working around these problems, take a look at
  3143. * enableVlanNetwork(). The following description assumes you have looked
  3144. * at the description on that method.
  3145. *
  3146. * In order to understand this, we have to see what type of networks are
  3147. * within a XenServer that's under CloudStack control.
  3148. *
  3149. * - Native Networks: these are networks that are untagged on the
  3150. * XenServer and are used to crate VLAN networks on. These are
  3151. * created by the user and is assumed to be one per cluster.
  3152. * - VLAN Networks: these are dynamically created by CloudStack and can
  3153. * have problems with duplicated names.
  3154. * - LinkLocal Networks: these are dynamically created by CloudStack and
  3155. * can also have problems with duplicated names but these don't have
  3156. * actual PIFs.
  3157. *
  3158. * In order to speed to retrieval of a network, we do the following:
  3159. * - We retrieve by the name. If only one network is retrieved, we
  3160. * assume we retrieved the right network.
  3161. * - If more than one network is retrieved, we check to see which one
  3162. * has the pif for the local host and use that.
  3163. * - If a pif is not found, then we look at the tags and find the
  3164. * one with the lowest timestamp. (See enableVlanNetwork())
  3165. *
  3166. * @param conn Xapi connection
  3167. * @param name name of the network
  3168. * @return XsNic an object that contains network, network record, pif, and pif record.
  3169. * @throws XenAPIException
  3170. * @throws XmlRpcException
  3171. *
  3172. * @see enableVlanNetwork
  3173. */
  3174. protected XsLocalNetwork getNetworkByName(Connection conn, String name) throws XenAPIException, XmlRpcException {
  3175. Set<Network> networks = Network.getByNameLabel(conn, name);
  3176. if (networks.size() == 1) {
  3177. return new XsLocalNetwork(networks.iterator().next(), null, null, null);
  3178. }
  3179. if (networks.size() == 0) {
  3180. return null;
  3181. }
  3182. if (s_logger.isDebugEnabled()) {
  3183. s_logger.debug("Found more than one network with the name " + name);
  3184. }
  3185. Network earliestNetwork = null;
  3186. Network.Record earliestNetworkRecord = null;
  3187. long earliestTimestamp = Long.MAX_VALUE;
  3188. int earliestRandom = Integer.MAX_VALUE;
  3189. for (Network network : networks) {
  3190. XsLocalNetwork nic = new XsLocalNetwork(network);
  3191. if (nic.getPif(conn) != null) {
  3192. return nic;
  3193. }
  3194. Network.Record record = network.getRecord(conn);
  3195. if (record.tags != null) {
  3196. for (String tag : record.tags) {
  3197. Pair<Long, Integer> stamp = parseTimestamp(tag);
  3198. if (stamp == null) {
  3199. continue;
  3200. }
  3201. if (stamp.first() < earliestTimestamp || (stamp.first() == earliestTimestamp && stamp.second() < earliestRandom)) {
  3202. earliestTimestamp = stamp.first();
  3203. earliestRandom = stamp.second();
  3204. earliestNetwork = network;
  3205. earliestNetworkRecord = record;
  3206. }
  3207. }
  3208. }
  3209. }
  3210. return earliestNetwork != null ? new XsLocalNetwork(earliestNetwork, earliestNetworkRecord, null, null) : null;
  3211. }
  3212. protected String generateTimeStamp() {
  3213. return new StringBuilder("CsCreateTime-").append(System.currentTimeMillis()).append("-").append(_rand.nextInt()).toString();
  3214. }
  3215. protected Pair<Long, Integer> parseTimestamp(String timeStampStr) {
  3216. String[] tokens = timeStampStr.split("-");
  3217. assert(tokens.length == 3) : "It's our timestamp but it doesn't fit our format: " + timeStampStr;
  3218. if (!tokens[0].equals("CsCreateTime-")) {
  3219. return null;
  3220. }
  3221. return new Pair<Long, Integer>(Long.parseLong(tokens[1]), Integer.parseInt(tokens[2]));
  3222. }
  3223. /**
  3224. * enableVlanNetwork creates a Network object, Vlan object, and thereby
  3225. * a tagged PIF object in Xapi.
  3226. *
  3227. * In XenServer, VLAN is added by
  3228. * - Create a network, which is unique cluster wide.
  3229. * - Find the PIF that you want to create the VLAN on.
  3230. * - Create a VLAN using the network and the PIF. As a result of this
  3231. * operation, a tagged PIF object is also created.
  3232. *
  3233. * Here is a list of problems with clustered Xapi implementation that
  3234. * we are trying to circumvent.
  3235. * - There can be multiple Networks with the same name-label so searching
  3236. * using name-label is not unique.
  3237. * - There are no other ways to search for Networks other than listing
  3238. * all of them which is not efficient in our implementation because
  3239. * we can have over 4000 VLAN networks.
  3240. * - In a clustered situation, it's possible for both hosts to detect
  3241. * that the Network is missing and both creates it. This causes a
  3242. * lot of problems as one host may be using one Network and another
  3243. * may be using a different network for their VMs. This causes
  3244. * problems in migration because the VMs are logically attached
  3245. * to different networks in Xapi's database but in reality, they
  3246. * are attached to the same network.
  3247. *
  3248. * To work around these problems, we do the following.
  3249. *
  3250. * - When creating the VLAN network, we name it as VLAN-UUID of the
  3251. * Network it is created on-VLAN Tag. Because VLAN tags is unique with
  3252. * one particular network, this is a unique name-label to quickly
  3253. * retrieve the the VLAN network with when we need it again.
  3254. * - When we create the VLAN network, we add a timestamp and a random
  3255. * number as a tag into the network. Then instead of creating
  3256. * VLAN on that network, we actually retrieve the Network again
  3257. * and this time uses the VLAN network with lowest timestamp or
  3258. * lowest random number as the VLAN network. This allows VLAN creation
  3259. * to happen on multiple hosts concurrently but even if two VLAN
  3260. * networks were created with the same name, only one of them is used.
  3261. *
  3262. * One cavaet about this approach is that it relies on the timestamp to
  3263. * be relatively accurate among different hosts.
  3264. *
  3265. * @param conn Xapi Connection
  3266. * @param tag VLAN tag
  3267. * @param network network on this host to create the VLAN on.
  3268. * @return VLAN Network created.
  3269. * @throws XenAPIException
  3270. * @throws XmlRpcException
  3271. */
  3272. protected Network enableVlanNetwork(Connection conn, long tag, XsLocalNetwork network) throws XenAPIException, XmlRpcException {
  3273. Network vlanNetwork = null;
  3274. String oldName = "VLAN" + Long.toString(tag);
  3275. String newName = "VLAN-" + network.getNetworkRecord(conn).uuid + "-" + tag;
  3276. XsLocalNetwork vlanNic = getNetworkByName(conn, newName);
  3277. if (vlanNic == null) {
  3278. if (s_logger.isDebugEnabled()) {
  3279. s_logger.debug("Couldn't find vlan network with the new name so trying old name: " + oldName);
  3280. }
  3281. vlanNic = getNetworkByName(conn, oldName);
  3282. if (vlanNic != null) {
  3283. s_logger.info("Renaming VLAN with old name " + oldName + " to " + newName);
  3284. vlanNic.getNetwork().setNameLabel(conn, newName);
  3285. }
  3286. }
  3287. if (vlanNic == null) { // Can't find it, then create it.
  3288. if (s_logger.isDebugEnabled()) {
  3289. s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip);
  3290. }
  3291. Network.Record nwr = new Network.Record();
  3292. nwr.nameLabel = newName;
  3293. nwr.tags = new HashSet<String>();
  3294. nwr.tags.add(generateTimeStamp());
  3295. vlanNetwork = Network.create(conn, nwr);
  3296. vlanNic = getNetworkByName(conn, newName);
  3297. }
  3298. PIF nPif = network.getPif(conn);
  3299. PIF.Record nPifr = network.getPifRecord(conn);
  3300. vlanNetwork = vlanNic.getNetwork();
  3301. if (vlanNic.getPif(conn) != null) {
  3302. return vlanNetwork;
  3303. }
  3304. if (s_logger.isDebugEnabled()) {
  3305. s_logger.debug("Creating VLAN " + tag + " on host " + _host.ip + " on device " + nPifr.device);
  3306. }
  3307. VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork);
  3308. VLAN.Record vlanr = vlan.getRecord(conn);
  3309. if (s_logger.isDebugEnabled()) {
  3310. s_logger.debug("VLAN is created for " + tag + ". The uuid is " + vlanr.uuid);
  3311. }
  3312. return vlanNetwork;
  3313. }
  3314. protected void disableVlanNetwork(Connection conn, Network network) {
  3315. }
  3316. protected SR getLocalLVMSR(Connection conn) {
  3317. try {
  3318. Map<SR, SR.Record> map = SR.getAllRecords(conn);
  3319. for (Map.Entry<SR, SR.Record> entry : map.entrySet()) {
  3320. SR.Record srRec = entry.getValue();
  3321. if (SRType.LVM.equals(srRec.type)) {
  3322. Set<PBD> pbds = srRec.PBDs;
  3323. if (pbds == null) {
  3324. continue;
  3325. }
  3326. for (PBD pbd : pbds) {
  3327. Host host = pbd.getHost(conn);
  3328. if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) {
  3329. if (!pbd.getCurrentlyAttached(conn)) {
  3330. pbd.plug(conn);
  3331. }
  3332. SR sr = entry.getKey();
  3333. sr.scan(conn);
  3334. return sr;
  3335. }
  3336. }
  3337. }
  3338. }
  3339. } catch (XenAPIException e) {
  3340. String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.toString();
  3341. s_logger.warn(msg);
  3342. } catch (XmlRpcException e) {
  3343. String msg = "Unable to get local LVMSR in host:" + _host.uuid + e.getCause();
  3344. s_logger.warn(msg);
  3345. }
  3346. return null;
  3347. }
  3348. protected SR getLocalEXTSR(Connection conn) {
  3349. try {
  3350. Map<SR, SR.Record> map = SR.getAllRecords(conn);
  3351. for (Map.Entry<SR, SR.Record> entry : map.entrySet()) {
  3352. SR.Record srRec = entry.getValue();
  3353. if (SRType.EXT.equals(srRec.type)) {
  3354. Set<PBD> pbds = srRec.PBDs;
  3355. if (pbds == null) {
  3356. continue;
  3357. }
  3358. for (PBD pbd : pbds) {
  3359. Host host = pbd.getHost(conn);
  3360. if (!isRefNull(host) && host.getUuid(conn).equals(_host.uuid)) {
  3361. if (!pbd.getCurrentlyAttached(conn)) {
  3362. pbd.plug(conn);
  3363. }
  3364. SR sr = entry.getKey();
  3365. sr.scan(conn);
  3366. return sr;
  3367. }
  3368. }
  3369. }
  3370. }
  3371. } catch (XenAPIException e) {
  3372. String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.toString();
  3373. s_logger.warn(msg);
  3374. } catch (XmlRpcException e) {
  3375. String msg = "Unable to get local EXTSR in host:" + _host.uuid + e.getCause();
  3376. s_logger.warn(msg);
  3377. }
  3378. return null;
  3379. }
  3380. protected StartupStorageCommand initializeLocalSR(Connection conn) {
  3381. SR lvmsr = getLocalLVMSR(conn);
  3382. if (lvmsr != null) {
  3383. try {
  3384. String lvmuuid = lvmsr.getUuid(conn);
  3385. long cap = lvmsr.getPhysicalSize(conn);
  3386. if (cap > 0) {
  3387. long avail = cap - lvmsr.getPhysicalUtilisation(conn);
  3388. lvmsr.setNameLabel(conn, lvmuuid);
  3389. String name = "Cloud Stack Local LVM Storage Pool for " + _host.uuid;
  3390. lvmsr.setNameDescription(conn, name);
  3391. Host host = Host.getByUuid(conn, _host.uuid);
  3392. String address = host.getAddress(conn);
  3393. StoragePoolInfo pInfo = new StoragePoolInfo(lvmuuid, address, SRType.LVM.toString(), SRType.LVM.toString(), StoragePoolType.LVM, cap, avail);
  3394. StartupStorageCommand cmd = new StartupStorageCommand();
  3395. cmd.setPoolInfo(pInfo);
  3396. cmd.setGuid(_host.uuid);
  3397. cmd.setDataCenter(Long.toString(_dcId));
  3398. cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL);
  3399. return cmd;
  3400. }
  3401. } catch (XenAPIException e) {
  3402. String msg = "build local LVM info err in host:" + _host.uuid + e.toString();
  3403. s_logger.warn(msg);
  3404. } catch (XmlRpcException e) {
  3405. String msg = "build local LVM info err in host:" + _host.uuid + e.getMessage();
  3406. s_logger.warn(msg);
  3407. }
  3408. }
  3409. SR extsr = getLocalEXTSR(conn);
  3410. if (extsr != null) {
  3411. try {
  3412. String extuuid = extsr.getUuid(conn);
  3413. long cap = extsr.getPhysicalSize(conn);
  3414. if (cap > 0) {
  3415. long avail = cap - extsr.getPhysicalUtilisation(conn);
  3416. extsr.setNameLabel(conn, extuuid);
  3417. String name = "Cloud Stack Local EXT Storage Pool for " + _host.uuid;
  3418. extsr.setNameDescription(conn, name);
  3419. Host host = Host.getByUuid(conn, _host.uuid);
  3420. String address = host.getAddress(conn);
  3421. StoragePoolInfo pInfo = new StoragePoolInfo(extuuid, address, SRType.EXT.toString(), SRType.EXT.toString(), StoragePoolType.EXT, cap, avail);
  3422. StartupStorageCommand cmd = new StartupStorageCommand();
  3423. cmd.setPoolInfo(pInfo);
  3424. cmd.setGuid(_host.uuid);
  3425. cmd.setDataCenter(Long.toString(_dcId));
  3426. cmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL);
  3427. return cmd;
  3428. }
  3429. } catch (XenAPIException e) {
  3430. String msg = "build local EXT info err in host:" + _host.uuid + e.toString();
  3431. s_logger.warn(msg);
  3432. } catch (XmlRpcException e) {
  3433. String msg = "build local EXT info err in host:" + _host.uuid + e.getMessage();
  3434. s_logger.warn(msg);
  3435. }
  3436. }
  3437. return null;
  3438. }
  3439. @Override
  3440. public PingCommand getCurrentStatus(long id) {
  3441. try {
  3442. if (!pingXenServer()) {
  3443. Thread.sleep(1000);
  3444. if (!pingXenServer()) {
  3445. s_logger.warn(" can not ping xenserver " + _host.uuid);
  3446. return null;
  3447. }
  3448. }
  3449. Connection conn = getConnection();
  3450. /**if (!_canBridgeFirewall && !_isOvs) {
  3451. return new PingRoutingCommand(getType(), id, null);
  3452. } else**/
  3453. if (_isOvs) {
  3454. List<Pair<String, Long>>ovsStates = ovsFullSyncStates();
  3455. return new PingRoutingWithOvsCommand(getType(), id, null, ovsStates);
  3456. }else {
  3457. HashMap<String, Pair<Long, Long>> nwGrpStates = syncNetworkGroups(conn, id);
  3458. return new PingRoutingWithNwGroupsCommand(getType(), id, null, nwGrpStates);
  3459. }
  3460. } catch (Exception e) {
  3461. s_logger.warn("Unable to get current status", e);
  3462. return null;
  3463. }
  3464. }
  3465. private HashMap<String, Pair<Long,Long>> syncNetworkGroups(Connection conn, long id) {
  3466. HashMap<String, Pair<Long,Long>> states = new HashMap<String, Pair<Long,Long>>();
  3467. String result = callHostPlugin(conn, "vmops", "get_rule_logs_for_vms", "host_uuid", _host.uuid);
  3468. s_logger.trace("syncNetworkGroups: id=" + id + " got: " + result);
  3469. String [] rulelogs = result != null ?result.split(";"): new String [0];
  3470. for (String rulesforvm: rulelogs){
  3471. String [] log = rulesforvm.split(",");
  3472. if (log.length != 6) {
  3473. continue;
  3474. }
  3475. //output = ','.join([vmName, vmID, vmIP, domID, signature, seqno])
  3476. try {
  3477. states.put(log[0], new Pair<Long,Long>(Long.parseLong(log[1]), Long.parseLong(log[5])));
  3478. } catch (NumberFormatException nfe) {
  3479. states.put(log[0], new Pair<Long,Long>(-1L, -1L));
  3480. }
  3481. }
  3482. return states;
  3483. }
  3484. @Override
  3485. public Type getType() {
  3486. return com.cloud.host.Host.Type.Routing;
  3487. }
  3488. protected boolean getHostInfo(Connection conn) throws IllegalArgumentException{
  3489. try {
  3490. Host myself = Host.getByUuid(conn, _host.uuid);
  3491. Set<HostCpu> hcs = myself.getHostCPUs(conn);
  3492. _host.cpus = hcs.size();
  3493. for (final HostCpu hc : hcs) {
  3494. _host.speed = hc.getSpeed(conn).intValue();
  3495. break;
  3496. }
  3497. Host.Record hr = myself.getRecord(conn);
  3498. _host.product_version = hr.softwareVersion.get("product_version").trim();
  3499. XsLocalNetwork privateNic = getManagementNetwork(conn);
  3500. _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel;
  3501. _host.privatePif = privateNic.getPifRecord(conn).uuid;
  3502. _host.privateNetwork = privateNic.getNetworkRecord(conn).uuid;
  3503. _host.systemvmisouuid = null;
  3504. XsLocalNetwork guestNic = null;
  3505. if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) {
  3506. guestNic = getNetworkByName(conn, _guestNetworkName);
  3507. if (guestNic == null) {
  3508. s_logger.warn("Unable to find guest network " + _guestNetworkName);
  3509. throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.ip);
  3510. }
  3511. } else {
  3512. guestNic = privateNic;
  3513. _guestNetworkName = _privateNetworkName;
  3514. }
  3515. _host.guestNetwork = guestNic.getNetworkRecord(conn).uuid;
  3516. _host.guestPif = guestNic.getPifRecord(conn).uuid;
  3517. XsLocalNetwork publicNic = null;
  3518. if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) {
  3519. publicNic = getNetworkByName(conn, _publicNetworkName);
  3520. if (publicNic == null) {
  3521. s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.ip);
  3522. throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.ip);
  3523. }
  3524. } else {
  3525. publicNic = guestNic;
  3526. _publicNetworkName = _guestNetworkName;
  3527. }
  3528. _host.publicPif = publicNic.getPifRecord(conn).uuid;
  3529. _host.publicNetwork = publicNic.getNetworkRecord(conn).uuid;
  3530. XsLocalNetwork storageNic1 = null;
  3531. if (_storageNetworkName1 != null && !_storageNetworkName1.equals(_guestNetworkName)) {
  3532. storageNic1 = getNetworkByName(conn, _storageNetworkName1);
  3533. }
  3534. if (storageNic1 == null) {
  3535. storageNic1 = guestNic;
  3536. _storageNetworkName1 = _guestNetworkName;
  3537. }
  3538. _host.storageNetwork1 = storageNic1.getNetworkRecord(conn).uuid;
  3539. _host.storagePif1 = storageNic1.getPifRecord(conn).uuid;
  3540. XsLocalNetwork storageNic2 = null;
  3541. if (_storageNetworkName2 != null && !_storageNetworkName2.equals(_guestNetworkName)) {
  3542. storageNic2 = getNetworkByName(conn, _storageNetworkName2);
  3543. }
  3544. if (storageNic2 == null) {
  3545. storageNic2 = guestNic;
  3546. _storageNetworkName2 = _guestNetworkName;
  3547. }
  3548. _host.storageNetwork2 = storageNic2.getNetworkRecord(conn).uuid;
  3549. _host.storagePif2 = storageNic2.getPifRecord(conn).uuid;
  3550. s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.ip);
  3551. s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.ip);
  3552. s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.ip);
  3553. s_logger.info("Storage Network 1 is " + _storageNetworkName1 + " for host " + _host.ip);
  3554. s_logger.info("Storage Network 2 is " + _storageNetworkName2 + " for host " + _host.ip);
  3555. return true;
  3556. } catch (XenAPIException e) {
  3557. s_logger.warn("Unable to get host information for " + _host.ip, e);
  3558. return false;
  3559. } catch (XmlRpcException e) {
  3560. s_logger.warn("Unable to get host information for " + _host.ip, e);
  3561. return false;
  3562. }
  3563. }
  3564. private void setupLinkLocalNetwork(Connection conn) {
  3565. try {
  3566. Network.Record rec = new Network.Record();
  3567. Set<Network> networks = Network.getByNameLabel(conn, _linkLocalPrivateNetworkName);
  3568. Network linkLocal = null;
  3569. if (networks.size() == 0) {
  3570. rec.nameDescription = "link local network used by system vms";
  3571. rec.nameLabel = _linkLocalPrivateNetworkName;
  3572. Map<String, String> configs = new HashMap<String, String>();
  3573. configs.put("ip_begin", NetUtils.getLinkLocalGateway());
  3574. configs.put("ip_end", NetUtils.getLinkLocalIpEnd());
  3575. configs.put("netmask", NetUtils.getLinkLocalNetMask());
  3576. rec.otherConfig = configs;
  3577. linkLocal = Network.create(conn, rec);
  3578. } else {
  3579. linkLocal = networks.iterator().next();
  3580. }
  3581. /* Make sure there is a physical bridge on this network */
  3582. VIF dom0vif = null;
  3583. Pair<VM, VM.Record> vm = getControlDomain(conn);
  3584. VM dom0 = vm.first();
  3585. Set<VIF> vifs = dom0.getVIFs(conn);
  3586. if (vifs.size() != 0) {
  3587. for (VIF vif : vifs) {
  3588. Map<String, String> otherConfig = vif.getOtherConfig(conn);
  3589. if (otherConfig != null) {
  3590. String nameLabel = otherConfig.get("nameLabel");
  3591. if ((nameLabel != null) && nameLabel.equalsIgnoreCase("link_local_network_vif")) {
  3592. dom0vif = vif;
  3593. }
  3594. }
  3595. }
  3596. }
  3597. /* create temp VIF0 */
  3598. if (dom0vif == null) {
  3599. s_logger.debug("Can't find a vif on dom0 for link local, creating a new one");
  3600. VIF.Record vifr = new VIF.Record();
  3601. vifr.VM = dom0;
  3602. vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0);
  3603. if (vifr.device == null) {
  3604. s_logger.debug("Failed to create link local network, no vif available");
  3605. return;
  3606. }
  3607. Map<String, String> config = new HashMap<String, String>();
  3608. config.put("nameLabel", "link_local_network_vif");
  3609. vifr.otherConfig = config;
  3610. vifr.MAC = "FE:FF:FF:FF:FF:FF";
  3611. vifr.network = linkLocal;
  3612. dom0vif = VIF.create(conn, vifr);
  3613. dom0vif.plug(conn);
  3614. } else {
  3615. s_logger.debug("already have a vif on dom0 for link local network");
  3616. if (!dom0vif.getCurrentlyAttached(conn)) {
  3617. dom0vif.plug(conn);
  3618. }
  3619. }
  3620. String brName = linkLocal.getBridge(conn);
  3621. callHostPlugin(conn, "vmops", "setLinkLocalIP", "brName", brName);
  3622. _host.linkLocalNetwork = linkLocal.getUuid(conn);
  3623. } catch (XenAPIException e) {
  3624. s_logger.warn("Unable to create local link network", e);
  3625. } catch (XmlRpcException e) {
  3626. s_logger.warn("Unable to create local link network", e);
  3627. }
  3628. }
  3629. protected boolean transferManagementNetwork(Connection conn, Host host, PIF src, PIF.Record spr, PIF dest) throws XmlRpcException, XenAPIException {
  3630. dest.reconfigureIp(conn, spr.ipConfigurationMode, spr.IP, spr.netmask, spr.gateway, spr.DNS);
  3631. Host.managementReconfigure(conn, dest);
  3632. String hostUuid = null;
  3633. int count = 0;
  3634. while (count < 10) {
  3635. try {
  3636. Thread.sleep(10000);
  3637. hostUuid = host.getUuid(conn);
  3638. if (hostUuid != null) {
  3639. break;
  3640. }
  3641. } catch (XmlRpcException e) {
  3642. s_logger.debug("Waiting for host to come back: " + e.getMessage());
  3643. } catch (XenAPIException e) {
  3644. s_logger.debug("Waiting for host to come back: " + e.getMessage());
  3645. } catch (InterruptedException e) {
  3646. s_logger.debug("Gotta run");
  3647. return false;
  3648. }
  3649. }
  3650. if (hostUuid == null) {
  3651. s_logger.warn("Unable to transfer the management network from " + spr.uuid);
  3652. return false;
  3653. }
  3654. src.reconfigureIp(conn, IpConfigurationMode.NONE, null, null, null, null);
  3655. return true;
  3656. }
  3657. @Override
  3658. public StartupCommand[] initialize() throws IllegalArgumentException{
  3659. Connection conn = getConnection();
  3660. if (!getHostInfo(conn)) {
  3661. s_logger.warn("Unable to get host information for " + _host.ip);
  3662. return null;
  3663. }
  3664. StartupRoutingCommand cmd = new StartupRoutingCommand();
  3665. fillHostInfo(conn, cmd);
  3666. cmd.setHypervisorType(HypervisorType.XenServer);
  3667. cmd.setCluster(_cluster);
  3668. cmd.setPoolSync(false);
  3669. Pool pool;
  3670. try {
  3671. pool = Pool.getByUuid(conn, _host.pool);
  3672. Pool.Record poolr = pool.getRecord(conn);
  3673. Host.Record hostr = poolr.master.getRecord(conn);
  3674. if (_host.uuid.equals(hostr.uuid)) {
  3675. HashMap<String, Pair<String, State>> allStates=fullClusterSync(conn);
  3676. cmd.setClusterVMStateChanges(allStates);
  3677. }
  3678. } catch (Throwable e) {
  3679. s_logger.warn("Check for master failed, failing the FULL Cluster sync command");
  3680. }
  3681. StartupStorageCommand sscmd = initializeLocalSR(conn);
  3682. if (sscmd != null) {
  3683. return new StartupCommand[] { cmd, sscmd };
  3684. }
  3685. return new StartupCommand[] { cmd };
  3686. }
  3687. private void cleanupTemplateSR(Connection conn) {
  3688. Set<PBD> pbds = null;
  3689. try {
  3690. Host host = Host.getByUuid(conn, _host.uuid);
  3691. pbds = host.getPBDs(conn);
  3692. } catch (XenAPIException e) {
  3693. s_logger.warn("Unable to get the SRs " + e.toString(), e);
  3694. throw new CloudRuntimeException("Unable to get SRs " + e.toString(), e);
  3695. } catch (Exception e) {
  3696. throw new CloudRuntimeException("Unable to get SRs " + e.getMessage(), e);
  3697. }
  3698. for (PBD pbd : pbds) {
  3699. SR sr = null;
  3700. SR.Record srRec = null;
  3701. try {
  3702. sr = pbd.getSR(conn);
  3703. srRec = sr.getRecord(conn);
  3704. } catch (Exception e) {
  3705. s_logger.warn("pbd.getSR get Exception due to ", e);
  3706. continue;
  3707. }
  3708. String type = srRec.type;
  3709. if (srRec.shared) {
  3710. continue;
  3711. }
  3712. if (SRType.NFS.equals(type) || (SRType.ISO.equals(type) && srRec.nameDescription.contains("template"))) {
  3713. try {
  3714. pbd.unplug(conn);
  3715. pbd.destroy(conn);
  3716. sr.forget(conn);
  3717. } catch (Exception e) {
  3718. s_logger.warn("forget SR catch Exception due to ", e);
  3719. }
  3720. }
  3721. }
  3722. }
  3723. protected SetupAnswer execute(SetupCommand cmd) {
  3724. Connection conn = getConnection();
  3725. setupServer(conn);
  3726. try {
  3727. if (!setIptables(conn)) {
  3728. s_logger.warn("set xenserver Iptable failed");
  3729. return null;
  3730. }
  3731. _canBridgeFirewall = can_bridge_firewall(conn);
  3732. String result = callHostPluginPremium(conn, "heartbeat", "host", _host.uuid, "interval", Integer
  3733. .toString(_heartbeatInterval));
  3734. if (result == null || !result.contains("> DONE <")) {
  3735. s_logger.warn("Unable to launch the heartbeat process on " + _host.ip);
  3736. return null;
  3737. }
  3738. cleanupTemplateSR(conn);
  3739. Host host = Host.getByUuid(conn, _host.uuid);
  3740. try {
  3741. if (cmd.useMultipath()) {
  3742. // the config value is set to true
  3743. host.addToOtherConfig(conn, "multipathing", "true");
  3744. host.addToOtherConfig(conn, "multipathhandle", "dmp");
  3745. }
  3746. } catch (Types.MapDuplicateKey e) {
  3747. s_logger.debug("multipath is already set");
  3748. }
  3749. if (cmd.needSetup() ) {
  3750. result = callHostPlugin(conn, "vmops", "setup_iscsi", "uuid", _host.uuid);
  3751. if (!result.contains("> DONE <")) {
  3752. s_logger.warn("Unable to setup iscsi: " + result);
  3753. return new SetupAnswer(cmd, result);
  3754. }
  3755. Pair<PIF, PIF.Record> mgmtPif = null;
  3756. Set<PIF> hostPifs = host.getPIFs(conn);
  3757. for (PIF pif : hostPifs) {
  3758. PIF.Record rec = pif.getRecord(conn);
  3759. if (rec.management) {
  3760. if (rec.VLAN != null && rec.VLAN != -1) {
  3761. String msg = new StringBuilder(
  3762. "Unsupported configuration. Management network is on a VLAN. host=").append(
  3763. _host.uuid).append("; pif=").append(rec.uuid).append("; vlan=").append(rec.VLAN)
  3764. .toString();
  3765. s_logger.warn(msg);
  3766. return new SetupAnswer(cmd, msg);
  3767. }
  3768. if (s_logger.isDebugEnabled()) {
  3769. s_logger.debug("Management network is on pif=" + rec.uuid);
  3770. }
  3771. mgmtPif = new Pair<PIF, PIF.Record>(pif, rec);
  3772. break;
  3773. }
  3774. }
  3775. if (mgmtPif == null) {
  3776. String msg = "Unable to find management network for " + _host.uuid;
  3777. s_logger.warn(msg);
  3778. return new SetupAnswer(cmd, msg);
  3779. }
  3780. Map<Network, Network.Record> networks = Network.getAllRecords(conn);
  3781. for (Network.Record network : networks.values()) {
  3782. if (network.nameLabel.equals("cloud-private")) {
  3783. for (PIF pif : network.PIFs) {
  3784. PIF.Record pr = pif.getRecord(conn);
  3785. if (_host.uuid.equals(pr.host.getUuid(conn))) {
  3786. if (s_logger.isDebugEnabled()) {
  3787. s_logger.debug("Found a network called cloud-private. host=" + _host.uuid
  3788. + "; Network=" + network.uuid + "; pif=" + pr.uuid);
  3789. }
  3790. if (pr.VLAN != null && pr.VLAN != -1) {
  3791. String msg = new StringBuilder(
  3792. "Unsupported configuration. Network cloud-private is on a VLAN. Network=")
  3793. .append(network.uuid).append(" ; pif=").append(pr.uuid).toString();
  3794. s_logger.warn(msg);
  3795. return new SetupAnswer(cmd, msg);
  3796. }
  3797. if (!pr.management && pr.bondMasterOf != null && pr.bondMasterOf.size() > 0) {
  3798. if (pr.bondMasterOf.size() > 1) {
  3799. String msg = new StringBuilder(
  3800. "Unsupported configuration. Network cloud-private has more than one bond. Network=")
  3801. .append(network.uuid).append("; pif=").append(pr.uuid).toString();
  3802. s_logger.warn(msg);
  3803. return new SetupAnswer(cmd, msg);
  3804. }
  3805. Bond bond = pr.bondMasterOf.iterator().next();
  3806. Set<PIF> slaves = bond.getSlaves(conn);
  3807. for (PIF slave : slaves) {
  3808. PIF.Record spr = slave.getRecord(conn);
  3809. if (spr.management) {
  3810. if (!transferManagementNetwork(conn, host, slave, spr, pif)) {
  3811. String msg = new StringBuilder(
  3812. "Unable to transfer management network. slave=" + spr.uuid
  3813. + "; master=" + pr.uuid + "; host=" + _host.uuid)
  3814. .toString();
  3815. s_logger.warn(msg);
  3816. return new SetupAnswer(cmd, msg);
  3817. }
  3818. break;
  3819. }
  3820. }
  3821. }
  3822. }
  3823. }
  3824. }
  3825. }
  3826. }
  3827. return new SetupAnswer(cmd, false);
  3828. } catch (XmlRpcException e) {
  3829. s_logger.warn("Unable to setup", e);
  3830. return new SetupAnswer(cmd, e.getMessage());
  3831. } catch (XenAPIException e) {
  3832. s_logger.warn("Unable to setup", e);
  3833. return new SetupAnswer(cmd, e.getMessage());
  3834. } catch (Exception e) {
  3835. s_logger.warn("Unable to setup", e);
  3836. return new SetupAnswer(cmd, e.getMessage());
  3837. }
  3838. }
  3839. /* return : if setup is needed */
  3840. protected boolean setupServer(Connection conn) {
  3841. String version = this.getClass().getName() + "-" + CitrixResourceBase.class.getPackage().getImplementationVersion();
  3842. try {
  3843. Host host = Host.getByUuid(conn, _host.uuid);
  3844. /* enable host in case it is disabled somehow */
  3845. host.enable(conn);
  3846. /* push patches to XenServer */
  3847. Host.Record hr = host.getRecord(conn);
  3848. Iterator<String> it = hr.tags.iterator();
  3849. while (it.hasNext()) {
  3850. String tag = it.next();
  3851. if (tag.startsWith("vmops-version-")) {
  3852. if (tag.contains(version)) {
  3853. s_logger.info(logX(host, "Host " + hr.address + " is already setup."));
  3854. return false;
  3855. } else {
  3856. it.remove();
  3857. }
  3858. }
  3859. }
  3860. com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22);
  3861. try {
  3862. sshConnection.connect(null, 60000, 60000);
  3863. if (!sshConnection.authenticateWithPassword(_username, _password.peek())) {
  3864. throw new CloudRuntimeException("Unable to authenticate");
  3865. }
  3866. SCPClient scp = new SCPClient(sshConnection);
  3867. List<File> files = getPatchFiles();
  3868. if( files == null || files.isEmpty() ) {
  3869. throw new CloudRuntimeException("Can not find patch file");
  3870. }
  3871. for( File file :files) {
  3872. String path = file.getParentFile().getAbsolutePath() + "/";
  3873. Properties props = new Properties();
  3874. props.load(new FileInputStream(file));
  3875. for (Map.Entry<Object, Object> entry : props.entrySet()) {
  3876. String k = (String) entry.getKey();
  3877. String v = (String) entry.getValue();
  3878. assert (k != null && k.length() > 0 && v != null && v.length() > 0) : "Problems with " + k + "=" + v;
  3879. String[] tokens = v.split(",");
  3880. String f = null;
  3881. if (tokens.length == 3 && tokens[0].length() > 0) {
  3882. if (tokens[0].startsWith("/")) {
  3883. f = tokens[0];
  3884. } else if (tokens[0].startsWith("~")) {
  3885. String homedir = System.getenv("HOME");
  3886. f = homedir + tokens[0].substring(1) + k;
  3887. } else {
  3888. f = path + tokens[0] + '/' + k;
  3889. }
  3890. } else {
  3891. f = path + k;
  3892. }
  3893. String d = tokens[tokens.length - 1];
  3894. f = f.replace('/', File.separatorChar);
  3895. String p = "0755";
  3896. if (tokens.length == 3) {
  3897. p = tokens[1];
  3898. } else if (tokens.length == 2) {
  3899. p = tokens[0];
  3900. }
  3901. if (!new File(f).exists()) {
  3902. s_logger.warn("We cannot locate " + f);
  3903. continue;
  3904. }
  3905. if (s_logger.isDebugEnabled()) {
  3906. s_logger.debug("Copying " + f + " to " + d + " on " + hr.address + " with permission " + p);
  3907. }
  3908. scp.put(f, d, p);
  3909. }
  3910. }
  3911. } catch (IOException e) {
  3912. throw new CloudRuntimeException("Unable to setup the server correctly", e);
  3913. } finally {
  3914. sshConnection.close();
  3915. }
  3916. hr.tags.add("vmops-version-" + version);
  3917. host.setTags(conn, hr.tags);
  3918. return true;
  3919. } catch (XenAPIException e) {
  3920. String msg = "Xen setup failed due to " + e.toString();
  3921. s_logger.warn(msg, e);
  3922. throw new CloudRuntimeException("Unable to get host information " + e.toString(), e);
  3923. } catch (XmlRpcException e) {
  3924. String msg = "Xen setup failed due to " + e.getMessage();
  3925. s_logger.warn(msg, e);
  3926. throw new CloudRuntimeException("Unable to get host information ", e);
  3927. }
  3928. }
  3929. protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
  3930. if (s_logger.isDebugEnabled()) {
  3931. s_logger.debug("Checking if network name setup is done on the resource");
  3932. }
  3933. List<PhysicalNetworkSetupInfo> infoList = cmd.getPhysicalNetworkInfoList();
  3934. try{
  3935. boolean errorout = false;
  3936. String msg = "";
  3937. for(PhysicalNetworkSetupInfo info : infoList){
  3938. if(!isNetworkSetupByName(info.getGuestNetworkName())){
  3939. msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Guest Network is not configured on the backend by name " + info.getGuestNetworkName();
  3940. errorout = true;
  3941. break;
  3942. }
  3943. if(!isNetworkSetupByName(info.getPrivateNetworkName())){
  3944. msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Private Network is not configured on the backend by name " + info.getPrivateNetworkName();
  3945. errorout = true;
  3946. break;
  3947. }
  3948. if(!isNetworkSetupByName(info.getPublicNetworkName())){
  3949. msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Public Network is not configured on the backend by name " + info.getPublicNetworkName();
  3950. errorout = true;
  3951. break;
  3952. }
  3953. /*if(!isNetworkSetupByName(info.getStorageNetworkName())){
  3954. msg = "For Physical Network id:"+ info.getPhysicalNetworkId() + ", Storage Network is not configured on the backend by name " + info.getStorageNetworkName();
  3955. errorout = true;
  3956. break;
  3957. }*/
  3958. }
  3959. if(errorout){
  3960. s_logger.error(msg);
  3961. return new CheckNetworkAnswer(cmd, false, msg);
  3962. }else{
  3963. return new CheckNetworkAnswer(cmd, true , "Network Setup check by names is done");
  3964. }
  3965. }catch (XenAPIException e) {
  3966. String msg = "CheckNetworkCommand failed with XenAPIException:" + e.toString() + " host:" + _host.uuid;
  3967. s_logger.warn(msg, e);
  3968. return new CheckNetworkAnswer(cmd, false, msg);
  3969. }catch (Exception e) {
  3970. String msg = "CheckNetworkCommand failed with Exception:" + e.getMessage() + " host:" + _host.uuid;
  3971. s_logger.warn(msg, e);
  3972. return new CheckNetworkAnswer(cmd, false, msg);
  3973. }
  3974. }
  3975. protected boolean isNetworkSetupByName(String nameTag) throws XenAPIException, XmlRpcException{
  3976. if (nameTag != null) {
  3977. if (s_logger.isDebugEnabled()) {
  3978. s_logger.debug("Looking for network setup by name " + nameTag);
  3979. }
  3980. Connection conn = getConnection();
  3981. XsLocalNetwork network = getNetworkByName(conn, nameTag);
  3982. if (network == null) {
  3983. return false;
  3984. }
  3985. }
  3986. return true;
  3987. }
  3988. protected List<File> getPatchFiles() {
  3989. return null;
  3990. }
  3991. protected SR getSRByNameLabelandHost(Connection conn, String name) throws BadServerResponse, XenAPIException, XmlRpcException {
  3992. Set<SR> srs = SR.getByNameLabel(conn, name);
  3993. SR ressr = null;
  3994. for (SR sr : srs) {
  3995. Set<PBD> pbds;
  3996. pbds = sr.getPBDs(conn);
  3997. for (PBD pbd : pbds) {
  3998. PBD.Record pbdr = pbd.getRecord(conn);
  3999. if (pbdr.host != null && pbdr.host.getUuid(conn).equals(_host.uuid)) {
  4000. if (!pbdr.currentlyAttached) {
  4001. pbd.plug(conn);
  4002. }
  4003. ressr = sr;
  4004. break;
  4005. }
  4006. }
  4007. }
  4008. return ressr;
  4009. }
  4010. protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) {
  4011. Connection conn = getConnection();
  4012. try {
  4013. Set<SR> srs = SR.getByNameLabel(conn, cmd.getStorageId());
  4014. if (srs.size() != 1) {
  4015. String msg = "There are " + srs.size() + " storageid: " + cmd.getStorageId();
  4016. s_logger.warn(msg);
  4017. return new GetStorageStatsAnswer(cmd, msg);
  4018. }
  4019. SR sr = srs.iterator().next();
  4020. sr.scan(conn);
  4021. long capacity = sr.getPhysicalSize(conn);
  4022. long used = sr.getPhysicalUtilisation(conn);
  4023. return new GetStorageStatsAnswer(cmd, capacity, used);
  4024. } catch (XenAPIException e) {
  4025. String msg = "GetStorageStats Exception:" + e.toString() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId();
  4026. s_logger.warn(msg);
  4027. return new GetStorageStatsAnswer(cmd, msg);
  4028. } catch (XmlRpcException e) {
  4029. String msg = "GetStorageStats Exception:" + e.getMessage() + "host:" + _host.uuid + "storageid: " + cmd.getStorageId();
  4030. s_logger.warn(msg);
  4031. return new GetStorageStatsAnswer(cmd, msg);
  4032. }
  4033. }
  4034. private void pbdPlug(Connection conn, PBD pbd, String uuid) {
  4035. try {
  4036. if (s_logger.isDebugEnabled()) {
  4037. s_logger.debug("Plugging in PBD " + uuid + " for " + _host);
  4038. }
  4039. pbd.plug(conn);
  4040. } catch (Exception e) {
  4041. String msg = "PBD " + uuid + " is not attached! and PBD plug failed due to "
  4042. + e.toString() + ". Please check this PBD in " + _host;
  4043. s_logger.warn(msg, e);
  4044. throw new CloudRuntimeException(msg);
  4045. }
  4046. }
  4047. protected boolean checkSR(Connection conn, SR sr) {
  4048. try {
  4049. SR.Record srr = sr.getRecord(conn);
  4050. Set<PBD> pbds = sr.getPBDs(conn);
  4051. if (pbds.size() == 0) {
  4052. String msg = "There is no PBDs for this SR: " + srr.nameLabel + " on host:" + _host.uuid;
  4053. s_logger.warn(msg);
  4054. return false;
  4055. }
  4056. if (s_logger.isDebugEnabled()) {
  4057. s_logger.debug("Checking " + srr.nameLabel + " or SR " + srr.uuid + " on " + _host);
  4058. }
  4059. if (srr.shared) {
  4060. Host host = Host.getByUuid(conn, _host.uuid);
  4061. boolean found = false;
  4062. for (PBD pbd : pbds) {
  4063. PBD.Record pbdr = pbd.getRecord(conn);
  4064. if (host.equals(pbdr.host)) {
  4065. if (!pbdr.currentlyAttached) {
  4066. pbdPlug(conn, pbd, pbdr.uuid);
  4067. }
  4068. found = true;
  4069. break;
  4070. }
  4071. }
  4072. if (!found) {
  4073. PBD.Record pbdr = srr.PBDs.iterator().next().getRecord(conn);
  4074. pbdr.host = host;
  4075. pbdr.uuid = "";
  4076. PBD pbd = PBD.create(conn, pbdr);
  4077. pbdPlug(conn, pbd, pbd.getUuid(conn));
  4078. }
  4079. } else {
  4080. for (PBD pbd : pbds) {
  4081. PBD.Record pbdr = pbd.getRecord(conn);
  4082. if (!pbdr.currentlyAttached) {
  4083. pbdPlug(conn, pbd, pbdr.uuid);
  4084. }
  4085. }
  4086. }
  4087. } catch (Exception e) {
  4088. String msg = "checkSR failed host:" + _host + " due to " + e.toString();
  4089. s_logger.warn(msg, e);
  4090. return false;
  4091. }
  4092. return true;
  4093. }
  4094. protected Answer execute(CreateStoragePoolCommand cmd) {
  4095. Connection conn = getConnection();
  4096. StorageFilerTO pool = cmd.getPool();
  4097. try {
  4098. if (pool.getType() == StoragePoolType.NetworkFilesystem) {
  4099. getNfsSR(conn, pool);
  4100. } else if (pool.getType() == StoragePoolType.IscsiLUN) {
  4101. getIscsiSR(conn, pool);
  4102. } else if (pool.getType() == StoragePoolType.PreSetup) {
  4103. } else {
  4104. return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported.");
  4105. }
  4106. return new Answer(cmd, true, "success");
  4107. } catch (Exception e) {
  4108. String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
  4109. s_logger.warn(msg, e);
  4110. return new Answer(cmd, false, msg);
  4111. }
  4112. }
  4113. protected String callHostPluginThroughMaster(Connection conn, String plugin, String cmd, String... params) {
  4114. Map<String, String> args = new HashMap<String, String>();
  4115. try {
  4116. Map<Pool, Pool.Record> poolRecs = Pool.getAllRecords(conn);
  4117. if (poolRecs.size() != 1) {
  4118. throw new CloudRuntimeException("There are " + poolRecs.size() + " pool for host :" + _host.uuid);
  4119. }
  4120. Host master = poolRecs.values().iterator().next().master;
  4121. for (int i = 0; i < params.length; i += 2) {
  4122. args.put(params[i], params[i + 1]);
  4123. }
  4124. if (s_logger.isTraceEnabled()) {
  4125. s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args));
  4126. }
  4127. String result = master.callPlugin(conn, plugin, cmd, args);
  4128. if (s_logger.isTraceEnabled()) {
  4129. s_logger.trace("callHostPlugin Result: " + result);
  4130. }
  4131. return result.replace("\n", "");
  4132. } catch (Types.HandleInvalid e) {
  4133. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args)
  4134. + " due to HandleInvalid clazz:" + e.clazz + ", handle:" + e.handle);
  4135. } catch (XenAPIException e) {
  4136. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to "
  4137. + e.toString(), e);
  4138. } catch (XmlRpcException e) {
  4139. s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to "
  4140. + e.getMessage(), e);
  4141. }
  4142. return null;
  4143. }
  4144. protected String callHostPluginPremium(Connection conn, String cmd, String... params) {
  4145. return callHostPlugin(conn, "vmopspremium", cmd, params);
  4146. }
  4147. protected String setupHeartbeatSr(Connection conn, SR sr, boolean force) throws XenAPIException, XmlRpcException {
  4148. SR.Record srRec = sr.getRecord(conn);
  4149. String srUuid = srRec.uuid;
  4150. if (!srRec.shared || (!SRType.LVMOHBA.equals(srRec.type) && !SRType.LVMOISCSI.equals(srRec.type) && !SRType.NFS.equals(srRec.type) )) {
  4151. return srUuid;
  4152. }
  4153. String result = null;
  4154. Host host = Host.getByUuid(conn, _host.uuid);
  4155. Set<String> tags = host.getTags(conn);
  4156. if (force || !tags.contains("cloud-heartbeat-" + srUuid)) {
  4157. if (s_logger.isDebugEnabled()) {
  4158. s_logger.debug("Setting up the heartbeat sr for host " + _host.ip + " and sr " + srUuid);
  4159. }
  4160. Set<PBD> pbds = sr.getPBDs(conn);
  4161. for (PBD pbd : pbds) {
  4162. PBD.Record pbdr = pbd.getRecord(conn);
  4163. if (!pbdr.currentlyAttached && pbdr.host.getUuid(conn).equals(_host.uuid)) {
  4164. pbd.plug(conn);
  4165. break;
  4166. }
  4167. }
  4168. result = callHostPluginThroughMaster(conn, "vmopspremium", "setup_heartbeat_sr", "host", _host.uuid,
  4169. "sr", srUuid);
  4170. if (result == null || !result.split("#")[1].equals("0")) {
  4171. throw new CloudRuntimeException("Unable to setup heartbeat sr on SR " + srUuid + " due to " + result);
  4172. }
  4173. if (!tags.contains("cloud-heartbeat-" + srUuid)) {
  4174. tags.add("cloud-heartbeat-" + srUuid);
  4175. host.setTags(conn, tags);
  4176. }
  4177. }
  4178. result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "true");
  4179. if (result == null || !result.split("#")[1].equals("0")) {
  4180. throw new CloudRuntimeException("Unable to setup heartbeat file entry on SR " + srUuid + " due to "
  4181. + result);
  4182. }
  4183. return srUuid;
  4184. }
  4185. protected Answer execute(ModifyStoragePoolCommand cmd) {
  4186. Connection conn = getConnection();
  4187. StorageFilerTO pool = cmd.getPool();
  4188. boolean add = cmd.getAdd();
  4189. if( add ) {
  4190. try {
  4191. SR sr = getStorageRepository(conn, pool);
  4192. setupHeartbeatSr(conn, sr, false);
  4193. long capacity = sr.getPhysicalSize(conn);
  4194. long available = capacity - sr.getPhysicalUtilisation(conn);
  4195. if (capacity == -1) {
  4196. String msg = "Pool capacity is -1! pool: " + pool.getHost() + pool.getPath();
  4197. s_logger.warn(msg);
  4198. return new Answer(cmd, false, msg);
  4199. }
  4200. Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
  4201. ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo);
  4202. return answer;
  4203. } catch (XenAPIException e) {
  4204. String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
  4205. s_logger.warn(msg, e);
  4206. return new Answer(cmd, false, msg);
  4207. } catch (Exception e) {
  4208. String msg = "ModifyStoragePoolCommand add XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
  4209. s_logger.warn(msg, e);
  4210. return new Answer(cmd, false, msg);
  4211. }
  4212. } else {
  4213. try {
  4214. SR sr = getStorageRepository(conn, pool);
  4215. String srUuid = sr.getUuid(conn);
  4216. String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false");
  4217. if (result == null || !result.split("#")[1].equals("0")) {
  4218. throw new CloudRuntimeException("Unable to remove heartbeat file entry for SR " + srUuid + " due to "
  4219. + result);
  4220. }
  4221. return new Answer(cmd, true , "seccuss");
  4222. } catch (XenAPIException e) {
  4223. String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.toString() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
  4224. s_logger.warn(msg, e);
  4225. return new Answer(cmd, false, msg);
  4226. } catch (Exception e) {
  4227. String msg = "ModifyStoragePoolCommand remove XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
  4228. s_logger.warn(msg, e);
  4229. return new Answer(cmd, false, msg);
  4230. }
  4231. }
  4232. }
  4233. protected boolean can_bridge_firewall(Connection conn) {
  4234. return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance));
  4235. }
  4236. private Answer execute(OvsDestroyTunnelCommand cmd) {
  4237. Connection conn = getConnection();
  4238. try {
  4239. Network nw = createTunnelNetwork(conn, cmd.getAccount());
  4240. if (nw == null) {
  4241. return new Answer(cmd, false, "No network found");
  4242. }
  4243. String bridge = nw.getBridge(conn);
  4244. String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName());
  4245. if (result.equalsIgnoreCase("SUCCESS")) {
  4246. return new Answer(cmd, true, result);
  4247. } else {
  4248. return new Answer(cmd, false, result);
  4249. }
  4250. } catch (Exception e) {
  4251. s_logger.warn("caught execption when destroy ovs tunnel", e);
  4252. return new Answer(cmd, false, e.getMessage());
  4253. }
  4254. }
  4255. private Answer execute(UpdateHostPasswordCommand cmd) {
  4256. _password.add(cmd.getNewPassword());
  4257. return new Answer(cmd, true, null);
  4258. }
  4259. private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) {
  4260. Connection conn = getConnection();
  4261. String bridge = "unknown";
  4262. try {
  4263. Network nw = createTunnelNetwork(conn, cmd.getAccount());
  4264. if (nw == null) {
  4265. return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge);
  4266. }
  4267. bridge = nw.getBridge(conn);
  4268. String result = callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), "key", cmd.getKey(), "from", cmd.getFrom().toString(), "to", cmd
  4269. .getTo().toString());
  4270. String[] res = result.split(":");
  4271. if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) {
  4272. return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge);
  4273. } else {
  4274. return new OvsCreateTunnelAnswer(cmd, false, result, bridge);
  4275. }
  4276. } catch (Exception e) {
  4277. s_logger.warn("caught execption when creating ovs tunnel", e);
  4278. return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge);
  4279. }
  4280. }
  4281. private Answer execute(OvsDeleteFlowCommand cmd) {
  4282. _isOvs = true;
  4283. Connection conn = getConnection();
  4284. try {
  4285. Network nw = setupvSwitchNetwork(conn);
  4286. String bridge = nw.getBridge(conn);
  4287. String result = callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge,
  4288. "vmName", cmd.getVmName());
  4289. if (result.equalsIgnoreCase("SUCCESS")) {
  4290. return new Answer(cmd, true, "success to delete flows for " + cmd.getVmName());
  4291. } else {
  4292. return new Answer(cmd, false, result);
  4293. }
  4294. } catch (Exception e) {
  4295. e.printStackTrace();
  4296. }
  4297. return new Answer(cmd, false, "failed to delete flow for " + cmd.getVmName());
  4298. }
  4299. private List<Pair<String, Long>> ovsFullSyncStates() {
  4300. Connection conn = getConnection();
  4301. try {
  4302. String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.uuid);
  4303. String [] logs = result != null ?result.split(";"): new String [0];
  4304. List<Pair<String, Long>> states = new ArrayList<Pair<String, Long>>();
  4305. for (String log: logs){
  4306. String [] info = log.split(",");
  4307. if (info.length != 5) {
  4308. s_logger.warn("Wrong element number in ovs log(" + log +")");
  4309. continue;
  4310. }
  4311. //','.join([bridge, vmName, vmId, seqno, tag])
  4312. try {
  4313. states.add(new Pair<String,Long>(info[0], Long.parseLong(info[3])));
  4314. } catch (NumberFormatException nfe) {
  4315. states.add(new Pair<String,Long>(info[0], -1L));
  4316. }
  4317. }
  4318. return states;
  4319. } catch (Exception e) {
  4320. e.printStackTrace();
  4321. }
  4322. return null;
  4323. }
  4324. private OvsSetTagAndFlowAnswer execute(OvsSetTagAndFlowCommand cmd) {
  4325. _isOvs = true;
  4326. Connection conn = getConnection();
  4327. try {
  4328. Network nw = setupvSwitchNetwork(conn);
  4329. String bridge = nw.getBridge(conn);
  4330. /*If VM is domainRouter, this will try to set flow and tag on its
  4331. * none guest network nic. don't worry, it will fail silently at host
  4332. * plugin side
  4333. */
  4334. String result = callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge,
  4335. "vmName", cmd.getVmName(), "tag", cmd.getTag(),
  4336. "vlans", cmd.getVlans(), "seqno", cmd.getSeqNo());
  4337. s_logger.debug("set flow for " + cmd.getVmName() + " " + result);
  4338. if (result.equalsIgnoreCase("SUCCESS")) {
  4339. return new OvsSetTagAndFlowAnswer(cmd, true, result);
  4340. } else {
  4341. return new OvsSetTagAndFlowAnswer(cmd, false, result);
  4342. }
  4343. } catch (Exception e) {
  4344. e.printStackTrace();
  4345. }
  4346. return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION");
  4347. }
  4348. private OvsCreateGreTunnelAnswer execute(OvsCreateGreTunnelCommand cmd) {
  4349. _isOvs = true;
  4350. Connection conn = getConnection();
  4351. String bridge = "unkonwn";
  4352. try {
  4353. Network nw = setupvSwitchNetwork(conn);
  4354. bridge = nw.getBridge(conn);
  4355. String result = callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge,
  4356. "remoteIP", cmd.getRemoteIp(), "greKey", cmd.getKey(), "from",
  4357. Long.toString(cmd.getFrom()), "to", Long.toString(cmd.getTo()));
  4358. String[] res = result.split(":");
  4359. if (res.length != 2 || (res.length == 2 && res[1].equalsIgnoreCase("[]"))) {
  4360. return new OvsCreateGreTunnelAnswer(cmd, false, result,
  4361. _host.ip, bridge);
  4362. } else {
  4363. return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.ip, bridge, Integer.parseInt(res[1]));
  4364. }
  4365. } catch (Exception e) {
  4366. e.printStackTrace();
  4367. }
  4368. return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge);
  4369. }
  4370. private Answer execute(SecurityGroupRulesCmd cmd) {
  4371. Connection conn = getConnection();
  4372. if (s_logger.isTraceEnabled()) {
  4373. s_logger.trace("Sending network rules command to " + _host.ip);
  4374. }
  4375. if (!_canBridgeFirewall) {
  4376. s_logger.warn("Host " + _host.ip + " cannot do bridge firewalling");
  4377. return new SecurityGroupRuleAnswer(cmd, false,
  4378. "Host " + _host.ip + " cannot do bridge firewalling",
  4379. SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL);
  4380. }
  4381. String result = callHostPlugin(conn, "vmops", "network_rules",
  4382. "vmName", cmd.getVmName(),
  4383. "vmIP", cmd.getGuestIp(),
  4384. "vmMAC", cmd.getGuestMac(),
  4385. "vmID", Long.toString(cmd.getVmId()),
  4386. "signature", cmd.getSignature(),
  4387. "seqno", Long.toString(cmd.getSeqNum()),
  4388. "deflated", "true",
  4389. "rules", cmd.compressStringifiedRules());
  4390. if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
  4391. s_logger.warn("Failed to program network rules for vm " + cmd.getVmName());
  4392. return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed");
  4393. } else {
  4394. s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", ingress numrules=" + cmd.getIngressRuleSet().length + ", egress numrules=" + cmd.getEgressRuleSet().length);
  4395. return new SecurityGroupRuleAnswer(cmd);
  4396. }
  4397. }
  4398. protected Answer execute(DeleteStoragePoolCommand cmd) {
  4399. Connection conn = getConnection();
  4400. StorageFilerTO poolTO = cmd.getPool();
  4401. try {
  4402. SR sr = getStorageRepository(conn, poolTO);
  4403. removeSR(conn, sr);
  4404. Answer answer = new Answer(cmd, true, "success");
  4405. return answer;
  4406. } catch (Exception e) {
  4407. String msg = "DeleteStoragePoolCommand XenAPIException:" + e.getMessage() + " host:" + _host.uuid + " pool: " + poolTO.getHost() + poolTO.getPath();
  4408. s_logger.warn(msg, e);
  4409. return new Answer(cmd, false, msg);
  4410. }
  4411. }
  4412. public Connection getConnection() {
  4413. return _connPool.connect(_host.uuid, _host.pool, _host.ip, _username, _password, _wait);
  4414. }
  4415. protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) {
  4416. final StringBuilder caps = new StringBuilder();
  4417. try {
  4418. Host host = Host.getByUuid(conn, _host.uuid);
  4419. Host.Record hr = host.getRecord(conn);
  4420. Map<String, String> details = cmd.getHostDetails();
  4421. if (details == null) {
  4422. details = new HashMap<String, String>();
  4423. }
  4424. details.put("product_brand", hr.softwareVersion.get("product_brand"));
  4425. details.put("product_version", hr.softwareVersion.get("product_version"));
  4426. if( hr.softwareVersion.get("product_version_text_short") != null ) {
  4427. details.put("product_version_text_short", hr.softwareVersion.get("product_version_text_short"));
  4428. cmd.setHypervisorVersion(hr.softwareVersion.get("product_version_text_short"));
  4429. }else{
  4430. cmd.setHypervisorVersion(hr.softwareVersion.get("product_version"));
  4431. }
  4432. if (_privateNetworkName != null) {
  4433. details.put("private.network.device", _privateNetworkName);
  4434. }
  4435. details.put("can_bridge_firewall", Boolean.toString(_canBridgeFirewall));
  4436. cmd.setHostDetails(details);
  4437. cmd.setName(hr.nameLabel);
  4438. cmd.setGuid(_host.uuid);
  4439. cmd.setPool(_host.pool);
  4440. cmd.setDataCenter(Long.toString(_dcId));
  4441. for (final String cap : hr.capabilities) {
  4442. if (cap.length() > 0) {
  4443. caps.append(cap).append(" , ");
  4444. }
  4445. }
  4446. if (caps.length() > 0) {
  4447. caps.delete(caps.length() - 3, caps.length());
  4448. }
  4449. cmd.setCaps(caps.toString());
  4450. cmd.setSpeed(_host.speed);
  4451. cmd.setCpus(_host.cpus);
  4452. HostMetrics hm = host.getMetrics(conn);
  4453. long ram = 0;
  4454. long dom0Ram = 0;
  4455. ram = hm.getMemoryTotal(conn);
  4456. Set<VM> vms = host.getResidentVMs(conn);
  4457. for (VM vm : vms) {
  4458. if (vm.getIsControlDomain(conn)) {
  4459. dom0Ram = vm.getMemoryDynamicMax(conn);
  4460. break;
  4461. }
  4462. }
  4463. ram = (long) ((ram - dom0Ram - _xs_memory_used) * _xs_virtualization_factor);
  4464. cmd.setMemory(ram);
  4465. cmd.setDom0MinMemory(dom0Ram);
  4466. if (s_logger.isDebugEnabled()) {
  4467. s_logger.debug("Total Ram: " + ram + " dom0 Ram: " + dom0Ram);
  4468. }
  4469. PIF pif = PIF.getByUuid(conn, _host.privatePif);
  4470. PIF.Record pifr = pif.getRecord(conn);
  4471. if (pifr.IP != null && pifr.IP.length() > 0) {
  4472. cmd.setPrivateIpAddress(pifr.IP);
  4473. cmd.setPrivateMacAddress(pifr.MAC);
  4474. cmd.setPrivateNetmask(pifr.netmask);
  4475. } else {
  4476. String msg = "Private network " + _privateNetworkName + " doesn't have IP address, please check the host network configuration";
  4477. s_logger.error(msg);
  4478. throw new CloudRuntimeException(msg);
  4479. }
  4480. pif = PIF.getByUuid(conn, _host.storagePif1);
  4481. pifr = pif.getRecord(conn);
  4482. if (pifr.IP != null && pifr.IP.length() > 0) {
  4483. cmd.setStorageIpAddress(pifr.IP);
  4484. cmd.setStorageMacAddress(pifr.MAC);
  4485. cmd.setStorageNetmask(pifr.netmask);
  4486. }
  4487. if (_host.storagePif2 != null) {
  4488. pif = PIF.getByUuid(conn, _host.storagePif2);
  4489. pifr = pif.getRecord(conn);
  4490. if (pifr.IP != null && pifr.IP.length() > 0) {
  4491. cmd.setStorageIpAddressDeux(pifr.IP);
  4492. cmd.setStorageMacAddressDeux(pifr.MAC);
  4493. cmd.setStorageNetmaskDeux(pifr.netmask);
  4494. }
  4495. }
  4496. Map<String, String> configs = hr.otherConfig;
  4497. cmd.setIqn(configs.get("iscsi_iqn"));
  4498. cmd.setPod(_pod);
  4499. cmd.setVersion(CitrixResourceBase.class.getPackage().getImplementationVersion());
  4500. } catch (final XmlRpcException e) {
  4501. throw new CloudRuntimeException("XML RPC Exception" + e.getMessage(), e);
  4502. } catch (XenAPIException e) {
  4503. throw new CloudRuntimeException("XenAPIException" + e.toString(), e);
  4504. }
  4505. }
  4506. public CitrixResourceBase() {
  4507. }
  4508. @Override
  4509. public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
  4510. _name = name;
  4511. try {
  4512. _dcId = Long.parseLong((String) params.get("zone"));
  4513. } catch (NumberFormatException e) {
  4514. throw new ConfigurationException("Unable to get the zone " + params.get("zone"));
  4515. }
  4516. _host.uuid = (String) params.get("guid");
  4517. _name = _host.uuid;
  4518. _host.ip = (String) params.get("ipaddress");
  4519. _username = (String) params.get("username");
  4520. _password.add((String) params.get("password"));
  4521. _pod = (String) params.get("pod");
  4522. _cluster = (String)params.get("cluster");
  4523. _privateNetworkName = (String) params.get("private.network.device");
  4524. _publicNetworkName = (String) params.get("public.network.device");
  4525. _guestNetworkName = (String)params.get("guest.network.device");
  4526. _instance = (String) params.get("instance.name");
  4527. _linkLocalPrivateNetworkName = (String) params.get("private.linkLocal.device");
  4528. if (_linkLocalPrivateNetworkName == null) {
  4529. _linkLocalPrivateNetworkName = "cloud_link_local_network";
  4530. }
  4531. _storageNetworkName1 = (String) params.get("storage.network.device1");
  4532. _storageNetworkName2 = (String) params.get("storage.network.device2");
  4533. _heartbeatInterval = NumbersUtil.parseInt((String) params.get("xen.heartbeat.interval"), 60);
  4534. String value = (String) params.get("wait");
  4535. _wait = NumbersUtil.parseInt(value, 600);
  4536. value = (String) params.get("migratewait");
  4537. _migratewait = NumbersUtil.parseInt(value, 3600);
  4538. if (_pod == null) {
  4539. throw new ConfigurationException("Unable to get the pod");
  4540. }
  4541. if (_host.ip == null) {
  4542. throw new ConfigurationException("Unable to get the host address");
  4543. }
  4544. if (_username == null) {
  4545. throw new ConfigurationException("Unable to get the username");
  4546. }
  4547. if (_password == null) {
  4548. throw new ConfigurationException("Unable to get the password");
  4549. }
  4550. if (_host.uuid == null) {
  4551. throw new ConfigurationException("Unable to get the uuid");
  4552. }
  4553. CheckXenHostInfo();
  4554. return true;
  4555. }
  4556. private void CheckXenHostInfo() throws ConfigurationException {
  4557. Connection conn = _connPool.slaveConnect(_host.ip, _username, _password);
  4558. if( conn == null ) {
  4559. throw new ConfigurationException("Can not create slave connection to " + _host.ip);
  4560. }
  4561. try {
  4562. Host.Record hostRec = null;
  4563. try {
  4564. Host host = Host.getByUuid(conn, _host.uuid);
  4565. hostRec = host.getRecord(conn);
  4566. Pool.Record poolRec = Pool.getAllRecords(conn).values().iterator().next();
  4567. _host.pool = poolRec.uuid;
  4568. } catch (Exception e) {
  4569. throw new ConfigurationException("Can not get host information from " + _host.ip);
  4570. }
  4571. if( !hostRec.address.equals(_host.ip) ) {
  4572. String msg = "Host " + _host.ip + " seems be reinstalled, please remove this host and readd";
  4573. s_logger.error(msg);
  4574. throw new ConfigurationException(msg);
  4575. }
  4576. } finally {
  4577. try {
  4578. Session.localLogout(conn);
  4579. } catch (Exception e) {
  4580. }
  4581. }
  4582. }
  4583. void destroyVDI(Connection conn, VDI vdi) {
  4584. try {
  4585. vdi.destroy(conn);
  4586. } catch (Exception e) {
  4587. String msg = "destroy VDI failed due to " + e.toString();
  4588. s_logger.warn(msg);
  4589. }
  4590. }
  4591. public CreateAnswer execute(CreateCommand cmd) {
  4592. Connection conn = getConnection();
  4593. StorageFilerTO pool = cmd.getPool();
  4594. DiskProfile dskch = cmd.getDiskCharacteristics();
  4595. VDI vdi = null;
  4596. try {
  4597. SR poolSr = getStorageRepository(conn, pool);
  4598. if (cmd.getTemplateUrl() != null) {
  4599. VDI tmpltvdi = null;
  4600. tmpltvdi = getVDIbyUuid(conn, cmd.getTemplateUrl());
  4601. vdi = tmpltvdi.createClone(conn, new HashMap<String, String>());
  4602. vdi.setNameLabel(conn, dskch.getName());
  4603. } else {
  4604. VDI.Record vdir = new VDI.Record();
  4605. vdir.nameLabel = dskch.getName();
  4606. vdir.SR = poolSr;
  4607. vdir.type = Types.VdiType.USER;
  4608. vdir.virtualSize = dskch.getSize();
  4609. vdi = VDI.create(conn, vdir);
  4610. }
  4611. VDI.Record vdir;
  4612. vdir = vdi.getRecord(conn);
  4613. s_logger.debug("Succesfully created VDI for " + cmd + ". Uuid = " + vdir.uuid);
  4614. VolumeTO vol = new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel,
  4615. pool.getPath(), vdir.uuid, vdir.virtualSize, null);
  4616. return new CreateAnswer(cmd, vol);
  4617. } catch (Exception e) {
  4618. s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: " + dskch, e);
  4619. return new CreateAnswer(cmd, e);
  4620. }
  4621. }
  4622. protected SR getISOSRbyVmName(Connection conn, String vmName) {
  4623. try {
  4624. Set<SR> srs = SR.getByNameLabel(conn, vmName + "-ISO");
  4625. if (srs.size() == 0) {
  4626. return null;
  4627. } else if (srs.size() == 1) {
  4628. return srs.iterator().next();
  4629. } else {
  4630. String msg = "getIsoSRbyVmName failed due to there are more than 1 SR having same Label";
  4631. s_logger.warn(msg);
  4632. }
  4633. } catch (XenAPIException e) {
  4634. String msg = "getIsoSRbyVmName failed due to " + e.toString();
  4635. s_logger.warn(msg, e);
  4636. } catch (Exception e) {
  4637. String msg = "getIsoSRbyVmName failed due to " + e.getMessage();
  4638. s_logger.warn(msg, e);
  4639. }
  4640. return null;
  4641. }
  4642. protected SR createNfsSRbyURI(Connection conn, URI uri, boolean shared) {
  4643. try {
  4644. if (s_logger.isDebugEnabled()) {
  4645. s_logger.debug("Creating a " + (shared ? "shared SR for " : "not shared SR for ") + uri);
  4646. }
  4647. Map<String, String> deviceConfig = new HashMap<String, String>();
  4648. String path = uri.getPath();
  4649. path = path.replace("//", "/");
  4650. deviceConfig.put("server", uri.getHost());
  4651. deviceConfig.put("serverpath", path);
  4652. String name = UUID.nameUUIDFromBytes(new String(uri.getHost() + path).getBytes()).toString();
  4653. if (!shared) {
  4654. Set<SR> srs = SR.getByNameLabel(conn, name);
  4655. for (SR sr : srs) {
  4656. SR.Record record = sr.getRecord(conn);
  4657. if (SRType.NFS.equals(record.type) && record.contentType.equals("user") && !record.shared) {
  4658. removeSRSync(conn, sr);
  4659. }
  4660. }
  4661. }
  4662. Host host = Host.getByUuid(conn, _host.uuid);
  4663. SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, new HashMap<String, String>());
  4664. if( !checkSR(conn, sr) ) {
  4665. throw new Exception("no attached PBD");
  4666. }
  4667. if (s_logger.isDebugEnabled()) {
  4668. s_logger.debug(logX(sr, "Created a SR; UUID is " + sr.getUuid(conn) + " device config is " + deviceConfig));
  4669. }
  4670. sr.scan(conn);
  4671. return sr;
  4672. } catch (XenAPIException e) {
  4673. String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString();
  4674. s_logger.warn(msg, e);
  4675. throw new CloudRuntimeException(msg, e);
  4676. } catch (Exception e) {
  4677. String msg = "Can not create second storage SR mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage();
  4678. s_logger.warn(msg, e);
  4679. throw new CloudRuntimeException(msg, e);
  4680. }
  4681. }
  4682. protected SR createIsoSRbyURI(Connection conn, URI uri, String vmName, boolean shared) {
  4683. try {
  4684. Map<String, String> deviceConfig = new HashMap<String, String>();
  4685. String path = uri.getPath();
  4686. path = path.replace("//", "/");
  4687. deviceConfig.put("location", uri.getHost() + ":" + path);
  4688. Host host = Host.getByUuid(conn, _host.uuid);
  4689. SR sr = SR.create(conn, host, deviceConfig, new Long(0), uri.getHost() + path, "iso", "iso", "iso", shared, new HashMap<String, String>());
  4690. sr.setNameLabel(conn, vmName + "-ISO");
  4691. sr.setNameDescription(conn, deviceConfig.get("location"));
  4692. sr.scan(conn);
  4693. return sr;
  4694. } catch (XenAPIException e) {
  4695. String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.toString();
  4696. s_logger.warn(msg, e);
  4697. throw new CloudRuntimeException(msg, e);
  4698. } catch (Exception e) {
  4699. String msg = "createIsoSRbyURI failed! mountpoint: " + uri.getHost() + uri.getPath() + " due to " + e.getMessage();
  4700. s_logger.warn(msg, e);
  4701. throw new CloudRuntimeException(msg, e);
  4702. }
  4703. }
  4704. protected VDI getVDIbyLocationandSR(Connection conn, String loc, SR sr) {
  4705. try {
  4706. Set<VDI> vdis = sr.getVDIs(conn);
  4707. for (VDI vdi : vdis) {
  4708. if (vdi.getLocation(conn).startsWith(loc)) {
  4709. return vdi;
  4710. }
  4711. }
  4712. String msg = "can not getVDIbyLocationandSR " + loc;
  4713. s_logger.warn(msg);
  4714. return null;
  4715. } catch (XenAPIException e) {
  4716. String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.toString();
  4717. s_logger.warn(msg, e);
  4718. throw new CloudRuntimeException(msg, e);
  4719. } catch (Exception e) {
  4720. String msg = "getVDIbyLocationandSR exception " + loc + " due to " + e.getMessage();
  4721. s_logger.warn(msg, e);
  4722. throw new CloudRuntimeException(msg, e);
  4723. }
  4724. }
  4725. protected VDI getVDIbyUuid(Connection conn, String uuid) {
  4726. try {
  4727. return VDI.getByUuid(conn, uuid);
  4728. } catch (Exception e) {
  4729. String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString();
  4730. s_logger.debug(msg);
  4731. throw new CloudRuntimeException(msg, e);
  4732. }
  4733. }
  4734. protected SR getIscsiSR(Connection conn, StorageFilerTO pool) {
  4735. synchronized (pool.getUuid().intern()) {
  4736. Map<String, String> deviceConfig = new HashMap<String, String>();
  4737. try {
  4738. String target = pool.getHost();
  4739. String path = pool.getPath();
  4740. if (path.endsWith("/")) {
  4741. path = path.substring(0, path.length() - 1);
  4742. }
  4743. String tmp[] = path.split("/");
  4744. if (tmp.length != 3) {
  4745. String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN";
  4746. s_logger.warn(msg);
  4747. throw new CloudRuntimeException(msg);
  4748. }
  4749. String targetiqn = tmp[1].trim();
  4750. String lunid = tmp[2].trim();
  4751. String scsiid = "";
  4752. Set<SR> srs = SR.getByNameLabel(conn, pool.getUuid());
  4753. for (SR sr : srs) {
  4754. if (!SRType.LVMOISCSI.equals(sr.getType(conn))) {
  4755. continue;
  4756. }
  4757. Set<PBD> pbds = sr.getPBDs(conn);
  4758. if (pbds.isEmpty()) {
  4759. continue;
  4760. }
  4761. PBD pbd = pbds.iterator().next();
  4762. Map<String, String> dc = pbd.getDeviceConfig(conn);
  4763. if (dc == null) {
  4764. continue;
  4765. }
  4766. if (dc.get("target") == null) {
  4767. continue;
  4768. }
  4769. if (dc.get("targetIQN") == null) {
  4770. continue;
  4771. }
  4772. if (dc.get("lunid") == null) {
  4773. continue;
  4774. }
  4775. if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) {
  4776. throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:"
  4777. + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + _host.uuid);
  4778. }
  4779. }
  4780. deviceConfig.put("target", target);
  4781. deviceConfig.put("targetIQN", targetiqn);
  4782. Host host = Host.getByUuid(conn, _host.uuid);
  4783. Map<String, String> smConfig = new HashMap<String, String>();
  4784. String type = SRType.LVMOISCSI.toString();
  4785. String poolId = Long.toString(pool.getId());
  4786. SR sr = null;
  4787. try {
  4788. sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
  4789. smConfig);
  4790. } catch (XenAPIException e) {
  4791. String errmsg = e.toString();
  4792. if (errmsg.contains("SR_BACKEND_FAILURE_107")) {
  4793. String lun[] = errmsg.split("<LUN>");
  4794. boolean found = false;
  4795. for (int i = 1; i < lun.length; i++) {
  4796. int blunindex = lun[i].indexOf("<LUNid>") + 7;
  4797. int elunindex = lun[i].indexOf("</LUNid>");
  4798. String ilun = lun[i].substring(blunindex, elunindex);
  4799. ilun = ilun.trim();
  4800. if (ilun.equals(lunid)) {
  4801. int bscsiindex = lun[i].indexOf("<SCSIid>") + 8;
  4802. int escsiindex = lun[i].indexOf("</SCSIid>");
  4803. scsiid = lun[i].substring(bscsiindex, escsiindex);
  4804. scsiid = scsiid.trim();
  4805. found = true;
  4806. break;
  4807. }
  4808. }
  4809. if (!found) {
  4810. String msg = "can not find LUN " + lunid + " in " + errmsg;
  4811. s_logger.warn(msg);
  4812. throw new CloudRuntimeException(msg);
  4813. }
  4814. } else {
  4815. String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
  4816. s_logger.warn(msg, e);
  4817. throw new CloudRuntimeException(msg, e);
  4818. }
  4819. }
  4820. deviceConfig.put("SCSIid", scsiid);
  4821. String result = SR.probe(conn, host, deviceConfig, type , smConfig);
  4822. String pooluuid = null;
  4823. if( result.indexOf("<UUID>") != -1) {
  4824. pooluuid = result.substring(result.indexOf("<UUID>") + 6, result.indexOf("</UUID>")).trim();
  4825. }
  4826. if( pooluuid == null || pooluuid.length() != 36) {
  4827. sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
  4828. smConfig);
  4829. } else {
  4830. sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId,
  4831. type, "user", true, smConfig);
  4832. Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn);
  4833. PBD.Record rec = new PBD.Record();
  4834. rec.deviceConfig = deviceConfig;
  4835. rec.host = pRec.master;
  4836. rec.SR = sr;
  4837. PBD pbd = PBD.create(conn, rec);
  4838. pbd.plug(conn);
  4839. }
  4840. sr.scan(conn);
  4841. return sr;
  4842. } catch (XenAPIException e) {
  4843. String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
  4844. s_logger.warn(msg, e);
  4845. throw new CloudRuntimeException(msg, e);
  4846. } catch (Exception e) {
  4847. String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage();
  4848. s_logger.warn(msg, e);
  4849. throw new CloudRuntimeException(msg, e);
  4850. }
  4851. }
  4852. }
  4853. protected SR getNfsSR(Connection conn, StorageFilerTO pool) {
  4854. Map<String, String> deviceConfig = new HashMap<String, String>();
  4855. try {
  4856. String server = pool.getHost();
  4857. String serverpath = pool.getPath();
  4858. serverpath = serverpath.replace("//", "/");
  4859. Set<SR> srs = SR.getAll(conn);
  4860. for (SR sr : srs) {
  4861. if (!SRType.NFS.equals(sr.getType(conn))) {
  4862. continue;
  4863. }
  4864. Set<PBD> pbds = sr.getPBDs(conn);
  4865. if (pbds.isEmpty()) {
  4866. continue;
  4867. }
  4868. PBD pbd = pbds.iterator().next();
  4869. Map<String, String> dc = pbd.getDeviceConfig(conn);
  4870. if (dc == null) {
  4871. continue;
  4872. }
  4873. if (dc.get("server") == null) {
  4874. continue;
  4875. }
  4876. if (dc.get("serverpath") == null) {
  4877. continue;
  4878. }
  4879. if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) {
  4880. throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:"
  4881. + dc.get("serverpath") + " for pool " + pool.getUuid() + "on host:" + _host.uuid);
  4882. }
  4883. }
  4884. deviceConfig.put("server", server);
  4885. deviceConfig.put("serverpath", serverpath);
  4886. Host host = Host.getByUuid(conn, _host.uuid);
  4887. SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true,
  4888. new HashMap<String, String>());
  4889. sr.scan(conn);
  4890. return sr;
  4891. } catch (XenAPIException e) {
  4892. throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
  4893. } catch (XmlRpcException e) {
  4894. throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
  4895. }
  4896. }
  4897. public Answer execute(DestroyCommand cmd) {
  4898. Connection conn = getConnection();
  4899. VolumeTO vol = cmd.getVolume();
  4900. // Look up the VDI
  4901. String volumeUUID = vol.getPath();
  4902. VDI vdi = null;
  4903. try {
  4904. vdi = getVDIbyUuid(conn, volumeUUID);
  4905. } catch (Exception e) {
  4906. return new Answer(cmd, true, "Success");
  4907. }
  4908. Set<VBD> vbds = null;
  4909. try {
  4910. vbds = vdi.getVBDs(conn);
  4911. } catch (Exception e) {
  4912. String msg = "VDI getVBDS for " + volumeUUID + " failed due to " + e.toString();
  4913. s_logger.warn(msg, e);
  4914. return new Answer(cmd, false, msg);
  4915. }
  4916. for (VBD vbd : vbds) {
  4917. try {
  4918. vbd.unplug(conn);
  4919. vbd.destroy(conn);
  4920. } catch (Exception e) {
  4921. String msg = "VM destroy for " + volumeUUID + " failed due to " + e.toString();
  4922. s_logger.warn(msg, e);
  4923. return new Answer(cmd, false, msg);
  4924. }
  4925. }
  4926. try {
  4927. Set<VDI> snapshots = vdi.getSnapshots(conn);
  4928. for( VDI snapshot: snapshots ) {
  4929. snapshot.destroy(conn);
  4930. }
  4931. vdi.destroy(conn);
  4932. } catch (Exception e) {
  4933. String msg = "VDI destroy for " + volumeUUID + " failed due to " + e.toString();
  4934. s_logger.warn(msg, e);
  4935. return new Answer(cmd, false, msg);
  4936. }
  4937. return new Answer(cmd, true, "Success");
  4938. }
  4939. public CopyVolumeAnswer execute(final CopyVolumeCommand cmd) {
  4940. Connection conn = getConnection();
  4941. String volumeUUID = cmd.getVolumePath();
  4942. StorageFilerTO poolTO = cmd.getPool();
  4943. String secondaryStorageURL = cmd.getSecondaryStorageURL();
  4944. boolean toSecondaryStorage = cmd.toSecondaryStorage();
  4945. int wait = cmd.getWait();
  4946. try {
  4947. URI uri = new URI(secondaryStorageURL);
  4948. String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/";
  4949. String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/";
  4950. String mountpoint = remoteVolumesMountPath + volumeFolder;
  4951. SR primaryStoragePool = getStorageRepository(conn, poolTO);
  4952. String srUuid = primaryStoragePool.getUuid(conn);
  4953. if (toSecondaryStorage) {
  4954. // Create the volume folder
  4955. if (!createSecondaryStorageFolder(conn, remoteVolumesMountPath, volumeFolder)) {
  4956. throw new InternalErrorException("Failed to create the volume folder.");
  4957. }
  4958. SR secondaryStorage = null;
  4959. try {
  4960. // Create a SR for the volume UUID folder
  4961. secondaryStorage = createNfsSRbyURI(conn, new URI(secondaryStorageURL + "/volumes/" + volumeFolder), false);
  4962. // Look up the volume on the source primary storage pool
  4963. VDI srcVolume = getVDIbyUuid(conn, volumeUUID);
  4964. // Copy the volume to secondary storage
  4965. VDI destVolume = cloudVDIcopy(conn, srcVolume, secondaryStorage, wait);
  4966. String destVolumeUUID = destVolume.getUuid(conn);
  4967. return new CopyVolumeAnswer(cmd, true, null, null, destVolumeUUID);
  4968. } finally {
  4969. removeSR(conn, secondaryStorage);
  4970. }
  4971. } else {
  4972. try {
  4973. String volumePath = mountpoint + "/" + volumeUUID + ".vhd";
  4974. String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait );
  4975. return new CopyVolumeAnswer(cmd, true, null, srUuid, uuid);
  4976. } finally {
  4977. deleteSecondaryStorageFolder(conn, remoteVolumesMountPath, volumeFolder);
  4978. }
  4979. }
  4980. } catch (Exception e) {
  4981. String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
  4982. s_logger.warn(msg, e);
  4983. return new CopyVolumeAnswer(cmd, false, msg, null, null);
  4984. }
  4985. }
  4986. protected AttachVolumeAnswer execute(final AttachVolumeCommand cmd) {
  4987. Connection conn = getConnection();
  4988. boolean attach = cmd.getAttach();
  4989. String vmName = cmd.getVmName();
  4990. Long deviceId = cmd.getDeviceId();
  4991. String errorMsg;
  4992. if (attach) {
  4993. errorMsg = "Failed to attach volume";
  4994. } else {
  4995. errorMsg = "Failed to detach volume";
  4996. }
  4997. try {
  4998. // Look up the VDI
  4999. VDI vdi = mount(conn, cmd.getPooltype(), cmd.getVolumeFolder(),cmd.getVolumePath());
  5000. // Look up the VM
  5001. VM vm = getVM(conn, vmName);
  5002. /* For HVM guest, if no pv driver installed, no attach/detach */
  5003. boolean isHVM;
  5004. if (vm.getPVBootloader(conn).equalsIgnoreCase("")) {
  5005. isHVM = true;
  5006. } else {
  5007. isHVM = false;
  5008. }
  5009. VMGuestMetrics vgm = vm.getGuestMetrics(conn);
  5010. boolean pvDrvInstalled = false;
  5011. if (!isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) {
  5012. pvDrvInstalled = true;
  5013. }
  5014. if (isHVM && !pvDrvInstalled) {
  5015. s_logger.warn(errorMsg + ": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected");
  5016. return new AttachVolumeAnswer(cmd, "You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso.");
  5017. }
  5018. if (attach) {
  5019. // Figure out the disk number to attach the VM to
  5020. String diskNumber = null;
  5021. if( deviceId != null ) {
  5022. if( deviceId.longValue() == 3 ) {
  5023. String msg = "Device 3 is reserved for CD-ROM, choose other device";
  5024. return new AttachVolumeAnswer(cmd,msg);
  5025. }
  5026. if(isDeviceUsed(conn, vm, deviceId)) {
  5027. String msg = "Device " + deviceId + " is used in VM " + vmName;
  5028. return new AttachVolumeAnswer(cmd,msg);
  5029. }
  5030. diskNumber = deviceId.toString();
  5031. } else {
  5032. diskNumber = getUnusedDeviceNum(conn, vm);
  5033. }
  5034. // Create a new VBD
  5035. VBD.Record vbdr = new VBD.Record();
  5036. vbdr.VM = vm;
  5037. vbdr.VDI = vdi;
  5038. vbdr.bootable = false;
  5039. vbdr.userdevice = diskNumber;
  5040. vbdr.mode = Types.VbdMode.RW;
  5041. vbdr.type = Types.VbdType.DISK;
  5042. vbdr.unpluggable = true;
  5043. VBD vbd = VBD.create(conn, vbdr);
  5044. // Attach the VBD to the VM
  5045. vbd.plug(conn);
  5046. // Update the VDI's label to include the VM name
  5047. vdi.setNameLabel(conn, vmName + "-DATA");
  5048. return new AttachVolumeAnswer(cmd, Long.parseLong(diskNumber));
  5049. } else {
  5050. // Look up all VBDs for this VDI
  5051. Set<VBD> vbds = vdi.getVBDs(conn);
  5052. // Detach each VBD from its VM, and then destroy it
  5053. for (VBD vbd : vbds) {
  5054. VBD.Record vbdr = vbd.getRecord(conn);
  5055. if (vbdr.currentlyAttached) {
  5056. vbd.unplug(conn);
  5057. }
  5058. vbd.destroy(conn);
  5059. }
  5060. // Update the VDI's label to be "detached"
  5061. vdi.setNameLabel(conn, "detached");
  5062. umount(conn, vdi);
  5063. return new AttachVolumeAnswer(cmd);
  5064. }
  5065. } catch (XenAPIException e) {
  5066. String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.toString();
  5067. s_logger.warn(msg, e);
  5068. return new AttachVolumeAnswer(cmd, msg);
  5069. } catch (Exception e) {
  5070. String msg = errorMsg + " for uuid: " + cmd.getVolumePath() + " due to " + e.getMessage();
  5071. s_logger.warn(msg, e);
  5072. return new AttachVolumeAnswer(cmd, msg);
  5073. }
  5074. }
  5075. protected void umount(Connection conn, VDI vdi) {
  5076. }
  5077. protected Answer execute(final AttachIsoCommand cmd) {
  5078. Connection conn = getConnection();
  5079. boolean attach = cmd.isAttach();
  5080. String vmName = cmd.getVmName();
  5081. String isoURL = cmd.getIsoPath();
  5082. String errorMsg;
  5083. if (attach) {
  5084. errorMsg = "Failed to attach ISO";
  5085. } else {
  5086. errorMsg = "Failed to detach ISO";
  5087. }
  5088. try {
  5089. if (attach) {
  5090. VBD isoVBD = null;
  5091. // Find the VM
  5092. VM vm = getVM(conn, vmName);
  5093. // Find the ISO VDI
  5094. VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL);
  5095. // Find the VM's CD-ROM VBD
  5096. Set<VBD> vbds = vm.getVBDs(conn);
  5097. for (VBD vbd : vbds) {
  5098. String userDevice = vbd.getUserdevice(conn);
  5099. Types.VbdType type = vbd.getType(conn);
  5100. if (userDevice.equals("3") && type == Types.VbdType.CD) {
  5101. isoVBD = vbd;
  5102. break;
  5103. }
  5104. }
  5105. if (isoVBD == null) {
  5106. throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName);
  5107. } else {
  5108. // If an ISO is already inserted, eject it
  5109. if (isoVBD.getEmpty(conn) == false) {
  5110. isoVBD.eject(conn);
  5111. }
  5112. // Insert the new ISO
  5113. isoVBD.insert(conn, isoVDI);
  5114. }
  5115. return new Answer(cmd);
  5116. } else {
  5117. // Find the VM
  5118. VM vm = getVM(conn, vmName);
  5119. String vmUUID = vm.getUuid(conn);
  5120. // Find the ISO VDI
  5121. VDI isoVDI = getIsoVDIByURL(conn, vmName, isoURL);
  5122. SR sr = isoVDI.getSR(conn);
  5123. // Look up all VBDs for this VDI
  5124. Set<VBD> vbds = isoVDI.getVBDs(conn);
  5125. // Iterate through VBDs, and if the VBD belongs the VM, eject
  5126. // the ISO from it
  5127. for (VBD vbd : vbds) {
  5128. VM vbdVM = vbd.getVM(conn);
  5129. String vbdVmUUID = vbdVM.getUuid(conn);
  5130. if (vbdVmUUID.equals(vmUUID)) {
  5131. // If an ISO is already inserted, eject it
  5132. if (!vbd.getEmpty(conn)) {
  5133. vbd.eject(conn);
  5134. }
  5135. break;
  5136. }
  5137. }
  5138. if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) {
  5139. removeSR(conn, sr);
  5140. }
  5141. return new Answer(cmd);
  5142. }
  5143. } catch (XenAPIException e) {
  5144. s_logger.warn(errorMsg + ": " + e.toString(), e);
  5145. return new Answer(cmd, false, e.toString());
  5146. } catch (Exception e) {
  5147. s_logger.warn(errorMsg + ": " + e.toString(), e);
  5148. return new Answer(cmd, false, e.getMessage());
  5149. }
  5150. }
  5151. boolean IsISCSI(String type) {
  5152. return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ;
  5153. }
  5154. protected ManageSnapshotAnswer execute(final ManageSnapshotCommand cmd) {
  5155. Connection conn = getConnection();
  5156. long snapshotId = cmd.getSnapshotId();
  5157. String snapshotName = cmd.getSnapshotName();
  5158. // By default assume failure
  5159. boolean success = false;
  5160. String cmdSwitch = cmd.getCommandSwitch();
  5161. String snapshotOp = "Unsupported snapshot command." + cmdSwitch;
  5162. if (cmdSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
  5163. snapshotOp = "create";
  5164. } else if (cmdSwitch.equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
  5165. snapshotOp = "destroy";
  5166. }
  5167. String details = "ManageSnapshotCommand operation: " + snapshotOp + " Failed for snapshotId: " + snapshotId;
  5168. String snapshotUUID = null;
  5169. try {
  5170. if (cmdSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
  5171. // Look up the volume
  5172. String volumeUUID = cmd.getVolumePath();
  5173. VDI volume = VDI.getByUuid(conn, volumeUUID);
  5174. // Create a snapshot
  5175. VDI snapshot = volume.snapshot(conn, new HashMap<String, String>());
  5176. if (snapshotName != null) {
  5177. snapshot.setNameLabel(conn, snapshotName);
  5178. }
  5179. // Determine the UUID of the snapshot
  5180. snapshotUUID = snapshot.getUuid(conn);
  5181. String preSnapshotUUID = cmd.getSnapshotPath();
  5182. //check if it is a empty snapshot
  5183. if( preSnapshotUUID != null) {
  5184. SR sr = volume.getSR(conn);
  5185. String srUUID = sr.getUuid(conn);
  5186. String type = sr.getType(conn);
  5187. Boolean isISCSI = IsISCSI(type);
  5188. String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI);
  5189. String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI);
  5190. if( snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) {
  5191. // this is empty snapshot, remove it
  5192. snapshot.destroy(conn);
  5193. snapshotUUID = preSnapshotUUID;
  5194. }
  5195. }
  5196. success = true;
  5197. details = null;
  5198. } else if (cmd.getCommandSwitch().equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
  5199. // Look up the snapshot
  5200. snapshotUUID = cmd.getSnapshotPath();
  5201. VDI snapshot = getVDIbyUuid(conn, snapshotUUID);
  5202. snapshot.destroy(conn);
  5203. snapshotUUID = null;
  5204. success = true;
  5205. details = null;
  5206. }
  5207. } catch (XenAPIException e) {
  5208. details += ", reason: " + e.toString();
  5209. s_logger.warn(details, e);
  5210. } catch (Exception e) {
  5211. details += ", reason: " + e.toString();
  5212. s_logger.warn(details, e);
  5213. }
  5214. return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, success, details);
  5215. }
  5216. protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromVolumeCommand cmd) {
  5217. Connection conn = getConnection();
  5218. String secondaryStoragePoolURL = cmd.getSecondaryStorageUrl();
  5219. String volumeUUID = cmd.getVolumePath();
  5220. Long accountId = cmd.getAccountId();
  5221. String userSpecifiedName = cmd.getTemplateName();
  5222. Long templateId = cmd.getTemplateId();
  5223. int wait = cmd.getWait();
  5224. String details = null;
  5225. SR tmpltSR = null;
  5226. boolean result = false;
  5227. String secondaryStorageMountPath = null;
  5228. String installPath = null;
  5229. try {
  5230. URI uri = new URI(secondaryStoragePoolURL);
  5231. secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
  5232. installPath = "template/tmpl/" + accountId + "/" + templateId;
  5233. if( !createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
  5234. details = " Filed to create folder " + installPath + " in secondary storage";
  5235. s_logger.warn(details);
  5236. return new CreatePrivateTemplateAnswer(cmd, false, details);
  5237. }
  5238. VDI volume = getVDIbyUuid(conn, volumeUUID);
  5239. // create template SR
  5240. URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
  5241. tmpltSR = createNfsSRbyURI(conn, tmpltURI, false);
  5242. // copy volume to template SR
  5243. VDI tmpltVDI = cloudVDIcopy(conn, volume, tmpltSR, wait);
  5244. // scan makes XenServer pick up VDI physicalSize
  5245. tmpltSR.scan(conn);
  5246. if (userSpecifiedName != null) {
  5247. tmpltVDI.setNameLabel(conn, userSpecifiedName);
  5248. }
  5249. String tmpltUUID = tmpltVDI.getUuid(conn);
  5250. String tmpltFilename = tmpltUUID + ".vhd";
  5251. long virtualSize = tmpltVDI.getVirtualSize(conn);
  5252. long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
  5253. // create the template.properties file
  5254. String templatePath = secondaryStorageMountPath + "/" + installPath;
  5255. result = postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, templateId);
  5256. if (!result) {
  5257. throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
  5258. }
  5259. installPath = installPath + "/" + tmpltFilename;
  5260. removeSR(conn, tmpltSR);
  5261. tmpltSR = null;
  5262. return new CreatePrivateTemplateAnswer(cmd, true, null, installPath, virtualSize, physicalSize, tmpltUUID, ImageFormat.VHD);
  5263. } catch (Exception e) {
  5264. if (tmpltSR != null) {
  5265. removeSR(conn, tmpltSR);
  5266. }
  5267. if ( secondaryStorageMountPath != null) {
  5268. deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
  5269. }
  5270. details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
  5271. s_logger.error(details, e);
  5272. }
  5273. return new CreatePrivateTemplateAnswer(cmd, result, details);
  5274. }
  5275. protected Answer execute(final UpgradeSnapshotCommand cmd) {
  5276. String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
  5277. String backedUpSnapshotUuid = cmd.getSnapshotUuid();
  5278. Long volumeId = cmd.getVolumeId();
  5279. Long accountId = cmd.getAccountId();
  5280. Long templateId = cmd.getTemplateId();
  5281. Long tmpltAcountId = cmd.getTmpltAccountId();
  5282. String version = cmd.getVersion();
  5283. if ( !version.equals("2.1") ) {
  5284. return new Answer(cmd, true, "success");
  5285. }
  5286. try {
  5287. Connection conn = getConnection();
  5288. URI uri = new URI(secondaryStorageUrl);
  5289. String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
  5290. String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + backedUpSnapshotUuid + ".vhd";
  5291. String templatePath = secondaryStorageMountPath + "/template/tmpl/" + tmpltAcountId + "/" + templateId;
  5292. upgradeSnapshot(conn, templatePath, snapshotPath);
  5293. return new Answer(cmd, true, "success");
  5294. } catch (Exception e) {
  5295. String details = "upgrading snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString();
  5296. s_logger.error(details, e);
  5297. }
  5298. return new Answer(cmd, false, "failure");
  5299. }
  5300. protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromSnapshotCommand cmd) {
  5301. Connection conn = getConnection();
  5302. Long accountId = cmd.getAccountId();
  5303. Long volumeId = cmd.getVolumeId();
  5304. String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
  5305. String backedUpSnapshotUuid = cmd.getSnapshotUuid();
  5306. Long newTemplateId = cmd.getNewTemplateId();
  5307. String userSpecifiedName = cmd.getTemplateName();
  5308. int wait = cmd.getWait();
  5309. // By default, assume failure
  5310. String details = null;
  5311. boolean result = false;
  5312. String secondaryStorageMountPath = null;
  5313. String installPath = null;
  5314. try {
  5315. URI uri = new URI(secondaryStorageUrl);
  5316. secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
  5317. installPath = "template/tmpl/" + accountId + "/" + newTemplateId;
  5318. if( !createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
  5319. details = " Filed to create folder " + installPath + " in secondary storage";
  5320. s_logger.warn(details);
  5321. return new CreatePrivateTemplateAnswer(cmd, false, details);
  5322. }
  5323. String templatePath = secondaryStorageMountPath + "/" + installPath;
  5324. // create snapshot SR
  5325. String filename = backedUpSnapshotUuid;
  5326. if ( !filename.startsWith("VHD-") && !filename.endsWith(".vhd")) {
  5327. filename = backedUpSnapshotUuid + ".vhd";
  5328. }
  5329. String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + filename;
  5330. String results = createTemplateFromSnapshot(conn, templatePath, snapshotPath, wait);
  5331. String[] tmp = results.split("#");
  5332. String tmpltUuid = tmp[1];
  5333. long physicalSize = Long.parseLong(tmp[2]);
  5334. long virtualSize = Long.parseLong(tmp[3]) * 1024 * 1024;
  5335. String tmpltFilename = tmpltUuid + ".vhd";
  5336. // create the template.properties file
  5337. result = postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUuid, userSpecifiedName, null, physicalSize, virtualSize, newTemplateId);
  5338. if (!result) {
  5339. throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templatePath);
  5340. }
  5341. installPath = installPath + "/" + tmpltFilename;
  5342. return new CreatePrivateTemplateAnswer(cmd, true, null, installPath, virtualSize, physicalSize, tmpltUuid, ImageFormat.VHD);
  5343. } catch (Exception e) {
  5344. if (secondaryStorageMountPath != null) {
  5345. deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
  5346. }
  5347. details = "Creating template from snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString();
  5348. s_logger.error(details, e);
  5349. }
  5350. return new CreatePrivateTemplateAnswer(cmd, result, details);
  5351. }
  5352. private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){
  5353. try {
  5354. VDI volume = getVDIbyUuid(conn, volumeUuid);
  5355. if (volume == null) {
  5356. throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it");
  5357. }
  5358. Set<VDI> snapshots = volume.getSnapshots(conn);
  5359. for( VDI snapshot : snapshots ) {
  5360. try {
  5361. if(! snapshot.getUuid(conn).equals(avoidSnapshotUuid)) {
  5362. snapshot.destroy(conn);
  5363. }
  5364. } catch (Exception e) {
  5365. String msg = "Destroying snapshot: " + snapshot+ " on primary storage failed due to " + e.toString();
  5366. s_logger.warn(msg, e);
  5367. }
  5368. }
  5369. s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid );
  5370. return true;
  5371. } catch (XenAPIException e) {
  5372. String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
  5373. s_logger.error(msg, e);
  5374. } catch (Exception e) {
  5375. String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
  5376. s_logger.warn(msg, e);
  5377. }
  5378. return false;
  5379. }
  5380. protected BackupSnapshotAnswer execute(final BackupSnapshotCommand cmd) {
  5381. Connection conn = getConnection();
  5382. String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
  5383. Long dcId = cmd.getDataCenterId();
  5384. Long accountId = cmd.getAccountId();
  5385. Long volumeId = cmd.getVolumeId();
  5386. String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
  5387. String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition.
  5388. String prevBackupUuid = cmd.getPrevBackupUuid();
  5389. String prevSnapshotUuid = cmd.getPrevSnapshotUuid();
  5390. int wait = cmd.getWait();
  5391. // By default assume failure
  5392. String details = null;
  5393. boolean success = false;
  5394. String snapshotBackupUuid = null;
  5395. boolean fullbackup = true;
  5396. try {
  5397. SR primaryStorageSR = getSRByNameLabelandHost(conn, primaryStorageNameLabel);
  5398. if (primaryStorageSR == null) {
  5399. throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel);
  5400. }
  5401. String psUuid = primaryStorageSR.getUuid(conn);
  5402. Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn));
  5403. URI uri = new URI(secondaryStorageUrl);
  5404. String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
  5405. VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid);
  5406. String snapshotPaUuid = null;
  5407. if ( prevBackupUuid != null ) {
  5408. try {
  5409. snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI);
  5410. if( snapshotPaUuid != null ) {
  5411. String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI);
  5412. String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI);
  5413. if (snashotPaPaPaUuid != null && prevSnashotPaUuid!= null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) {
  5414. fullbackup = false;
  5415. }
  5416. }
  5417. } catch (Exception e) {
  5418. }
  5419. }
  5420. if (fullbackup) {
  5421. // the first snapshot is always a full snapshot
  5422. String folder = "snapshots/" + accountId + "/" + volumeId;
  5423. if( !createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) {
  5424. details = " Filed to create folder " + folder + " in secondary storage";
  5425. s_logger.warn(details);
  5426. return new BackupSnapshotAnswer(cmd, false, details, null, false);
  5427. }
  5428. String snapshotMountpoint = secondaryStorageUrl + "/" + folder;
  5429. SR snapshotSr = null;
  5430. try {
  5431. snapshotSr = createNfsSRbyURI(conn, new URI(snapshotMountpoint), false);
  5432. VDI backedVdi = cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait);
  5433. snapshotBackupUuid = backedVdi.getUuid(conn);
  5434. if( cmd.getSwift() != null ) {
  5435. try {
  5436. swiftBackupSnapshot(conn, cmd.getSwift(), snapshotSr.getUuid(conn), snapshotBackupUuid, "S-" + volumeId.toString(), false, wait);
  5437. snapshotBackupUuid = snapshotBackupUuid + ".vhd";
  5438. } finally {
  5439. deleteSnapshotBackup(conn, dcId, accountId, volumeId, secondaryStorageMountPath, snapshotBackupUuid);
  5440. }
  5441. }
  5442. success = true;
  5443. } finally {
  5444. if( snapshotSr != null) {
  5445. removeSR(conn, snapshotSr);
  5446. }
  5447. }
  5448. } else {
  5449. String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
  5450. if( cmd.getSwift() != null ) {
  5451. swiftBackupSnapshot(conn, cmd.getSwift(), primaryStorageSRUuid, snapshotPaUuid, "S-" + volumeId.toString(), isISCSI, wait);
  5452. if ( isISCSI ) {
  5453. snapshotBackupUuid = "VHD-" + snapshotPaUuid;
  5454. } else {
  5455. snapshotBackupUuid = snapshotPaUuid + ".vhd";
  5456. }
  5457. success = true;
  5458. } else {
  5459. snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, dcId, accountId, volumeId, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait);
  5460. success = (snapshotBackupUuid != null);
  5461. }
  5462. }
  5463. String volumeUuid = cmd.getVolumePath();
  5464. destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
  5465. if (success) {
  5466. details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
  5467. }
  5468. } catch (XenAPIException e) {
  5469. details = "BackupSnapshot Failed due to " + e.toString();
  5470. s_logger.warn(details, e);
  5471. } catch (Exception e) {
  5472. details = "BackupSnapshot Failed due to " + e.getMessage();
  5473. s_logger.warn(details, e);
  5474. }
  5475. return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, fullbackup);
  5476. }
  5477. protected CreateVolumeFromSnapshotAnswer execute(final CreateVolumeFromSnapshotCommand cmd) {
  5478. Connection conn = getConnection();
  5479. String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
  5480. Long accountId = cmd.getAccountId();
  5481. Long volumeId = cmd.getVolumeId();
  5482. String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
  5483. String backedUpSnapshotUuid = cmd.getSnapshotUuid();
  5484. int wait = cmd.getWait();
  5485. boolean result = false;
  5486. // Generic error message.
  5487. String details = null;
  5488. String volumeUUID = null;
  5489. SR snapshotSR = null;
  5490. if (secondaryStorageUrl == null) {
  5491. details += " because the URL passed: " + secondaryStorageUrl + " is invalid.";
  5492. return new CreateVolumeFromSnapshotAnswer(cmd, result, details, volumeUUID);
  5493. }
  5494. try {
  5495. SR primaryStorageSR = getSRByNameLabelandHost(conn, primaryStorageNameLabel);
  5496. if (primaryStorageSR == null) {
  5497. throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: "
  5498. + primaryStorageNameLabel);
  5499. }
  5500. // Get the absolute path of the snapshot on the secondary storage.
  5501. URI snapshotURI = new URI(secondaryStorageUrl + "/snapshots/" + accountId + "/" + volumeId);
  5502. String filename = backedUpSnapshotUuid;
  5503. if ( !filename.startsWith("VHD-") && !filename.endsWith(".vhd")) {
  5504. filename = backedUpSnapshotUuid + ".vhd";
  5505. }
  5506. String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath() + "/" + filename;
  5507. String srUuid = primaryStorageSR.getUuid(conn);
  5508. volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait);
  5509. result = true;
  5510. } catch (XenAPIException e) {
  5511. details += " due to " + e.toString();
  5512. s_logger.warn(details, e);
  5513. } catch (Exception e) {
  5514. details += " due to " + e.getMessage();
  5515. s_logger.warn(details, e);
  5516. } finally {
  5517. // In all cases, if the temporary SR was created, forget it.
  5518. if (snapshotSR != null) {
  5519. removeSR(conn, snapshotSR);
  5520. }
  5521. }
  5522. if (!result) {
  5523. // Is this logged at a higher level?
  5524. s_logger.error(details);
  5525. }
  5526. // In all cases return something.
  5527. return new CreateVolumeFromSnapshotAnswer(cmd, result, details, volumeUUID);
  5528. }
  5529. protected VM getVM(Connection conn, String vmName) {
  5530. // Look up VMs with the specified name
  5531. Set<VM> vms;
  5532. try {
  5533. vms = VM.getByNameLabel(conn, vmName);
  5534. } catch (XenAPIException e) {
  5535. throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.toString(), e);
  5536. } catch (Exception e) {
  5537. throw new CloudRuntimeException("Unable to get " + vmName + ": " + e.getMessage(), e);
  5538. }
  5539. // If there are no VMs, throw an exception
  5540. if (vms.size() == 0) {
  5541. throw new CloudRuntimeException("VM with name: " + vmName + " does not exist.");
  5542. }
  5543. // If there is more than one VM, print a warning
  5544. if (vms.size() > 1) {
  5545. s_logger.warn("Found " + vms.size() + " VMs with name: " + vmName);
  5546. }
  5547. // Return the first VM in the set
  5548. return vms.iterator().next();
  5549. }
  5550. protected VDI getIsoVDIByURL(Connection conn, String vmName, String isoURL) {
  5551. SR isoSR = null;
  5552. String mountpoint = null;
  5553. if (isoURL.startsWith("xs-tools")) {
  5554. try {
  5555. Set<VDI> vdis = VDI.getByNameLabel(conn, isoURL);
  5556. if (vdis.isEmpty()) {
  5557. throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL);
  5558. }
  5559. return vdis.iterator().next();
  5560. } catch (XenAPIException e) {
  5561. throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString());
  5562. } catch (Exception e) {
  5563. throw new CloudRuntimeException("Unable to get pv iso: " + isoURL + " due to " + e.toString());
  5564. }
  5565. }
  5566. int index = isoURL.lastIndexOf("/");
  5567. mountpoint = isoURL.substring(0, index);
  5568. URI uri;
  5569. try {
  5570. uri = new URI(mountpoint);
  5571. } catch (URISyntaxException e) {
  5572. throw new CloudRuntimeException("isoURL is wrong: " + isoURL);
  5573. }
  5574. isoSR = getISOSRbyVmName(conn, vmName);
  5575. if (isoSR == null) {
  5576. isoSR = createIsoSRbyURI(conn, uri, vmName, false);
  5577. }
  5578. String isoName = isoURL.substring(index + 1);
  5579. VDI isoVDI = getVDIbyLocationandSR(conn, isoName, isoSR);
  5580. if (isoVDI != null) {
  5581. return isoVDI;
  5582. } else {
  5583. throw new CloudRuntimeException("Could not find ISO with URL: " + isoURL);
  5584. }
  5585. }
  5586. protected SR getStorageRepository(Connection conn, StorageFilerTO pool) {
  5587. Set<SR> srs;
  5588. try {
  5589. srs = SR.getByNameLabel(conn, pool.getUuid());
  5590. } catch (XenAPIException e) {
  5591. throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.toString(), e);
  5592. } catch (Exception e) {
  5593. throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.getMessage(), e);
  5594. }
  5595. if (srs.size() > 1) {
  5596. throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + pool.getUuid());
  5597. } else if (srs.size() == 1) {
  5598. SR sr = srs.iterator().next();
  5599. if (s_logger.isDebugEnabled()) {
  5600. s_logger.debug("SR retrieved for " + pool.getId());
  5601. }
  5602. if (checkSR(conn, sr)) {
  5603. return sr;
  5604. }
  5605. throw new CloudRuntimeException("SR check failed for storage pool: " + pool.getUuid() + "on host:" + _host.uuid);
  5606. } else {
  5607. throw new CloudRuntimeException("Can not see storage pool: " + pool.getUuid() + " from on host:" + _host.uuid);
  5608. }
  5609. }
  5610. protected Answer execute(final CheckConsoleProxyLoadCommand cmd) {
  5611. return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort());
  5612. }
  5613. protected Answer execute(final WatchConsoleProxyLoadCommand cmd) {
  5614. return executeProxyLoadScan(cmd, cmd.getProxyVmId(), cmd.getProxyVmName(), cmd.getProxyManagementIp(), cmd.getProxyCmdPort());
  5615. }
  5616. protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) {
  5617. String result = null;
  5618. final StringBuffer sb = new StringBuffer();
  5619. sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus");
  5620. boolean success = true;
  5621. try {
  5622. final URL url = new URL(sb.toString());
  5623. final URLConnection conn = url.openConnection();
  5624. // setting TIMEOUTs to avoid possible waiting until death situations
  5625. conn.setConnectTimeout(5000);
  5626. conn.setReadTimeout(5000);
  5627. final InputStream is = conn.getInputStream();
  5628. final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
  5629. final StringBuilder sb2 = new StringBuilder();
  5630. String line = null;
  5631. try {
  5632. while ((line = reader.readLine()) != null) {
  5633. sb2.append(line + "\n");
  5634. }
  5635. result = sb2.toString();
  5636. } catch (final IOException e) {
  5637. success = false;
  5638. } finally {
  5639. try {
  5640. is.close();
  5641. } catch (final IOException e) {
  5642. s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
  5643. success = false;
  5644. }
  5645. }
  5646. } catch (final IOException e) {
  5647. s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp);
  5648. success = false;
  5649. }
  5650. return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result);
  5651. }
  5652. protected boolean createSecondaryStorageFolder(Connection conn, String remoteMountPath, String newFolder) {
  5653. String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder);
  5654. return (result != null);
  5655. }
  5656. protected boolean deleteSecondaryStorageFolder(Connection conn, String remoteMountPath, String folder) {
  5657. String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder);
  5658. return (details != null && details.equals("1"));
  5659. }
  5660. protected boolean postCreatePrivateTemplate(Connection conn, String templatePath, String tmpltFilename, String templateName, String templateDescription, String checksum, long size, long virtualSize, long templateId) {
  5661. if (templateDescription == null) {
  5662. templateDescription = "";
  5663. }
  5664. if (checksum == null) {
  5665. checksum = "";
  5666. }
  5667. String result = callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, "templateName", templateName, "templateDescription", templateDescription,
  5668. "checksum", checksum, "size", String.valueOf(size), "virtualSize", String.valueOf(virtualSize), "templateId", String.valueOf(templateId));
  5669. boolean success = false;
  5670. if (result != null && !result.isEmpty()) {
  5671. // Else, command threw an exception which has already been logged.
  5672. if (result.equalsIgnoreCase("1")) {
  5673. s_logger.debug("Successfully created template.properties file on secondary storage for " + tmpltFilename);
  5674. success = true;
  5675. } else {
  5676. s_logger.warn("Could not create template.properties file on secondary storage for " + tmpltFilename + " for templateId: " + templateId);
  5677. }
  5678. }
  5679. return success;
  5680. }
  5681. protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) {
  5682. String parentUuid = callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid,
  5683. "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
  5684. if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) {
  5685. s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
  5686. // errString is already logged.
  5687. return null;
  5688. }
  5689. return parentUuid;
  5690. }
  5691. protected boolean destroySnapshotOnPrimaryStorage(Connection conn, String snapshotUuid) {
  5692. // Precondition snapshotUuid != null
  5693. try {
  5694. VDI snapshot = getVDIbyUuid(conn, snapshotUuid);
  5695. if (snapshot == null) {
  5696. throw new InternalErrorException("Could not destroy snapshot " + snapshotUuid + " because the snapshot VDI was null");
  5697. }
  5698. snapshot.destroy(conn);
  5699. s_logger.debug("Successfully destroyed snapshotUuid: " + snapshotUuid + " on primary storage");
  5700. return true;
  5701. } catch (XenAPIException e) {
  5702. String msg = "Destroy snapshotUuid: " + snapshotUuid + " on primary storage failed due to " + e.toString();
  5703. s_logger.error(msg, e);
  5704. } catch (Exception e) {
  5705. String msg = "Destroy snapshotUuid: " + snapshotUuid + " on primary storage failed due to " + e.getMessage();
  5706. s_logger.warn(msg, e);
  5707. }
  5708. return false;
  5709. }
  5710. protected String deleteSnapshotBackup(Connection conn, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath, String backupUUID) {
  5711. // If anybody modifies the formatting below again, I'll skin them
  5712. String result = callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "dcId", dcId.toString(), "accountId", accountId.toString(),
  5713. "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath);
  5714. return result;
  5715. }
  5716. protected boolean deleteSnapshotsDir(Connection conn, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath) {
  5717. return deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, "snapshots" + "/" + accountId.toString() + "/" + volumeId.toString());
  5718. }
  5719. @Override
  5720. public boolean start() {
  5721. return true;
  5722. }
  5723. @Override
  5724. public boolean stop() {
  5725. disconnected();
  5726. return true;
  5727. }
  5728. @Override
  5729. public String getName() {
  5730. return _name;
  5731. }
  5732. @Override
  5733. public IAgentControl getAgentControl() {
  5734. return _agentControl;
  5735. }
  5736. @Override
  5737. public void setAgentControl(IAgentControl agentControl) {
  5738. _agentControl = agentControl;
  5739. }
  5740. protected Answer execute(PoolEjectCommand cmd) {
  5741. Connection conn = getConnection();
  5742. String hostuuid = cmd.getHostuuid();
  5743. try {
  5744. Map<Host, Host.Record> hostrs = Host.getAllRecords(conn);
  5745. boolean found = false;
  5746. for( Host.Record hr : hostrs.values() ) {
  5747. if( hr.uuid.equals(hostuuid)) {
  5748. found = true;
  5749. }
  5750. }
  5751. if( ! found) {
  5752. s_logger.debug("host " + hostuuid + " has already been ejected from pool " + _host.pool);
  5753. return new Answer(cmd);
  5754. }
  5755. Pool pool = Pool.getAll(conn).iterator().next();
  5756. Pool.Record poolr = pool.getRecord(conn);
  5757. Host.Record masterRec = poolr.master.getRecord(conn);
  5758. if (hostuuid.equals(masterRec.uuid)) {
  5759. s_logger.debug("This is last host to eject, so don't need to eject: " + hostuuid);
  5760. return new Answer(cmd);
  5761. }
  5762. Host host = Host.getByUuid(conn, hostuuid);
  5763. // remove all tags cloud stack add before eject
  5764. Host.Record hr = host.getRecord(conn);
  5765. Iterator<String> it = hr.tags.iterator();
  5766. while (it.hasNext()) {
  5767. String tag = it.next();
  5768. if (tag.startsWith("vmops-version-")) {
  5769. it.remove();
  5770. }
  5771. }
  5772. // eject from pool
  5773. try {
  5774. Pool.eject(conn, host);
  5775. try {
  5776. Thread.sleep(10 * 1000);
  5777. } catch (InterruptedException e) {
  5778. }
  5779. } catch (XenAPIException e) {
  5780. String msg = "Unable to eject host " + _host.uuid + " due to " + e.toString();
  5781. s_logger.warn(msg);
  5782. host.destroy(conn);
  5783. }
  5784. return new Answer(cmd);
  5785. } catch (XenAPIException e) {
  5786. String msg = "XenAPIException Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.toString();
  5787. s_logger.warn(msg, e);
  5788. return new Answer(cmd, false, msg);
  5789. } catch (Exception e) {
  5790. String msg = "Exception Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.getMessage();
  5791. s_logger.warn(msg, e);
  5792. return new Answer(cmd, false, msg);
  5793. }
  5794. }
  5795. private Answer execute(CleanupNetworkRulesCmd cmd) {
  5796. if (!_canBridgeFirewall) {
  5797. return new Answer(cmd, true, null);
  5798. }
  5799. Connection conn = getConnection();
  5800. String result = callHostPlugin(conn, "vmops","cleanup_rules", "instance", _instance);
  5801. int numCleaned = Integer.parseInt(result);
  5802. if (result == null || result.isEmpty() || (numCleaned < 0)) {
  5803. s_logger.warn("Failed to cleanup rules for host " + _host.ip);
  5804. return new Answer(cmd, false, result);
  5805. }
  5806. if (numCleaned > 0) {
  5807. s_logger.info("Cleaned up rules for " + result + " vms on host " + _host.ip);
  5808. }
  5809. return new Answer(cmd, true, result);
  5810. }
  5811. /**
  5812. * XsNic represents a network and the host's specific PIF.
  5813. */
  5814. protected class XsLocalNetwork {
  5815. private final Network _n;
  5816. private Network.Record _nr;
  5817. private PIF _p;
  5818. private PIF.Record _pr;
  5819. public XsLocalNetwork(Network n) {
  5820. this(n, null, null, null);
  5821. }
  5822. public XsLocalNetwork(Network n, Network.Record nr, PIF p, PIF.Record pr) {
  5823. _n = n;
  5824. _nr = nr;
  5825. _p = p;
  5826. _pr = pr;
  5827. }
  5828. public Network getNetwork() {
  5829. return _n;
  5830. }
  5831. public Network.Record getNetworkRecord(Connection conn) throws XenAPIException, XmlRpcException {
  5832. if (_nr == null) {
  5833. _nr = _n.getRecord(conn);
  5834. }
  5835. return _nr;
  5836. }
  5837. public PIF getPif(Connection conn) throws XenAPIException, XmlRpcException {
  5838. if (_p == null) {
  5839. Network.Record nr = getNetworkRecord(conn);
  5840. for (PIF pif : nr.PIFs) {
  5841. PIF.Record pr = pif.getRecord(conn);
  5842. if (_host.uuid.equals(pr.host.getUuid(conn))) {
  5843. if (s_logger.isDebugEnabled()) {
  5844. s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.ip + "; Network=" + nr.uuid + "; pif=" + pr.uuid);
  5845. }
  5846. _p = pif;
  5847. _pr = pr;
  5848. break;
  5849. }
  5850. }
  5851. }
  5852. return _p;
  5853. }
  5854. public PIF.Record getPifRecord(Connection conn) throws XenAPIException, XmlRpcException {
  5855. if (_pr == null) {
  5856. PIF p = getPif(conn);
  5857. if (_pr == null) {
  5858. _pr = p.getRecord(conn);
  5859. }
  5860. }
  5861. return _pr;
  5862. }
  5863. }
  5864. // A list of UUIDs that are gathered from the XenServer when
  5865. // the resource first connects to XenServer. These UUIDs do
  5866. // not change over time.
  5867. protected class XsHost {
  5868. public String systemvmisouuid;
  5869. public String uuid;
  5870. public String ip;
  5871. public String publicNetwork;
  5872. public String privateNetwork;
  5873. public String linkLocalNetwork;
  5874. public Network vswitchNetwork;
  5875. public String storageNetwork1;
  5876. public String storageNetwork2;
  5877. public String guestNetwork;
  5878. public String guestPif;
  5879. public String publicPif;
  5880. public String privatePif;
  5881. public String storagePif1;
  5882. public String storagePif2;
  5883. public String pool;
  5884. public int speed;
  5885. public int cpus;
  5886. public String product_version;
  5887. @Override
  5888. public String toString() {
  5889. return new StringBuilder("XS[").append(uuid).append("-").append(ip).append("]").toString();
  5890. }
  5891. }
  5892. /*Override by subclass*/
  5893. protected String getGuestOsType(String stdType, boolean bootFromCD) {
  5894. return stdType;
  5895. }
  5896. private Answer execute(NetworkRulesSystemVmCommand cmd) {
  5897. boolean success = true;
  5898. Connection conn = getConnection();
  5899. if (cmd.getType() != VirtualMachine.Type.User) {
  5900. String result = callHostPlugin(conn, "vmops", "default_network_rules_systemvm", "vmName", cmd.getVmName());
  5901. if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
  5902. success = false;
  5903. }
  5904. }
  5905. return new Answer(cmd, success, "");
  5906. }
  5907. protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
  5908. String[] results = new String[cmd.getRules().length];
  5909. String callResult;
  5910. Connection conn = getConnection();
  5911. String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
  5912. if (routerIp == null) {
  5913. return new SetFirewallRulesAnswer(cmd, false, results);
  5914. }
  5915. String[][] rules = cmd.generateFwRules();
  5916. String args = "";
  5917. args += routerIp + " -F ";
  5918. StringBuilder sb = new StringBuilder();
  5919. String[] fwRules = rules[0];
  5920. if (fwRules.length > 0) {
  5921. for (int i = 0; i < fwRules.length; i++) {
  5922. sb.append(fwRules[i]).append(',');
  5923. }
  5924. args += " -a " + sb.toString();
  5925. }
  5926. callResult = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args);
  5927. if (callResult == null || callResult.isEmpty()) {
  5928. //FIXME - in the future we have to process each rule separately; now we temporarily set every rule to be false if single rule fails
  5929. for (int i=0; i < results.length; i++) {
  5930. results[i] = "Failed";
  5931. }
  5932. return new SetFirewallRulesAnswer(cmd, false, results);
  5933. }
  5934. return new SetFirewallRulesAnswer(cmd, true, results);
  5935. }
  5936. protected Answer execute(final ClusterSyncCommand cmd) {
  5937. Connection conn = getConnection();
  5938. //check if this is master
  5939. Pool pool;
  5940. try {
  5941. pool = Pool.getByUuid(conn, _host.pool);
  5942. Pool.Record poolr = pool.getRecord(conn);
  5943. Host.Record hostr = poolr.master.getRecord(conn);
  5944. if (!_host.uuid.equals(hostr.uuid)) {
  5945. return new Answer(cmd);
  5946. }
  5947. } catch (Throwable e) {
  5948. s_logger.warn("Check for master failed, failing the Cluster sync command");
  5949. return new Answer(cmd);
  5950. }
  5951. HashMap<String, Pair<String, State>> newStates = deltaClusterSync(conn);
  5952. return new ClusterSyncAnswer(cmd.getClusterId(), newStates);
  5953. }
  5954. protected HashMap<String, Pair<String, State>> fullClusterSync(Connection conn) {
  5955. synchronized (_cluster.intern()) {
  5956. s_vms.clear(_cluster);
  5957. }
  5958. try {
  5959. Map<VM, VM.Record> vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER
  5960. for (VM.Record record: vm_map.values()) {
  5961. if (record.isControlDomain || record.isASnapshot || record.isATemplate) {
  5962. continue; // Skip DOM0
  5963. }
  5964. String vm_name = record.nameLabel;
  5965. VmPowerState ps = record.powerState;
  5966. final State state = convertToState(ps);
  5967. Host host = record.residentOn;
  5968. String host_uuid = null;
  5969. if( ! isRefNull(host) ) {
  5970. host_uuid = host.getUuid(conn);
  5971. synchronized (_cluster.intern()) {
  5972. s_vms.put(_cluster, host_uuid, vm_name, state);
  5973. }
  5974. }
  5975. if (s_logger.isTraceEnabled()) {
  5976. s_logger.trace("VM " + vm_name + ": powerstate = " + ps + "; vm state=" + state.toString());
  5977. }
  5978. }
  5979. } catch (final Throwable e) {
  5980. String msg = "Unable to get vms through host " + _host.uuid + " due to to " + e.toString();
  5981. s_logger.warn(msg, e);
  5982. throw new CloudRuntimeException(msg);
  5983. }
  5984. return s_vms.getClusterVmState(_cluster);
  5985. }
  5986. protected HashMap<String, Pair<String, State>> deltaClusterSync(Connection conn) {
  5987. final HashMap<String, Pair<String, State>> changes = new HashMap<String, Pair<String, State>>();
  5988. synchronized (_cluster.intern()) {
  5989. HashMap<String, Pair<String, State>> newStates = getAllVms(conn);
  5990. if (newStates == null) {
  5991. s_logger.warn("Unable to get the vm states so no state sync at this point.");
  5992. return null;
  5993. }
  5994. HashMap<String, Pair<String, State>> oldStates = new HashMap<String, Pair<String, State>>(s_vms.size(_cluster));
  5995. oldStates.putAll(s_vms.getClusterVmState(_cluster));
  5996. for (final Map.Entry<String, Pair<String, State>> entry : newStates.entrySet()) {
  5997. final String vm = entry.getKey();
  5998. State newState = entry.getValue().second();
  5999. String host_uuid = entry.getValue().first();
  6000. final Pair<String, State> oldState = oldStates.remove(vm);
  6001. //check if host is changed
  6002. if (host_uuid != null && oldState != null){
  6003. if (!host_uuid.equals(oldState.first()) && newState != State.Stopped && newState != State.Stopping){
  6004. s_logger.warn("Detecting a change in host for " + vm);
  6005. changes.put(vm, new Pair<String, State>(host_uuid, newState));
  6006. s_logger.debug("11. The VM " + vm + " is in " + newState + " state");
  6007. s_vms.put(_cluster, host_uuid, vm, newState);
  6008. continue;
  6009. }
  6010. }
  6011. if (newState == State.Stopped && oldState != null && oldState.second() != State.Stopping && oldState.second() != State.Stopped) {
  6012. newState = getRealPowerState(conn, vm);
  6013. }
  6014. if (s_logger.isTraceEnabled()) {
  6015. s_logger.trace("VM " + vm + ": xen has state " + newState + " and we have state " + (oldState != null ? oldState.toString() : "null"));
  6016. }
  6017. if (vm.startsWith("migrating")) {
  6018. s_logger.warn("Migrating from xen detected. Skipping");
  6019. continue;
  6020. }
  6021. if (oldState == null) {
  6022. s_vms.put(_cluster, host_uuid, vm, newState);
  6023. s_logger.warn("Detecting a new state but couldn't find a old state so adding it to the changes: " + vm);
  6024. changes.put(vm, new Pair<String, State>(host_uuid, newState));
  6025. } else if (oldState.second() == State.Starting) {
  6026. if (newState == State.Running) {
  6027. s_logger.debug("12. The VM " + vm + " is in " + State.Running + " state");
  6028. s_vms.put(_cluster, host_uuid, vm, newState);
  6029. } else if (newState == State.Stopped) {
  6030. s_logger.warn("Ignoring vm " + vm + " because of a lag in starting the vm.");
  6031. }
  6032. } else if (oldState.second() == State.Migrating) {
  6033. if (newState == State.Running) {
  6034. s_logger.debug("Detected that an migrating VM is now running: " + vm);
  6035. s_vms.put(_cluster, host_uuid, vm, newState);
  6036. }
  6037. } else if (oldState.second() == State.Stopping) {
  6038. if (newState == State.Stopped) {
  6039. s_logger.debug("13. The VM " + vm + " is in " + State.Stopped + " state");
  6040. s_vms.put(_cluster, host_uuid, vm, newState);
  6041. } else if (newState == State.Running) {
  6042. s_logger.warn("Ignoring vm " + vm + " because of a lag in stopping the vm. ");
  6043. }
  6044. } else if (oldState.second() != newState) {
  6045. s_logger.debug("14. The VM " + vm + " is in " + newState + " state was " + oldState.second());
  6046. s_vms.put(_cluster, host_uuid, vm, newState);
  6047. if (newState == State.Stopped) {
  6048. /*
  6049. * if (s_vmsKilled.remove(vm)) { s_logger.debug("VM " + vm + " has been killed for storage. ");
  6050. * newState = State.Error; }
  6051. */
  6052. }
  6053. changes.put(vm, new Pair<String, State>(host_uuid, newState));
  6054. }
  6055. }
  6056. for (final Map.Entry<String, Pair<String, State>> entry : oldStates.entrySet()) {
  6057. final String vm = entry.getKey();
  6058. final State oldState = entry.getValue().second();
  6059. String host_uuid = entry.getValue().first();
  6060. if (s_logger.isTraceEnabled()) {
  6061. s_logger.trace("VM " + vm + " is now missing from xen so reporting stopped");
  6062. }
  6063. if (oldState == State.Stopping) {
  6064. s_logger.warn("Ignoring VM " + vm + " in transition state stopping.");
  6065. s_vms.remove(_cluster, host_uuid, vm);
  6066. } else if (oldState == State.Starting) {
  6067. s_logger.warn("Ignoring VM " + vm + " in transition state starting.");
  6068. } else if (oldState == State.Stopped) {
  6069. s_logger.debug("VM missing " + vm + " old state stopped so removing.");
  6070. s_vms.remove(_cluster, host_uuid, vm);
  6071. } else if (oldState == State.Migrating) {
  6072. s_logger.warn("Ignoring VM " + vm + " in migrating state.");
  6073. } else {
  6074. State newState = State.Stopped;
  6075. s_logger.warn("The VM is now missing marking it as Stopped " + vm);
  6076. changes.put(vm, new Pair<String, State>(host_uuid, newState));
  6077. }
  6078. }
  6079. }
  6080. return changes;
  6081. }
  6082. }