mirror of https://github.com/apache/cloudstack.git
Full opensource
This commit is contained in:
parent
fb6fb03175
commit
b3478c377e
|
|
@ -0,0 +1,137 @@
|
|||
#!/usr/bin/python
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
import socket
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
|
||||
from cloudutils.utilities import initLoging, bash
|
||||
from cloudutils.configFileOps import configFileOps
|
||||
from cloudutils.globalEnv import globalEnv
|
||||
from cloudutils.networkConfig import networkConfig
|
||||
from cloudutils.syscfg import sysConfigFactory
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
url="http://rightscale-cloudstack.s3.amazonaws.com/kvm/centos/5.4/RightImage_CentOS_5.4_x64_v5.6.34.qcow2.bz2"
|
||||
destFolder="/mnt/template/tmpl/1/4/"
|
||||
metaFile="template.properties"
|
||||
|
||||
def getUserInputs():
|
||||
print "Welcome to myCloud Setup:"
|
||||
|
||||
mgtSvr = "myagent.cloud.com"
|
||||
|
||||
cfo = configFileOps("/etc/cloud/agent/agent.properties")
|
||||
oldToken = cfo.getEntry("zone")
|
||||
if oldToken == "default":
|
||||
oldToken = ""
|
||||
zoneToken = raw_input("Please input the Zone Token:[%s]"%oldToken)
|
||||
|
||||
if zoneToken == "":
|
||||
if oldToken == "":
|
||||
print "Please input a valid zone token"
|
||||
exit(1)
|
||||
zoneToken = oldToken
|
||||
|
||||
try:
|
||||
defaultNic = networkConfig.getDefaultNetwork()
|
||||
except:
|
||||
print "Failed to get default route. Please configure your network to add a default route"
|
||||
exit(1)
|
||||
|
||||
network = defaultNic.name
|
||||
|
||||
return [mgtSvr, zoneToken, network]
|
||||
|
||||
def downloadTemplate():
|
||||
if not os.path.exists(destFolder):
|
||||
os.makedirs(destFolder)
|
||||
oldName =url.split("/")[-1]
|
||||
templateFile=url.split("/")[-1].replace(".bz2","")
|
||||
|
||||
templateFullPath = destFolder + templateFile
|
||||
metaFullPath = destFolder + metaFile
|
||||
if os.path.exists(templateFullPath):
|
||||
if os.path.exists(metaFullPath):
|
||||
return True
|
||||
os.remove(templateFullPath)
|
||||
|
||||
print "Need to download myCloud template into your local disk, from " + url + " to " + destFolder + " :"
|
||||
try:
|
||||
proc = subprocess.Popen(["/bin/bash", "-c", "wget -O - " + url + " | bunzip2 > " + destFolder + templateFile])
|
||||
proc.communicate()
|
||||
ret = proc.poll()
|
||||
if ret is None or ret < 0:
|
||||
raise CloudRuntimeException("Failed to download template")
|
||||
except KeyboardInterrupt:
|
||||
if os.path.exists(templateFullPath):
|
||||
os.remove(templateFullPath)
|
||||
raise CloudRuntimeException("Downloading process is interrupted")
|
||||
|
||||
file = open(metaFullPath, "w")
|
||||
physicalSize = os.stat(templateFullPath).st_size
|
||||
virtualSize = bash("qemu-img info " + templateFullPath + " |grep virtual").getStdout().split("(")[1].split(" ")[0]
|
||||
cfo = configFileOps(metaFullPath)
|
||||
cfo.addEntry("filename", templateFile)
|
||||
cfo.addEntry("id", "4")
|
||||
cfo.addEntry("qcow2.size", str(physicalSize))
|
||||
cfo.addEntry("public", "true")
|
||||
cfo.addEntry("uniquename", "Rightscale CentOS 5.4")
|
||||
cfo.addEntry("qcow2.virtualsize", virtualSize)
|
||||
cfo.addEntry("virtualsize", virtualSize)
|
||||
cfo.addEntry("hvm", "true")
|
||||
cfo.addEntry("description", "Rightscale CentOS 5.4")
|
||||
cfo.addEntry("qcow2", "true")
|
||||
cfo.addEntry("qcow2.filename", templateFile)
|
||||
cfo.addEntry("size", str(physicalSize))
|
||||
cfo.save()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
initLoging("/var/log/cloud/setupAgent.log")
|
||||
|
||||
glbEnv = globalEnv()
|
||||
|
||||
glbEnv.mode = "Agent"
|
||||
glbEnv.agentMode = "myCloud"
|
||||
parser = OptionParser()
|
||||
parser.add_option("-z", "--zone-token", dest="zone", help="zone token")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if options.zone is None:
|
||||
userInputs = getUserInputs()
|
||||
glbEnv.mgtSvr = userInputs[0]
|
||||
glbEnv.zone = userInputs[1]
|
||||
glbEnv.defaultNic = userInputs[2]
|
||||
else:
|
||||
glbEnv.zone = options.zone
|
||||
try:
|
||||
defaultNic = networkConfig.getDefaultNetwork()
|
||||
glbEnv.defaultNic = defaultNic.name
|
||||
except:
|
||||
print "Failed to get default route. Please configure your network to have a default route"
|
||||
sys.exit(2)
|
||||
|
||||
#generate UUID
|
||||
glbEnv.uuid = configFileOps("/etc/cloud/agent/agent.properties").getEntry("guid")
|
||||
if glbEnv.uuid == "":
|
||||
glbEnv.uuid = bash("uuidgen").getStdout()
|
||||
|
||||
print "Starting to configure your system:"
|
||||
syscfg = sysConfigFactory.getSysConfigFactory(glbEnv)
|
||||
try:
|
||||
syscfg.config()
|
||||
downloadTemplate()
|
||||
syscfg.svo.stopService("cloud-agent")
|
||||
syscfg.svo.enableService("cloud-agent")
|
||||
print "myCloud setup is Done!"
|
||||
except (CloudRuntimeException,CloudInternalException), e:
|
||||
print e
|
||||
print "Try to restore your system:"
|
||||
try:
|
||||
syscfg.restore()
|
||||
except:
|
||||
pass
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
package com.cloud.agent.dhcp;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Formatter;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jnetpcap.packet.JMemoryPacket;
|
||||
import org.jnetpcap.packet.JPacket;
|
||||
import org.jnetpcap.packet.PcapPacket;
|
||||
import org.jnetpcap.protocol.lan.Ethernet;
|
||||
import org.jnetpcap.protocol.lan.IEEE802dot1q;
|
||||
import org.jnetpcap.protocol.network.Ip4;
|
||||
import org.jnetpcap.protocol.tcpip.Udp;
|
||||
|
||||
import com.cloud.agent.dhcp.DhcpSnooperImpl.DHCPState;
|
||||
|
||||
public class DhcpPacketParser implements Runnable{
|
||||
private static final Logger s_logger = Logger.getLogger(DhcpPacketParser.class);
|
||||
private enum DHCPPACKET {
|
||||
OP(0),
|
||||
HTYPE(1),
|
||||
HLEN(2),
|
||||
HOPS(3),
|
||||
XID(4),
|
||||
SECS(8),
|
||||
FLAGS(10),
|
||||
CIADDR(12),
|
||||
YIADDR(16),
|
||||
SIDADDR(20),
|
||||
GIADDR(24),
|
||||
CHADDR(28),
|
||||
SNAME(44),
|
||||
FILE(108),
|
||||
MAGIC(236),
|
||||
OPTIONS(240);
|
||||
int offset;
|
||||
DHCPPACKET(int i) {
|
||||
offset = i;
|
||||
}
|
||||
int getValue() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
private enum DHCPOPTIONTYPE {
|
||||
PAD(0),
|
||||
MESSAGETYPE(53),
|
||||
REQUESTEDIP(50),
|
||||
END(255);
|
||||
int type;
|
||||
DHCPOPTIONTYPE(int i) {
|
||||
type = i;
|
||||
}
|
||||
int getValue() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
private enum DHCPMSGTYPE {
|
||||
DHCPDISCOVER(1),
|
||||
DHCPOFFER(2),
|
||||
DHCPREQUEST(3),
|
||||
DHCPDECLINE(4),
|
||||
DHCPACK(5),
|
||||
DHCPNAK(6),
|
||||
DHCPRELEASE(7),
|
||||
DHCPINFORM(8);
|
||||
int _type;
|
||||
DHCPMSGTYPE(int type) {
|
||||
_type = type;
|
||||
}
|
||||
int getValue() {
|
||||
return _type;
|
||||
}
|
||||
public static DHCPMSGTYPE valueOf(int type) {
|
||||
for (DHCPMSGTYPE t : values()) {
|
||||
if (type == t.getValue()) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class DHCPMSG {
|
||||
DHCPMSGTYPE msgType;
|
||||
byte[] caddr;
|
||||
byte[] yaddr;
|
||||
byte[] chaddr;
|
||||
byte[] requestedIP;
|
||||
public DHCPMSG() {
|
||||
caddr = new byte[4];
|
||||
yaddr = new byte[4];
|
||||
chaddr = new byte[6];
|
||||
}
|
||||
}
|
||||
|
||||
private PcapPacket _buffer;
|
||||
private int _offset;
|
||||
private int _len;
|
||||
private DhcpSnooperImpl _manager;
|
||||
|
||||
|
||||
public DhcpPacketParser(PcapPacket buffer, int offset, int len, DhcpSnooperImpl manager) {
|
||||
_buffer = buffer;
|
||||
_offset = offset;
|
||||
_len = len;
|
||||
_manager = manager;
|
||||
}
|
||||
private int getPos(int pos) {
|
||||
return _offset + pos;
|
||||
}
|
||||
private byte getByte(int offset) {
|
||||
return _buffer.getByte(getPos(offset));
|
||||
}
|
||||
private void getByteArray(int offset, byte[] array) {
|
||||
_buffer.getByteArray(getPos(offset), array);
|
||||
}
|
||||
private long getUInt(int offset) {
|
||||
return _buffer.getUInt(getPos(offset));
|
||||
}
|
||||
|
||||
private DHCPMSG getDhcpMsg() {
|
||||
long magic = getUInt(DHCPPACKET.MAGIC.getValue());
|
||||
if (magic != 0x63538263) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DHCPMSG msg = new DHCPMSG();
|
||||
|
||||
int pos = DHCPPACKET.OPTIONS.getValue();
|
||||
while (pos <= _len) {
|
||||
int type = (int)getByte(pos++) & 0xff;
|
||||
|
||||
if (type == DHCPOPTIONTYPE.END.getValue()) {
|
||||
break;
|
||||
}
|
||||
if (type == DHCPOPTIONTYPE.PAD.getValue()) {
|
||||
continue;
|
||||
}
|
||||
int len = 0;
|
||||
if (pos <= _len) {
|
||||
len = ((int)getByte(pos++)) & 0xff;
|
||||
}
|
||||
|
||||
if (type == DHCPOPTIONTYPE.MESSAGETYPE.getValue() || type == DHCPOPTIONTYPE.REQUESTEDIP.getValue()) {
|
||||
/*Read data only if needed */
|
||||
byte[] data = null;
|
||||
if ((len + pos) <= _len) {
|
||||
data = new byte[len];
|
||||
getByteArray(pos, data);
|
||||
}
|
||||
|
||||
if (type == DHCPOPTIONTYPE.MESSAGETYPE.getValue()) {
|
||||
msg.msgType = DHCPMSGTYPE.valueOf((int)data[0]);
|
||||
} else if (type == DHCPOPTIONTYPE.REQUESTEDIP.getValue()) {
|
||||
msg.requestedIP = data;
|
||||
}
|
||||
}
|
||||
|
||||
pos += len;
|
||||
}
|
||||
|
||||
if (msg.msgType == DHCPMSGTYPE.DHCPREQUEST) {
|
||||
getByteArray(DHCPPACKET.CHADDR.getValue(), msg.chaddr);
|
||||
getByteArray(DHCPPACKET.CIADDR.getValue(), msg.caddr);
|
||||
} else if (msg.msgType == DHCPMSGTYPE.DHCPACK) {
|
||||
getByteArray(DHCPPACKET.YIADDR.getValue(), msg.yaddr);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
private String formatMacAddress(byte[] mac) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Formatter formatter = new Formatter(sb);
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
formatter.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : "");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getDestMacAddress() {
|
||||
Ethernet ether = new Ethernet();
|
||||
if (_buffer.hasHeader(ether)) {
|
||||
byte[] destMac = ether.destination();
|
||||
return formatMacAddress(destMac);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private InetAddress getDHCPServerIP() {
|
||||
Ip4 ip = new Ip4();
|
||||
if (_buffer.hasHeader(ip)) {
|
||||
try {
|
||||
return InetAddress.getByAddress(ip.source());
|
||||
} catch (UnknownHostException e) {
|
||||
s_logger.debug("Failed to get dhcp server ip address: " + e.toString());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
DHCPMSG msg = getDhcpMsg();
|
||||
|
||||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.msgType == DHCPMSGTYPE.DHCPACK) {
|
||||
InetAddress ip = null;
|
||||
try {
|
||||
ip = InetAddress.getByAddress(msg.yaddr);
|
||||
String macAddr = getDestMacAddress();
|
||||
_manager.setIPAddr(macAddr, ip, DHCPState.DHCPACKED, getDHCPServerIP());
|
||||
} catch (UnknownHostException e) {
|
||||
|
||||
}
|
||||
} else if (msg.msgType == DHCPMSGTYPE.DHCPREQUEST) {
|
||||
InetAddress ip = null;
|
||||
if (msg.requestedIP != null) {
|
||||
try {
|
||||
ip = InetAddress.getByAddress(msg.requestedIP);
|
||||
} catch (UnknownHostException e) {
|
||||
}
|
||||
}
|
||||
if (ip == null) {
|
||||
try {
|
||||
ip = InetAddress.getByAddress(msg.caddr);
|
||||
} catch (UnknownHostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ip != null) {
|
||||
String macAddr = formatMacAddress(msg.chaddr);
|
||||
_manager.setIPAddr(macAddr, ip, DHCPState.DHCPREQUESTED, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void test() {
|
||||
JPacket packet = new JMemoryPacket(Ethernet.ID,
|
||||
" 06fa 8800 00b3 0656 d200 0027 8100 001a 0800 4500 0156 64bf 0000 4011 f3f2 ac1a 6412 ac1a 649e 0043 0044 0001 0000 0001");
|
||||
Ethernet eth = new Ethernet();
|
||||
if (packet.hasHeader(eth)) {
|
||||
System.out.print(" ether:" + eth);
|
||||
}
|
||||
IEEE802dot1q vlan = new IEEE802dot1q();
|
||||
if (packet.hasHeader(vlan)) {
|
||||
System.out.print(" vlan: " + vlan);
|
||||
}
|
||||
|
||||
if (packet.hasHeader(Udp.ID)) {
|
||||
System.out.print("has udp");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.cloud.agent.dhcp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
|
||||
public class DhcpProtocolParserServer extends Thread {
|
||||
private static final Logger s_logger = Logger.getLogger(DhcpProtocolParserServer.class);;
|
||||
protected ExecutorService _executor;
|
||||
private int dhcpServerPort = 67;
|
||||
private int bufferSize = 300;
|
||||
protected boolean _running = false;
|
||||
public DhcpProtocolParserServer(int workers) {
|
||||
_executor = new ThreadPoolExecutor(workers, 10 * workers, 1, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>(), new NamedThreadFactory("DhcpListener"));
|
||||
_running = true;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(_running) {
|
||||
try {
|
||||
DatagramSocket dhcpSocket = new DatagramSocket(dhcpServerPort, InetAddress.getByAddress(new byte[]{0,0,0,0}));
|
||||
dhcpSocket.setBroadcast(true);
|
||||
|
||||
while (true) {
|
||||
byte[] buf = new byte[bufferSize];
|
||||
DatagramPacket dgp = new DatagramPacket(buf, buf.length);
|
||||
dhcpSocket.receive(dgp);
|
||||
// _executor.execute(new DhcpPacketParser(buf));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
s_logger.debug(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,327 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.cloud.agent.dhcp;
|
||||
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jnetpcap.Pcap;
|
||||
import org.jnetpcap.PcapBpfProgram;
|
||||
import org.jnetpcap.PcapIf;
|
||||
import org.jnetpcap.packet.PcapPacket;
|
||||
import org.jnetpcap.packet.PcapPacketHandler;
|
||||
import org.jnetpcap.protocol.tcpip.Udp;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
|
||||
@Local(value = { DhcpSnooper.class})
|
||||
public class DhcpSnooperImpl implements DhcpSnooper {
|
||||
private static final Logger s_logger = Logger.getLogger(DhcpSnooperImpl.class);
|
||||
public enum DHCPState {
|
||||
DHCPACKED,
|
||||
DHCPREQUESTED,
|
||||
DHCPRESET;
|
||||
}
|
||||
public class IPAddr {
|
||||
String _vmName;
|
||||
InetAddress _ip;
|
||||
DHCPState _state;
|
||||
public IPAddr(InetAddress ip, DHCPState state, String vmName) {
|
||||
_ip = ip;
|
||||
_state = state;
|
||||
_vmName = vmName;
|
||||
}
|
||||
}
|
||||
protected ExecutorService _executor;
|
||||
protected Map<String, IPAddr> _macIpMap;
|
||||
protected Map<InetAddress, String> _ipMacMap;
|
||||
private DhcpServer _server;
|
||||
protected long _timeout = 1200000;
|
||||
protected InetAddress _dhcpServerIp;
|
||||
|
||||
public DhcpSnooperImpl(String bridge, long timeout) {
|
||||
|
||||
_timeout = timeout;
|
||||
_executor = new ThreadPoolExecutor(10, 10 * 10, 1, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>(), new NamedThreadFactory("DhcpListener"));
|
||||
_macIpMap = new ConcurrentHashMap<String, IPAddr>();
|
||||
_ipMacMap = new ConcurrentHashMap<InetAddress, String>();
|
||||
_server = new DhcpServer(this, bridge);
|
||||
_server.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InetAddress getIPAddr(String macAddr, String vmName) {
|
||||
String macAddrLowerCase = macAddr.toLowerCase();
|
||||
IPAddr addr = _macIpMap.get(macAddrLowerCase);
|
||||
if (addr == null) {
|
||||
addr = new IPAddr(null, DHCPState.DHCPRESET, vmName);
|
||||
_macIpMap.put(macAddrLowerCase, addr);
|
||||
} else {
|
||||
addr._state = DHCPState.DHCPRESET;
|
||||
}
|
||||
|
||||
synchronized(addr) {
|
||||
try {
|
||||
addr.wait(_timeout);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (addr._state == DHCPState.DHCPACKED) {
|
||||
addr._state = DHCPState.DHCPRESET;
|
||||
return addr._ip;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public InetAddress getDhcpServerIP() {
|
||||
return _dhcpServerIp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cleanup(String macAddr, String vmName) {
|
||||
try {
|
||||
if (macAddr == null) {
|
||||
return;
|
||||
}
|
||||
_macIpMap.remove(macAddr);
|
||||
_ipMacMap.values().remove(macAddr);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to cleanup: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, InetAddress> syncIpAddr() {
|
||||
Collection<IPAddr> ips = _macIpMap.values();
|
||||
HashMap<String, InetAddress> vmIpMap = new HashMap<String, InetAddress>();
|
||||
for(IPAddr ip : ips) {
|
||||
if (ip._state == DHCPState.DHCPACKED) {
|
||||
vmIpMap.put(ip._vmName, ip._ip);
|
||||
}
|
||||
}
|
||||
return vmIpMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeMacTable(List<Pair<String, String>> macVmNameList) {
|
||||
for (Pair<String, String> macVmname : macVmNameList) {
|
||||
IPAddr ipAdrr = new IPAddr(null, DHCPState.DHCPRESET, macVmname.second());
|
||||
_macIpMap.put(macVmname.first(), ipAdrr);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setIPAddr(String macAddr, InetAddress ip, DHCPState state, InetAddress dhcpServerIp) {
|
||||
String macAddrLowerCase = macAddr.toLowerCase();
|
||||
if (state == DHCPState.DHCPREQUESTED) {
|
||||
IPAddr ipAddr = _macIpMap.get(macAddrLowerCase);
|
||||
if (ipAddr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ipMacMap.put(ip, macAddr);
|
||||
} else if (state == DHCPState.DHCPACKED) {
|
||||
_dhcpServerIp = dhcpServerIp;
|
||||
String destMac = macAddrLowerCase;
|
||||
if (macAddrLowerCase.equalsIgnoreCase("ff:ff:ff:ff:ff:ff")) {
|
||||
destMac = _ipMacMap.get(ip);
|
||||
if (destMac == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddr addr = _macIpMap.get(destMac);
|
||||
if (addr != null) {
|
||||
addr._ip = ip;
|
||||
addr._state = state;
|
||||
synchronized (addr) {
|
||||
addr.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.agent.dhcp.DhcpSnooper#stop()
|
||||
*/
|
||||
@Override
|
||||
public boolean stop() {
|
||||
_executor.shutdown();
|
||||
_server.StopServer();
|
||||
return true;
|
||||
}
|
||||
|
||||
private class DhcpServer extends Thread {
|
||||
private DhcpSnooperImpl _manager;
|
||||
private String _bridge;
|
||||
private Pcap _pcapedDev;
|
||||
private boolean _loop;
|
||||
public DhcpServer(DhcpSnooperImpl mgt, String bridge) {
|
||||
_manager = mgt;
|
||||
_bridge = bridge;
|
||||
_loop = true;
|
||||
}
|
||||
public void StopServer() {
|
||||
_loop = false;
|
||||
_pcapedDev.breakloop();
|
||||
_pcapedDev.close();
|
||||
}
|
||||
|
||||
private Pcap initializePcap() {
|
||||
try {
|
||||
List<PcapIf> alldevs = new ArrayList<PcapIf>();
|
||||
StringBuilder errBuf = new StringBuilder();
|
||||
int r = Pcap.findAllDevs(alldevs, errBuf);
|
||||
if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PcapIf dev = null;
|
||||
for (PcapIf device : alldevs) {
|
||||
if (device.getName().equalsIgnoreCase(_bridge)) {
|
||||
dev = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev == null) {
|
||||
s_logger.debug("Pcap: Can't find device: " + _bridge + " to listen on");
|
||||
return null;
|
||||
}
|
||||
|
||||
int snaplen = 64*1024;
|
||||
int flags = Pcap.MODE_PROMISCUOUS;
|
||||
int timeout = 10 * 1000;
|
||||
Pcap pcap = Pcap.openLive(dev.getName(), snaplen, flags, timeout, errBuf);
|
||||
if (pcap == null) {
|
||||
s_logger.debug("Pcap: Can't open " + _bridge);
|
||||
return null;
|
||||
}
|
||||
|
||||
PcapBpfProgram program = new PcapBpfProgram();
|
||||
String expr = "dst port 68 or 67";
|
||||
int optimize = 0;
|
||||
int netmask = 0xFFFFFF00;
|
||||
if (pcap.compile(program, expr, optimize, netmask) != Pcap.OK) {
|
||||
s_logger.debug("Pcap: can't compile BPF");
|
||||
return null;
|
||||
}
|
||||
|
||||
if(pcap.setFilter(program) != Pcap.OK) {
|
||||
s_logger.debug("Pcap: Can't set filter");
|
||||
return null;
|
||||
}
|
||||
return pcap;
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to initialized: " + e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (_loop) {
|
||||
try {
|
||||
_pcapedDev = initializePcap();
|
||||
if (_pcapedDev == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
|
||||
public void nextPacket(PcapPacket packet, String user) {
|
||||
Udp u = new Udp();
|
||||
if (packet.hasHeader(u)) {
|
||||
int offset = u.getOffset() + u.getLength();
|
||||
_executor.execute(new DhcpPacketParser(packet, offset, u.length() - u.getLength(), _manager));
|
||||
}
|
||||
}
|
||||
};
|
||||
s_logger.debug("Starting DHCP snooping on " + _bridge);
|
||||
int retValue = _pcapedDev.loop(-1, jpacketHandler, "pcapPacketHandler");
|
||||
if ( retValue == -1) {
|
||||
s_logger.debug("Pcap: failed to set loop handler");
|
||||
} else if ( retValue == -2 && !_loop) {
|
||||
s_logger.debug("Pcap: terminated");
|
||||
return;
|
||||
}
|
||||
_pcapedDev.close();
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Pcap error:" + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void main(String args[]) {
|
||||
s_logger.addAppender(new org.apache.log4j.ConsoleAppender(new org.apache.log4j.PatternLayout(), "System.out"));
|
||||
final DhcpSnooperImpl manager = new DhcpSnooperImpl("cloudbr0", 10000);
|
||||
s_logger.debug(manager.getIPAddr("02:00:4c:66:00:03", "i-2-5-VM"));
|
||||
manager.stop();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
// TODO configure timeout here
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DhcpSnooperImpl";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package com.cloud.agent.resource.computing;
|
||||
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.StartAnswer;
|
||||
import com.cloud.agent.api.StartCommand;
|
||||
|
||||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.StopCommand;
|
||||
|
||||
import com.cloud.agent.api.routing.SavePasswordCommand;
|
||||
import com.cloud.agent.api.routing.VmDataCommand;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.dhcp.DhcpSnooper;
|
||||
import com.cloud.agent.dhcp.DhcpSnooperImpl;
|
||||
|
||||
|
||||
import com.cloud.agent.resource.computing.LibvirtComputingResource;
|
||||
import com.cloud.agent.resource.computing.LibvirtConnection;
|
||||
import com.cloud.agent.resource.computing.LibvirtVMDef;
|
||||
import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef;
|
||||
import com.cloud.agent.resource.computing.LibvirtVMDef.InterfaceDef;
|
||||
import com.cloud.agent.vmdata.JettyVmDataServer;
|
||||
import com.cloud.agent.vmdata.VmDataServer;
|
||||
|
||||
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
|
||||
/**
|
||||
* Logic specific to the Cloudzones feature
|
||||
*
|
||||
* }
|
||||
**/
|
||||
|
||||
|
||||
public class CloudZonesComputingResource extends LibvirtComputingResource {
|
||||
private static final Logger s_logger = Logger.getLogger(CloudZonesComputingResource.class);
|
||||
protected DhcpSnooper _dhcpSnooper;
|
||||
String _parent;
|
||||
long _dhcpTimeout;
|
||||
protected String _hostIp;
|
||||
protected String _hostMacAddress;
|
||||
protected VmDataServer _vmDataServer = new JettyVmDataServer();
|
||||
|
||||
|
||||
private void setupDhcpManager(Connect conn, String bridgeName) {
|
||||
|
||||
_dhcpSnooper = new DhcpSnooperImpl(bridgeName, _dhcpTimeout);
|
||||
|
||||
List<Pair<String, String>> macs = new ArrayList<Pair<String, String>>();
|
||||
try {
|
||||
int[] domainIds = conn.listDomains();
|
||||
for (int i = 0; i < domainIds.length; i++) {
|
||||
Domain vm = conn.domainLookupByID(domainIds[i]);
|
||||
if (vm.getName().startsWith("i-")) {
|
||||
List<InterfaceDef> nics = getInterfaces(conn, vm.getName());
|
||||
InterfaceDef nic = nics.get(0);
|
||||
macs.add(new Pair<String, String>(nic.getMacAddress(), vm.getName()));
|
||||
}
|
||||
}
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get MACs: " + e.toString());
|
||||
}
|
||||
|
||||
_dhcpSnooper.initializeMacTable(macs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
boolean success = super.configure(name, params);
|
||||
if (! success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_parent = (String)params.get("mount.path");
|
||||
|
||||
try {
|
||||
_dhcpTimeout = Long.parseLong((String)params.get("dhcp.timeout"));
|
||||
} catch (Exception e) {
|
||||
_dhcpTimeout = 1200000;
|
||||
}
|
||||
|
||||
_hostIp = (String)params.get("host.ip");
|
||||
_hostMacAddress = (String)params.get("host.mac.address");
|
||||
|
||||
try {
|
||||
Connect conn;
|
||||
conn = LibvirtConnection.getConnection();
|
||||
setupDhcpManager(conn, _guestBridgeName);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get libvirt connection:" + e.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
_dhcpSnooper.configure(name, params);
|
||||
_vmDataServer.configure(name, params);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized StartAnswer execute(StartCommand cmd) {
|
||||
VirtualMachineTO vmSpec = cmd.getVirtualMachine();
|
||||
String vmName = vmSpec.getName();
|
||||
LibvirtVMDef vm = null;
|
||||
|
||||
State state = State.Stopped;
|
||||
Connect conn = null;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
synchronized (_vms) {
|
||||
_vms.put(vmName, State.Starting);
|
||||
}
|
||||
|
||||
vm = createVMFromSpec(vmSpec);
|
||||
|
||||
createVbd(conn, vmSpec, vmName, vm);
|
||||
|
||||
createVifs(conn, vmSpec, vm);
|
||||
|
||||
s_logger.debug("starting " + vmName + ": " + vm.toString());
|
||||
startDomain(conn, vmName, vm.toString());
|
||||
|
||||
|
||||
NicTO[] nics = vmSpec.getNics();
|
||||
for (NicTO nic : nics) {
|
||||
if (nic.isSecurityGroupEnabled()) {
|
||||
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||
default_network_rules_for_systemvm(conn, vmName);
|
||||
} else {
|
||||
nic.setIp(null);
|
||||
default_network_rules(conn, vmName, nic, vmSpec.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach each data volume to the VM, if there is a deferred attached disk
|
||||
for (DiskDef disk : vm.getDevices().getDisks()) {
|
||||
if (disk.isAttachDeferred()) {
|
||||
attachOrDetachDisk(conn, true, vmName, disk.getDiskPath(), disk.getDiskSeq());
|
||||
}
|
||||
}
|
||||
|
||||
if (vmSpec.getType() == VirtualMachine.Type.User) {
|
||||
for (NicTO nic: nics) {
|
||||
if (nic.getType() == TrafficType.Guest) {
|
||||
InetAddress ipAddr = _dhcpSnooper.getIPAddr(nic.getMac(), vmName);
|
||||
if (ipAddr == null) {
|
||||
s_logger.debug("Failed to get guest DHCP ip, stop it");
|
||||
StopCommand stpCmd = new StopCommand(vmName);
|
||||
execute(stpCmd);
|
||||
return new StartAnswer(cmd, "Failed to get guest DHCP ip, stop it");
|
||||
}
|
||||
s_logger.debug(ipAddr);
|
||||
nic.setIp(ipAddr.getHostAddress());
|
||||
|
||||
post_default_network_rules(conn, vmName, nic, vmSpec.getId(), _dhcpSnooper.getDhcpServerIP(), _hostIp, _hostMacAddress);
|
||||
_vmDataServer.handleVmStarted(cmd.getVirtualMachine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state = State.Running;
|
||||
return new StartAnswer(cmd);
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Exception ", e);
|
||||
if (conn != null) {
|
||||
handleVmStartFailure(conn, vmName, vm);
|
||||
}
|
||||
return new StartAnswer(cmd, e.getMessage());
|
||||
} finally {
|
||||
synchronized (_vms) {
|
||||
if (state != State.Stopped) {
|
||||
_vms.put(vmName, state);
|
||||
} else {
|
||||
_vms.remove(vmName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(StopCommand cmd) {
|
||||
final String vmName = cmd.getVmName();
|
||||
|
||||
Long bytesReceived = new Long(0);
|
||||
Long bytesSent = new Long(0);
|
||||
|
||||
State state = null;
|
||||
synchronized(_vms) {
|
||||
state = _vms.get(vmName);
|
||||
_vms.put(vmName, State.Stopping);
|
||||
}
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
|
||||
try {
|
||||
Domain dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes()));
|
||||
} catch (LibvirtException e) {
|
||||
state = State.Stopped;
|
||||
return new StopAnswer(cmd, null, 0, bytesSent, bytesReceived);
|
||||
}
|
||||
|
||||
String macAddress = null;
|
||||
if (vmName.startsWith("i-")) {
|
||||
List<InterfaceDef> nics = getInterfaces(conn, vmName);
|
||||
if (!nics.isEmpty()) {
|
||||
macAddress = nics.get(0).getMacAddress();
|
||||
}
|
||||
}
|
||||
|
||||
destroy_network_rules_for_vm(conn, vmName);
|
||||
String result = stopVM(conn, vmName, defineOps.UNDEFINE_VM);
|
||||
|
||||
try {
|
||||
cleanupVnet(conn, cmd.getVnet());
|
||||
_dhcpSnooper.cleanup(macAddress, vmName);
|
||||
_vmDataServer.handleVmStopped(cmd.getVmName());
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
state = State.Stopped;
|
||||
return new StopAnswer(cmd, result, 0, bytesSent, bytesReceived);
|
||||
} catch (LibvirtException e) {
|
||||
return new StopAnswer(cmd, e.getMessage());
|
||||
} finally {
|
||||
synchronized(_vms) {
|
||||
if (state != null) {
|
||||
_vms.put(vmName, state);
|
||||
} else {
|
||||
_vms.remove(vmName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof VmDataCommand) {
|
||||
return execute((VmDataCommand)cmd);
|
||||
} else if (cmd instanceof SavePasswordCommand) {
|
||||
return execute ((SavePasswordCommand)cmd);
|
||||
}
|
||||
return super.executeRequest(cmd);
|
||||
}
|
||||
|
||||
protected Answer execute(final VmDataCommand cmd) {
|
||||
return _vmDataServer.handleVmDataCommand(cmd);
|
||||
}
|
||||
|
||||
protected Answer execute(final SavePasswordCommand cmd) {
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
23
build.xml
23
build.xml
|
|
@ -17,25 +17,12 @@
|
|||
|
||||
<property file="${build-cloud.properties.file}"/>
|
||||
|
||||
<property name="premium.name" value="cloudstack-proprietary"/>
|
||||
<property name="premium.base.dir" location="${base.dir}/${premium.name}"/>
|
||||
|
||||
<condition property="my.build.dir" value="${premium.base.dir}/build" else="${base.dir}/build">
|
||||
<and>
|
||||
<available file="${premium.base.dir}/build"/>
|
||||
<not>
|
||||
<isset property="OSS"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
|
||||
<property name="dist.dir" location="${base.dir}/dist"/>
|
||||
<property name="target.dir" location="${base.dir}/target"/>
|
||||
|
||||
<import file="${my.build.dir}/build-cloud.xml" optional="false"/>
|
||||
<import file="${my.build.dir}/build-docs.xml" optional="true"/>
|
||||
<import file="${my.build.dir}/build-tests.xml" optional="true"/>
|
||||
<import file="${my.build.dir}/package.xml" optional="true"/>
|
||||
<import file="${my.build.dir}/developer.xml" optional="true"/>
|
||||
<import file="${base.dir}/build/build-cloud.xml" optional="false"/>
|
||||
<import file="${base.dir}/build/build-docs.xml" optional="true"/>
|
||||
<import file="${base.dir}/build/build-tests.xml" optional="true"/>
|
||||
<import file="${base.dir}/build/package.xml" optional="true"/>
|
||||
<import file="${base.dir}/build/developer.xml" optional="true"/>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@
|
|||
<path refid="deps.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-server" depends="-init, compile-utils, compile-core" description="Compile the management server.">
|
||||
<target name="compile-server" depends="-init, compile-utils, compile-core, compile-agent" description="Compile the management server.">
|
||||
<compile-java jar.name="${server.jar}" top.dir="${server.dir}" classpath="server.classpath" />
|
||||
</target>
|
||||
|
||||
|
|
@ -280,6 +280,8 @@
|
|||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="build-ovm" depends="compile-ovm" />
|
||||
|
||||
<target name="build-server" depends="compile-server">
|
||||
<mkdir dir="${server.dist.dir}" />
|
||||
<mkdir dir="${server.dist.dir}/lib" />
|
||||
|
|
@ -529,7 +531,7 @@
|
|||
|
||||
<target name="build-servers" depends="-init, build-server" />
|
||||
|
||||
<target name="build-opensource" depends="-init, build-server, build-agent, build-console-proxy, build-scripts, build-ui, package-oss-systemvm-iso">
|
||||
<target name="build-opensource" depends="-init, build-server, build-agent, build-console-proxy, build-scripts, build-ui, build-ovm, package-oss-systemvm-iso">
|
||||
<copy overwrite="true" todir="${dist.dir}">
|
||||
<fileset dir="${base.dir}/build/deploy/">
|
||||
<include name="deploy-agent.sh" />
|
||||
|
|
@ -629,7 +631,19 @@
|
|||
<delete dir="${unittest.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile-all" description="Compile all of the jars" depends="compile-utils, compile-api, compile-core, compile-server"/>
|
||||
<!-- ===================== Ovm.Jar ===================== -->
|
||||
<property name="ovm.jar" value="cloud-ovm.jar" />
|
||||
<property name="ovm.dir" location="${base.dir}/ovm" />
|
||||
<property name="ovm-scripts.dir" location="${ovm.dir}/scripts" />
|
||||
<path id="ovm.classpath" >
|
||||
<path refid="thirdparty.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-ovm" depends="-init, compile-server" description="Compile OVM">
|
||||
<compile-java jar.name="${ovm.jar}" top.dir="${ovm.dir}" classpath="ovm.classpath" />
|
||||
</target>
|
||||
|
||||
<target name="compile-all" description="Compile all of the jars" depends="compile-utils, compile-api, compile-core, compile-server, compile-ovm"/>
|
||||
|
||||
<target name="clean-all" depends="clean" description="Clean all of the generated files, including dependency cache and javadoc">
|
||||
<delete dir="${target.dir}" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
#### usage commands
|
||||
generateUsageRecords=com.cloud.api.commands.GenerateUsageRecordsCmd;1
|
||||
listUsageRecords=com.cloud.api.commands.GetUsageRecordsCmd;1
|
||||
listUsageTypes=com.cloud.api.commands.ListUsageTypesCmd;1
|
||||
|
||||
#### external firewall commands
|
||||
addExternalFirewall=com.cloud.api.commands.AddExternalFirewallCmd;1
|
||||
deleteExternalFirewall=com.cloud.api.commands.DeleteExternalFirewallCmd;1
|
||||
listExternalFirewalls=com.cloud.api.commands.ListExternalFirewallsCmd;1
|
||||
|
||||
#### external loadbalancer commands
|
||||
addExternalLoadBalancer=com.cloud.api.commands.AddExternalLoadBalancerCmd;1
|
||||
deleteExternalLoadBalancer=com.cloud.api.commands.DeleteExternalLoadBalancerCmd;1
|
||||
listExternalLoadBalancers=com.cloud.api.commands.ListExternalLoadBalancersCmd;1
|
||||
|
||||
### Network Devices commands
|
||||
addNetworkDevice=com.cloud.api.commands.AddNetworkDeviceCmd;1
|
||||
listNetworkDevice=com.cloud.api.commands.ListNetworkDeviceCmd;1
|
||||
deleteNetworkDevice=com.cloud.api.commands.DeleteNetworkDeviceCmd;1
|
||||
|
||||
#### traffic monitor commands
|
||||
addTrafficMonitor=com.cloud.api.commands.AddTrafficMonitorCmd;1
|
||||
deleteTrafficMonitor=com.cloud.api.commands.DeleteTrafficMonitorCmd;1
|
||||
listTrafficMonitors=com.cloud.api.commands.ListTrafficMonitorsCmd;1
|
||||
|
||||
####Netapp integration commands
|
||||
createVolumeOnFiler=com.cloud.api.commands.netapp.CreateVolumeCmd;15
|
||||
destroyVolumeOnFiler=com.cloud.api.commands.netapp.DestroyVolumeCmd;15
|
||||
listVolumesOnFiler=com.cloud.api.commands.netapp.ListVolumesCmd;15
|
||||
createLunOnFiler=com.cloud.api.commands.netapp.CreateLunCmd;15
|
||||
destroyLunOnFiler=com.cloud.api.commands.netapp.DestroyLunCmd;15
|
||||
listLunsOnFiler=com.cloud.api.commands.netapp.ListLunsCmd;15
|
||||
associateLun=com.cloud.api.commands.netapp.AssociateLunCmd;15
|
||||
dissociateLun=com.cloud.api.commands.netapp.DissociateLunCmd;15
|
||||
createPool=com.cloud.api.commands.netapp.CreatePoolCmd;15
|
||||
deletePool=com.cloud.api.commands.netapp.DeletePoolCmd;15
|
||||
modifyPool=com.cloud.api.commands.netapp.ModifyPoolCmd;15
|
||||
listPools=com.cloud.api.commands.netapp.ListPoolsCmd;15
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<components-cloudzones.xml>
|
||||
<system-integrity-checker class="com.cloud.upgrade.DatabaseUpgradeChecker">
|
||||
<checker name="ManagementServerNode" class="com.cloud.cluster.ManagementServerNode"/>
|
||||
<checker name="PremiumDatabaseUpgradeChecker" class="com.cloud.upgrade.PremiumDatabaseUpgradeChecker"/>
|
||||
</system-integrity-checker>
|
||||
|
||||
<management-server class="com.cloud.server.ManagementServerExtImpl" library="com.cloud.configuration.CloudZonesComponentLibrary" extends="components-premium.xml:management-server"/>
|
||||
|
||||
<configuration-server class="com.cloud.server.ConfigurationServerImpl" extends="components.xml:configuration-server">
|
||||
<dao name="Configuration configuration server" class="com.cloud.configuration.dao.ConfigurationDaoImpl" singleton="false">
|
||||
<param name="premium">true</param>
|
||||
</dao>
|
||||
</configuration-server>
|
||||
</components-cloudzones.xml>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0"?>
|
||||
<components-premium.xml>
|
||||
<system-integrity-checker class="com.cloud.upgrade.DatabaseUpgradeChecker">
|
||||
<checker name="ManagementServerNode" class="com.cloud.cluster.ManagementServerNode"/>
|
||||
<checker name="DatabaseIntegrityChecker" class="com.cloud.upgrade.DatabaseIntegrityChecker"/>
|
||||
<checker name="PremiumDatabaseUpgradeChecker" class="com.cloud.upgrade.PremiumDatabaseUpgradeChecker"/>
|
||||
</system-integrity-checker>
|
||||
|
||||
<management-server class="com.cloud.server.ManagementServerExtImpl" library="com.cloud.configuration.PremiumComponentLibrary" extends="components.xml:management-server">
|
||||
<dao name="Configuration configuration server" class="com.cloud.configuration.dao.ConfigurationDaoImpl">
|
||||
<param name="premium">true</param>
|
||||
</dao>
|
||||
<adapters key="com.cloud.ha.Investigator">
|
||||
<adapter name="SimpleInvestigator" class="com.cloud.ha.CheckOnAgentInvestigator"/>
|
||||
<adapter name="XenServerInvestigator" class="com.cloud.ha.XenServerInvestigator"/>
|
||||
<adapter name="PingInvestigator" class="com.cloud.ha.UserVmDomRInvestigator"/>
|
||||
<adapter name="ManagementIPSysVMInvestigator" class="com.cloud.ha.ManagementIPSystemVMInvestigator"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.ha.FenceBuilder">
|
||||
<adapter name="XenServerFenceBuilder" class="com.cloud.ha.XenServerFencer"/>
|
||||
<adapter name="KVMFenceBuilder" class="com.cloud.ha.KVMFencer"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.network.guru.NetworkGuru">
|
||||
<adapter name="ExternalGuestNetworkGuru" class="com.cloud.network.guru.ExternalGuestNetworkGuru"/>
|
||||
<adapter name="OvsGuestNetworkGuru" class="com.cloud.network.guru.OvsGuestNetworkGuru"/>
|
||||
<adapter name="PublicNetworkGuru" class="com.cloud.network.guru.PublicNetworkGuru"/>
|
||||
<adapter name="PodBasedNetworkGuru" class="com.cloud.network.guru.PodBasedNetworkGuru"/>
|
||||
<adapter name="ControlNetworkGuru" class="com.cloud.network.guru.ControlNetworkGuru"/>
|
||||
<adapter name="DirectNetworkGuru" class="com.cloud.network.guru.DirectNetworkGuru"/>
|
||||
<adapter name="DirectPodBasedNetworkGuru" class="com.cloud.network.guru.DirectPodBasedNetworkGuru"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.network.element.NetworkElement">
|
||||
<adapter name="ExternalFirewall" class="com.cloud.network.element.ExternalFirewallElement"/>
|
||||
<adapter name="ExternalLoadBalancer" class="com.cloud.network.element.ExternalLoadBalancerElement"/>
|
||||
<adapter name="DomainRouter" class="com.cloud.network.element.VirtualRouterElement"/>
|
||||
<adapter name="Dhcp" class="com.cloud.network.element.DhcpElement"/>
|
||||
<adapter name="Ovs" class="com.cloud.network.element.OvsElement"/>
|
||||
<adapter name="ExternalDhcp" class="com.cloud.network.element.ExternalDhcpElement"/>
|
||||
<adapter name="BareMetal" class="com.cloud.network.element.BareMetalElement"/>
|
||||
<adapter name="ElasticLoadBalancer" class="com.cloud.network.element.ElasticLoadBalancerElement"/>
|
||||
|
||||
|
||||
</adapters>
|
||||
<adapters key="com.cloud.resource.Discoverer">
|
||||
<adapter name="XCP Agent" class="com.cloud.hypervisor.xen.discoverer.XcpServerDiscoverer"/>
|
||||
<adapter name="SecondaryStorage" class="com.cloud.storage.secondary.SecondaryStorageDiscoverer"/>
|
||||
<adapter name="KVM Agent" class="com.cloud.hypervisor.kvm.discoverer.KvmServerDiscoverer"/>
|
||||
<adapter name="VShpereServer" class="com.cloud.hypervisor.vmware.VmwareServerDiscoverer"/>
|
||||
<adapter name="Bare Metal Agent" class="com.cloud.baremetal.BareMetalDiscoverer"/>
|
||||
<adapter name="SCVMMServer" class="com.cloud.hypervisor.hyperv.HypervServerDiscoverer"/>
|
||||
<adapter name="Ovm Discover" class="com.cloud.ovm.hypervisor.OvmDiscoverer" />
|
||||
</adapters>
|
||||
<adapters key="com.cloud.alert.AlertAdapter">
|
||||
<adapter name="ClusterAlert" class="com.cloud.alert.ClusterAlertAdapter"/>
|
||||
<adapter name="ConsoleProxyAlert" class="com.cloud.alert.ConsoleProxyAlertAdapter"/>
|
||||
<adapter name="SecondaryStorageVmAlert" class="com.cloud.alert.SecondaryStorageVmAlertAdapter"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.hypervisor.HypervisorGuru">
|
||||
<adapter name="XenServerGuru" class="com.cloud.hypervisor.XenServerGuru"/>
|
||||
<adapter name="KVMGuru" class="com.cloud.hypervisor.KVMGuru"/>
|
||||
<adapter name="VMwareGuru" class="com.cloud.hypervisor.guru.VMwareGuru"/>
|
||||
<adapter name="BareMetalGuru" class="com.cloud.baremetal.BareMetalGuru"/>
|
||||
<adapter name="HypervGuru" class="com.cloud.hypervisor.guru.HypervGuru"/>
|
||||
<adapter name="OvmGuru" class="com.cloud.ovm.hypervisor.OvmGuru" />
|
||||
</adapters>
|
||||
<adapters key="com.cloud.agent.StartupCommandProcessor">
|
||||
<adapter name="BasicAgentAuthorizer" class="com.cloud.agent.manager.authn.impl.BasicAgentAuthManager"/>
|
||||
</adapters>
|
||||
</management-server>
|
||||
|
||||
<configuration-server class="com.cloud.server.ConfigurationServerImpl" extends="components.xml:configuration-server">
|
||||
<dao name="Configuration configuration server" class="com.cloud.configuration.dao.ConfigurationDaoImpl" singleton="false">
|
||||
<param name="premium">true</param>
|
||||
</dao>
|
||||
</configuration-server>
|
||||
|
||||
</components-premium.xml>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
host=127.0.0.1
|
||||
port=8250
|
||||
workers=3
|
||||
zone=1
|
||||
pod=1
|
||||
run=13
|
||||
sequence=r
|
||||
agent.save.path=/tmp/agents
|
||||
latency=2
|
||||
latency.start.range=2
|
||||
latency.end.range=2
|
||||
delay.distribution={(5,10); (5,10); (5,10); (5,10); (5,10); (5,10); (5,10); (5,10); (5,10); (10,120)}
|
||||
property.scan.enabled=1
|
||||
property.scan.interval=300
|
||||
218
cloud.spec
218
cloud.spec
|
|
@ -36,7 +36,7 @@ BuildRequires: glibc-devel
|
|||
BuildRequires: /usr/bin/mkisofs
|
||||
BuildRequires: MySQL-python
|
||||
|
||||
%global _premium %(tar jtvmf %{SOURCE0} '*/cloudstack-proprietary/' --occurrence=1 2>/dev/null | wc -l)
|
||||
#%global _premium %(tar jtvmf %{SOURCE0} '*/cloudstack-proprietary/' --occurrence=1 2>/dev/null | wc -l)
|
||||
|
||||
%description
|
||||
This is the Cloud.com Stack, a highly-scalable elastic, open source,
|
||||
|
|
@ -161,6 +161,8 @@ Requires: /usr/bin/ssh-keygen
|
|||
Requires: mkisofs
|
||||
Requires: MySQL-python
|
||||
Requires: python-paramiko
|
||||
Requires: ipmitool
|
||||
Requires: %{name}-utils = %{version}
|
||||
Group: System Environment/Libraries
|
||||
%description client
|
||||
The Cloud.com management server is the central point of coordination,
|
||||
|
|
@ -223,13 +225,21 @@ Requires: /sbin/service
|
|||
Requires: /sbin/chkconfig
|
||||
Group: System Environment/Libraries
|
||||
|
||||
%if 0%{?rhel} >= 6
|
||||
Requires: cloud-kvm
|
||||
%else
|
||||
Requires: kvm
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 14
|
||||
Requires: cloud-qemu-kvm
|
||||
Requires: cloud-qemu-img
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} >= 6
|
||||
Requires: cloud-qemu-img
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} >= 5
|
||||
Requires: qemu-img
|
||||
%endif
|
||||
|
|
@ -290,64 +300,37 @@ Group: System Environment/Libraries
|
|||
The Cloud.com command line tools contain a few Python modules that can call cloudStack APIs.
|
||||
|
||||
|
||||
%if %{_premium}
|
||||
|
||||
%package premium-agent
|
||||
Summary: Cloud.com premium agent
|
||||
Requires: cloud-agent
|
||||
Requires: jnetpcap
|
||||
Group: System Environment/Libraries
|
||||
%description premium-agent
|
||||
The Cloud.com premium agent
|
||||
|
||||
%package test
|
||||
Summary: Cloud.com test suite
|
||||
Requires: java >= 1.6.0
|
||||
Requires: %{name}-utils = %{version}, %{name}-deps = %{version}, wget
|
||||
Group: System Environment/Libraries
|
||||
Obsoletes: vmops-test < %{version}-%{release}
|
||||
%description test
|
||||
The Cloud.com test package contains a suite of automated tests
|
||||
that the very much appreciated QA team at Cloud.com constantly
|
||||
uses to help increase the quality of the Cloud.com Stack.
|
||||
|
||||
%package premium
|
||||
Summary: Cloud.com premium components
|
||||
Obsoletes: vmops-premium < %{version}-%{release}
|
||||
Provides: %{name}-premium-plugin-zynga = %{version}-%{release}
|
||||
Obsoletes: %{name}-premium-plugin-zynga < %{version}-%{release}
|
||||
Provides: %{name}-premium-vendor-zynga = %{version}-%{release}
|
||||
Obsoletes: %{name}-premium-vendor-zynga < %{version}-%{release}
|
||||
Requires: java >= 1.6.0
|
||||
Requires: ipmitool
|
||||
Requires: %{name}-utils = %{version}
|
||||
License: CSL 1.1
|
||||
Group: System Environment/Libraries
|
||||
%description premium
|
||||
The Cloud.com premium components expand the range of features on your Cloud.com Stack.
|
||||
|
||||
%package usage
|
||||
Summary: Cloud.com usage monitor
|
||||
Obsoletes: vmops-usage < %{version}-%{release}
|
||||
Requires: java >= 1.6.0
|
||||
Requires: %{name}-utils = %{version}, %{name}-core = %{version}, %{name}-deps = %{version}, %{name}-server = %{version}, %{name}-premium = %{version}, %{name}-daemonize = %{version}
|
||||
Requires: %{name}-setup = %{version}
|
||||
Requires: %{name}-client = %{version}
|
||||
License: CSL 1.1
|
||||
Group: System Environment/Libraries
|
||||
%description usage
|
||||
The Cloud.com usage monitor provides usage accounting across the entire cloud for
|
||||
cloud operators to charge based on usage parameters.
|
||||
|
||||
%endif
|
||||
#%if %{_premium}
|
||||
#
|
||||
#%package test
|
||||
#Summary: Cloud.com test suite
|
||||
#Requires: java >= 1.6.0
|
||||
#Requires: %{name}-utils = %{version}, %{name}-deps = %{version}, wget
|
||||
#Group: System Environment/Libraries
|
||||
#Obsoletes: vmops-test < %{version}-%{release}
|
||||
#%description test
|
||||
#The Cloud.com test package contains a suite of automated tests
|
||||
#that the very much appreciated QA team at Cloud.com constantly
|
||||
#uses to help increase the quality of the Cloud.com Stack.
|
||||
#
|
||||
#%package usage
|
||||
#Summary: Cloud.com usage monitor
|
||||
#Obsoletes: vmops-usage < %{version}-%{release}
|
||||
#Requires: java >= 1.6.0
|
||||
#Requires: %{name}-utils = %{version}, %{name}-core = %{version}, %{name}-deps = %{version}, %{name}-server = %{version}, %{name}-premium = %{version}, %{name}-daemonize = %{version}
|
||||
#Requires: %{name}-setup = %{version}
|
||||
#Requires: %{name}-client = %{version}
|
||||
#License: CSL 1.1
|
||||
#Group: System Environment/Libraries
|
||||
#%description usage
|
||||
#The Cloud.com usage monitor provides usage accounting across the entire cloud for
|
||||
#cloud operators to charge based on usage parameters.
|
||||
#
|
||||
#%endif
|
||||
|
||||
%prep
|
||||
|
||||
%if %{_premium}
|
||||
echo Doing premium build
|
||||
%else
|
||||
echo Doing open source build
|
||||
%endif
|
||||
echo Doing CloudStack build
|
||||
|
||||
%setup -q -n %{name}-%{_ver}
|
||||
|
||||
|
|
@ -381,11 +364,9 @@ id %{name} > /dev/null 2>&1 || /usr/sbin/useradd -M -c "Cloud.com unprivileged u
|
|||
-r -s /bin/sh -d %{_sharedstatedir}/%{name}/management %{name}|| true
|
||||
|
||||
# set max file descriptors for cloud user to 4096
|
||||
grep "cloud" /etc/security/limits.conf &>/dev/null
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "cloud hard nofile 4096" >> /etc/security/limits.conf
|
||||
echo "cloud soft nofile 4096" >> /etc/security/limits.conf
|
||||
fi
|
||||
sed -i /"cloud"/d /etc/security/limits.conf
|
||||
echo "cloud hard nofile 4096" >> /etc/security/limits.conf
|
||||
echo "cloud soft nofile 4096" >> /etc/security/limits.conf
|
||||
rm -rf %{_localstatedir}/cache/%{name}
|
||||
# user harcoded here, also hardcoded on wscript
|
||||
|
||||
|
|
@ -409,28 +390,28 @@ fi
|
|||
|
||||
|
||||
|
||||
%if %{_premium}
|
||||
|
||||
%preun usage
|
||||
if [ "$1" == "0" ] ; then
|
||||
/sbin/chkconfig --del %{name}-usage > /dev/null 2>&1 || true
|
||||
/sbin/service %{name}-usage stop > /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
%pre usage
|
||||
id %{name} > /dev/null 2>&1 || /usr/sbin/useradd -M -c "Cloud.com unprivileged user" \
|
||||
-r -s /bin/sh -d %{_sharedstatedir}/%{name}/management %{name}|| true
|
||||
# user harcoded here, also hardcoded on wscript
|
||||
|
||||
%post usage
|
||||
if [ "$1" == "1" ] ; then
|
||||
/sbin/chkconfig --add %{name}-usage > /dev/null 2>&1 || true
|
||||
/sbin/chkconfig --level 345 %{name}-usage on > /dev/null 2>&1 || true
|
||||
else
|
||||
/sbin/service %{name}-usage condrestart >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
%endif
|
||||
#%if %{_premium}
|
||||
#
|
||||
#%preun usage
|
||||
#if [ "$1" == "0" ] ; then
|
||||
# /sbin/chkconfig --del %{name}-usage > /dev/null 2>&1 || true
|
||||
# /sbin/service %{name}-usage stop > /dev/null 2>&1 || true
|
||||
#fi
|
||||
#
|
||||
#%pre usage
|
||||
#id %{name} > /dev/null 2>&1 || /usr/sbin/useradd -M -c "Cloud.com unprivileged user" \
|
||||
# -r -s /bin/sh -d %{_sharedstatedir}/%{name}/management %{name}|| true
|
||||
## user harcoded here, also hardcoded on wscript
|
||||
#
|
||||
#%post usage
|
||||
#if [ "$1" == "1" ] ; then
|
||||
# /sbin/chkconfig --add %{name}-usage > /dev/null 2>&1 || true
|
||||
# /sbin/chkconfig --level 345 %{name}-usage on > /dev/null 2>&1 || true
|
||||
#else
|
||||
# /sbin/service %{name}-usage condrestart >/dev/null 2>&1 || true
|
||||
#fi
|
||||
#
|
||||
#%endif
|
||||
|
||||
%pre agent-scripts
|
||||
id %{name} > /dev/null 2>&1 || /usr/sbin/useradd -M -c "Cloud.com unprivileged user" \
|
||||
|
|
@ -484,6 +465,8 @@ fi
|
|||
%files server
|
||||
%defattr(0644,root,root,0755)
|
||||
%{_javadir}/%{name}-server.jar
|
||||
%{_javadir}/%{name}-vmware-base.jar
|
||||
%{_javadir}/%{name}-ovm.jar
|
||||
%{_sysconfdir}/%{name}/server/*
|
||||
|
||||
%files agent-scripts
|
||||
|
|
@ -524,10 +507,7 @@ fi
|
|||
%{_javadir}/%{name}-jsch-0.1.42.jar
|
||||
%{_javadir}/%{name}-iControl.jar
|
||||
%{_javadir}/%{name}-manageontap.jar
|
||||
|
||||
%defattr(0644,root,root,0755)
|
||||
%{_javadir}/%{name}-premium/*.jar
|
||||
%exclude %{_javadir}/%{name}-premium/servlet-api.jar
|
||||
%{_javadir}/vmware*.jar
|
||||
|
||||
%files core
|
||||
%defattr(0644,root,root,0755)
|
||||
|
|
@ -555,9 +535,7 @@ fi
|
|||
%files client
|
||||
%defattr(0644,root,root,0775)
|
||||
%{_sysconfdir}/%{name}/management/*
|
||||
%if %{_premium}
|
||||
%exclude %{_sysconfdir}/%{name}/management/*premium*
|
||||
%endif
|
||||
%{_sysconfdir}/%{name}/management/*premium*
|
||||
%config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/%{name}/management/db.properties
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/management/log4j-%{name}.xml
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/management/tomcat6.conf
|
||||
|
|
@ -596,6 +574,7 @@ fi
|
|||
%{_libdir}/%{name}/agent/images
|
||||
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
|
||||
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/agent
|
||||
%attr(0755,root,root) %{_bindir}/mycloud-setup-agent
|
||||
|
||||
%files console-proxy
|
||||
%defattr(0644,root,root,0755)
|
||||
|
|
@ -618,44 +597,27 @@ fi
|
|||
%files baremetal-agent
|
||||
%attr(0755,root,root) %{_bindir}/cloud-setup-baremetal
|
||||
|
||||
%if %{_premium}
|
||||
|
||||
%files premium-agent
|
||||
%{_javadir}/cloud-agent-extras.jar
|
||||
%attr(0755,root,root) %{_bindir}/mycloud-setup-agent
|
||||
|
||||
%files test
|
||||
%defattr(0644,root,root,0755)
|
||||
%attr(0755,root,root) %{_bindir}/%{name}-run-test
|
||||
%{_javadir}/%{name}-test.jar
|
||||
%{_sharedstatedir}/%{name}/test/*
|
||||
%{_libdir}/%{name}/test/*
|
||||
%{_sysconfdir}/%{name}/test/*
|
||||
|
||||
%files premium
|
||||
%defattr(0644,root,root,0755)
|
||||
%{_javadir}/%{name}-core-extras.jar
|
||||
%{_javadir}/%{name}-server-extras.jar
|
||||
%{_javadir}/%{name}-vmware-base.jar
|
||||
%{_javadir}/%{name}-ovm.jar
|
||||
# maintain the following list in sync with files agent-scripts
|
||||
%{_libdir}/%{name}/agent/premium-scripts/*
|
||||
%{_sysconfdir}/%{name}/management/commands-ext.properties
|
||||
%{_sysconfdir}/%{name}/management/components-premium.xml
|
||||
%{_datadir}/%{name}/setup/create-database-premium.sql
|
||||
%{_datadir}/%{name}/setup/create-schema-premium.sql
|
||||
|
||||
%files usage
|
||||
%defattr(0644,root,root,0775)
|
||||
%{_javadir}/%{name}-usage.jar
|
||||
%attr(0755,root,root) %{_initrddir}/%{name}-usage
|
||||
%attr(0755,root,root) %{_libexecdir}/usage-runner
|
||||
%dir %attr(0770,root,%{name}) %{_localstatedir}/log/%{name}/usage
|
||||
%{_sysconfdir}/%{name}/usage/usage-components.xml
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/usage/log4j-%{name}_usage.xml
|
||||
%config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/%{name}/usage/db.properties
|
||||
|
||||
%endif
|
||||
#%if %{_premium}
|
||||
#
|
||||
#%files test
|
||||
#%defattr(0644,root,root,0755)
|
||||
#%attr(0755,root,root) %{_bindir}/%{name}-run-test
|
||||
#%{_javadir}/%{name}-test.jar
|
||||
#%{_sharedstatedir}/%{name}/test/*
|
||||
#%{_libdir}/%{name}/test/*
|
||||
#%{_sysconfdir}/%{name}/test/*
|
||||
#
|
||||
#%files usage
|
||||
#%defattr(0644,root,root,0775)
|
||||
#%{_javadir}/%{name}-usage.jar
|
||||
#%attr(0755,root,root) %{_initrddir}/%{name}-usage
|
||||
#%attr(0755,root,root) %{_libexecdir}/usage-runner
|
||||
#%dir %attr(0770,root,%{name}) %{_localstatedir}/log/%{name}/usage
|
||||
#%{_sysconfdir}/%{name}/usage/usage-components.xml
|
||||
#%config(noreplace) %{_sysconfdir}/%{name}/usage/log4j-%{name}_usage.xml
|
||||
#%config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/%{name}/usage/db.properties
|
||||
#
|
||||
#%endif
|
||||
|
||||
%changelog
|
||||
* Mon May 3 2010 Manuel Amador (Rudd-O) <manuel@vmops.com> 1.9.12
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DirectNetworkUsageAnswer extends Answer {
|
||||
|
||||
Map<String, long[]> ipBytesSentAndReceived;
|
||||
|
||||
protected DirectNetworkUsageAnswer() {
|
||||
}
|
||||
|
||||
public DirectNetworkUsageAnswer(Command command) {
|
||||
super(command);
|
||||
this.ipBytesSentAndReceived = new HashMap<String, long[]>();
|
||||
}
|
||||
|
||||
public DirectNetworkUsageAnswer(Command command, Exception e) {
|
||||
super(command, e);
|
||||
this.ipBytesSentAndReceived = null;
|
||||
}
|
||||
|
||||
public void put(String ip, long[] bytesSentAndReceived) {
|
||||
this.ipBytesSentAndReceived.put(ip, bytesSentAndReceived);
|
||||
}
|
||||
|
||||
public long[] get(String ip) {
|
||||
long[] entry = ipBytesSentAndReceived.get(ip);
|
||||
if (entry == null) {
|
||||
ipBytesSentAndReceived.put(ip, new long[]{0, 0});
|
||||
return ipBytesSentAndReceived.get(ip);
|
||||
} else {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, long[]> getIpBytesSentAndReceived() {
|
||||
return ipBytesSentAndReceived;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class DirectNetworkUsageCommand extends Command {
|
||||
|
||||
private List<String> publicIps;
|
||||
private Date start;
|
||||
private Date end;
|
||||
|
||||
public DirectNetworkUsageCommand(List<String> publicIps, Date start, Date end) {
|
||||
this.setPublicIps(publicIps);
|
||||
this.setStart(start);
|
||||
this.setEnd(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPublicIps(List<String> publicIps) {
|
||||
this.publicIps = publicIps;
|
||||
}
|
||||
|
||||
public List<String> getPublicIps() {
|
||||
return publicIps;
|
||||
}
|
||||
|
||||
public void setStart(Date start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setEnd(Date end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public Date getEnd() {
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExternalNetworkResourceUsageAnswer extends Answer {
|
||||
public Map<String, long[]> ipBytes;
|
||||
public Map<String, long[]> guestVlanBytes;
|
||||
|
||||
protected ExternalNetworkResourceUsageAnswer() {
|
||||
}
|
||||
|
||||
public ExternalNetworkResourceUsageAnswer(Command command) {
|
||||
super(command);
|
||||
this.ipBytes = new HashMap<String, long[]>();
|
||||
this.guestVlanBytes = new HashMap<String, long[]>();
|
||||
}
|
||||
|
||||
public ExternalNetworkResourceUsageAnswer(Command command, Exception e) {
|
||||
super(command, e);
|
||||
this.ipBytes = null;
|
||||
this.guestVlanBytes = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
public class ExternalNetworkResourceUsageCommand extends Command {
|
||||
|
||||
public ExternalNetworkResourceUsageCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
|
||||
public class RecurringNetworkUsageAnswer extends Answer {
|
||||
|
||||
|
||||
protected RecurringNetworkUsageAnswer() {
|
||||
}
|
||||
|
||||
public RecurringNetworkUsageAnswer(Command command) {
|
||||
super(command);
|
||||
}
|
||||
|
||||
public RecurringNetworkUsageAnswer(Command command, Exception e) {
|
||||
super(command, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
|
||||
public class RecurringNetworkUsageCommand extends Command implements CronCommand{
|
||||
int interval;
|
||||
|
||||
public RecurringNetworkUsageCommand(int interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public int getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.host.Host;
|
||||
|
||||
/**
|
||||
* Implementation of bootstrap command sent from management server to agent running on
|
||||
* System Center Virtual Machine Manager host
|
||||
**/
|
||||
|
||||
public class StartupVMMAgentCommand extends Command {
|
||||
Host.Type type;
|
||||
long dataCenter;
|
||||
Long pod;
|
||||
String clusterName;
|
||||
String guid;
|
||||
String managementServerIP;
|
||||
String port;
|
||||
String version;
|
||||
|
||||
public StartupVMMAgentCommand() {
|
||||
|
||||
}
|
||||
|
||||
public StartupVMMAgentCommand(long dataCenter, Long pod, String clusterName, String guid, String managementServerIP, String port, String version) {
|
||||
super();
|
||||
this.dataCenter = dataCenter;
|
||||
this.pod = pod;
|
||||
this.clusterName = clusterName;
|
||||
this.guid = guid;
|
||||
this.type = Host.Type.Routing;
|
||||
this.managementServerIP = managementServerIP;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public long getDataCenter() {
|
||||
return dataCenter;
|
||||
}
|
||||
|
||||
public Long getPod() {
|
||||
return pod;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public String getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public String getManagementServerIP() {
|
||||
return managementServerIP;
|
||||
}
|
||||
|
||||
public String getport() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.hyperv.resource;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.ServerResourceBase;
|
||||
|
||||
/**
|
||||
* Implementation of dummy resource to be returned from discoverer
|
||||
**/
|
||||
|
||||
public class HypervDummyResourceBase extends ServerResourceBase implements
|
||||
ServerResource {
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(long id) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScriptsDir() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,954 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.hyperv.resource;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.IAgentControl;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.AttachIsoCommand;
|
||||
import com.cloud.agent.api.AttachVolumeCommand;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CheckHealthCommand;
|
||||
import com.cloud.agent.api.CheckOnHostCommand;
|
||||
import com.cloud.agent.api.CheckVirtualMachineCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.DeleteStoragePoolCommand;
|
||||
import com.cloud.agent.api.GetHostStatsAnswer;
|
||||
import com.cloud.agent.api.GetHostStatsCommand;
|
||||
import com.cloud.agent.api.GetStorageStatsAnswer;
|
||||
import com.cloud.agent.api.GetStorageStatsCommand;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.GetVncPortCommand;
|
||||
import com.cloud.agent.api.HostStatsEntry;
|
||||
import com.cloud.agent.api.MaintainCommand;
|
||||
import com.cloud.agent.api.ManageSnapshotCommand;
|
||||
import com.cloud.agent.api.MigrateCommand;
|
||||
import com.cloud.agent.api.ModifySshKeysCommand;
|
||||
import com.cloud.agent.api.ModifyStoragePoolAnswer;
|
||||
import com.cloud.agent.api.ModifyStoragePoolCommand;
|
||||
import com.cloud.agent.api.NetworkUsageCommand;
|
||||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.PingRoutingCommand;
|
||||
import com.cloud.agent.api.PingTestCommand;
|
||||
import com.cloud.agent.api.PoolEjectCommand;
|
||||
import com.cloud.agent.api.PrepareForMigrationCommand;
|
||||
import com.cloud.agent.api.ReadyAnswer;
|
||||
import com.cloud.agent.api.ReadyCommand;
|
||||
import com.cloud.agent.api.RebootCommand;
|
||||
import com.cloud.agent.api.RebootRouterCommand;
|
||||
import com.cloud.agent.api.SetupCommand;
|
||||
import com.cloud.agent.api.StartAnswer;
|
||||
import com.cloud.agent.api.StartCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.agent.api.StopCommand;
|
||||
import com.cloud.agent.api.ValidateSnapshotCommand;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshCommand;
|
||||
import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocCommand;
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.routing.NetworkElementCommand;
|
||||
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
|
||||
import com.cloud.agent.api.routing.SavePasswordCommand;
|
||||
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
|
||||
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
|
||||
import com.cloud.agent.api.routing.VmDataCommand;
|
||||
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreateCommand;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.vmware.resource.SshHelper;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.ServerResourceBase;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.template.TemplateInfo;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* Implementation of resource base class for Hyper-V hypervisor
|
||||
**/
|
||||
|
||||
@Local(value={ServerResource.class})
|
||||
public class HypervResource extends ServerResourceBase implements ServerResource{
|
||||
private String _dcId;
|
||||
private String _podId;
|
||||
private String _clusterId;
|
||||
private String _guid;
|
||||
private String _name;
|
||||
private static final Logger s_logger = Logger.getLogger(HypervResource.class);
|
||||
private IAgentControl agentControl;
|
||||
private volatile Boolean _wakeUp = false;
|
||||
protected Gson _gson;
|
||||
protected HashMap<String, State> _vms = new HashMap<String, State>(512);
|
||||
protected final int DEFAULT_DOMR_SSHPORT = 3922;
|
||||
|
||||
public HypervResource()
|
||||
{
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
|
||||
if (cmd instanceof CreateCommand) {
|
||||
return execute((CreateCommand) cmd);
|
||||
} else if (cmd instanceof SetPortForwardingRulesCommand) {
|
||||
s_logger.info("SCVMM agent recived command SetPortForwardingRulesCommand");
|
||||
//return execute((SetPortForwardingRulesCommand) cmd);
|
||||
} else if (cmd instanceof SetStaticNatRulesCommand) {
|
||||
s_logger.info("SCVMM agent recived command SetStaticNatRulesCommand");
|
||||
//return execute((SetStaticNatRulesCommand) cmd);
|
||||
}else if (cmd instanceof LoadBalancerConfigCommand) {
|
||||
s_logger.info("SCVMM agent recived command SetStaticNatRulesCommand");
|
||||
//return execute((LoadBalancerConfigCommand) cmd);
|
||||
} else if (cmd instanceof IpAssocCommand) {
|
||||
s_logger.info("SCVMM agent recived command IPAssocCommand");
|
||||
//return execute((IPAssocCommand) cmd);
|
||||
} else if (cmd instanceof SavePasswordCommand) {
|
||||
s_logger.info("SCVMM agent recived command SavePasswordCommand");
|
||||
//return execute((SavePasswordCommand) cmd);
|
||||
} else if (cmd instanceof DhcpEntryCommand) {
|
||||
return execute((DhcpEntryCommand) cmd);
|
||||
} else if (cmd instanceof VmDataCommand) {
|
||||
//return execute((VmDataCommand) cmd);
|
||||
} else if (cmd instanceof ReadyCommand) {
|
||||
s_logger.info("SCVMM agent recived ReadyCommand: " + _gson.toJson(cmd));
|
||||
return new ReadyAnswer((ReadyCommand) cmd);
|
||||
} else if (cmd instanceof GetHostStatsCommand) {
|
||||
return execute((GetHostStatsCommand) cmd);
|
||||
} else if (cmd instanceof GetVmStatsCommand) {
|
||||
s_logger.info("SCVMM agent recived command GetVmStatsCommand");
|
||||
//return execute((GetVmStatsCommand) cmd);
|
||||
} else if (cmd instanceof CheckHealthCommand) {
|
||||
//return execute((CheckHealthCommand) cmd);
|
||||
} else if (cmd instanceof StopCommand) {
|
||||
//return execute((StopCommand) cmd);
|
||||
} else if (cmd instanceof RebootRouterCommand) {
|
||||
//return execute((RebootRouterCommand) cmd);
|
||||
} else if (cmd instanceof RebootCommand) {
|
||||
//return execute((RebootCommand) cmd);
|
||||
} else if (cmd instanceof CheckVirtualMachineCommand) {
|
||||
s_logger.info("SCVMM agent recived command CheckVirtualMachineCommand");
|
||||
//return execute((CheckVirtualMachineCommand) cmd);
|
||||
} else if (cmd instanceof PrepareForMigrationCommand) {
|
||||
//return execute((PrepareForMigrationCommand) cmd);
|
||||
} else if (cmd instanceof MigrateCommand) {
|
||||
//return execute((MigrateCommand) cmd);
|
||||
} else if (cmd instanceof DestroyCommand) {
|
||||
//return execute((DestroyCommand) cmd);
|
||||
} else if (cmd instanceof ModifyStoragePoolCommand) {
|
||||
return execute((ModifyStoragePoolCommand) cmd);
|
||||
} else if (cmd instanceof DeleteStoragePoolCommand) {
|
||||
s_logger.info("SCVMM agent recived command DeleteStoragePoolCommand");
|
||||
Answer answer = new Answer(cmd, true, "success");
|
||||
return answer;
|
||||
//return execute((DeleteStoragePoolCommand) cmd);
|
||||
} else if (cmd instanceof CopyVolumeCommand) {
|
||||
s_logger.info("SCVMM agent recived command CopyVolumeCommand");
|
||||
//return execute((CopyVolumeCommand) cmd);
|
||||
} else if (cmd instanceof AttachVolumeCommand) {
|
||||
s_logger.info("SCVMM agent recived command AttachVolumeCommand");
|
||||
//return execute((AttachVolumeCommand) cmd);
|
||||
} else if (cmd instanceof AttachIsoCommand) {
|
||||
//return execute((AttachIsoCommand) cmd);
|
||||
} else if (cmd instanceof ValidateSnapshotCommand) {
|
||||
//return execute((ValidateSnapshotCommand) cmd);
|
||||
} else if (cmd instanceof ManageSnapshotCommand) {
|
||||
//return execute((ManageSnapshotCommand) cmd);
|
||||
} else if (cmd instanceof BackupSnapshotCommand) {
|
||||
//return execute((BackupSnapshotCommand) cmd);
|
||||
} else if (cmd instanceof DeleteSnapshotBackupCommand) {
|
||||
//return execute((DeleteSnapshotBackupCommand) cmd);
|
||||
} else if (cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
//return execute((CreateVolumeFromSnapshotCommand) cmd);
|
||||
} else if (cmd instanceof DeleteSnapshotsDirCommand) {
|
||||
//return execute((DeleteSnapshotsDirCommand) cmd);
|
||||
} else if (cmd instanceof CreatePrivateTemplateFromVolumeCommand) {
|
||||
//return execute((CreatePrivateTemplateFromVolumeCommand) cmd);
|
||||
} else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) {
|
||||
//return execute((CreatePrivateTemplateFromSnapshotCommand) cmd);
|
||||
} else if (cmd instanceof GetStorageStatsCommand) {
|
||||
return execute((GetStorageStatsCommand) cmd);
|
||||
} else if (cmd instanceof PrimaryStorageDownloadCommand) {
|
||||
s_logger.info("SCVMM agent recived command PrimaryStorageDownloadCommand");
|
||||
return execute((PrimaryStorageDownloadCommand) cmd);
|
||||
} else if (cmd instanceof GetVncPortCommand) {
|
||||
//return execute((GetVncPortCommand) cmd);
|
||||
} else if (cmd instanceof SetupCommand) {
|
||||
//return execute((SetupCommand) cmd);
|
||||
} else if (cmd instanceof MaintainCommand) {
|
||||
//return execute((MaintainCommand) cmd);
|
||||
} else if (cmd instanceof PingTestCommand) {
|
||||
s_logger.info("SCVMM agent recived command PingTestCommand");
|
||||
//return execute((PingTestCommand) cmd);
|
||||
} else if (cmd instanceof CheckOnHostCommand) {
|
||||
s_logger.info("SCVMM agent recived command CheckOnHostCommand");
|
||||
//return execute((CheckOnHostCommand) cmd);
|
||||
} else if (cmd instanceof ModifySshKeysCommand) {
|
||||
//return execute((ModifySshKeysCommand) cmd);
|
||||
} else if (cmd instanceof PoolEjectCommand) {
|
||||
//return execute((PoolEjectCommand) cmd);
|
||||
} else if (cmd instanceof NetworkUsageCommand) {
|
||||
//return execute((NetworkUsageCommand) cmd);
|
||||
} else if (cmd instanceof StartCommand) {
|
||||
return execute((StartCommand) cmd);
|
||||
} else if (cmd instanceof RemoteAccessVpnCfgCommand) {
|
||||
//return execute((RemoteAccessVpnCfgCommand) cmd);
|
||||
} else if (cmd instanceof VpnUsersCfgCommand) {
|
||||
//return execute((VpnUsersCfgCommand) cmd);
|
||||
} else if (cmd instanceof CheckSshCommand) {
|
||||
return execute((CheckSshCommand)cmd);
|
||||
} else {
|
||||
s_logger.info("SCVMM agent recived unimplemented command: " + _gson.toJson(cmd));
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
|
||||
public PrimaryStorageDownloadAnswer execute(PrimaryStorageDownloadCommand cmd) {
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource PrimaryStorageDownloadCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
try {
|
||||
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
|
||||
String primaryStroageUrl = cmd.getPrimaryStorageUrl();
|
||||
String templateUuidName =null;
|
||||
assert ((primaryStroageUrl != null) && (secondaryStorageUrl != null));
|
||||
// FIXME: paths and system vm name are hard coded
|
||||
String templateUrl = cmd.getUrl();
|
||||
String templatePath = templateUrl.replace('/', '\\');
|
||||
templatePath = templatePath.substring(4);
|
||||
if (!templatePath.endsWith(".vhd")) {
|
||||
String templateName = cmd.getName();
|
||||
templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + cmd.getPoolUuid()).getBytes()).toString();
|
||||
if (!templatePath.endsWith("\\")) {
|
||||
templatePath = templatePath + "\\";
|
||||
}
|
||||
//templatePath = templatePath + templateUuidName + ".vhd";
|
||||
templatePath = templatePath + "systemvm.vhd";
|
||||
}
|
||||
|
||||
s_logger.info("template URL: "+ templateUrl + "template name: "+ cmd.getName() + " sec storage " + secondaryStorageUrl+ " pri storage" + primaryStroageUrl);
|
||||
|
||||
StringBuilder cmdStr = new StringBuilder("cmd /c powershell.exe ");
|
||||
cmdStr.append("copy-item '");
|
||||
cmdStr.append(templatePath.toCharArray());
|
||||
cmdStr.append("' 'C:\\programdata\\Virtual Machine Manager Library Files\\VHDs\\';");
|
||||
|
||||
s_logger.info("Running command: " + cmdStr);
|
||||
Process p = Runtime.getRuntime().exec(cmdStr.toString());
|
||||
p.getOutputStream().close();
|
||||
|
||||
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
|
||||
BufferedReader errreader = new BufferedReader(temperrReader);
|
||||
if (errreader.ready()) {
|
||||
String errorOutput = new String("");
|
||||
s_logger.info("errors found while running cmdlet: " + cmdStr.toString());
|
||||
while (true){
|
||||
String errline = errreader.readLine();
|
||||
if (errline == null) {
|
||||
break;
|
||||
}
|
||||
errorOutput = errorOutput + errline;
|
||||
}
|
||||
s_logger.info(errorOutput);
|
||||
}
|
||||
|
||||
p.getErrorStream().close();
|
||||
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
|
||||
BufferedReader reader = new BufferedReader(tempReader);
|
||||
|
||||
String output = new String("");
|
||||
|
||||
while (true){
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
output = output + line;
|
||||
}
|
||||
p.getInputStream().close();
|
||||
|
||||
s_logger.info("Command output: "+ output);
|
||||
|
||||
if (output.contains("FullyQualifiedErrorId") || output.contains("Error") || output.contains("Exception")) {
|
||||
return new PrimaryStorageDownloadAnswer("Failed to copy template to SCVMM library share from secondary storage.");
|
||||
}
|
||||
|
||||
return new PrimaryStorageDownloadAnswer(templateUuidName, 0);
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
s_logger.info("Exception caught: "+e.getMessage());
|
||||
return new PrimaryStorageDownloadAnswer("Failed to copy template to SCVMM library share from secondary storage.");
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(CreateCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource CreateCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
try {
|
||||
long volId = cmd.getVolumeId();
|
||||
String templateUrl = cmd.getTemplateUrl();;
|
||||
StorageFilerTO pool = cmd.getPool();
|
||||
DiskProfile diskchar = cmd.getDiskCharacteristics();
|
||||
|
||||
if (diskchar.getType() == Volume.Type.ROOT) {
|
||||
if (cmd.getTemplateUrl() == null) {
|
||||
//create root volume
|
||||
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
|
||||
diskchar.getType(),
|
||||
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
|
||||
pool.getPath(), cmd.getDiskCharacteristics().getName(), cmd.getDiskCharacteristics().getSize(),
|
||||
null);
|
||||
return new CreateAnswer(cmd, vol);
|
||||
} else {
|
||||
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
|
||||
diskchar.getType(),
|
||||
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
|
||||
pool.getPath(), cmd.getDiskCharacteristics().getName(), cmd.getDiskCharacteristics().getSize(), null);
|
||||
return new CreateAnswer(cmd, vol);
|
||||
}
|
||||
|
||||
} else {
|
||||
//create data volume
|
||||
String volumeUuid = "cloud.worker." + UUID.randomUUID().toString();
|
||||
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
|
||||
diskchar.getType(),
|
||||
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
|
||||
pool.getPath(), volumeUuid, cmd.getDiskCharacteristics().getSize(), null);
|
||||
return new CreateAnswer(cmd, vol);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected StartAnswer execute(StartCommand cmd) {
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource StartCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
VirtualMachineTO vmSpec = cmd.getVirtualMachine();
|
||||
String vmName = vmSpec.getName();
|
||||
State state = State.Stopped;
|
||||
String scriptFileName = vmName+ ".ps1";
|
||||
String newLine = System.getProperty("line.separator");
|
||||
String bootArgsDiskName = vmName+"-bootparams.vhd";
|
||||
String bootArgsDiskPath = "C:\\ProgramData\\Virtual Machine Manager Library Files\\VHDs\\"+bootArgsDiskName;
|
||||
|
||||
try {
|
||||
// mark VM as starting state so that sync() can know not to report stopped too early
|
||||
synchronized (_vms) {
|
||||
_vms.put(vmName, State.Starting);
|
||||
{
|
||||
// create and attach boot parameter disk
|
||||
String diskpartScriptName = vmName+"-Diskpart.txt";
|
||||
|
||||
StringBuilder cmdDiskpart = new StringBuilder("create vdisk file=\"");cmdDiskpart.append(bootArgsDiskPath.toCharArray());cmdDiskpart.append("\" maximum=10 type=expandable" + newLine);
|
||||
cmdDiskpart.append("select vdisk file=\"");cmdDiskpart.append(bootArgsDiskPath.toCharArray());cmdDiskpart.append("\"" + newLine);
|
||||
cmdDiskpart.append("attach vdisk" + newLine);
|
||||
cmdDiskpart.append("create partition primary" + newLine);
|
||||
cmdDiskpart.append("format fs=ntfs label=\"test vhd\" quick" + newLine);
|
||||
cmdDiskpart.append("assign letter="+vmName.toCharArray()[0]+ newLine);
|
||||
cmdDiskpart.append("attach vdisk" + newLine);
|
||||
|
||||
File f=new File(diskpartScriptName);
|
||||
FileOutputStream fop=new FileOutputStream(f);
|
||||
fop.write(cmdDiskpart.toString().getBytes());
|
||||
fop.flush();
|
||||
fop.close();
|
||||
|
||||
s_logger.info("Running diskpart attach command");
|
||||
Process p = Runtime.getRuntime().exec("cmd.exe /c diskpart.exe /s "+diskpartScriptName);
|
||||
p.getOutputStream().close();
|
||||
|
||||
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
|
||||
BufferedReader errreader = new BufferedReader(temperrReader);
|
||||
|
||||
if (errreader.ready()) {
|
||||
String errorOutput = new String("");
|
||||
while (true){
|
||||
String errline = errreader.readLine();
|
||||
if (errline == null) {
|
||||
break;
|
||||
}
|
||||
errorOutput = errorOutput + errline;
|
||||
}
|
||||
s_logger.info("errors found while running diskpart command: " + errorOutput);
|
||||
}
|
||||
|
||||
p.getErrorStream().close();
|
||||
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
|
||||
BufferedReader reader = new BufferedReader(tempReader);
|
||||
|
||||
String output = new String("");
|
||||
|
||||
while (true){
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
output = output + line;
|
||||
}
|
||||
p.getInputStream().close();
|
||||
s_logger.info("diskpart detahc command output: "+ output);
|
||||
}
|
||||
// wait for a while so that disk formatting is done
|
||||
Thread.sleep(60000);
|
||||
|
||||
//create boot args on the disk
|
||||
String bootArgs = vmSpec.getBootArgs();
|
||||
String Drive = vmName.substring(0,1);
|
||||
File fBootargs =new File(Drive+":\\cmdline");
|
||||
FileOutputStream fopBoot=new FileOutputStream(fBootargs);
|
||||
fopBoot.write(bootArgs.toString().getBytes());
|
||||
fopBoot.flush();
|
||||
fopBoot.close();
|
||||
|
||||
//detach the boot parameter disk
|
||||
{
|
||||
String diskpartDetachScriptName = vmName+"-Detach-Diskpart.txt";
|
||||
|
||||
StringBuilder cmdDetachDiskpart = new StringBuilder("select vdisk file=\"");
|
||||
cmdDetachDiskpart.append(bootArgsDiskPath.toCharArray());cmdDetachDiskpart.append("\"" + newLine);
|
||||
cmdDetachDiskpart.append("detach vdisk" + newLine);
|
||||
|
||||
File fd=new File(diskpartDetachScriptName);
|
||||
FileOutputStream fdop=new FileOutputStream(fd);
|
||||
fdop.write(cmdDetachDiskpart.toString().getBytes());
|
||||
fdop.flush();
|
||||
fdop.close();
|
||||
|
||||
s_logger.info("Running diskpart detach command");
|
||||
Process pd = Runtime.getRuntime().exec("cmd.exe /c diskpart.exe /s "+diskpartDetachScriptName);
|
||||
pd.getOutputStream().close();
|
||||
InputStreamReader temperrReader1 = new InputStreamReader(new BufferedInputStream(pd.getErrorStream()));
|
||||
BufferedReader errreader1 = new BufferedReader(temperrReader1);
|
||||
|
||||
if (errreader1.ready()) {
|
||||
String errorOutput = new String("");
|
||||
while (true){
|
||||
String errline = errreader1.readLine();
|
||||
if (errline == null) {
|
||||
break;
|
||||
}
|
||||
errorOutput = errorOutput + errline;
|
||||
}
|
||||
s_logger.info("errors found while running diskpart detach command: " + errorOutput);
|
||||
}
|
||||
|
||||
pd.getErrorStream().close();
|
||||
InputStreamReader tempReader1 = new InputStreamReader(new BufferedInputStream(pd.getInputStream()));
|
||||
BufferedReader reader1 = new BufferedReader(tempReader1);
|
||||
|
||||
String output1 = new String("");
|
||||
|
||||
while (true){
|
||||
String line = reader1.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
output1 = output1 + line;
|
||||
}
|
||||
|
||||
pd.getInputStream().close();
|
||||
s_logger.info("diskpart detach command output: "+ output1);
|
||||
}
|
||||
}
|
||||
|
||||
UUID id = UUID.randomUUID();
|
||||
String hwProfileId = id.toString();
|
||||
|
||||
StringBuilder cmdStr = new StringBuilder("Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager;" + newLine);
|
||||
cmdStr.append("Get-VMMServer -ComputerName localhost;" + newLine);
|
||||
cmdStr.append("$JobGroupId = [Guid]::NewGuid().ToString();" + newLine);
|
||||
cmdStr.append("$hwProfileId = [Guid]::NewGuid().ToString(); " + newLine);
|
||||
cmdStr.append("$CPUType = Get-CPUType -VMMServer localhost | where {$_.Name -eq " + "'1.20 GHz Athlon MP'}; " + newLine);
|
||||
cmdStr.append("$ISO = Get-ISO -VMMServer localhost | where { $_.Name -match \"systemvm\" }; " + newLine);
|
||||
cmdStr.append("$VMHost = Get-VMHost -VMMServer localhost | where {$_.Name -eq \"HYPERVHOST.hypervdc.intranet.lab.vmops.com\"}; " + newLine);
|
||||
cmdStr.append("$VNetwork = Get-VirtualNetwork -VMHost $VMHost -Name \"public\"; " + newLine);
|
||||
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
|
||||
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
|
||||
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
|
||||
cmdStr.append("New-VirtualDVDDrive -VMMServer localhost -JobGroup $JobGroupID -Bus 1 -LUN 0 -ISO $ISO ; " + newLine);
|
||||
cmdStr.append("New-HardwareProfile -VMMServer localhost -JobGroup $JobGroupID -Owner \"HYPERVDC\\Administrator\" -CPUType $CPUType -Name $hwProfileId");
|
||||
cmdStr.append(" -Description \"Profile used to create a VM/Template\"" +
|
||||
" -CPUCount 1 -MemoryMB 512 -RelativeWeight 100 -HighlyAvailable $true -NumLock $false -BootOrder \"CD\", " +
|
||||
"\"IdeHardDrive\", \"PxeBoot\", \"Floppy\" -LimitCPUFunctionality $false -LimitCPUForMigration $false; " + newLine);
|
||||
|
||||
cmdStr.append("$JobGroupId = [Guid]::NewGuid().ToString(); " + newLine);
|
||||
|
||||
//refresh library share
|
||||
cmdStr.append("$share = Get-LibraryShare;"+newLine);
|
||||
cmdStr.append("Refresh-LibraryShare -LibraryShare $share;"+newLine);
|
||||
|
||||
// create root disk
|
||||
cmdStr.append("$VirtualHardDisk1 = Get-VirtualHardDisk -VMMServer localhost | where {$_.Location -eq \"\\\\scvmm.hypervdc.intranet.lab.vmops.com\\MSSCVMMLibrary\\VHDs\\systemvm.vhd\"} | where {$_.HostName -eq \"scvmm.hypervdc.intranet.lab.vmops.com\"}" + newLine);
|
||||
cmdStr.append("New-VirtualDiskDrive -VMMServer localhost -JobGroup $JobGroupID -IDE -Bus 0 -LUN 0 -VirtualHardDisk $VirtualHardDisk1 -Filename \"");
|
||||
cmdStr.append(vmName.toCharArray());
|
||||
cmdStr.append("-systemvm.vhd\"; " + newLine);
|
||||
|
||||
// create boot param data disk
|
||||
cmdStr.append("$VirtualHardDisk2 = Get-VirtualHardDisk -VMMServer localhost " +
|
||||
" | where {$_.Location -eq \"\\\\scvmm.hypervdc.intranet.lab.vmops.com\\MSSCVMMLibrary\\VHDs\\");
|
||||
cmdStr.append(bootArgsDiskName.toCharArray());
|
||||
cmdStr.append("\" } | where {$_.HostName -eq \"scvmm.hypervdc.intranet.lab.vmops.com\"}" + newLine);
|
||||
cmdStr.append("New-VirtualDiskDrive -VMMServer localhost -JobGroup $JobGroupID -IDE -Bus 0 -LUN 1 -VirtualHardDisk $VirtualHardDisk2 -Filename \"");
|
||||
cmdStr.append(bootArgsDiskName.toCharArray());
|
||||
cmdStr.append("\";"+newLine);
|
||||
|
||||
cmdStr.append("$HardwareProfile = Get-HardwareProfile -VMMServer localhost | where {$_.Name -eq $hwProfileId};" + newLine);
|
||||
cmdStr.append("$OperatingSystem = Get-OperatingSystem -VMMServer localhost | where {$_.Name -eq 'Other Linux (32 bit)'};" + newLine);
|
||||
|
||||
cmdStr.append("New-VM -VMMServer localhost -Name \"");
|
||||
cmdStr.append(vmName.toCharArray());
|
||||
|
||||
cmdStr.append("\" -Description \"\" -Owner \"HYPERVDC\\Administrator\" -VMHost $VMHost -Path \"C:\\ClusterStorage\\Volume1\" -HardwareProfile $HardwareProfile " +
|
||||
" -JobGroup $JobGroupID" +
|
||||
" -OperatingSystem $OperatingSystem -RunAsSystem -StartVM -StartAction NeverAutoTurnOnVM -StopAction SaveVM;" + newLine);
|
||||
|
||||
File f=new File(scriptFileName);
|
||||
FileOutputStream fop=new FileOutputStream(f);
|
||||
fop.write(cmdStr.toString().getBytes());
|
||||
fop.flush();
|
||||
fop.close();
|
||||
s_logger.info("Running command: " + cmdStr);
|
||||
Process p = Runtime.getRuntime().exec("cmd.exe /c Powershell -Command \" & '.\\" + scriptFileName +"'\"");
|
||||
p.getOutputStream().close();
|
||||
|
||||
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
|
||||
BufferedReader errreader = new BufferedReader(temperrReader);
|
||||
|
||||
if (errreader.ready()) {
|
||||
String errorOutput = new String("");
|
||||
while (true){
|
||||
String errline = errreader.readLine();
|
||||
if (errline == null) {
|
||||
break;
|
||||
}
|
||||
errorOutput = errorOutput + errline;
|
||||
}
|
||||
s_logger.info("errors found while running cmdlet to create VM: " + errorOutput);
|
||||
}
|
||||
|
||||
p.getErrorStream().close();
|
||||
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
|
||||
BufferedReader reader = new BufferedReader(tempReader);
|
||||
|
||||
String output = new String("");
|
||||
|
||||
while (true){
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
output = output + line;
|
||||
}
|
||||
p.getInputStream().close();
|
||||
|
||||
s_logger.info("vm create cmmdlet output: "+ output);
|
||||
|
||||
if (output.contains("FullyQualifiedErrorId") || output.contains("Error") || output.contains("Exception")) {
|
||||
s_logger.info("No errors found in running cmdlet "+ cmdStr.toString());
|
||||
return new StartAnswer(cmd, "Failed to start VM");
|
||||
}
|
||||
|
||||
state = State.Running;
|
||||
return new StartAnswer(cmd);
|
||||
} catch (Exception e){
|
||||
return new StartAnswer(cmd, "Failed to start VM");
|
||||
} finally {
|
||||
//delete the PS script file
|
||||
//File f=new File(".\\"+scriptFileName);
|
||||
//f.delete();
|
||||
synchronized (_vms) {
|
||||
if (state != State.Stopped) {
|
||||
_vms.put(vmName, state);
|
||||
} else {
|
||||
_vms.remove(vmName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(DhcpEntryCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource DhcpEntryCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
String args = " " + cmd.getVmMac();
|
||||
args += " " + cmd.getVmIpAddress();
|
||||
args += " " + cmd.getVmName();
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args);
|
||||
}
|
||||
|
||||
try {
|
||||
Pair<Boolean, String> result = SshHelper.sshExecute(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP), DEFAULT_DOMR_SSHPORT, "root",
|
||||
new File("id_rsa.cloud"), null, "/root/edithosts.sh " + args);
|
||||
|
||||
if (!result.first()) {
|
||||
s_logger.error("dhcp_entry command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)
|
||||
+ " failed, message: " + result.second());
|
||||
|
||||
return new Answer(cmd, false, "DhcpEntry failed due to " + result.second());
|
||||
}
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("dhcp_entry command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("Unexpected exception ", e);
|
||||
return new Answer(cmd, false, "DhcpEntry failed due to exception");
|
||||
}
|
||||
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
protected CheckSshAnswer execute(CheckSshCommand cmd) {
|
||||
String vmName = cmd.getName();
|
||||
String privateIp = cmd.getIp();
|
||||
int cmdPort = cmd.getPort();
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Ping VM:" + cmd.getName() + " IP:" + privateIp + " port:" + cmdPort);
|
||||
}
|
||||
return new CheckSshAnswer(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgentControl(IAgentControl agentControl) {
|
||||
this.agentControl = agentControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
|
||||
s_logger.info("recieved initialize request for cluster:" + _clusterId);
|
||||
List<String> vmHostList = getHostsInCluster(_clusterId);
|
||||
|
||||
if (vmHostList.size() == 0) {
|
||||
s_logger.info("cluster is not recognized or zero instances in the cluster");
|
||||
}
|
||||
|
||||
StartupCommand[] answerCmds = new StartupCommand[vmHostList.size()];
|
||||
|
||||
int index =0;
|
||||
for (String hostName: vmHostList) {
|
||||
s_logger.info("Node :" + hostName);
|
||||
StartupRoutingCommand cmd = new StartupRoutingCommand();
|
||||
answerCmds[index] = cmd;
|
||||
fillHostInfo(cmd,hostName);
|
||||
index++;
|
||||
}
|
||||
|
||||
s_logger.info("response sent to initialize request for cluster:" + _clusterId);
|
||||
return answerCmds;
|
||||
}
|
||||
|
||||
protected void fillHostInfo(StartupRoutingCommand cmd, String hostName) {
|
||||
|
||||
Map<String, String> details = cmd.getHostDetails();
|
||||
if (details == null) {
|
||||
details = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
try {
|
||||
fillHostHardwareInfo(cmd);
|
||||
fillHostNetworkInfo(cmd);
|
||||
fillHostDetailsInfo(details);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Exception while retrieving host info ", e);
|
||||
throw new CloudRuntimeException("Exception while retrieving host info");
|
||||
}
|
||||
|
||||
cmd.setName(hostName);
|
||||
cmd.setHostDetails(details);
|
||||
cmd.setGuid(_guid);
|
||||
cmd.setDataCenter(_dcId);
|
||||
cmd.setPod(_podId);
|
||||
cmd.setCluster(_clusterId);
|
||||
cmd.setHypervisorType(HypervisorType.Hyperv);
|
||||
}
|
||||
|
||||
private void fillHostDetailsInfo(Map<String, String> details) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
private Answer execute(GetHostStatsCommand cmd) {
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource GetHostStatsCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
try {
|
||||
// FIXME: get the actual host stats by running powershell cmdlet. This is just for prototype.
|
||||
HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), 0, 10000, 10000,
|
||||
"host", 2*1024*1024, 1*1024*1024, 1*1024*1024, 0);
|
||||
s_logger.info("returning stats :" + 2*1024*1024 + " " + 1*1024*1024 + " " + 1*1024*1024);
|
||||
return new GetHostStatsAnswer(cmd, hostStats);
|
||||
} catch (Exception e) {
|
||||
HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), 0, 0, 0,
|
||||
"host", 0, 0, 0, 0);
|
||||
String msg = "Unable to execute GetHostStatsCommand due to exception " + e.getMessage();
|
||||
s_logger.error(msg, e);
|
||||
return new GetHostStatsAnswer(cmd, hostStats);
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(ModifyStoragePoolCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource ModifyStoragePoolCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
try {
|
||||
StorageFilerTO pool = cmd.getPool();
|
||||
s_logger.info("Primary storage pool details: " + pool.getHost() + " " + pool.getPath());
|
||||
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
|
||||
// FIXME: get the actual storage capacity and storage stats of CSV volume
|
||||
// by running powershell cmdlet. This hardcoding just for prototype.
|
||||
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
|
||||
1024*1024*1024*1024L, 512*1024*1024*1024L, tInfo);
|
||||
|
||||
return answer;
|
||||
} catch (Throwable e) {
|
||||
return new Answer(cmd, false, "Unable to execute ModifyStoragePoolCommand due to exception " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(GetStorageStatsCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing GetStorageStatsCommand command: " + _gson.toJson(cmd));
|
||||
}
|
||||
// FIXME: get the actual storage capacity and storage stats of CSV volume
|
||||
return new GetStorageStatsAnswer(cmd, 1024*1024*1024*1024L, 512*1024*1024*1024L);
|
||||
}
|
||||
|
||||
private void fillHostHardwareInfo(StartupRoutingCommand cmd) throws RemoteException {
|
||||
try {
|
||||
// FIXME: get the actual host capacity by running cmdlet.This hardcoding just for prototype
|
||||
cmd.setCaps("hvm");
|
||||
cmd.setDom0MinMemory(0);
|
||||
cmd.setSpeed(100000);
|
||||
cmd.setCpus(6);
|
||||
long ram = new Long("211642163904");
|
||||
cmd.setMemory(ram);
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("Unable to query host network info due to exception ", e);
|
||||
throw new CloudRuntimeException("Unable to query host network info due to exception");
|
||||
}
|
||||
}
|
||||
|
||||
private void fillHostNetworkInfo(StartupRoutingCommand cmd) throws RemoteException {
|
||||
try {
|
||||
// FIXME: get the actual host and storage IP by running cmdlet.This hardcoding just for prototype
|
||||
cmd.setPrivateIpAddress("192.168.154.236");
|
||||
cmd.setPrivateNetmask("255.255.255.0");
|
||||
cmd.setPrivateMacAddress("00:16:3e:77:e2:a0");
|
||||
|
||||
cmd.setStorageIpAddress("192.168.154.36");
|
||||
cmd.setStorageNetmask("255.255.255.0");
|
||||
cmd.setStorageMacAddress("00:16:3e:77:e2:a0");
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("Unable to query host network info due to exception ", e);
|
||||
throw new CloudRuntimeException("Unable to query host network info due to exception");
|
||||
}
|
||||
}
|
||||
|
||||
private List <String> getHostsInCluster(String clusterName)
|
||||
{
|
||||
List<String> hypervHosts = new ArrayList<String>();
|
||||
|
||||
try {
|
||||
//StringBuilder cmd = new StringBuilder("cmd /c powershell.exe -OutputFormat XML ");
|
||||
StringBuilder cmd = new StringBuilder("cmd /c powershell.exe ");
|
||||
cmd.append("-Command Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager; ");
|
||||
cmd.append("Get-VMMServer -ComputerName localhost; ");
|
||||
cmd.append("Get-VMHostCluster ");
|
||||
cmd.append(clusterName.toCharArray());
|
||||
|
||||
Process p = Runtime.getRuntime().exec(cmd.toString());
|
||||
p.getOutputStream().close();
|
||||
|
||||
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
|
||||
BufferedReader errreader = new BufferedReader(temperrReader);
|
||||
if (errreader.ready()) {
|
||||
String errorOutput = new String("");
|
||||
s_logger.info("errors found while running cmdlet Get-VMHostCluster");
|
||||
while (true){
|
||||
String errline = errreader.readLine();
|
||||
if (errline == null) {
|
||||
break;
|
||||
}
|
||||
errorOutput = errorOutput + errline;
|
||||
}
|
||||
s_logger.info(errorOutput);
|
||||
} else {
|
||||
s_logger.info("No errors found in running cmdlet:" + cmd);
|
||||
}
|
||||
|
||||
p.getErrorStream().close();
|
||||
/*
|
||||
InputStream in = (InputStream) p.getInputStream();
|
||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader parser = factory.createXMLStreamReader(in);
|
||||
|
||||
while(parser.hasNext()) {
|
||||
|
||||
int eventType = parser.next();
|
||||
switch (eventType) {
|
||||
|
||||
case START_ELEMENT:
|
||||
// Do something
|
||||
break;
|
||||
case END_ELEMENT:
|
||||
// Do something
|
||||
break;
|
||||
// And so on ...
|
||||
}
|
||||
}
|
||||
parser.close();
|
||||
*/
|
||||
|
||||
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
|
||||
BufferedReader reader = new BufferedReader(tempReader);
|
||||
|
||||
String output = new String("");
|
||||
|
||||
while (true){
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
output = output + line;
|
||||
}
|
||||
|
||||
String nodesListStr = output.substring(output.indexOf("Nodes"));
|
||||
nodesListStr = nodesListStr.substring(nodesListStr.indexOf('{', 0)+1, nodesListStr.indexOf('}', 0));
|
||||
String[] nodesList = nodesListStr.split(",");
|
||||
|
||||
for (String node : nodesList) {
|
||||
hypervHosts.add(node);
|
||||
}
|
||||
|
||||
p.getInputStream().close();
|
||||
} catch (Exception e)
|
||||
{
|
||||
s_logger.info("Exception caught: "+e.getMessage());
|
||||
}
|
||||
return hypervHosts;
|
||||
}
|
||||
|
||||
protected HashMap<String, State> sync() {
|
||||
HashMap<String, State> changes = new HashMap<String, State>();
|
||||
|
||||
try {
|
||||
synchronized (_vms) {
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("Unable to perform sync information collection process at this point due to exception ", e);
|
||||
return null;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(long id) {
|
||||
HashMap<String, State> newStates = sync();
|
||||
if (newStates == null) {
|
||||
newStates = new HashMap<String, State>();
|
||||
}
|
||||
PingRoutingCommand cmd = new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id, newStates);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
|
||||
_dcId = params.get("zone").toString();
|
||||
_podId= params.get("pod").toString();
|
||||
_clusterId = params.get("cluster").toString();
|
||||
_guid = params.get("guid").toString();
|
||||
|
||||
boolean success = super.configure(name, params);
|
||||
if (! success) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScriptsDir() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,989 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.network.resource;
|
||||
|
||||
import iControl.CommonEnabledState;
|
||||
import iControl.CommonIPPortDefinition;
|
||||
import iControl.CommonStatistic;
|
||||
import iControl.CommonStatisticType;
|
||||
import iControl.CommonVirtualServerDefinition;
|
||||
import iControl.Interfaces;
|
||||
import iControl.LocalLBLBMethod;
|
||||
import iControl.LocalLBNodeAddressBindingStub;
|
||||
import iControl.LocalLBPoolBindingStub;
|
||||
import iControl.LocalLBProfileContextType;
|
||||
import iControl.LocalLBVirtualServerBindingStub;
|
||||
import iControl.LocalLBVirtualServerVirtualServerPersistence;
|
||||
import iControl.LocalLBVirtualServerVirtualServerProfile;
|
||||
import iControl.LocalLBVirtualServerVirtualServerResource;
|
||||
import iControl.LocalLBVirtualServerVirtualServerStatisticEntry;
|
||||
import iControl.LocalLBVirtualServerVirtualServerStatistics;
|
||||
import iControl.LocalLBVirtualServerVirtualServerType;
|
||||
import iControl.NetworkingMemberTagType;
|
||||
import iControl.NetworkingMemberType;
|
||||
import iControl.NetworkingRouteDomainBindingStub;
|
||||
import iControl.NetworkingSelfIPBindingStub;
|
||||
import iControl.NetworkingVLANBindingStub;
|
||||
import iControl.NetworkingVLANMemberEntry;
|
||||
import iControl.SystemConfigSyncBindingStub;
|
||||
import iControl.SystemConfigSyncSaveMode;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.IAgentControl;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer;
|
||||
import com.cloud.agent.api.ExternalNetworkResourceUsageCommand;
|
||||
import com.cloud.agent.api.MaintainAnswer;
|
||||
import com.cloud.agent.api.MaintainCommand;
|
||||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.ReadyAnswer;
|
||||
import com.cloud.agent.api.ReadyCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocAnswer;
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.routing.NetworkElementCommand;
|
||||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.exception.ExecutionException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
public class F5BigIpResource implements ServerResource {
|
||||
|
||||
private enum LbAlgorithm {
|
||||
RoundRobin(null, LocalLBLBMethod.LB_METHOD_ROUND_ROBIN),
|
||||
LeastConn(null, LocalLBLBMethod.LB_METHOD_LEAST_CONNECTION_MEMBER);
|
||||
|
||||
String persistenceProfileName;
|
||||
LocalLBLBMethod method;
|
||||
|
||||
LbAlgorithm(String persistenceProfileName, LocalLBLBMethod method) {
|
||||
this.persistenceProfileName = persistenceProfileName;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getPersistenceProfileName() {
|
||||
return persistenceProfileName;
|
||||
}
|
||||
|
||||
public LocalLBLBMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
private enum LbProtocol {
|
||||
tcp,
|
||||
udp;
|
||||
}
|
||||
|
||||
private String _name;
|
||||
private String _zoneId;
|
||||
private String _ip;
|
||||
private String _username;
|
||||
private String _password;
|
||||
private String _publicInterface;
|
||||
private String _privateInterface;
|
||||
private Integer _numRetries;
|
||||
private String _guid;
|
||||
private boolean _inline;
|
||||
|
||||
private Interfaces _interfaces;
|
||||
private LocalLBVirtualServerBindingStub _virtualServerApi;
|
||||
private LocalLBPoolBindingStub _loadbalancerApi;
|
||||
private LocalLBNodeAddressBindingStub _nodeApi;
|
||||
private NetworkingVLANBindingStub _vlanApi;
|
||||
private NetworkingSelfIPBindingStub _selfIpApi;
|
||||
private NetworkingRouteDomainBindingStub _routeDomainApi;
|
||||
private SystemConfigSyncBindingStub _configSyncApi;
|
||||
private String _objectNamePathSep = "-";
|
||||
private String _routeDomainIdentifier = "%";
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(F5BigIpResource.class);
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
try {
|
||||
XTrustProvider.install();
|
||||
|
||||
_name = (String) params.get("name");
|
||||
if (_name == null) {
|
||||
throw new ConfigurationException("Unable to find name");
|
||||
}
|
||||
|
||||
_zoneId = (String) params.get("zoneId");
|
||||
if (_zoneId == null) {
|
||||
throw new ConfigurationException("Unable to find zone");
|
||||
}
|
||||
|
||||
_ip = (String) params.get("ip");
|
||||
if (_ip == null) {
|
||||
throw new ConfigurationException("Unable to find IP");
|
||||
}
|
||||
|
||||
_username = (String) params.get("username");
|
||||
if (_username == null) {
|
||||
throw new ConfigurationException("Unable to find username");
|
||||
}
|
||||
|
||||
_password = (String) params.get("password");
|
||||
if (_password == null) {
|
||||
throw new ConfigurationException("Unable to find password");
|
||||
}
|
||||
|
||||
_publicInterface = (String) params.get("publicInterface");
|
||||
if (_publicInterface == null) {
|
||||
throw new ConfigurationException("Unable to find public interface");
|
||||
}
|
||||
|
||||
_privateInterface = (String) params.get("privateInterface");
|
||||
if (_privateInterface == null) {
|
||||
throw new ConfigurationException("Unable to find private interface");
|
||||
}
|
||||
|
||||
_numRetries = NumbersUtil.parseInt((String) params.get("numRetries"), 1);
|
||||
|
||||
_guid = (String)params.get("guid");
|
||||
if (_guid == null) {
|
||||
throw new ConfigurationException("Unable to find the guid");
|
||||
}
|
||||
|
||||
_inline = Boolean.parseBoolean((String) params.get("inline"));
|
||||
|
||||
if (!login()) {
|
||||
throw new ExecutionException("Failed to login to the F5 BigIp.");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand();
|
||||
cmd.setName(_name);
|
||||
cmd.setDataCenter(_zoneId);
|
||||
cmd.setPod("");
|
||||
cmd.setPrivateIpAddress(_ip);
|
||||
cmd.setStorageIpAddress("");
|
||||
cmd.setVersion("");
|
||||
cmd.setGuid(_guid);
|
||||
return new StartupCommand[]{cmd};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Host.Type getType() {
|
||||
return Host.Type.ExternalLoadBalancer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(final long id) {
|
||||
return new PingCommand(Host.Type.ExternalLoadBalancer, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAgentControl getAgentControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgentControl(IAgentControl agentControl) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
return executeRequest(cmd, _numRetries);
|
||||
}
|
||||
|
||||
private Answer executeRequest(Command cmd, int numRetries) {
|
||||
if (cmd instanceof ReadyCommand) {
|
||||
return execute((ReadyCommand) cmd);
|
||||
} else if (cmd instanceof MaintainCommand) {
|
||||
return execute((MaintainCommand) cmd);
|
||||
} else if (cmd instanceof IpAssocCommand) {
|
||||
return execute((IpAssocCommand) cmd, numRetries);
|
||||
} else if (cmd instanceof LoadBalancerConfigCommand) {
|
||||
return execute((LoadBalancerConfigCommand) cmd, numRetries);
|
||||
} else if (cmd instanceof ExternalNetworkResourceUsageCommand) {
|
||||
return execute((ExternalNetworkResourceUsageCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
private Answer retry(Command cmd, int numRetries) {
|
||||
int numRetriesRemaining = numRetries - 1;
|
||||
s_logger.error("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetriesRemaining);
|
||||
return executeRequest(cmd, numRetriesRemaining);
|
||||
}
|
||||
|
||||
private boolean shouldRetry(int numRetries) {
|
||||
return (numRetries > 0 && login());
|
||||
}
|
||||
|
||||
private Answer execute(ReadyCommand cmd) {
|
||||
return new ReadyAnswer(cmd);
|
||||
}
|
||||
|
||||
private Answer execute(MaintainCommand cmd) {
|
||||
return new MaintainAnswer(cmd);
|
||||
}
|
||||
|
||||
private synchronized Answer execute(IpAssocCommand cmd, int numRetries) {
|
||||
String[] results = new String[cmd.getIpAddresses().length];
|
||||
int i = 0;
|
||||
try {
|
||||
IpAddressTO[] ips = cmd.getIpAddresses();
|
||||
for (IpAddressTO ip : ips) {
|
||||
long guestVlanTag = Long.valueOf(ip.getVlanId());
|
||||
String vlanSelfIp = _inline ? tagAddressWithRouteDomain(ip.getVlanGateway(), guestVlanTag) : ip.getVlanGateway();
|
||||
String vlanNetmask = ip.getVlanNetmask();
|
||||
|
||||
// Delete any existing guest VLAN with this tag, self IP, and netmask
|
||||
deleteGuestVlan(guestVlanTag, vlanSelfIp, vlanNetmask);
|
||||
|
||||
if (ip.isAdd()) {
|
||||
// Add a new guest VLAN
|
||||
addGuestVlan(guestVlanTag, vlanSelfIp, vlanNetmask);
|
||||
}
|
||||
|
||||
saveConfiguration();
|
||||
results[i++] = ip.getPublicIp() + " - success";
|
||||
}
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("Failed to execute IPAssocCommand due to " + e);
|
||||
|
||||
if (shouldRetry(numRetries)) {
|
||||
return retry(cmd, numRetries);
|
||||
} else {
|
||||
results[i++] = IpAssocAnswer.errorResult;
|
||||
}
|
||||
}
|
||||
|
||||
return new IpAssocAnswer(cmd, results);
|
||||
}
|
||||
|
||||
private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) {
|
||||
try {
|
||||
long guestVlanTag = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG));
|
||||
LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
|
||||
for (LoadBalancerTO loadBalancer : loadBalancers) {
|
||||
LbProtocol lbProtocol;
|
||||
try {
|
||||
if (loadBalancer.getProtocol() == null) {
|
||||
lbProtocol = LbProtocol.tcp;
|
||||
} else {
|
||||
lbProtocol = LbProtocol.valueOf(loadBalancer.getProtocol());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ExecutionException("Got invalid protocol: " + loadBalancer.getProtocol());
|
||||
}
|
||||
|
||||
LbAlgorithm lbAlgorithm;
|
||||
if (loadBalancer.getAlgorithm().equals("roundrobin")) {
|
||||
lbAlgorithm = LbAlgorithm.RoundRobin;
|
||||
} else if (loadBalancer.getAlgorithm().equals("leastconn")) {
|
||||
lbAlgorithm = LbAlgorithm.LeastConn;
|
||||
} else {
|
||||
throw new ExecutionException("Got invalid algorithm: " + loadBalancer.getAlgorithm());
|
||||
}
|
||||
|
||||
String srcIp = _inline ? tagAddressWithRouteDomain(loadBalancer.getSrcIp(), guestVlanTag) : loadBalancer.getSrcIp();
|
||||
int srcPort = loadBalancer.getSrcPort();
|
||||
String virtualServerName = genVirtualServerName(lbProtocol, srcIp, srcPort);
|
||||
|
||||
boolean destinationsToAdd = false;
|
||||
for (DestinationTO destination : loadBalancer.getDestinations()) {
|
||||
if (!destination.isRevoked()) {
|
||||
destinationsToAdd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadBalancer.isRevoked() && destinationsToAdd) {
|
||||
// Add the pool
|
||||
addPool(virtualServerName, lbAlgorithm);
|
||||
|
||||
// Add pool members
|
||||
List<String> activePoolMembers = new ArrayList<String>();
|
||||
for (DestinationTO destination : loadBalancer.getDestinations()) {
|
||||
if (!destination.isRevoked()) {
|
||||
String destIp = _inline ? tagAddressWithRouteDomain(destination.getDestIp(), guestVlanTag) : destination.getDestIp();
|
||||
addPoolMember(virtualServerName, destIp, destination.getDestPort());
|
||||
activePoolMembers.add(destIp + "-" + destination.getDestPort());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any pool members that aren't in the current list of destinations
|
||||
deleteInactivePoolMembers(virtualServerName, activePoolMembers);
|
||||
|
||||
// Add the virtual server
|
||||
addVirtualServer(virtualServerName, lbProtocol, srcIp, srcPort);
|
||||
} else {
|
||||
// Delete the virtual server with this protocol, source IP, and source port, along with its default pool and all pool members
|
||||
deleteVirtualServerAndDefaultPool(virtualServerName);
|
||||
}
|
||||
}
|
||||
|
||||
saveConfiguration();
|
||||
return new Answer(cmd);
|
||||
} catch (ExecutionException e) {
|
||||
s_logger.error("Failed to execute LoadBalancerConfigCommand due to " + e);
|
||||
|
||||
if (shouldRetry(numRetries)) {
|
||||
return retry(cmd, numRetries);
|
||||
} else {
|
||||
return new Answer(cmd, e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
|
||||
try {
|
||||
return getIpBytesSentAndReceived(cmd);
|
||||
} catch (ExecutionException e) {
|
||||
return new ExternalNetworkResourceUsageAnswer(cmd, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveConfiguration() throws ExecutionException {
|
||||
try {
|
||||
_configSyncApi.save_configuration("", SystemConfigSyncSaveMode.SAVE_BASE_LEVEL_CONFIG);
|
||||
_configSyncApi.save_configuration("", SystemConfigSyncSaveMode.SAVE_HIGH_LEVEL_CONFIG);
|
||||
s_logger.debug("Successfully saved F5 BigIp configuration.");
|
||||
} catch (RemoteException e) {
|
||||
s_logger.error("Failed to save F5 BigIp configuration due to: " + e);
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void addGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException {
|
||||
try {
|
||||
String vlanName = genVlanName(vlanTag);
|
||||
List<String> allVlans = getVlans();
|
||||
if (!allVlans.contains(vlanName)) {
|
||||
String[] vlanNames = genStringArray(vlanName);
|
||||
long[] vlanTags = genLongArray(vlanTag);
|
||||
CommonEnabledState[] commonEnabledState = {CommonEnabledState.STATE_DISABLED};
|
||||
|
||||
// Create the interface name
|
||||
NetworkingVLANMemberEntry[][] vlanMemberEntries = {{new NetworkingVLANMemberEntry()}};
|
||||
vlanMemberEntries[0][0].setMember_type(NetworkingMemberType.MEMBER_INTERFACE);
|
||||
vlanMemberEntries[0][0].setTag_state(NetworkingMemberTagType.MEMBER_TAGGED);
|
||||
vlanMemberEntries[0][0].setMember_name(_privateInterface);
|
||||
|
||||
s_logger.debug("Creating a guest VLAN with tag " + vlanTag);
|
||||
_vlanApi.create(vlanNames, vlanTags, vlanMemberEntries, commonEnabledState, new long[]{10L}, new String[]{"00:00:00:00:00:00"});
|
||||
|
||||
if (!getVlans().contains(vlanName)) {
|
||||
throw new ExecutionException("Failed to create vlan with tag " + vlanTag);
|
||||
}
|
||||
}
|
||||
|
||||
if (_inline) {
|
||||
List<Long> allRouteDomains = getRouteDomains();
|
||||
if (!allRouteDomains.contains(vlanTag)) {
|
||||
long[] routeDomainIds = genLongArray(vlanTag);
|
||||
String[][] vlanNames = new String[][]{genStringArray(genVlanName(vlanTag))};
|
||||
|
||||
s_logger.debug("Creating route domain " + vlanTag);
|
||||
_routeDomainApi.create(routeDomainIds, vlanNames);
|
||||
|
||||
if (!getRouteDomains().contains(vlanTag)) {
|
||||
throw new ExecutionException("Failed to create route domain " + vlanTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> allSelfIps = getSelfIps();
|
||||
if (!allSelfIps.contains(vlanSelfIp)) {
|
||||
String[] selfIpsToCreate = genStringArray(vlanSelfIp);
|
||||
String[] vlans = genStringArray(vlanName);
|
||||
String[] netmasks = genStringArray(vlanNetmask);
|
||||
long[] unitIds = genLongArray(0L);
|
||||
CommonEnabledState[] enabledStates = new CommonEnabledState[]{CommonEnabledState.STATE_DISABLED};
|
||||
|
||||
s_logger.debug("Creating self IP " + vlanSelfIp);
|
||||
_selfIpApi.create(selfIpsToCreate, vlans, netmasks, unitIds, enabledStates);
|
||||
|
||||
if (!getSelfIps().contains(vlanSelfIp)) {
|
||||
throw new ExecutionException("Failed to create self IP " + vlanSelfIp);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
s_logger.error(e);
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void deleteGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException {
|
||||
try {
|
||||
// Delete all virtual servers and pools that use this guest VLAN
|
||||
deleteVirtualServersInGuestVlan(vlanSelfIp, vlanNetmask);
|
||||
|
||||
List<String> allSelfIps = getSelfIps();
|
||||
if (allSelfIps.contains(vlanSelfIp)) {
|
||||
s_logger.debug("Deleting self IP " + vlanSelfIp);
|
||||
_selfIpApi.delete_self_ip(genStringArray(vlanSelfIp));
|
||||
|
||||
if (getSelfIps().contains(vlanSelfIp)) {
|
||||
throw new ExecutionException("Failed to delete self IP " + vlanSelfIp);
|
||||
}
|
||||
}
|
||||
|
||||
if (_inline) {
|
||||
List<Long> allRouteDomains = getRouteDomains();
|
||||
if (allRouteDomains.contains(vlanTag)) {
|
||||
s_logger.debug("Deleting route domain " + vlanTag);
|
||||
_routeDomainApi.delete_route_domain(genLongArray(vlanTag));
|
||||
|
||||
if (getRouteDomains().contains(vlanTag)) {
|
||||
throw new ExecutionException("Failed to delete route domain " + vlanTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String vlanName = genVlanName(vlanTag);
|
||||
List<String> allVlans = getVlans();
|
||||
if (allVlans.contains(vlanName)) {
|
||||
_vlanApi.delete_vlan(genStringArray(vlanName));
|
||||
|
||||
if (getVlans().contains(vlanName)) {
|
||||
throw new ExecutionException("Failed to delete VLAN with tag: " + vlanTag);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteVirtualServersInGuestVlan(String vlanSelfIp, String vlanNetmask) throws ExecutionException {
|
||||
vlanSelfIp = stripRouteDomainFromAddress(vlanSelfIp);
|
||||
List<String> virtualServersToDelete = new ArrayList<String>();
|
||||
|
||||
List<String> allVirtualServers = getVirtualServers();
|
||||
for (String virtualServerName : allVirtualServers) {
|
||||
// Check if the virtual server's default pool has members in this guest VLAN
|
||||
List<String> poolMembers = getMembers(virtualServerName);
|
||||
for (String poolMemberName : poolMembers) {
|
||||
String poolMemberIp = stripRouteDomainFromAddress(getIpAndPort(poolMemberName)[0]);
|
||||
if (NetUtils.sameSubnet(vlanSelfIp, poolMemberIp, vlanNetmask)) {
|
||||
virtualServersToDelete.add(virtualServerName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String virtualServerName : virtualServersToDelete) {
|
||||
s_logger.debug("Found a virtual server (" + virtualServerName + ") for guest network with self IP " + vlanSelfIp + " that is active when the guest network is being destroyed.");
|
||||
deleteVirtualServerAndDefaultPool(virtualServerName);
|
||||
}
|
||||
}
|
||||
|
||||
private String genVlanName(long vlanTag) {
|
||||
return "vlan-" + String.valueOf(vlanTag);
|
||||
}
|
||||
|
||||
private List<Long> getRouteDomains() throws ExecutionException {
|
||||
try {
|
||||
List<Long> routeDomains = new ArrayList<Long>();
|
||||
long[] routeDomainsArray = _routeDomainApi.get_list();
|
||||
|
||||
for (long routeDomainName : routeDomainsArray) {
|
||||
routeDomains.add(routeDomainName);
|
||||
}
|
||||
|
||||
return routeDomains;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getSelfIps() throws ExecutionException {
|
||||
try {
|
||||
List<String> selfIps = new ArrayList<String>();
|
||||
String[] selfIpsArray = _selfIpApi.get_list();
|
||||
|
||||
for (String selfIp : selfIpsArray) {
|
||||
selfIps.add(selfIp);
|
||||
}
|
||||
|
||||
return selfIps;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getVlans() throws ExecutionException {
|
||||
try {
|
||||
List<String> vlans = new ArrayList<String>();
|
||||
String[] vlansArray = _vlanApi.get_list();
|
||||
|
||||
for (String vlan : vlansArray) {
|
||||
vlans.add(vlan);
|
||||
}
|
||||
|
||||
return vlans;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Login
|
||||
|
||||
private boolean login() {
|
||||
try {
|
||||
_interfaces = new Interfaces();
|
||||
|
||||
if (!_interfaces.initialize(_ip, _username, _password)) {
|
||||
throw new ExecutionException("Failed to log in to BigIp appliance");
|
||||
}
|
||||
|
||||
_virtualServerApi = _interfaces.getLocalLBVirtualServer();
|
||||
_loadbalancerApi = _interfaces.getLocalLBPool();
|
||||
_nodeApi = _interfaces.getLocalLBNodeAddress();
|
||||
_vlanApi = _interfaces.getNetworkingVLAN();
|
||||
_selfIpApi = _interfaces.getNetworkingSelfIP();
|
||||
_routeDomainApi = _interfaces.getNetworkingRouteDomain();
|
||||
_configSyncApi = _interfaces.getSystemConfigSync();
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Virtual server methods
|
||||
|
||||
private void addVirtualServer(String virtualServerName, LbProtocol protocol, String srcIp, int srcPort) throws ExecutionException {
|
||||
try {
|
||||
if (!virtualServerExists(virtualServerName)) {
|
||||
s_logger.debug("Adding virtual server " + virtualServerName);
|
||||
_virtualServerApi.create(genVirtualServerDefinition(virtualServerName, protocol, srcIp, srcPort), new String[]{"255.255.255.255"}, genVirtualServerResource(virtualServerName), genVirtualServerProfile(protocol));
|
||||
_virtualServerApi.set_snat_automap(genStringArray(virtualServerName));
|
||||
|
||||
if (!virtualServerExists(virtualServerName)) {
|
||||
throw new ExecutionException("Failed to add virtual server " + virtualServerName);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteVirtualServerAndDefaultPool(String virtualServerName) throws ExecutionException {
|
||||
try {
|
||||
if (virtualServerExists(virtualServerName)) {
|
||||
// Delete the default pool's members
|
||||
List<String> poolMembers = getMembers(virtualServerName);
|
||||
for (String poolMember : poolMembers) {
|
||||
String[] destIpAndPort = getIpAndPort(poolMember);
|
||||
deletePoolMember(virtualServerName, destIpAndPort[0], Integer.valueOf(destIpAndPort[1]));
|
||||
}
|
||||
|
||||
// Delete the virtual server
|
||||
s_logger.debug("Deleting virtual server " + virtualServerName);
|
||||
_virtualServerApi.delete_virtual_server(genStringArray(virtualServerName));
|
||||
|
||||
if (getVirtualServers().contains(virtualServerName)) {
|
||||
throw new ExecutionException("Failed to delete virtual server " + virtualServerName);
|
||||
}
|
||||
|
||||
// Delete the default pool
|
||||
deletePool(virtualServerName);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String genVirtualServerName(LbProtocol protocol, String srcIp, long srcPort) {
|
||||
srcIp = stripRouteDomainFromAddress(srcIp);
|
||||
return genObjectName("vs", protocol, srcIp, srcPort);
|
||||
}
|
||||
|
||||
private boolean virtualServerExists(String virtualServerName) throws ExecutionException {
|
||||
return getVirtualServers().contains(virtualServerName);
|
||||
}
|
||||
|
||||
private List<String> getVirtualServers() throws ExecutionException {
|
||||
try {
|
||||
List<String> virtualServers = new ArrayList<String>();
|
||||
String[] virtualServersArray = _virtualServerApi.get_list();
|
||||
|
||||
for (String virtualServer : virtualServersArray) {
|
||||
virtualServers.add(virtualServer);
|
||||
}
|
||||
|
||||
return virtualServers;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private iControl.CommonVirtualServerDefinition[] genVirtualServerDefinition(String name, LbProtocol protocol, String srcIp, long srcPort) {
|
||||
CommonVirtualServerDefinition vsDefs[] = {new CommonVirtualServerDefinition()};
|
||||
vsDefs[0].setName(name);
|
||||
vsDefs[0].setAddress(srcIp);
|
||||
vsDefs[0].setPort(srcPort);
|
||||
|
||||
if (protocol.equals(LbProtocol.tcp)) {
|
||||
vsDefs[0].setProtocol(iControl.CommonProtocolType.PROTOCOL_TCP);
|
||||
} else if (protocol.equals(LbProtocol.udp)) {
|
||||
vsDefs[0].setProtocol(iControl.CommonProtocolType.PROTOCOL_UDP);
|
||||
}
|
||||
|
||||
return vsDefs;
|
||||
}
|
||||
|
||||
private iControl.LocalLBVirtualServerVirtualServerResource[] genVirtualServerResource(String poolName) {
|
||||
LocalLBVirtualServerVirtualServerResource vsRes[] = {new LocalLBVirtualServerVirtualServerResource()};
|
||||
vsRes[0].setType(LocalLBVirtualServerVirtualServerType.RESOURCE_TYPE_POOL);
|
||||
vsRes[0].setDefault_pool_name(poolName);
|
||||
return vsRes;
|
||||
}
|
||||
|
||||
private LocalLBVirtualServerVirtualServerProfile[][] genVirtualServerProfile(LbProtocol protocol) {
|
||||
LocalLBVirtualServerVirtualServerProfile vsProfs[][] = {{new LocalLBVirtualServerVirtualServerProfile()}};
|
||||
vsProfs[0][0].setProfile_context(LocalLBProfileContextType.PROFILE_CONTEXT_TYPE_ALL);
|
||||
|
||||
if (protocol.equals(LbProtocol.tcp)) {
|
||||
vsProfs[0][0].setProfile_name("http");
|
||||
} else if (protocol.equals(LbProtocol.udp)) {
|
||||
vsProfs[0][0].setProfile_name("udp");
|
||||
}
|
||||
|
||||
return vsProfs;
|
||||
}
|
||||
|
||||
private LocalLBVirtualServerVirtualServerPersistence[][] genPersistenceProfile(String persistenceProfileName) {
|
||||
LocalLBVirtualServerVirtualServerPersistence[][] persistenceProfs = {{new LocalLBVirtualServerVirtualServerPersistence()}};
|
||||
persistenceProfs[0][0].setDefault_profile(true);
|
||||
persistenceProfs[0][0].setProfile_name(persistenceProfileName);
|
||||
return persistenceProfs;
|
||||
}
|
||||
|
||||
// Load balancing pool methods
|
||||
|
||||
private void addPool(String virtualServerName, LbAlgorithm algorithm) throws ExecutionException {
|
||||
try {
|
||||
if (!poolExists(virtualServerName)) {
|
||||
if (algorithm.getPersistenceProfileName() != null) {
|
||||
algorithm = LbAlgorithm.RoundRobin;
|
||||
}
|
||||
|
||||
s_logger.debug("Adding pool for virtual server " + virtualServerName + " with algorithm " + algorithm);
|
||||
_loadbalancerApi.create(genStringArray(virtualServerName), genLbMethod(algorithm), genEmptyMembersArray());
|
||||
|
||||
if (!poolExists(virtualServerName)) {
|
||||
throw new ExecutionException("Failed to create new pool for virtual server " + virtualServerName);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePool(String virtualServerName) throws ExecutionException {
|
||||
try {
|
||||
if (poolExists(virtualServerName) && getMembers(virtualServerName).size() == 0) {
|
||||
s_logger.debug("Deleting pool for virtual server " + virtualServerName);
|
||||
_loadbalancerApi.delete_pool(genStringArray(virtualServerName));
|
||||
|
||||
if (poolExists(virtualServerName)) {
|
||||
throw new ExecutionException("Failed to delete pool for virtual server " + virtualServerName);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPoolMember(String virtualServerName, String destIp, int destPort) throws ExecutionException {
|
||||
try {
|
||||
String memberIdentifier = destIp + "-" + destPort;
|
||||
|
||||
if (poolExists(virtualServerName) && !memberExists(virtualServerName, memberIdentifier)) {
|
||||
s_logger.debug("Adding member " + memberIdentifier + " into pool for virtual server " + virtualServerName);
|
||||
_loadbalancerApi.add_member(genStringArray(virtualServerName), genMembers(destIp, destPort));
|
||||
|
||||
if (!memberExists(virtualServerName, memberIdentifier)) {
|
||||
throw new ExecutionException("Failed to add new member " + memberIdentifier + " into pool for virtual server " + virtualServerName);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteInactivePoolMembers(String virtualServerName, List<String> activePoolMembers) throws ExecutionException {
|
||||
List<String> allPoolMembers = getMembers(virtualServerName);
|
||||
|
||||
for (String member : allPoolMembers) {
|
||||
if (!activePoolMembers.contains(member)) {
|
||||
String[] ipAndPort = member.split("-");
|
||||
deletePoolMember(virtualServerName, ipAndPort[0], Integer.valueOf(ipAndPort[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePoolMember(String virtualServerName, String destIp, int destPort) throws ExecutionException {
|
||||
try {
|
||||
String memberIdentifier = destIp + "-" + destPort;
|
||||
List<String> lbPools = getAllLbPools();
|
||||
|
||||
if (lbPools.contains(virtualServerName) && memberExists(virtualServerName, memberIdentifier)) {
|
||||
s_logger.debug("Deleting member " + memberIdentifier + " from pool for virtual server " + virtualServerName);
|
||||
_loadbalancerApi.remove_member(genStringArray(virtualServerName), genMembers(destIp, destPort));
|
||||
|
||||
if (memberExists(virtualServerName, memberIdentifier)) {
|
||||
throw new ExecutionException("Failed to delete member " + memberIdentifier + " from pool for virtual server " + virtualServerName);
|
||||
}
|
||||
|
||||
if (nodeExists(destIp)) {
|
||||
boolean nodeNeeded = false;
|
||||
done:
|
||||
for (String poolToCheck : lbPools) {
|
||||
for (String memberInPool : getMembers(poolToCheck)) {
|
||||
if (getIpAndPort(memberInPool)[0].equals(destIp)) {
|
||||
nodeNeeded = true;
|
||||
break done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nodeNeeded) {
|
||||
s_logger.debug("Deleting node " + destIp);
|
||||
_nodeApi.delete_node_address(genStringArray(destIp));
|
||||
|
||||
if (nodeExists(destIp)) {
|
||||
throw new ExecutionException("Failed to delete node " + destIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean poolExists(String poolName) throws ExecutionException {
|
||||
return getAllLbPools().contains(poolName);
|
||||
}
|
||||
|
||||
private boolean memberExists(String poolName, String memberIdentifier) throws ExecutionException {
|
||||
return getMembers(poolName).contains(memberIdentifier);
|
||||
}
|
||||
|
||||
private boolean nodeExists(String destIp) throws RemoteException {
|
||||
return getNodes().contains(destIp);
|
||||
}
|
||||
|
||||
private String[] getIpAndPort(String memberIdentifier) {
|
||||
return memberIdentifier.split("-");
|
||||
}
|
||||
|
||||
public List<String> getAllLbPools() throws ExecutionException {
|
||||
try {
|
||||
List<String> lbPools = new ArrayList<String>();
|
||||
String[] pools = _loadbalancerApi.get_list();
|
||||
|
||||
for (String pool : pools) {
|
||||
lbPools.add(pool);
|
||||
}
|
||||
|
||||
return lbPools;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getMembers(String virtualServerName) throws ExecutionException {
|
||||
try {
|
||||
List<String> members = new ArrayList<String>();
|
||||
String[] virtualServerNames = genStringArray(virtualServerName);
|
||||
CommonIPPortDefinition[] membersArray = _loadbalancerApi.get_member(virtualServerNames)[0];
|
||||
|
||||
for (CommonIPPortDefinition member : membersArray) {
|
||||
members.add(member.getAddress() + "-" + member.getPort());
|
||||
}
|
||||
|
||||
return members;
|
||||
} catch (RemoteException e) {
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getNodes() throws RemoteException {
|
||||
List<String> nodes = new ArrayList<String>();
|
||||
String[] nodesArray = _nodeApi.get_list();
|
||||
|
||||
for (String node : nodesArray) {
|
||||
nodes.add(node);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private iControl.CommonIPPortDefinition[][] genMembers(String destIp, long destPort) {
|
||||
iControl.CommonIPPortDefinition[] membersInnerArray = new iControl.CommonIPPortDefinition[1];
|
||||
membersInnerArray[0] = new iControl.CommonIPPortDefinition(destIp, destPort);
|
||||
return new iControl.CommonIPPortDefinition[][]{membersInnerArray};
|
||||
}
|
||||
|
||||
private iControl.CommonIPPortDefinition[][] genEmptyMembersArray() {
|
||||
iControl.CommonIPPortDefinition[] membersInnerArray = new iControl.CommonIPPortDefinition[0];
|
||||
return new iControl.CommonIPPortDefinition[][]{membersInnerArray};
|
||||
}
|
||||
|
||||
private LocalLBLBMethod[] genLbMethod(LbAlgorithm algorithm) {
|
||||
if (algorithm.getMethod() != null) {
|
||||
return new LocalLBLBMethod[]{algorithm.getMethod()};
|
||||
} else {
|
||||
return new LocalLBLBMethod[]{LbAlgorithm.RoundRobin.getMethod()};
|
||||
}
|
||||
}
|
||||
|
||||
// Stats methods
|
||||
|
||||
private ExternalNetworkResourceUsageAnswer getIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
|
||||
ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
|
||||
|
||||
try {
|
||||
LocalLBVirtualServerVirtualServerStatistics stats = _virtualServerApi.get_all_statistics();
|
||||
for (LocalLBVirtualServerVirtualServerStatisticEntry entry : stats.getStatistics()) {
|
||||
String virtualServerIp = entry.getVirtual_server().getAddress();
|
||||
|
||||
if (_inline) {
|
||||
virtualServerIp = stripRouteDomainFromAddress(virtualServerIp);
|
||||
}
|
||||
|
||||
long[] bytesSentAndReceived = answer.ipBytes.get(virtualServerIp);
|
||||
|
||||
if (bytesSentAndReceived == null) {
|
||||
bytesSentAndReceived = new long[]{0, 0};
|
||||
}
|
||||
|
||||
for (CommonStatistic stat : entry.getStatistics()) {
|
||||
if (stat.getType().equals(CommonStatisticType.STATISTIC_CLIENT_SIDE_BYTES_OUT)) {
|
||||
// Add to the outgoing bytes
|
||||
bytesSentAndReceived[0] += stat.getValue().getLow();
|
||||
} else if (stat.getType().equals(CommonStatisticType.STATISTIC_CLIENT_SIDE_BYTES_IN)) {
|
||||
// Add to the incoming bytes
|
||||
bytesSentAndReceived[1] += stat.getValue().getLow();
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) {
|
||||
answer.ipBytes.put(virtualServerIp, bytesSentAndReceived);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error(e);
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Misc methods
|
||||
|
||||
private String tagAddressWithRouteDomain(String address, long vlanTag) {
|
||||
return address + _routeDomainIdentifier + vlanTag;
|
||||
}
|
||||
|
||||
private String stripRouteDomainFromAddress(String address) {
|
||||
int i = address.indexOf(_routeDomainIdentifier);
|
||||
|
||||
if (i > 0) {
|
||||
address = address.substring(0, i);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
private String genObjectName(Object... args) {
|
||||
String objectName = "";
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
objectName += args[i];
|
||||
if (i != args.length -1) {
|
||||
objectName += _objectNamePathSep;
|
||||
}
|
||||
}
|
||||
|
||||
return objectName;
|
||||
}
|
||||
|
||||
private long[] genLongArray(long l) {
|
||||
return new long[]{l};
|
||||
}
|
||||
|
||||
private static String[] genStringArray(String s) {
|
||||
return new String[]{s};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,294 @@
|
|||
/**
|
||||
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.network.resource;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.IAgentControl;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.DirectNetworkUsageAnswer;
|
||||
import com.cloud.agent.api.DirectNetworkUsageCommand;
|
||||
import com.cloud.agent.api.MaintainAnswer;
|
||||
import com.cloud.agent.api.MaintainCommand;
|
||||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.ReadyAnswer;
|
||||
import com.cloud.agent.api.ReadyCommand;
|
||||
import com.cloud.agent.api.RecurringNetworkUsageAnswer;
|
||||
import com.cloud.agent.api.RecurringNetworkUsageCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupTrafficMonitorCommand;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.exception.ExecutionException;
|
||||
|
||||
public class TrafficSentinelResource implements ServerResource {
|
||||
|
||||
private String _name;
|
||||
private String _zoneId;
|
||||
private String _ip;
|
||||
private String _guid;
|
||||
private String _url;
|
||||
private static Integer _numRetries;
|
||||
private static Integer _timeoutInSeconds;
|
||||
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(TrafficSentinelResource.class);
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
try {
|
||||
|
||||
_name = name;
|
||||
|
||||
_zoneId = (String) params.get("zone");
|
||||
if (_zoneId == null) {
|
||||
throw new ConfigurationException("Unable to find zone");
|
||||
}
|
||||
|
||||
_ip = (String) params.get("ipaddress");
|
||||
if (_ip == null) {
|
||||
throw new ConfigurationException("Unable to find IP");
|
||||
}
|
||||
|
||||
_guid = (String)params.get("guid");
|
||||
if (_guid == null) {
|
||||
throw new ConfigurationException("Unable to find the guid");
|
||||
}
|
||||
|
||||
_url = (String)params.get("url");
|
||||
if (_url == null) {
|
||||
throw new ConfigurationException("Unable to find url");
|
||||
}
|
||||
|
||||
_numRetries = NumbersUtil.parseInt((String) params.get("numRetries"), 1);
|
||||
|
||||
_timeoutInSeconds = NumbersUtil.parseInt((String) params.get("timeoutInSeconds"), 300);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
StartupTrafficMonitorCommand cmd = new StartupTrafficMonitorCommand();
|
||||
cmd.setName(_name);
|
||||
cmd.setDataCenter(_zoneId);
|
||||
cmd.setPod("");
|
||||
cmd.setPrivateIpAddress(_ip);
|
||||
cmd.setStorageIpAddress("");
|
||||
cmd.setVersion("");
|
||||
cmd.setGuid(_guid);
|
||||
return new StartupCommand[]{cmd};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Host.Type getType() {
|
||||
return Host.Type.TrafficMonitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(final long id) {
|
||||
return new PingCommand(Host.Type.TrafficMonitor, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAgentControl getAgentControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgentControl(IAgentControl agentControl) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof ReadyCommand) {
|
||||
return execute((ReadyCommand) cmd);
|
||||
} else if (cmd instanceof MaintainCommand) {
|
||||
return execute((MaintainCommand) cmd);
|
||||
} else if (cmd instanceof DirectNetworkUsageCommand) {
|
||||
return execute((DirectNetworkUsageCommand) cmd);
|
||||
} else if (cmd instanceof RecurringNetworkUsageCommand) {
|
||||
return execute((RecurringNetworkUsageCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
private Answer execute(ReadyCommand cmd) {
|
||||
return new ReadyAnswer(cmd);
|
||||
}
|
||||
|
||||
private synchronized RecurringNetworkUsageAnswer execute(RecurringNetworkUsageCommand cmd) {
|
||||
return new RecurringNetworkUsageAnswer(cmd);
|
||||
}
|
||||
|
||||
private synchronized DirectNetworkUsageAnswer execute(DirectNetworkUsageCommand cmd) {
|
||||
try {
|
||||
return getPublicIpBytesSentAndReceived(cmd);
|
||||
} catch (ExecutionException e) {
|
||||
return new DirectNetworkUsageAnswer(cmd, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Answer execute(MaintainCommand cmd) {
|
||||
return new MaintainAnswer(cmd);
|
||||
}
|
||||
|
||||
|
||||
private DirectNetworkUsageAnswer getPublicIpBytesSentAndReceived(DirectNetworkUsageCommand cmd) throws ExecutionException {
|
||||
DirectNetworkUsageAnswer answer = new DirectNetworkUsageAnswer(cmd);
|
||||
|
||||
try {
|
||||
//Direct Network Usage
|
||||
URL trafficSentinel;
|
||||
try {
|
||||
//Query traffic Sentinel
|
||||
trafficSentinel = new URL(_url+"/inmsf/Query?script="+URLEncoder.encode(getScript(cmd.getPublicIps(), cmd.getStart(), cmd.getEnd()),"UTF-8")
|
||||
+"&authenticate=basic&resultFormat=txt");
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(trafficSentinel.openStream()));
|
||||
|
||||
String inputLine;
|
||||
|
||||
while ((inputLine = in.readLine()) != null){
|
||||
//Parse the script output
|
||||
StringTokenizer st = new StringTokenizer(inputLine, ",");
|
||||
if(st.countTokens() == 3){
|
||||
String publicIp = st.nextToken();
|
||||
Long bytesSent = new Long(st.nextToken());
|
||||
Long bytesRcvd = new Long(st.nextToken());
|
||||
if(bytesSent == null || bytesRcvd == null){
|
||||
s_logger.debug("Incorrect bytes for IP: "+publicIp);
|
||||
}
|
||||
long[] bytesSentAndReceived = new long[2];
|
||||
bytesSentAndReceived[0] = bytesSent;
|
||||
bytesSentAndReceived[1] = bytesRcvd;
|
||||
answer.put(publicIp, bytesSentAndReceived);
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
} catch (MalformedURLException e1) {
|
||||
s_logger.info("Invalid Traffic Sentinel URL",e1);
|
||||
} catch (IOException e) {
|
||||
s_logger.debug("Error in direct network usage accounting",e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error(e);
|
||||
throw new ExecutionException(e.getMessage());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private String getScript(List<String> Ips, Date start, Date end){
|
||||
String IpAddresses = "";
|
||||
for(int i=0; i<Ips.size(); i++ ){
|
||||
IpAddresses += Ips.get(i);
|
||||
if(i != (Ips.size() - 1)){
|
||||
// Append comma for all Ips except the last Ip
|
||||
IpAddresses += ",";
|
||||
}
|
||||
}
|
||||
String startDate = getDateString(start);
|
||||
String endtDate = getDateString(end);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("var q = Query.topN(\"historytrmx\",");
|
||||
sb.append(" \"ipsource,bytes\",");
|
||||
sb.append(" \"ipsource = "+IpAddresses+" & destinationzone = EXTERNAL\",");
|
||||
sb.append(" \""+startDate+", "+endtDate+"\",");
|
||||
sb.append(" \"bytes\",");
|
||||
sb.append(" 100000);");
|
||||
sb.append("var totalsSent = {};");
|
||||
sb.append("var t = q.run(");
|
||||
sb.append(" function(row,table) {");
|
||||
sb.append(" if(row[0]) { ");
|
||||
sb.append(" totalsSent[row[0]] = row[1];");
|
||||
sb.append(" }");
|
||||
sb.append(" });");
|
||||
sb.append("var q = Query.topN(\"historytrmx\",");
|
||||
sb.append(" \"ipdestination,bytes\",");
|
||||
sb.append(" \"ipdestination = "+IpAddresses+" & sourcezone = EXTERNAL\",");
|
||||
sb.append(" \""+startDate+", "+endtDate+"\",");
|
||||
sb.append(" \"bytes\",");
|
||||
sb.append(" 100000);");
|
||||
sb.append("var totalsRcvd = {};");
|
||||
sb.append("var t = q.run(");
|
||||
sb.append(" function(row,table) {");
|
||||
sb.append(" if(row[0]) {");
|
||||
sb.append(" totalsRcvd[row[0]] = row[1];");
|
||||
sb.append(" }");
|
||||
sb.append(" });");
|
||||
sb.append("for (var addr in totalsSent) {");
|
||||
sb.append(" var TS = 0;");
|
||||
sb.append(" var TR = 0;");
|
||||
sb.append(" if(totalsSent[addr]) TS = totalsSent[addr];");
|
||||
sb.append(" if(totalsRcvd[addr]) TR = totalsRcvd[addr];");
|
||||
sb.append(" println(addr + \",\" + TS + \",\" + TR);");
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getDateString(Date date){
|
||||
DateFormat dfDate = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
|
||||
return dfDate.format(date);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5
|
||||
* Software Development Kit for iControl"; you may not use this file except in
|
||||
* compliance with the License. The License is included in the iControl
|
||||
* Software Development Kit.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is iControl Code and related documentation
|
||||
* distributed by F5.
|
||||
*
|
||||
* Portions created by F5 are Copyright (C) 1996-2004 F5 Networks
|
||||
* Inc. All Rights Reserved. iControl (TM) is a registered trademark of
|
||||
* F5 Networks, Inc.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms
|
||||
* of the GNU General Public License (the "GPL"), in which case the
|
||||
* provisions of GPL are applicable instead of those above. If you wish
|
||||
* to allow use of your version of this file only under the terms of the
|
||||
* GPL and not to allow others to use your version of this file under the
|
||||
* License, indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by the GPL.
|
||||
* If you do not delete the provisions above, a recipient may use your
|
||||
* version of this file under either the License or the GPL.
|
||||
*/
|
||||
package com.cloud.network.resource;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.ManagerFactoryParameters;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactorySpi;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public final class XTrustProvider extends java.security.Provider
|
||||
{
|
||||
private final static String NAME = "XTrustJSSE";
|
||||
private final static String INFO =
|
||||
"XTrust JSSE Provider (implements trust factory with truststore validation disabled)";
|
||||
private final static double VERSION = 1.0D;
|
||||
|
||||
public XTrustProvider()
|
||||
{
|
||||
super(NAME, VERSION, INFO);
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction()
|
||||
{
|
||||
public Object run()
|
||||
{
|
||||
put("TrustManagerFactory." + TrustManagerFactoryImpl.getAlgorithm(),
|
||||
TrustManagerFactoryImpl.class.getName());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void install()
|
||||
{
|
||||
if(Security.getProvider(NAME) == null)
|
||||
{
|
||||
Security.insertProviderAt(new XTrustProvider(), 2);
|
||||
Security.setProperty("ssl.TrustManagerFactory.algorithm",
|
||||
TrustManagerFactoryImpl.getAlgorithm());
|
||||
}
|
||||
}
|
||||
|
||||
public final static class TrustManagerFactoryImpl extends TrustManagerFactorySpi
|
||||
{
|
||||
public TrustManagerFactoryImpl() { }
|
||||
public static String getAlgorithm() { return "XTrust509"; }
|
||||
protected void engineInit(KeyStore keystore) throws KeyStoreException { }
|
||||
protected void engineInit(ManagerFactoryParameters mgrparams)
|
||||
throws InvalidAlgorithmParameterException
|
||||
{
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
XTrustProvider.NAME + " does not use ManagerFactoryParameters");
|
||||
}
|
||||
|
||||
protected TrustManager[] engineGetTrustManagers()
|
||||
{
|
||||
return new TrustManager[] { new X509TrustManager()
|
||||
{
|
||||
public X509Certificate[] getAcceptedIssuers() { return null; }
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
|
||||
}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
import re
|
||||
class ConfigFileOps:
|
||||
class entry:
|
||||
def __init__(self, name, value, op, separator):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.state = "new"
|
||||
self.op = op
|
||||
self.separator = separator
|
||||
def setState(self, state):
|
||||
self.state = state
|
||||
def getState(self):
|
||||
return self.state
|
||||
|
||||
def __init__(self, fileName, cfg=None):
|
||||
self.fileName = fileName
|
||||
self.entries = []
|
||||
self.backups = []
|
||||
|
||||
if cfg is not None:
|
||||
cfg.cfoHandlers.append(self)
|
||||
|
||||
def addEntry(self, name, value, separator="="):
|
||||
e = self.entry(name, value, "add", separator)
|
||||
self.entries.append(e)
|
||||
|
||||
def rmEntry(self, name, value, separator="="):
|
||||
entry = self.entry(name, value, "rm", separator)
|
||||
self.entries.append(entry)
|
||||
|
||||
def getEntry(self, name, separator="="):
|
||||
try:
|
||||
ctx = file(self.fileName).read(-1)
|
||||
match = re.search("^" + name + ".*", ctx, re.MULTILINE)
|
||||
if match is None:
|
||||
return ""
|
||||
line = match.group(0).split(separator, 1)
|
||||
return line[1]
|
||||
except:
|
||||
return ""
|
||||
|
||||
def save(self):
|
||||
fp = open(self.fileName, "r")
|
||||
newLines = []
|
||||
for line in fp.readlines():
|
||||
matched = False
|
||||
for entry in self.entries:
|
||||
if entry.op == "add":
|
||||
if entry.separator == "=":
|
||||
matchString = "^\ *" + entry.name + ".*"
|
||||
elif entry.separator == " ":
|
||||
matchString = "^\ *" + entry.name + "\ *" + entry.value
|
||||
else:
|
||||
if entry.separator == "=":
|
||||
matchString = "^\ *" + entry.name + "\ *=\ *" + entry.value
|
||||
else:
|
||||
matchString = "^\ *" + entry.name + "\ *" + entry.value
|
||||
|
||||
match = re.match(matchString, line)
|
||||
if match is not None:
|
||||
if entry.op == "add" and entry.separator == "=":
|
||||
newline = entry.name + "=" + entry.value + "\n"
|
||||
entry.setState("set")
|
||||
newLines.append(newline)
|
||||
self.backups.append([line, newline])
|
||||
matched = True
|
||||
break
|
||||
elif entry.op == "rm":
|
||||
entry.setState("set")
|
||||
self.backups.append([line, None])
|
||||
matched = True
|
||||
break
|
||||
|
||||
if not matched:
|
||||
newLines.append(line)
|
||||
|
||||
for entry in self.entries:
|
||||
if entry.getState() != "set":
|
||||
if entry.op == "add":
|
||||
newline = entry.name + entry.separator + entry.value + "\n"
|
||||
newLines.append(newline)
|
||||
self.backups.append([None, newline])
|
||||
entry.setState("set")
|
||||
|
||||
fp.close()
|
||||
|
||||
file(self.fileName, "w").writelines(newLines)
|
||||
|
||||
def replace_line(self, startswith,stanza,always_add=False):
|
||||
lines = [ s.strip() for s in file(self.fileName).readlines() ]
|
||||
newlines = []
|
||||
replaced = False
|
||||
for line in lines:
|
||||
if re.search(startswith, line):
|
||||
if stanza is not None:
|
||||
newlines.append(stanza)
|
||||
self.backups.append([line, stanza])
|
||||
replaced = True
|
||||
else: newlines.append(line)
|
||||
if not replaced and always_add:
|
||||
newlines.append(stanza)
|
||||
self.backups.append([None, stanza])
|
||||
newlines = [ s + '\n' for s in newlines ]
|
||||
file(self.fileName,"w").writelines(newlines)
|
||||
|
||||
def replace_or_add_line(self, startswith,stanza):
|
||||
return self.replace_line(startswith,stanza,always_add=True)
|
||||
|
||||
def add_lines(self, lines, addToBackup=True):
|
||||
fp = file(self.fileName).read(-1)
|
||||
sh = re.escape(lines)
|
||||
match = re.search(sh, fp, re.MULTILINE)
|
||||
if match is not None:
|
||||
return
|
||||
|
||||
fp += lines
|
||||
file(self.fileName, "w").write(fp)
|
||||
self.backups.append([None, lines])
|
||||
|
||||
def replace_lines(self, src, dst, addToBackup=True):
|
||||
fp = file(self.fileName).read(-1)
|
||||
sh = re.escape(src)
|
||||
if dst is None:
|
||||
dst = ""
|
||||
repl,nums = re.subn(sh, dst, fp)
|
||||
if nums <=0:
|
||||
return
|
||||
file(self.fileName, "w").write(repl)
|
||||
if addToBackup:
|
||||
self.backups.append([src, dst])
|
||||
|
||||
def append_lines(self, match_lines, append_lines):
|
||||
fp = file(self.fileName).read(-1)
|
||||
sh = re.escape(match_lines)
|
||||
match = re.search(sh, fp, re.MULTILINE)
|
||||
if match is None:
|
||||
return
|
||||
|
||||
sh = re.escape(append_lines)
|
||||
if re.search(sh, fp, re.MULTILINE) is not None:
|
||||
return
|
||||
|
||||
newlines = []
|
||||
for line in file(self.fileName).readlines():
|
||||
if re.search(match_lines, line) is not None:
|
||||
newlines.append(line + append_lines)
|
||||
self.backups.append([line, line + append_lines])
|
||||
else:
|
||||
newlines.append(line)
|
||||
|
||||
file(self.fileName, "w").writelines(newlines)
|
||||
|
||||
def backup(self):
|
||||
for oldLine, newLine in self.backups:
|
||||
if newLine is None:
|
||||
self.add_lines(oldLine, False)
|
||||
else:
|
||||
self.replace_lines(newLine, oldLine, False)
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
'''
|
||||
Created on May 17, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
|
||||
from OvmObjectModule import *
|
||||
import types
|
||||
import logging
|
||||
import popen2
|
||||
from OvmFaultConstants import toErrCode, dispatchErrCode, NoVmFoundException
|
||||
from xmlrpclib import Fault as XmlRpcFault
|
||||
from OVSCommons import *
|
||||
from OvmLoggerModule import OvmLogger
|
||||
from OVSXXenStore import xen_get_vm_path
|
||||
|
||||
HEARTBEAT_TIMESTAMP_FORMAT='<timestamp>%s</timestamp>'
|
||||
HEARTBEAT_TIMESTAMP_PATTERN='(\<timestamp\>\d+.\d+<\/timestamp\>)'
|
||||
HEARTBEAT_DIR='heart_beat'
|
||||
ETC_HOSTS='/etc/hosts'
|
||||
|
||||
logger = OvmLogger('OvmCommon')
|
||||
|
||||
def setAttrFromDict(obj, name, refDict, convertFunc=None):
|
||||
if not convertFunc:
|
||||
setattr(obj, name, refDict[name])
|
||||
else:
|
||||
setattr(obj, name, convertFunc(refDict[name]))
|
||||
|
||||
def safeSetAttr(obj, name, value):
|
||||
if not hasattr(obj, name): raise Exception("%s doesn't have attribute %s"%(obj.__class__.__name__, name))
|
||||
setattr(obj, name, value)
|
||||
|
||||
def toAscii(jstr):
|
||||
return str(jstr).encode('ascii', 'ignore')
|
||||
|
||||
def toAsciiHook(dct):
|
||||
for k in dct:
|
||||
v = dct[k]
|
||||
if type(v) is types.UnicodeType:
|
||||
v = toAscii(v)
|
||||
del dct[k]
|
||||
k = toAscii(k)
|
||||
dct[k] = v
|
||||
return dct
|
||||
|
||||
def asciiLoads(jStr):
|
||||
jStr = str(jStr).replace("'", '"').replace('False', 'false').replace('True', 'true')
|
||||
return json.loads(jStr, object_hook=toAsciiHook)
|
||||
|
||||
def exceptionIfNoSuccess(str, errMsg=None):
|
||||
if not errMsg: errMsg = str
|
||||
if not "success" in str: raise Exception("%s (%s)"%(errMsg, str))
|
||||
|
||||
def successToMap(str, sep=';'):
|
||||
if not str.startswith("success"): raise Exception(str)
|
||||
str = str[len('success:'):]
|
||||
dct = {}
|
||||
for pair in str.split(sep):
|
||||
(key, value) = pair.split('=', 1)
|
||||
dct[key] = value
|
||||
return dct
|
||||
|
||||
def jsonSuccessToMap(str):
|
||||
dct = json.loads(str)
|
||||
if dct['status'] != 'SUCC': raise Exception(str)
|
||||
return dct['value']
|
||||
|
||||
def safeDictSet(obj, dct, name):
|
||||
if not hasattr(obj, name): raise Exception("%s has no attribute %s for encoding"%(obj.__class__.__name__, name))
|
||||
dct[name] = getattr(obj, name)
|
||||
|
||||
def normalizeToGson(str):
|
||||
return str.replace('\\', '').strip('"').replace('"{', '{').replace('}"', '}');
|
||||
|
||||
def toGson(obj):
|
||||
return normalizeToGson(json.dumps(obj))
|
||||
|
||||
def MtoBytes(M):
|
||||
return M * 1024 * 1024
|
||||
|
||||
def BytesToM(bytes):
|
||||
return bytes/(1024*1024)
|
||||
|
||||
def BytesToG(bytes):
|
||||
return bytes/(1024*1024*1024)
|
||||
|
||||
def doCmd(lst):
|
||||
cmds = [str(i) for i in lst]
|
||||
logger.debug(doCmd, ' '.join(cmds))
|
||||
res = run_cmd(cmds)
|
||||
logger.debug(doCmd, 'result:' + res)
|
||||
return res
|
||||
|
||||
def execute(cmd):
|
||||
p = popen2.Popen3(cmd, True)
|
||||
if (p.wait() != 0):
|
||||
raise Exception("Failed to execute command. Command: " + cmd + ", Error: " + p.childerr.read())
|
||||
return p.fromchild.read()
|
||||
|
||||
def getDomId(vm_name):
|
||||
return execute("xm list | grep " + vm_name + " | awk '{print $2}'").strip()
|
||||
|
||||
def raiseExceptionIfFail(res):
|
||||
if not "success" in res and not "SUCC" in res: raise Exception(res)
|
||||
|
||||
def ipToHeartBeatFileName(ip):
|
||||
return ip.replace('.', '_') + "_HEARTBEAT"
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
'''
|
||||
Created on May 17, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
|
||||
from OvmCommonModule import *
|
||||
|
||||
class OvmDiskDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDict = asciiLoads(jStr)
|
||||
disk = OvmDisk()
|
||||
setAttrFromDict(disk, 'path', deDict)
|
||||
setAttrFromDict(disk, 'type', deDict)
|
||||
setAttrFromDict(disk, 'isIso', deDict)
|
||||
return disk
|
||||
|
||||
class OvmDiskEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmDisk): raise Exception("%s is not instance of OvmDisk"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'path')
|
||||
safeDictSet(obj, dct, 'type')
|
||||
return dct
|
||||
|
||||
def fromOvmDisk(disk):
|
||||
return normalizeToGson(json.dumps(disk, cls=OvmDiskEncoder))
|
||||
|
||||
def fromOvmDiskList(diskList):
|
||||
return [fromOvmDisk(d) for d in diskList]
|
||||
|
||||
def toOvmDisk(jStr):
|
||||
return json.loads(jStr, cls=OvmDiskDecoder)
|
||||
|
||||
def toOvmDiskList(jStr):
|
||||
disks = []
|
||||
for i in jStr:
|
||||
d = toOvmDisk(i)
|
||||
disks.append(d)
|
||||
return disks
|
||||
|
||||
class OvmDisk(OvmObject):
|
||||
path = ''
|
||||
type = ''
|
||||
isIso = False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print toOvmDisk('''{"type":"w","path":"/data/data.raw"}''')
|
||||
print toOvmDisk('''{"path":"/data/data.raw'","type":"w"}''')
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import types
|
||||
from OvmCommonModule import *
|
||||
from xmlrpclib import Fault
|
||||
from OVSCommons import *
|
||||
import OvmFaultConstants
|
||||
|
||||
import OvmHostModule
|
||||
import OvmStoragePoolModule
|
||||
import OvmVmModule
|
||||
import OvmNetworkModule
|
||||
import OvmVolumeModule
|
||||
import OvmSecurityGroupModule
|
||||
from OvmHaHeartBeatModule import OvmHaHeartBeat
|
||||
|
||||
ExposedClass = {}
|
||||
logger = OvmLogger('OvmDispatcher')
|
||||
def InitOvmDispacther():
|
||||
global ExposedClass
|
||||
modules = [ eval(attr) for attr in globals() if isinstance(eval(attr), types.ModuleType) ]
|
||||
for m in modules:
|
||||
for name in dir(m):
|
||||
clz = getattr(m, name)
|
||||
if type(clz) is types.TypeType and issubclass(clz, OvmObject):
|
||||
ExposedClass[name] = clz
|
||||
logger.debug(InitOvmDispacther, "Discovered exposed class:\n\n%s"%"\n".join(ExposedClass))
|
||||
|
||||
@exposed
|
||||
def OvmDispatch(methodName, *params):
|
||||
global ExposedClass
|
||||
p = methodName.split('.')
|
||||
if len(p) != 2:
|
||||
logger.error(OvmDispatch, "%s is not a vaild format, should be classname.methodname"%p)
|
||||
raise Fault(dispatchErrCode('InvalidCallMethodFormat'), "%s is not a vaild format, should be classname.methodname"%p)
|
||||
clzName = p[0]
|
||||
funcName = p[1]
|
||||
if clzName not in ExposedClass.keys():
|
||||
logger.error(OvmDispatch, "class %s is not exposed by agent"%clzName)
|
||||
raise Fault(dispatchErrCode('InvaildClass'), "class %s is not exposed by agent"%clzName)
|
||||
clz = ExposedClass[clzName]
|
||||
if not hasattr(clz, funcName):
|
||||
logger.error(OvmDispatch, "class %s has no function %s"%(clzName, funcName))
|
||||
raise Fault(dispatchErrCode('InvaildFunction'), "class %s has no function %s"%(clzName, funcName))
|
||||
logger.debug(OvmDispatch, "Entering %s.%s ===>"%(clzName, funcName))
|
||||
rs = getattr(clz, funcName)(*params)
|
||||
logger.debug(OvmDispatch, "Exited %s.%s <==="%(clzName, funcName))
|
||||
return rs
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/OVSAgentAutoStart.py b/OVSAgentAutoStart.py
|
||||
index 88fa18c..794a363 100755
|
||||
--- a/OVSAgentAutoStart.py
|
||||
+++ b/OVSAgentAutoStart.py
|
||||
@@ -111,8 +111,6 @@ def prepare_cluster_heartbeat():
|
||||
JOBS = [
|
||||
["command", join(dirname(__file__), "utils/upgrade_agent.py")],
|
||||
["function", "get_agent_version", ()],
|
||||
- ["function", "prepare_cluster_root", ()],
|
||||
- ["function", "prepare_cluster_heartbeat", ()],
|
||||
["command", join(dirname(__file__), "utils/upgrade.py")],
|
||||
["command_bg", join(dirname(__file__), "OVSRemasterServer.py")],
|
||||
["command_bg", join(dirname(__file__), "OVSMonitorServer.py")],
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
OvmDispatcherStub = 0
|
||||
OvmHostErrCodeStub = 1000
|
||||
OvmVmErrCodeStub = 2000
|
||||
OvmStoragePoolErrCodeStub = 3000
|
||||
OvmNetworkErrCodeStub = 4000
|
||||
OvmVolumeErrCodeStub = 5000
|
||||
|
||||
class NoVmFoundException(Exception):
|
||||
pass
|
||||
|
||||
errCode = {
|
||||
# OvmDispatch is not class, these error codes are reserved
|
||||
"OvmDispatch.InvalidCallMethodFormat":OvmDispatcherStub+1,
|
||||
"OvmDispatch.InvaildClass":OvmDispatcherStub+2,
|
||||
"OvmDispatch.InvaildFunction":OvmDispatcherStub+3,
|
||||
"OvmVm.reboot":OvmDispatcherStub+4,
|
||||
|
||||
"OvmHost.registerAsMaster":OvmHostErrCodeStub+1,
|
||||
"OvmHost.registerAsVmServer":OvmHostErrCodeStub+2,
|
||||
"OvmHost.ping":OvmHostErrCodeStub+3,
|
||||
"OvmHost.getDetails":OvmHostErrCodeStub+4,
|
||||
"OvmHost.getPerformanceStats":OvmHostErrCodeStub+5,
|
||||
"OvmHost.getAllVms":OvmHostErrCodeStub+6,
|
||||
"OvmHost.fence":OvmHostErrCodeStub+7,
|
||||
"OvmHost.setupHeartBeat":OvmHostErrCodeStub+8,
|
||||
"OvmHost.pingAnotherHost":OvmHostErrCodeStub+9,
|
||||
|
||||
"OvmVm.create":OvmVmErrCodeStub+1,
|
||||
"OvmVm.stop":OvmVmErrCodeStub+2,
|
||||
"OvmVm.getDetails":OvmVmErrCodeStub+3,
|
||||
"OvmVm.getVmStats":OvmVmErrCodeStub+4,
|
||||
"OvmVm.migrate":OvmVmErrCodeStub+5,
|
||||
"OvmVm.register":OvmVmErrCodeStub+6,
|
||||
"OvmVm.getVncPort":OvmVmErrCodeStub+7,
|
||||
"OvmVm.detachOrAttachIso":OvmVmErrCodeStub+8,
|
||||
|
||||
"OvmStoragePool.create":OvmStoragePoolErrCodeStub+1,
|
||||
"OvmStoragePool.getDetailsByUuid":OvmStoragePoolErrCodeStub+2,
|
||||
"OvmStoragePool.downloadTemplate":OvmStoragePoolErrCodeStub+3,
|
||||
"OvmStoragePool.prepareOCFS2Nodes":OvmStoragePoolErrCodeStub+4,
|
||||
|
||||
"OvmNetwork.createBridge":OvmNetworkErrCodeStub+1,
|
||||
"OvmNetwork.deleteBridge":OvmNetworkErrCodeStub+2,
|
||||
"OvmNetwork.createVlan":OvmNetworkErrCodeStub+3,
|
||||
"OvmNetwork.deleteVlan":OvmNetworkErrCodeStub+4,
|
||||
"OvmNetwork.getAllBridges":OvmNetworkErrCodeStub+5,
|
||||
"OvmNetwork.getBridgeByIp":OvmNetworkErrCodeStub+6,
|
||||
"OvmNetwork.createVlanBridge":OvmNetworkErrCodeStub+7,
|
||||
"OvmNetwork.deleteVlanBridge":OvmNetworkErrCodeStub+8,
|
||||
|
||||
"OvmVolume.createDataDisk":OvmVolumeErrCodeStub+1,
|
||||
"OvmVolume.createFromTemplate":OvmVolumeErrCodeStub+2,
|
||||
"OvmVolume.destroy":OvmVolumeErrCodeStub+3,
|
||||
}
|
||||
|
||||
|
||||
def toErrCode(clz, func):
|
||||
global errCode
|
||||
if not callable(func): raise Exception("%s is not a callable, cannot get error code"%func)
|
||||
name = clz.__name__ + '.' + func.__name__
|
||||
if name not in errCode.keys(): return -1
|
||||
return errCode[name]
|
||||
|
||||
def dispatchErrCode(funcName):
|
||||
name = "OvmDispatch." + funcName
|
||||
if name not in errCode.keys(): return -1
|
||||
return errCode[name]
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
'''
|
||||
Created on Jun 6, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
from OvmCommonModule import *
|
||||
try:
|
||||
from multiprocessing import Process, Manager
|
||||
except ImportError:
|
||||
from processing import Process, Manager
|
||||
import signal
|
||||
|
||||
logger = OvmLogger("OvmHaHeartBeat")
|
||||
|
||||
class OvmHaHeartBeat(object):
|
||||
'''
|
||||
classdocs
|
||||
'''
|
||||
def __init__(self, mountPoint, ip):
|
||||
self.mountPoint = mountPoint
|
||||
self.ip = ip
|
||||
|
||||
def mark(self, file):
|
||||
timestamp = HEARTBEAT_TIMESTAMP_FORMAT % time.time()
|
||||
try:
|
||||
fd = open(file, 'w')
|
||||
fd.write(timestamp)
|
||||
fd.close()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHaHeartBeat.mark, errmsg)
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
Constructor
|
||||
'''
|
||||
heartBeatDir = join(self.mountPoint, HEARTBEAT_DIR)
|
||||
if not exists(heartBeatDir):
|
||||
os.makedirs(heartBeatDir)
|
||||
hearBeatFile = join(heartBeatDir, ipToHeartBeatFileName(self.ip))
|
||||
while True:
|
||||
self.mark(hearBeatFile)
|
||||
time.sleep(120)
|
||||
|
||||
@staticmethod
|
||||
def start(poolPath, ip):
|
||||
pidFile = join(PID_DIR, "heartbeat.pid")
|
||||
|
||||
def isLive():
|
||||
if exists(pidFile):
|
||||
f = open(pidFile)
|
||||
pid = f.read().strip()
|
||||
f.close()
|
||||
if isdir("/proc/%s" % pid):
|
||||
return long(pid)
|
||||
return None
|
||||
|
||||
def stopOldHeartBeat(pid):
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
time.sleep(5)
|
||||
pid = isLive()
|
||||
if pid != None:
|
||||
logger.debug(OvmHaHeartBeat.start, "SIGTERM cannot stop heartbeat process %s, will try SIGKILL"%pid)
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
time.sleep(5)
|
||||
pid = isLive()
|
||||
if pid != None:
|
||||
raise Exception("Cannot stop old heartbeat process %s, setup heart beat failed"%pid)
|
||||
|
||||
def heartBeat(hb):
|
||||
hb.run()
|
||||
|
||||
def setupHeartBeat():
|
||||
hb = OvmHaHeartBeat(poolPath, ip)
|
||||
p = Process(target=heartBeat, args=(hb,))
|
||||
p.start()
|
||||
pid = p.pid
|
||||
if not isdir(PID_DIR):
|
||||
os.makedirs(PID_DIR)
|
||||
pidFd = open(pidFile, 'w')
|
||||
pidFd.write(str(pid))
|
||||
pidFd.close()
|
||||
logger.info(OvmHaHeartBeat.start, "Set up heart beat successfully, pid is %s" % pid)
|
||||
|
||||
pid = isLive()
|
||||
if pid != None:
|
||||
stopOldHeartBeat(pid)
|
||||
|
||||
setupHeartBeat()
|
||||
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
#/usr/bin/python
|
||||
|
||||
from OvmCommonModule import *
|
||||
from OVSSiteRMServer import get_master_ip, register_server
|
||||
from OVSCommons import *
|
||||
from OVSXMonitor import xen_get_xm_info
|
||||
from OVSXSysInfo import get_agent_version
|
||||
from OVSSiteRMServer import get_srv_agent_status
|
||||
from OVSXMonitor import sys_perf_info
|
||||
from OVSDB import db_get_vm
|
||||
from OvmStoragePoolModule import OvmStoragePool
|
||||
from OvmHaHeartBeatModule import OvmHaHeartBeat
|
||||
import re
|
||||
|
||||
logger = OvmLogger('OvmHost')
|
||||
|
||||
class OvmHostEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmHost): raise Exception("%s is not instance of OvmHost"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'masterIp')
|
||||
safeDictSet(obj, dct, 'cpuNum')
|
||||
safeDictSet(obj, dct, 'cpuSpeed')
|
||||
safeDictSet(obj, dct, 'totalMemory')
|
||||
safeDictSet(obj, dct, 'freeMemory')
|
||||
safeDictSet(obj, dct, 'dom0Memory')
|
||||
safeDictSet(obj, dct, 'agentVersion')
|
||||
safeDictSet(obj, dct, 'name')
|
||||
safeDictSet(obj, dct, 'dom0KernelVersion')
|
||||
safeDictSet(obj, dct, 'hypervisorVersion')
|
||||
return dct
|
||||
|
||||
|
||||
def fromOvmHost(host):
|
||||
return normalizeToGson(json.dumps(host, cls=OvmHostEncoder))
|
||||
|
||||
class OvmHost(OvmObject):
|
||||
masterIp = ''
|
||||
cpuNum = 0
|
||||
cpuSpeed = 0
|
||||
totalMemory = 0
|
||||
freeMemory = 0
|
||||
dom0Memory = 0
|
||||
agentVersion = ''
|
||||
name = ''
|
||||
dom0KernelVersion = ''
|
||||
hypervisorVersion = ''
|
||||
|
||||
def _getVmPathFromPrimaryStorage(self, vmName):
|
||||
'''
|
||||
we don't have a database to store vm states, so there is no way to retrieve information of a vm
|
||||
when it was already stopped. The trick is to try to find the vm path in primary storage then we
|
||||
can read information from its configure file.
|
||||
'''
|
||||
mps = OvmStoragePool()._getAllMountPoints()
|
||||
vmPath = None
|
||||
for p in mps:
|
||||
vmPath = join(p, 'running_pool', vmName)
|
||||
if exists(vmPath): break
|
||||
if not vmPath:
|
||||
logger.error(self._getVmPathFromPrimaryStorage, "Cannot find link for %s in any primary storage, the vm was really gone!"%vmName)
|
||||
raise Exception("Cannot find link for %s in any primary storage, the vm was really gone!"%vmName)
|
||||
return vmPath
|
||||
|
||||
def _vmNameToPath(self, vmName):
|
||||
return successToMap(xen_get_vm_path(vmName))['path']
|
||||
|
||||
def _getAllDomains(self):
|
||||
stdout = timeout_command(["xm", "list"])
|
||||
l = [ line.split()[:2] for line in stdout.splitlines() ]
|
||||
l = [ (name, id) for (name, id) in l if name not in ("Name", "Domain-0") ]
|
||||
return l
|
||||
|
||||
def _getDomainIdByName(self, vmName):
|
||||
l = self._getAllDomains()
|
||||
for name, id in l:
|
||||
if vmName == name: return id
|
||||
raise NoVmFoundException("No domain id for %s found"%vmName)
|
||||
|
||||
@staticmethod
|
||||
def registerAsMaster(hostname, username="oracle", password="password", port=8899, isSsl=False):
|
||||
try:
|
||||
logger.debug(OvmHost.registerAsMaster, "ip=%s, username=%s, password=%s, port=%s, isSsl=%s"%(hostname, username, password, port, isSsl))
|
||||
exceptionIfNoSuccess(register_server(hostname, 'site', False, username, password, port, isSsl),
|
||||
"Register %s as site failed"%hostname)
|
||||
exceptionIfNoSuccess(register_server(hostname, 'utility', False, username, password, port, isSsl),
|
||||
"Register %s as utility failed"%hostname)
|
||||
rs = SUCC()
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.registerAsMaster, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.registerAsMaster), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def registerAsVmServer(hostname, username="oracle", password="password", port=8899, isSsl=False):
|
||||
try:
|
||||
logger.debug(OvmHost.registerAsVmServer, "ip=%s, username=%s, password=%s, port=%s, isSsl=%s"%(hostname, username, password, port, isSsl))
|
||||
exceptionIfNoSuccess(register_server(hostname, 'xen', False, username, password, port, isSsl),
|
||||
"Register %s as site failed"%hostname)
|
||||
rs = SUCC()
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.registerAsVmServer, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.registerAsVmServer), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def ping(hostname):
|
||||
try:
|
||||
logger.debug(OvmHost.ping, "ping %s"%hostname)
|
||||
exceptionIfNoSuccess(get_srv_agent_status(hostname), "Ovs agent is down")
|
||||
rs = SUCC()
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.ping, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.ping, errmsg))
|
||||
|
||||
@staticmethod
|
||||
def getDetails():
|
||||
try:
|
||||
obj = OvmHost()
|
||||
masterIp = successToMap(get_master_ip())
|
||||
safeSetAttr(obj, 'masterIp', masterIp['ip'])
|
||||
xmInfo = successToMap(xen_get_xm_info())
|
||||
totalMemory = MtoBytes(long(xmInfo['total_memory']))
|
||||
safeSetAttr(obj, 'totalMemory', totalMemory)
|
||||
freeMemory = MtoBytes(long(xmInfo['free_memory']))
|
||||
safeSetAttr(obj, 'freeMemory', freeMemory)
|
||||
dom0Memory = totalMemory - freeMemory
|
||||
safeSetAttr(obj, 'dom0Memory', dom0Memory)
|
||||
cpuNum = int(xmInfo['nr_cpus'])
|
||||
safeSetAttr(obj, 'cpuNum', cpuNum)
|
||||
cpuSpeed = int(xmInfo['cpu_mhz'])
|
||||
safeSetAttr(obj, 'cpuSpeed', cpuSpeed)
|
||||
name = xmInfo['host']
|
||||
safeSetAttr(obj, 'name', name)
|
||||
dom0KernelVersion = xmInfo['release']
|
||||
safeSetAttr(obj, 'dom0KernelVersion', dom0KernelVersion)
|
||||
hypervisorVersion = xmInfo['xen_major'] + '.' + xmInfo['xen_minor'] + xmInfo['xen_extra']
|
||||
safeSetAttr(obj, 'hypervisorVersion', hypervisorVersion)
|
||||
agtVersion = successToMap(get_agent_version())
|
||||
safeSetAttr(obj, 'agentVersion', agtVersion['agent_version'])
|
||||
res = fromOvmHost(obj)
|
||||
logger.debug(OvmHost.getDetails, res)
|
||||
return res
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.getDetails, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.getDetails), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getPerformanceStats(bridgeName):
|
||||
try:
|
||||
rxBytesPath = join("/sys/class/net/", bridgeName, "statistics/rx_bytes")
|
||||
txBytesPath = join("/sys/class/net/", bridgeName, "statistics/tx_bytes")
|
||||
if not exists(rxBytesPath): raise Exception("Cannot find %s"%rxBytesPath)
|
||||
if not exists(txBytesPath): raise Exception("Cannot find %s"%txBytesPath)
|
||||
rxBytes = long(doCmd(['cat', rxBytesPath])) / 1000
|
||||
txBytes = long(doCmd(['cat', txBytesPath])) / 1000
|
||||
sysPerf = successToMap(sys_perf_info())
|
||||
cpuUtil = float(100 - float(sysPerf['cpu_idle']) * 100)
|
||||
freeMemory = MtoBytes(long(sysPerf['mem_free']))
|
||||
xmInfo = successToMap(xen_get_xm_info())
|
||||
totalMemory = MtoBytes(long(xmInfo['total_memory']))
|
||||
rs = toGson({"cpuUtil":cpuUtil, "totalMemory":totalMemory, "freeMemory":freeMemory, "rxBytes":rxBytes, "txBytes":txBytes})
|
||||
logger.info(OvmHost.getPerformanceStats, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.getPerformanceStats, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.getPerformanceStats), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getAllVms():
|
||||
try:
|
||||
l = OvmHost()._getAllDomains()
|
||||
dct = {}
|
||||
host = OvmHost()
|
||||
for name, id in l:
|
||||
vmPath = host._getVmPathFromPrimaryStorage(name)
|
||||
vmStatus = db_get_vm(vmPath)
|
||||
dct[name] = vmStatus['status']
|
||||
rs = toGson(dct)
|
||||
logger.info(OvmHost.getAllVms, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.getAllVms, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.getAllVms), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def fence(ip):
|
||||
# try 3 times to avoid race condition that read when heartbeat file is being written
|
||||
def getTimeStamp(hbFile):
|
||||
for i in range(1, 3):
|
||||
f = open(hbFile, 'r')
|
||||
str = f.readline()
|
||||
items = re.findall(HEARTBEAT_TIMESTAMP_PATTERN, str)
|
||||
if len(items) == 0:
|
||||
logger.debug(OvmHost.fence, "Get an incorrect heartbeat data %s, will retry %s times" % (str, 3-i))
|
||||
f.close()
|
||||
time.sleep(5)
|
||||
else:
|
||||
f.close()
|
||||
timestamp = items[0]
|
||||
return timestamp.lstrip('<timestamp>').rstrip('</timestamp>')
|
||||
|
||||
# totally check in 6 mins, the update frequency is 2 mins
|
||||
def check(hbFile):
|
||||
for i in range(1, 6):
|
||||
ts = getTimeStamp(hbFile)
|
||||
time.sleep(60)
|
||||
nts = getTimeStamp(hbFile)
|
||||
if ts != nts: return True
|
||||
else: logger.debug(OvmHost.fence, '%s is not updated, old value=%s, will retry %s times'%(hbFile, ts, 6-i))
|
||||
return False
|
||||
|
||||
try:
|
||||
mountpoints = OvmStoragePool()._getAllMountPoints()
|
||||
hbFile = None
|
||||
for m in mountpoints:
|
||||
p = join(m, HEARTBEAT_DIR, ipToHeartBeatFileName(ip))
|
||||
if exists(p):
|
||||
hbFile = p
|
||||
break
|
||||
|
||||
if not hbFile: raise Exception('Can not find heartbeat file for %s in pools %s'%(ip, mountpoints))
|
||||
rs = toGson({"isLive":check(hbFile)})
|
||||
logger.debug(OvmHost.fence, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.fence, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.fence), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def setupHeartBeat(poolUuid, ip):
|
||||
try:
|
||||
sr = OvmStoragePool()._getSrByNameLable(poolUuid)
|
||||
OvmHaHeartBeat.start(sr.mountpoint, ip)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.setupHeartBeat, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.setupHeartBeat), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def pingAnotherHost(ip):
|
||||
try:
|
||||
doCmd(['ping', '-c', '1', '-n', '-q', ip])
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmHost.pingAnotherHost, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmHost, OvmHost.pingAnotherHost), errmsg)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print OvmHost.getAllVms()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
'''
|
||||
Created on May 19, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
import logging
|
||||
|
||||
class OvmLogger(object):
|
||||
'''
|
||||
classdocs
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, className):
|
||||
'''
|
||||
Constructor
|
||||
'''
|
||||
self.className = className
|
||||
self.logger = logging.getLogger(className)
|
||||
|
||||
def info(self, func, msg=None):
|
||||
assert callable(func), "%s is not a function"%func
|
||||
fmt = "[%s.%s]: "%(self.className, func.__name__)
|
||||
self.logger.info("%s%s"%(fmt,msg))
|
||||
|
||||
def debug(self, func, msg=None):
|
||||
assert callable(func), "%s is not a function"%func
|
||||
fmt = "[%s.%s]: "%(self.className, func.__name__)
|
||||
self.logger.debug("%s%s"%(fmt,msg))
|
||||
|
||||
def error(self, func, msg=None):
|
||||
assert callable(func), "%s is not a function"%func
|
||||
fmt = "[%s.%s]: "%(self.className, func.__name__)
|
||||
self.logger.error("%s%s"%(fmt,msg))
|
||||
|
||||
def warning(self, func, msg=None):
|
||||
assert callable(func), "%s is not a function"%func
|
||||
fmt = "[%s.%s]: "%(self.className, func.__name__)
|
||||
self.logger.warning("%s%s"%(fmt,msg))
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
from OvmCommonModule import *
|
||||
import traceback
|
||||
import time
|
||||
import re
|
||||
|
||||
logger = OvmLogger("OvmNetwork")
|
||||
|
||||
class Filter:
|
||||
class Network:
|
||||
IFNAME_LO = r'(lo)'
|
||||
IFNAME_PIF = r'(eth\d+$)'
|
||||
IFNAME_VLAN = r'(eth\d+.\d+$)'
|
||||
IFNAME_BRIDGE = r'(xenbr\d+|vlan\d+)'
|
||||
|
||||
class Parser(object):
|
||||
'''
|
||||
classdocs
|
||||
'''
|
||||
def findall(self, pattern, samples):
|
||||
"""
|
||||
@param pattern: search pattern
|
||||
@param result: Parser line execution result
|
||||
@return : list of search
|
||||
find result of Parser which has same pattern
|
||||
findall Parser find all pattern in a string
|
||||
"""
|
||||
result = []
|
||||
for line in samples:
|
||||
items = re.findall(pattern, line)
|
||||
for item in items:
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
def checkPattern(self, pattern, cmd_result):
|
||||
"""
|
||||
@param pattern: search pattern
|
||||
@param cmd_result: Parser line execution result
|
||||
@return : True (if pattern is occurred)
|
||||
"""
|
||||
for line in cmd_result:
|
||||
items = re.findall(pattern, line)
|
||||
if len(items) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def search(self, cmd_result, pattern):
|
||||
return None
|
||||
|
||||
class OvmVlanDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDict = asciiLoads(jStr)
|
||||
vlan = OvmVlan()
|
||||
setAttrFromDict(vlan, 'vid', deDict, int)
|
||||
setAttrFromDict(vlan, 'pif', deDict)
|
||||
return vlan
|
||||
|
||||
class OvmVlanEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmVlan): raise Exception("%s is not instance of OvmVlan"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'name')
|
||||
safeDictSet(obj, dct, 'vid')
|
||||
safeDictSet(obj, dct, 'pif')
|
||||
return dct
|
||||
|
||||
def toOvmVlan(jStr):
|
||||
return json.loads(jStr, cls=OvmVlanDecoder)
|
||||
|
||||
def fromOvmVlan(vlan):
|
||||
return normalizeToGson(json.dumps(vlan, cls=OvmVlanEncoder))
|
||||
|
||||
class OvmBridgeDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDic = asciiLoads(jStr)
|
||||
bridge = OvmBridge()
|
||||
setAttrFromDict(bridge, 'name', deDic)
|
||||
setAttrFromDict(bridge, 'attach', deDic)
|
||||
return bridge
|
||||
|
||||
class OvmBridgeEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmBridge): raise Exception("%s is not instance of OvmBridge"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'name')
|
||||
safeDictSet(obj, dct, 'attach')
|
||||
safeDictSet(obj, dct, 'interfaces')
|
||||
return dct
|
||||
|
||||
def toOvmBridge(jStr):
|
||||
return json.loads(jStr, cls=OvmBridgeDecoder)
|
||||
|
||||
def fromOvmBridge(bridge):
|
||||
return normalizeToGson(json.dumps(bridge, cls=OvmBridgeEncoder))
|
||||
|
||||
class OvmInterface(OvmObject):
|
||||
name = ''
|
||||
|
||||
class OvmVlan(OvmInterface):
|
||||
vid = 0
|
||||
pif = ''
|
||||
|
||||
class OvmBridge(OvmInterface):
|
||||
attach = ''
|
||||
interfaces = []
|
||||
|
||||
|
||||
class OvmNetwork(OvmObject):
|
||||
'''
|
||||
Network
|
||||
'''
|
||||
|
||||
@property
|
||||
def pifs(self):
|
||||
return self._getInterfaces("pif")
|
||||
|
||||
@property
|
||||
def vlans(self):
|
||||
return self._getInterfaces("vlan")
|
||||
|
||||
@property
|
||||
def bridges(self):
|
||||
return self._getInterfaces("bridge")
|
||||
|
||||
def __init__(self):
|
||||
self.Parser = Parser()
|
||||
|
||||
def _createVlan(self, vlan):
|
||||
"""
|
||||
@param jsonString : parameter from client side
|
||||
@return : succ xxxxx
|
||||
ex. jsonString => {vid:100, pif:eth0}
|
||||
ex. return =>
|
||||
"""
|
||||
|
||||
#Pre-condition
|
||||
#check Physical Interface Name
|
||||
if vlan.pif not in self.pifs.keys():
|
||||
msg = "Physical Interface(%s) does not exist" % vlan.pif
|
||||
logger.debug(self._createVlan, msg)
|
||||
raise Exception(msg)
|
||||
|
||||
#Pre-condition
|
||||
#check Vlan Interface Name
|
||||
ifName = "%s.%s" % (vlan.pif, vlan.vid)
|
||||
if ifName in self.vlans.keys():
|
||||
msg = "Vlan Interface(%s) already exist, return it" % ifName
|
||||
logger.debug(self._createVlan, msg)
|
||||
return self.vlans[ifName]
|
||||
|
||||
doCmd(['vconfig', 'add', vlan.pif, vlan.vid])
|
||||
self.bringUP(ifName)
|
||||
logger.debug(self._createVlan, "Create vlan %s successfully"%ifName)
|
||||
return self.vlans[ifName]
|
||||
|
||||
def _deleteVlan(self, name):
|
||||
if name not in self.vlans.keys():
|
||||
raise Exception("No vlan device %s found"%name)
|
||||
|
||||
vlan = self.vlans[name]
|
||||
self.bringDown(vlan.name)
|
||||
doCmd(['vconfig', 'rem', vlan.name])
|
||||
logger.debug(self._deleteVlan, "Delete vlan %s successfully"%vlan.name)
|
||||
|
||||
|
||||
def _createBridge(self, bridge):
|
||||
"""
|
||||
@return : success
|
||||
ex. {bridge:xapi100, attach:eth0.100}
|
||||
create bridge interface, and attached it
|
||||
cmd 1: brctl addbr bridge
|
||||
cmd 2: brctl addif brdige attach
|
||||
"""
|
||||
|
||||
if "xenbr" not in bridge.name and "vlan" not in bridge.name:
|
||||
raise Exception("Invalid bridge name %s. Bridge name must be in partten xenbr/vlan, e.g. xenbr0"%bridge.name)
|
||||
|
||||
#pre-condition
|
||||
#check Bridge Interface Name
|
||||
if bridge.name in self.bridges.keys():
|
||||
msg = "Bridge(%s) already exist, return it" % bridge.name
|
||||
logger.debug(self._createBridge, msg)
|
||||
return self.bridges[bridge.name]
|
||||
|
||||
#pre-condition
|
||||
#check attach must exist
|
||||
#possible to attach in PIF or VLAN
|
||||
if bridge.attach not in self.vlans.keys() and bridge.attach not in self.pifs.keys():
|
||||
msg = "%s is not either pif or vlan" % bridge.attach
|
||||
logger.error(self._createBridge, msg)
|
||||
raise Exception(msg)
|
||||
|
||||
doCmd(['brctl', 'addbr', bridge.name])
|
||||
doCmd(['brctl', 'addif', bridge.name, bridge.attach])
|
||||
self.bringUP(bridge.name)
|
||||
logger.debug(self._createBridge, "Create bridge %s on %s successfully"%(bridge.name, bridge.attach))
|
||||
return self.bridges[bridge.name]
|
||||
|
||||
def _getBridges(self):
|
||||
return self.bridges.keys()
|
||||
|
||||
def _getVlans(self):
|
||||
return self.vlans.keys()
|
||||
|
||||
def _deleteBridge(self, name):
|
||||
if name not in self.bridges.keys():
|
||||
raise Exception("Can not find bridge %s"%name)
|
||||
|
||||
bridge = self.bridges[name]
|
||||
if bridge.attach in bridge.interfaces: bridge.interfaces.remove(bridge.attach)
|
||||
if len(bridge.interfaces) != 0:
|
||||
logger.debug(self._deleteBridge, "There are still some interfaces(%s) on bridge %s"%(bridge.interfaces, bridge.name))
|
||||
return False
|
||||
self.bringDown(bridge.name)
|
||||
doCmd(['brctl', 'delbr', bridge.name])
|
||||
logger.debug(self._deleteBridge, "Delete bridge %s successfully"%bridge.name)
|
||||
return True
|
||||
|
||||
def _getInterfaces(self, type):
|
||||
"""
|
||||
@param type : ["pif", "bridge", "tap"]
|
||||
@return : dictionary of Interface Objects
|
||||
get All Interfaces based on type
|
||||
"""
|
||||
devices = os.listdir('/sys/class/net')
|
||||
ifs = {}
|
||||
if type == "pif":
|
||||
devs = self.Parser.findall(Filter.Network.IFNAME_PIF, devices)
|
||||
for dev in set(devs):
|
||||
ifInst = OvmInterface()
|
||||
ifInst.name = dev
|
||||
ifs[dev] = ifInst
|
||||
|
||||
elif type == "vlan":
|
||||
devs = self.Parser.findall(Filter.Network.IFNAME_VLAN, devices)
|
||||
for dev in set(devs):
|
||||
ifInst = OvmVlan()
|
||||
ifInst.name = dev
|
||||
(pif, vid) = dev.split('.')
|
||||
ifInst.pif = pif
|
||||
ifInst.vid = vid
|
||||
ifs[dev] = ifInst
|
||||
|
||||
elif type == "bridge":
|
||||
devs = self.Parser.findall(Filter.Network.IFNAME_BRIDGE, devices)
|
||||
for dev in set(devs):
|
||||
ifInst = OvmBridge()
|
||||
ifInst.name = dev
|
||||
devs = os.listdir(join('/sys/class/net', dev, 'brif'))
|
||||
ifInst.interfaces = devs
|
||||
attches = self.Parser.findall(Filter.Network.IFNAME_PIF, devs) + self.Parser.findall(Filter.Network.IFNAME_VLAN, devs)
|
||||
if len(attches) > 1: raise Exception("Multiple PIF on bridge %s (%s)"%(dev, attches))
|
||||
elif len(attches) == 0: ifInst.attach = "null"
|
||||
elif len(attches) == 1: ifInst.attach = attches[0]
|
||||
ifs[dev] = ifInst
|
||||
|
||||
return ifs
|
||||
|
||||
def bringUP(self, ifName):
|
||||
doCmd(['ifconfig', ifName, 'up'])
|
||||
|
||||
def bringDown(self, ifName):
|
||||
doCmd(['ifconfig', ifName, 'down'])
|
||||
|
||||
@staticmethod
|
||||
def createBridge(jStr):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
network._createBridge(toOvmBridge(jStr))
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.createBridge, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createBridge), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def deleteBridge(name):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
network._deleteBridge(name)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.deleteBridge, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteBridge), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getAllBridges():
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
rs = toGson(network._getBridges())
|
||||
logger.debug(OvmNetwork.getAllBridges, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.getAllBridges, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getAllBridges), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getBridgeByIp(ip):
|
||||
try:
|
||||
routes = doCmd(['ip', 'route']).split('\n')
|
||||
brName = None
|
||||
for r in routes:
|
||||
if ip in r and "xenbr" in r or "vlan" in r:
|
||||
brName = r.split(' ')[2]
|
||||
break
|
||||
if not brName: raise Exception("Cannot find bridge with IP %s"%ip)
|
||||
logger.debug(OvmNetwork.getBridgeByIp, "bridge:%s, ip:%s"%(brName, ip))
|
||||
return toGson({"bridge":brName})
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.getBridgeByIp, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getBridgeByIp), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getVlans():
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
rs = toGson(network._getVlans())
|
||||
logger.debug(OvmNetwork.getVlans, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.getVlans, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getVlans), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def createVlan(jStr):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
vlan = network._createVlan(toOvmVlan(jStr))
|
||||
rs = fromOvmVlan(vlan)
|
||||
logger.debug(OvmNetwork.createVlan, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.createVlan, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createVlan), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def createVlanBridge(bridgeDetails, vlanDetails):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
v = toOvmVlan(vlanDetails)
|
||||
b = toOvmBridge(bridgeDetails)
|
||||
vlan = network._createVlan(v)
|
||||
b.attach = vlan.name
|
||||
network._createBridge(b)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.createVlanBridge, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createVlanBridge), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def deleteVlanBridge(name):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
if name not in network.bridges.keys():
|
||||
logger.debug(OvmNetwork.deleteVlanBridge, "No bridge %s found"%name)
|
||||
return SUCC()
|
||||
|
||||
bridge = network.bridges[name]
|
||||
vlanName = bridge.attach
|
||||
if network._deleteBridge(name):
|
||||
if vlanName != "null":
|
||||
network._deleteVlan(vlanName)
|
||||
else:
|
||||
logger.warning(OvmNetwork.deleteVlanBridge, "Bridge %s has no vlan device"%name)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.deleteVlanBridge, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteVlanBridge), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getBridgeDetails(name):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
if name not in network.bridges.keys():
|
||||
raise Exception("No bridge %s found"%name)
|
||||
bridge = network.bridges[name]
|
||||
rs = fromOvmBridge(bridge)
|
||||
logger.debug(OvmNetwork.getBridgeDetails, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.getBridgeDetails, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getBridgeDetails), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def deleteVlan(name):
|
||||
try:
|
||||
network = OvmNetwork()
|
||||
network._deleteVlan(name)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmNetwork.deleteVlan, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteVlan), errmsg)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
OvmNetwork.getBridgeDetails(sys.argv[1])
|
||||
#=======================================================================
|
||||
# txt = json.dumps({"vid":104, "pif":"eth0"})
|
||||
# txt2 = json.dumps({"name":"xapi3", "attach":"eth0.104"})
|
||||
# print nw.createVlan(txt)
|
||||
# print nw.createBridge(txt2)
|
||||
#
|
||||
# nw.deleteBridge("xapi3")
|
||||
# nw.deleteVlan("eth0.104")
|
||||
#=======================================================================
|
||||
|
||||
except Exception, e:
|
||||
print e
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
'''
|
||||
Created on May 17, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
|
||||
class OvmObject(object):
|
||||
pass
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
*** OVSServices.py 2011-06-06 12:31:23.279919998 -0700
|
||||
--- /tmp/OVSServices.py 2011-06-06 12:32:13.275919997 -0700
|
||||
***************
|
||||
*** 68,73 ****
|
||||
--- 68,75 ----
|
||||
import OVSVMXParser #pylint: disable-msg=W0611
|
||||
import OVSVMDKParser #pylint: disable-msg=W0611
|
||||
|
||||
+ import OvmDispatcher
|
||||
+
|
||||
from OVSWrappers import D
|
||||
from OVSCommons import exposed
|
||||
|
||||
***************
|
||||
*** 113,118 ****
|
||||
--- 115,121 ----
|
||||
self.sleep = sleep
|
||||
|
||||
self._load_modules()
|
||||
+ OvmDispatcher.InitOvmDispacther()
|
||||
|
||||
# #xenapi
|
||||
# import xen.xend.XendAPI as XendAPI
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
from OvmCommonModule import *
|
||||
from ConfigFileOps import *
|
||||
import os
|
||||
import logging
|
||||
|
||||
class OvmSecurityGroup(OvmObject):
|
||||
|
||||
@staticmethod
|
||||
def can_bridge_firewall():
|
||||
try:
|
||||
execute("which iptables")
|
||||
except:
|
||||
print "iptables was not found on the host"
|
||||
return False
|
||||
|
||||
try:
|
||||
execute("which ebtables")
|
||||
except:
|
||||
print "ebtables was not found on the host"
|
||||
return False
|
||||
|
||||
if not os.path.exists('/var/run/cloud'):
|
||||
os.makedirs('/var/run/cloud')
|
||||
|
||||
return OvmSecurityGroup.cleanup_rules()
|
||||
|
||||
@staticmethod
|
||||
def cleanup_rules():
|
||||
try:
|
||||
chainscmd = "iptables-save | grep '^:' | grep -v '.*-def' | awk '{print $1}' | cut -d':' -f2"
|
||||
chains = execute(chainscmd).split('\n')
|
||||
cleaned = 0
|
||||
cleanup = []
|
||||
for chain in chains:
|
||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
||||
vm_name = chain
|
||||
else:
|
||||
continue
|
||||
|
||||
cmd = "xm list | grep " + vm_name
|
||||
try:
|
||||
result = execute(cmd)
|
||||
except:
|
||||
result = None
|
||||
|
||||
if result == None or len(result) == 0:
|
||||
logging.debug("chain " + chain + " does not correspond to a vm, cleaning up")
|
||||
cleanup.append(vm_name)
|
||||
|
||||
for vm_name in cleanup:
|
||||
OvmSecurityGroup.delete_all_network_rules_for_vm(vm_name)
|
||||
|
||||
logging.debug("Cleaned up rules for " + str(len(cleanup)) + " chains")
|
||||
return True
|
||||
except:
|
||||
logging.debug("Failed to cleanup rules !")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def add_fw_framework(bridge_name):
|
||||
try:
|
||||
cfo = ConfigFileOps("/etc/sysctl.conf")
|
||||
cfo.addEntry("net.bridge.bridge-nf-call-arptables", "1")
|
||||
cfo.addEntry("net.bridge.bridge-nf-call-iptables", "1")
|
||||
cfo.addEntry("net.bridge.bridge-nf-call-ip6tables", "1")
|
||||
cfo.save()
|
||||
|
||||
execute("sysctl -p /etc/sysctl.conf")
|
||||
except:
|
||||
logging.debug("failed to turn on bridge netfilter")
|
||||
return False
|
||||
|
||||
brfw = "BF-" + bridge_name
|
||||
try:
|
||||
execute("iptables -L " + brfw)
|
||||
except:
|
||||
execute("iptables -N " + brfw)
|
||||
|
||||
brfwout = brfw + "-OUT"
|
||||
try:
|
||||
execute("iptables -L " + brfwout)
|
||||
except:
|
||||
execute("iptables -N " + brfwout)
|
||||
|
||||
brfwin = brfw + "-IN"
|
||||
try:
|
||||
execute("iptables -L " + brfwin)
|
||||
except:
|
||||
execute("iptables -N " + brfwin)
|
||||
|
||||
try:
|
||||
refs = execute("iptables -n -L " + brfw + " |grep " + brfw + " | cut -d \( -f2 | awk '{print $1}'").strip()
|
||||
if refs == "0":
|
||||
execute("iptables -I FORWARD -i " + bridge_name + " -j DROP")
|
||||
execute("iptables -I FORWARD -o " + bridge_name + " -j DROP")
|
||||
execute("iptables -I FORWARD -i " + bridge_name + " -m physdev --physdev-is-bridged -j " + brfw)
|
||||
execute("iptables -I FORWARD -o " + bridge_name + " -m physdev --physdev-is-bridged -j " + brfw)
|
||||
phydev = execute("brctl show |grep " + bridge_name + " | awk '{print $4}'").strip()
|
||||
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-out " + phydev + " -j ACCEPT")
|
||||
execute("iptables -A " + brfw + " -m state --state RELATED,ESTABLISHED -j ACCEPT")
|
||||
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-out -j " + brfwout)
|
||||
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-in -j " + brfwin)
|
||||
|
||||
return True
|
||||
except:
|
||||
try:
|
||||
execute("iptables -F " + brfw)
|
||||
except:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def default_network_rules_user_vm(vm_name, vm_id, vm_ip, vm_mac, vif, bridge_name):
|
||||
if not OvmSecurityGroup.add_fw_framework(bridge_name):
|
||||
return False
|
||||
|
||||
OvmSecurityGroup.delete_iptables_rules_for_vm(vm_name)
|
||||
OvmSecurityGroup.delete_ebtables_rules_for_vm(vm_name)
|
||||
|
||||
bridge_firewall_chain = "BF-" + bridge_name
|
||||
vm_chain = vm_name
|
||||
default_vm_chain = '-'.join(vm_chain.split('-')[:-1]) + "-def"
|
||||
dom_id = getDomId(vm_name)
|
||||
|
||||
try:
|
||||
execute("iptables -N " + vm_chain)
|
||||
except:
|
||||
execute("iptables -F " + vm_chain)
|
||||
|
||||
try:
|
||||
execute("iptables -N " + default_vm_chain)
|
||||
except:
|
||||
execute("iptables -F " + default_vm_chain)
|
||||
|
||||
try:
|
||||
execute("iptables -A " + bridge_firewall_chain + "-OUT" + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + default_vm_chain)
|
||||
execute("iptables -A " + bridge_firewall_chain + "-IN" + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -j " + default_vm_chain)
|
||||
execute("iptables -A " + default_vm_chain + " -m state --state RELATED,ESTABLISHED -j ACCEPT")
|
||||
|
||||
# Allow DHCP
|
||||
execute("iptables -A " + default_vm_chain + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --dport 67 --sport 68 -j ACCEPT")
|
||||
execute("iptables -A " + default_vm_chain + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -p udp --dport 68 --sport 67 -j ACCEPT")
|
||||
|
||||
# Don't let a VM spoof its ip address
|
||||
if vm_ip is not None:
|
||||
execute("iptables -A " + default_vm_chain + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT")
|
||||
|
||||
execute("iptables -A " + default_vm_chain + " -j " + vm_chain)
|
||||
execute("iptables -A " + vm_chain + " -j DROP")
|
||||
except:
|
||||
logging.debug("Failed to program default rules for vm " + vm_name)
|
||||
return False
|
||||
|
||||
OvmSecurityGroup.default_ebtables_rules(vm_chain, vm_ip, vm_mac, vif)
|
||||
|
||||
if vm_ip is not None:
|
||||
if (OvmSecurityGroup.write_rule_log_for_vm(vm_name, vm_id, vm_ip, dom_id, '_initial_', '-1') == False):
|
||||
logging.debug("Failed to log default network rules, ignoring")
|
||||
|
||||
logging.debug("Programmed default rules for vm " + vm_name)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif):
|
||||
vm_chain_in = vm_name + "-in"
|
||||
vm_chain_out = vm_name + "-out"
|
||||
|
||||
for chain in [vm_chain_in, vm_chain_out]:
|
||||
try:
|
||||
execute("ebtables -t nat -N " + chain)
|
||||
except:
|
||||
execute("ebtables -t nat -F " + chain)
|
||||
|
||||
try:
|
||||
execute("ebtables -t nat -A PREROUTING -i " + vif + " -j " + vm_chain_in)
|
||||
execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vm_chain_out)
|
||||
except:
|
||||
logging.debug("Failed to program default rules")
|
||||
return False
|
||||
|
||||
try:
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -s ! " + vm_mac + " -j DROP")
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP -s ! " + vm_mac + " -j DROP")
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP --arp-mac-src ! " + vm_mac + " -j DROP")
|
||||
if vm_ip is not None:
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP --arp-ip-src ! " + vm_ip + " -j DROP")
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP --arp-op Request -j ACCEPT")
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP --arp-op Reply -j ACCEPT")
|
||||
execute("ebtables -t nat -A " + vm_chain_in + " -p ARP -j DROP")
|
||||
except:
|
||||
logging.exception("Failed to program default ebtables IN rules")
|
||||
return False
|
||||
|
||||
try:
|
||||
execute("ebtables -t nat -A " + vm_chain_out + " -p ARP --arp-op Reply --arp-mac-dst ! " + vm_mac + " -j DROP")
|
||||
if vm_ip is not None:
|
||||
execute("ebtables -t nat -A " + vm_chain_out + " -p ARP --arp-ip-dst ! " + vm_ip + " -j DROP")
|
||||
execute("ebtables -t nat -A " + vm_chain_out + " -p ARP --arp-op Request -j ACCEPT")
|
||||
execute("ebtables -t nat -A " + vm_chain_out + " -p ARP --arp-op Reply -j ACCEPT")
|
||||
execute("ebtables -t nat -A " + vm_chain_out + " -p ARP -j DROP")
|
||||
except:
|
||||
logging.debug("Failed to program default ebtables OUT rules")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vm_mac, rules, vif, bridge_name):
|
||||
try:
|
||||
vm_chain = vm_name
|
||||
dom_id = getDomId(vm_name)
|
||||
|
||||
changes = []
|
||||
changes = OvmSecurityGroup.check_rule_log_for_vm(vm_name, vm_id, vm_ip, dom_id, signature, seqno)
|
||||
|
||||
if not 1 in changes:
|
||||
logging.debug("Rules already programmed for vm " + vm_name)
|
||||
return True
|
||||
|
||||
if changes[0] or changes[1] or changes[2] or changes[3]:
|
||||
if not OvmSecurityGroup.default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, bridge_name):
|
||||
return False
|
||||
|
||||
if rules == "" or rules == None:
|
||||
lines = []
|
||||
else:
|
||||
lines = rules.split(';')[:-1]
|
||||
|
||||
logging.debug("Programming network rules for IP: " + vm_ip + " vmname=" + vm_name)
|
||||
execute("iptables -F " + vm_chain)
|
||||
|
||||
for line in lines:
|
||||
tokens = line.split(':')
|
||||
if len(tokens) != 4:
|
||||
continue
|
||||
protocol = tokens[0]
|
||||
start = tokens[1]
|
||||
end = tokens[2]
|
||||
cidrs = tokens.pop();
|
||||
ips = cidrs.split(",")
|
||||
ips.pop()
|
||||
allow_any = False
|
||||
if '0.0.0.0/0' in ips:
|
||||
i = ips.index('0.0.0.0/0')
|
||||
del ips[i]
|
||||
allow_any = True
|
||||
|
||||
port_range = start + ":" + end
|
||||
if ips:
|
||||
if protocol == 'all':
|
||||
for ip in ips:
|
||||
execute("iptables -I " + vm_chain + " -m state --state NEW -s " + ip + " -j ACCEPT")
|
||||
elif protocol != 'icmp':
|
||||
for ip in ips:
|
||||
execute("iptables -I " + vm_chain + " -p " + protocol + " -m " + protocol + " --dport " + port_range + " -m state --state NEW -s " + ip + " -j ACCEPT")
|
||||
else:
|
||||
port_range = start + "/" + end
|
||||
if start == "-1":
|
||||
port_range = "any"
|
||||
for ip in ips:
|
||||
execute("iptables -I " + vm_chain + " -p icmp --icmp-type " + port_range + " -s " + ip + " -j ACCEPT")
|
||||
|
||||
if allow_any and protocol != 'all':
|
||||
if protocol != 'icmp':
|
||||
execute("iptables -I " + vm_chain + " -p " + protocol + " -m " + protocol + " --dport " + port_range + " -m state --state NEW -j ACCEPT")
|
||||
else:
|
||||
port_range = start + "/" + end
|
||||
if start == "-1":
|
||||
port_range = "any"
|
||||
execute("iptables -I " + vm_chain + " -p icmp --icmp-type " + port_range + " -j ACCEPT")
|
||||
|
||||
iptables = "iptables -A " + vm_chain + " -j DROP"
|
||||
execute(iptables)
|
||||
|
||||
return OvmSecurityGroup.write_rule_log_for_vm(vm_name, vm_id, vm_ip, dom_id, signature, seqno)
|
||||
except:
|
||||
logging.debug("Failed to network rule !: " + sys.exc_type)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def delete_all_network_rules_for_vm(vm_name, vif = None):
|
||||
OvmSecurityGroup.delete_iptables_rules_for_vm(vm_name)
|
||||
OvmSecurityGroup.delete_ebtables_rules_for_vm(vm_name)
|
||||
|
||||
vm_chain = vm_name
|
||||
default_vm_chain = None
|
||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
||||
default_vm_chain = '-'.join(vm_name.split('-')[:-1]) + "-def"
|
||||
|
||||
try:
|
||||
if default_vm_chain != None:
|
||||
execute("iptables -F " + default_vm_chain)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete chain " + default_vm_chain)
|
||||
|
||||
try:
|
||||
if default_vm_chain != None:
|
||||
execute("iptables -X " + vmchain_default)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete chain " + default_vm_chain)
|
||||
|
||||
try:
|
||||
execute("iptables -F " + vm_chain)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete chain " + vm_chain)
|
||||
|
||||
try:
|
||||
execute("iptables -X " + vm_chain)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete chain " + vm_chain)
|
||||
|
||||
if vif is not None:
|
||||
try:
|
||||
dnats = execute("iptables-save -t nat | grep " + vif + " | sed 's/-A/-D/'").split("\n")
|
||||
for dnat in dnats:
|
||||
try:
|
||||
execute("iptables -t nat " + dnat)
|
||||
except:
|
||||
logging.debug("Igoring failure to delete dnat: " + dnat)
|
||||
except:
|
||||
pass
|
||||
|
||||
OvmSecurityGroup.remove_rule_log_for_vm(vm_name)
|
||||
|
||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def delete_iptables_rules_for_vm(vm_name):
|
||||
vm_name = OvmSecurityGroup.truncate_vm_name(vm_name)
|
||||
vm_chain = vm_name
|
||||
query = "iptables-save | grep " + vm_chain + " | grep physdev-is-bridged | sed 's/-A/-D/'"
|
||||
delete_cmds = execute(query).split('\n')
|
||||
delete_cmds.pop()
|
||||
|
||||
for cmd in delete_cmds:
|
||||
try:
|
||||
execute("iptables " + cmd)
|
||||
except:
|
||||
logging.exception("Ignoring failure to delete rules for vm " + vm_name)
|
||||
|
||||
@staticmethod
|
||||
def delete_ebtables_rules_for_vm(vm_name):
|
||||
vm_name = OvmSecurityGroup.truncate_vm_name(vm_name)
|
||||
query = "ebtables -t nat -L --Lx | grep ROUTING | grep " + vm_name + " | sed 's/-A/-D/'"
|
||||
delete_cmds = execute(query).split('\n')
|
||||
delete_cmds.pop()
|
||||
|
||||
for cmd in delete_cmds:
|
||||
try:
|
||||
execute(cmd)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete ebtables rules for vm " + vm_name)
|
||||
|
||||
chains = [vm_name + "-in", vm_name + "-out"]
|
||||
|
||||
for chain in chains:
|
||||
try:
|
||||
execute("ebtables -t nat -F " + chain)
|
||||
execute("ebtables -t nat -X " + chain)
|
||||
except:
|
||||
logging.debug("Ignoring failure to delete ebtables chain for vm " + vm_name)
|
||||
|
||||
@staticmethod
|
||||
def truncate_vm_name(vm_name):
|
||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
||||
truncated_vm_name = '-'.join(vm_name.split('-')[:-1])
|
||||
else:
|
||||
truncated_vm_name = vm_name
|
||||
return truncated_vm_name
|
||||
|
||||
@staticmethod
|
||||
def write_rule_log_for_vm(vm_name, vm_id, vm_ip, dom_id, signature, seqno):
|
||||
log_file_name = "/var/run/cloud/" + vm_name + ".log"
|
||||
logging.debug("Writing log to " + log_file_name)
|
||||
logf = open(log_file_name, 'w')
|
||||
output = ','.join([vm_name, vm_id, vm_ip, dom_id, signature, seqno])
|
||||
|
||||
result = True
|
||||
try:
|
||||
logf.write(output)
|
||||
logf.write('\n')
|
||||
except:
|
||||
logging.debug("Failed to write to rule log file " + log_file_name)
|
||||
result = False
|
||||
|
||||
logf.close()
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def remove_rule_log_for_vm(vm_name):
|
||||
log_file_name = "/var/run/cloud/" + vm_name +".log"
|
||||
|
||||
result = True
|
||||
try:
|
||||
os.remove(log_file_name)
|
||||
except:
|
||||
logging.debug("Failed to delete rule log file " + log_file_name)
|
||||
result = False
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def check_rule_log_for_vm(vm_name, vm_id, vm_ip, dom_id, signature, seqno):
|
||||
log_file_name = "/var/run/cloud/" + vm_name + ".log"
|
||||
if not os.path.exists(log_file_name):
|
||||
return [True, True, True, True, True, True]
|
||||
|
||||
try:
|
||||
lines = (line.rstrip() for line in open(log_file_name))
|
||||
except:
|
||||
logging.debug("failed to open " + log_file_name)
|
||||
return [True, True, True, True, True, True]
|
||||
|
||||
[_vm_name, _vm_id, _vm_ip, _dom_id, _signature, _seqno] = ['_', '-1', '_', '-1', '_', '-1']
|
||||
try:
|
||||
for line in lines:
|
||||
[_vm_name, _vm_id, _vm_ip, _dom_id, _signature, _seqno] = line.split(',')
|
||||
break
|
||||
except:
|
||||
logging.debug("Failed to parse log file for vm " + vm_name)
|
||||
remove_rule_log_for_vm(vm_name)
|
||||
return [True, True, True, True, True, True]
|
||||
|
||||
return [(vm_name != _vm_name), (vm_id != _vm_id), (vm_ip != _vm_ip), (dom_id != _dom_id), (signature != _signature), (seqno != _seqno)]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
from OvmCommonModule import *
|
||||
from OVSSiteSR import sp_create, sr_create, sr_do
|
||||
from OVSParser import parse_ocfs2_cluster_conf
|
||||
from OVSXCluster import clusterm_set_ocfs2_cluster_conf, clusterm_start_o2cb_service
|
||||
import re
|
||||
|
||||
class OvmStoragePoolDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
dct = asciiLoads(jStr)
|
||||
pool = OvmStoragePool()
|
||||
setAttrFromDict(pool, 'uuid', dct)
|
||||
setAttrFromDict(pool, 'type', dct)
|
||||
setAttrFromDict(pool, 'path', dct)
|
||||
return pool
|
||||
|
||||
class OvmStoragePoolEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmStoragePool): raise Exception("%s is not instance of OvmStoragePool"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'uuid')
|
||||
safeDictSet(obj, dct, 'type')
|
||||
safeDictSet(obj, dct, 'path')
|
||||
safeDictSet(obj, dct, 'mountPoint')
|
||||
safeDictSet(obj, dct, 'totalSpace')
|
||||
safeDictSet(obj, dct, 'freeSpace')
|
||||
safeDictSet(obj, dct, 'usedSpace')
|
||||
return dct
|
||||
|
||||
def fromOvmStoragePool(pool):
|
||||
return normalizeToGson(json.dumps(pool, cls=OvmStoragePoolEncoder))
|
||||
|
||||
def toOvmStoragePool(jStr):
|
||||
return json.loads(jStr, cls=OvmStoragePoolDecoder)
|
||||
|
||||
logger = OvmLogger('OvmStoragePool')
|
||||
class OvmStoragePool(OvmObject):
|
||||
uuid = ''
|
||||
type = ''
|
||||
path = ''
|
||||
mountPoint = ''
|
||||
totalSpace = 0
|
||||
freeSpace = 0
|
||||
usedSpace = 0
|
||||
|
||||
def _getSrByNameLable(self, poolUuid):
|
||||
d = db_dump('sr')
|
||||
for uuid, sr in d.items():
|
||||
if sr.name_label == poolUuid:
|
||||
return sr
|
||||
|
||||
raise Exception("No SR matching to %s" % poolUuid)
|
||||
|
||||
def _getSpaceinfoOfDir(self, dir):
|
||||
stat = os.statvfs(dir)
|
||||
freeSpace = stat.f_frsize * stat.f_bavail;
|
||||
totalSpace = stat.f_blocks * stat.f_frsize;
|
||||
return (totalSpace, freeSpace)
|
||||
|
||||
def _checkDirSizeForImage(self, dir, image):
|
||||
(x, free_storage_size) = OvmStoragePool()._getSpaceinfoOfDir(dir)
|
||||
image_size = os.path.getsize(image)
|
||||
if image_size > (free_storage_size + 1024 * 1024 * 1024):
|
||||
raise Exception("No space on dir %s (free storage:%s, vm size:%s)"%(dir, free_storage_size, image_size))
|
||||
|
||||
def _getAllMountPoints(self):
|
||||
mps = []
|
||||
d = db_dump('sr')
|
||||
for uuid, sr in d.items():
|
||||
mps.append(sr.mountpoint)
|
||||
return mps
|
||||
|
||||
def _isMounted(self, path):
|
||||
res = doCmd(['mount'])
|
||||
return (path in res)
|
||||
|
||||
def _mount(self, target, mountpoint):
|
||||
if not exists(mountpoint):
|
||||
os.makedirs(mountpoint)
|
||||
|
||||
if not OvmStoragePool()._isMounted(mountpoint):
|
||||
doCmd(['mount', target, mountpoint, '-r'])
|
||||
|
||||
@staticmethod
|
||||
def create(jStr):
|
||||
try:
|
||||
pool = toOvmStoragePool(jStr)
|
||||
logger.debug(OvmStoragePool.create, fromOvmStoragePool(pool))
|
||||
spUuid = jsonSuccessToMap(sp_create(pool.type, pool.path))['uuid']
|
||||
srUuid = jsonSuccessToMap(sr_create(spUuid, name_label=pool.uuid))['uuid']
|
||||
sr_do(srUuid, "initialize")
|
||||
rs = SUCC()
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmStoragePool.create, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.create), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getDetailsByUuid(uuid):
|
||||
try:
|
||||
sr = OvmStoragePool()._getSrByNameLable(uuid)
|
||||
pool = OvmStoragePool()
|
||||
safeSetAttr(pool, 'uuid', uuid)
|
||||
#Note: the sr.sp.fs_type is not mapped to its class name which we use in mgmt server
|
||||
safeSetAttr(pool, 'type', sr.sp.__class__.__name__)
|
||||
safeSetAttr(pool, 'path', sr.sp.get_fs_spec())
|
||||
safeSetAttr(pool, 'mountPoint', sr.mountpoint)
|
||||
(totalSpace, freeSpace) = OvmStoragePool()._getSpaceinfoOfDir(sr.mountpoint)
|
||||
safeSetAttr(pool, 'totalSpace', totalSpace)
|
||||
safeSetAttr(pool, 'freeSpace', freeSpace)
|
||||
safeSetAttr(pool, 'usedSpace', totalSpace - freeSpace)
|
||||
res = fromOvmStoragePool(pool)
|
||||
logger.debug(OvmStoragePool.getDetailsByUuid, res)
|
||||
return res
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmStoragePool.getDetailsByUuid, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.getDetailsByUuid), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def downloadTemplate(uuid, secPath):
|
||||
secMountPoint = None
|
||||
try:
|
||||
logger.debug(OvmStoragePool.downloadTemplate, "download %s to pool %s"%(secPath, uuid))
|
||||
try:
|
||||
tmpUuid = get_uuid()
|
||||
secMountPoint = join("/var/cloud/", tmpUuid)
|
||||
if not exists(secMountPoint):
|
||||
os.makedirs(secMountPoint)
|
||||
|
||||
templateFile = None
|
||||
if secPath.endswith("raw"):
|
||||
secPathDir = os.path.dirname(secPath)
|
||||
templateFile = os.path.basename(secPath)
|
||||
else:
|
||||
secPathDir = secPath
|
||||
|
||||
# mount as read-only
|
||||
mountCmd = ['mount.nfs', secPathDir, secMountPoint, '-r']
|
||||
doCmd(mountCmd)
|
||||
|
||||
if not templateFile:
|
||||
for f in os.listdir(secMountPoint):
|
||||
if isfile(join(secMountPoint, f)) and f.endswith('raw'):
|
||||
templateFile = f
|
||||
break
|
||||
|
||||
if not templateFile:
|
||||
raise Exception("Can not find raw template in secondary storage")
|
||||
templateSecPath = join(secMountPoint, templateFile)
|
||||
|
||||
sr = OvmStoragePool()._getSrByNameLable(uuid)
|
||||
priStorageMountPoint = sr.mountpoint
|
||||
# Although mgmt server will check the size, we check again for safety
|
||||
OvmStoragePool()._checkDirSizeForImage(priStorageMountPoint, templateSecPath)
|
||||
seedDir = join(priStorageMountPoint, 'seed_pool', tmpUuid)
|
||||
if exists(seedDir):
|
||||
raise Exception("%s already here, cannot override existing template" % seedDir)
|
||||
os.makedirs(seedDir)
|
||||
|
||||
tgt = join(seedDir, templateFile)
|
||||
cpTemplateCmd = ['cp', templateSecPath, tgt]
|
||||
logger.info(OvmStoragePool.downloadTemplate, " ".join(cpTemplateCmd))
|
||||
doCmd(cpTemplateCmd)
|
||||
templateSize = os.path.getsize(tgt)
|
||||
logger.info(OvmStoragePool.downloadTemplate, "primary_storage_download success:installPath:%s, templateSize:%s"%(tgt,templateSize))
|
||||
rs = toGson({"installPath":tgt, "templateSize":templateSize})
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmStoragePool.downloadTemplate, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.downloadTemplate), errmsg)
|
||||
finally:
|
||||
if exists(secMountPoint):
|
||||
try:
|
||||
umountCmd = ['umount', '-f', secMountPoint]
|
||||
doCmd(umountCmd)
|
||||
ls = os.listdir(secMountPoint)
|
||||
if len(ls) == 0:
|
||||
rmDirCmd = ['rm', '-r', secMountPoint]
|
||||
doCmd(rmDirCmd)
|
||||
else:
|
||||
logger.warning(OvmStoragePool.downloadTemplate, "Something wrong when umount %s, there are still files in directory:%s", secMountPoint, " ".join(ls))
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmStoragePool.downloadTemplate, 'unmount secondary storage at %s failed, %s'%(secMountPoint, errmsg))
|
||||
|
||||
@staticmethod
|
||||
def prepareOCFS2Nodes(clusterName, nodeString):
|
||||
def compareClusterConfig(nodes):
|
||||
def sortNodes(nodes):
|
||||
ns = []
|
||||
for n in nodes:
|
||||
ns.insert(int(n["number"]), n)
|
||||
return ns
|
||||
|
||||
def compareNodes(ns1, ns2):
|
||||
if len(ns1) != len(ns2):
|
||||
return False
|
||||
|
||||
for i in range(0, len(ns1)):
|
||||
n1 = ns1[i]
|
||||
n2 = ns2[i]
|
||||
if n1["ip_address"] != n2["ip_address"] or n1["number"] != n2["number"] \
|
||||
or n1["name"] != n2["name"]:
|
||||
return False
|
||||
return True
|
||||
|
||||
if exists(OCFS2_CLUSTER_CONF):
|
||||
oldConf = parse_ocfs2_cluster_conf()
|
||||
cluster = oldConf["cluster"]
|
||||
nodesNum = cluster["node_count"]
|
||||
if len(nodes) != nodesNum:
|
||||
return False
|
||||
|
||||
new = sortNodes(nodes)
|
||||
old = sortNodes(oldConf["nodes"])
|
||||
return compareNodes(new, old)
|
||||
else:
|
||||
return False
|
||||
|
||||
def configureEtcHosts(nodes):
|
||||
if not exists(ETC_HOSTS):
|
||||
orignalConf = ""
|
||||
else:
|
||||
fd = open(ETC_HOSTS, "r")
|
||||
orignalConf = fd.read()
|
||||
fd.close()
|
||||
|
||||
pattern = r"(.*%s.*)|(.*%s.*)"
|
||||
newlines = []
|
||||
for n in nodes:
|
||||
p = pattern % (n["ip_address"], n["name"])
|
||||
orignalConf = re.sub(p, "", orignalConf)
|
||||
newlines.append("%s\t%s\n"%(n["ip_address"], n["name"]))
|
||||
|
||||
orignalConf = orignalConf + "".join(newlines)
|
||||
# remove extra empty lines
|
||||
orignalConf = re.sub(r"\n\s*\n*", "\n", orignalConf)
|
||||
logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure /etc/hosts:%s\n"%orignalConf)
|
||||
fd = open(ETC_HOSTS, "w")
|
||||
fd.write(orignalConf)
|
||||
fd.close()
|
||||
|
||||
try:
|
||||
nodeString = nodeString.strip(";")
|
||||
nodes = []
|
||||
for n in nodeString.split(";"):
|
||||
params = n.split(":")
|
||||
if len(params) != 3: raise Exception("Wrong parameter(%s) in node string(%s)"%(n, nodeString))
|
||||
dict = {"number":params[0], "ip_address":params[1], "name":params[2]}
|
||||
nodes.append(dict)
|
||||
|
||||
if len(nodes) > 255:
|
||||
raise Exception("%s nodes beyond maximum 255 allowed by OCFS2"%len(nodes))
|
||||
|
||||
if compareClusterConfig(nodes):
|
||||
logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Nodes configure are the same, return")
|
||||
rs = SUCC()
|
||||
return rs
|
||||
|
||||
lines = []
|
||||
for n in nodes:
|
||||
lines.append("node:\n")
|
||||
lines.append("\tip_port = %s\n" % "7777")
|
||||
lines.append("\tip_address = %s\n" % n["ip_address"])
|
||||
lines.append("\tnumber = %s\n" % n["number"])
|
||||
lines.append("\tname = %s\n" % n["name"])
|
||||
lines.append("\tcluster = %s\n" % clusterName)
|
||||
lines.append("\n")
|
||||
lines.append("cluster:\n")
|
||||
lines.append("\tnode_count = %d\n" % len(nodes))
|
||||
lines.append("\tname = %s\n" % clusterName)
|
||||
lines.append("\n")
|
||||
conf = "".join(lines)
|
||||
clusterm_set_ocfs2_cluster_conf(conf)
|
||||
clusterm_start_o2cb_service()
|
||||
logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure cluster.conf to:\n%s"%conf)
|
||||
configureEtcHosts(nodes)
|
||||
rs = SUCC()
|
||||
return rs
|
||||
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmStoragePool.prepareOCFS2Nodes, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmStoragePool, OvmStoragePool.prepareOCFS2Nodes), errmsg)
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
'''
|
||||
Created on May 17, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
from OvmCommonModule import *
|
||||
|
||||
class OvmVifDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDict = asciiLoads(jStr)
|
||||
vif = OvmVif()
|
||||
vif.mac = deDict['mac']
|
||||
vif.bridge = deDict['bridge']
|
||||
return vif
|
||||
|
||||
class OvmVifEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmVif): raise Exception("%s is not instance of OvmVif"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'mac')
|
||||
safeDictSet(obj, dct, 'bridge')
|
||||
safeDictSet(obj, dct, 'type')
|
||||
safeDictSet(obj, dct, 'name')
|
||||
return dct
|
||||
|
||||
def fromOvmVif(vif):
|
||||
return normalizeToGson(json.dumps(vif, cls=OvmVifEncoder))
|
||||
|
||||
def fromOvmVifList(vifList):
|
||||
return [fromOvmVif(v) for v in vifList]
|
||||
|
||||
def toOvmVif(jStr):
|
||||
return json.loads(jStr, cls=OvmVifDecoder)
|
||||
|
||||
def toOvmVifList(jStr):
|
||||
vifs = []
|
||||
for i in jStr:
|
||||
vif = toOvmVif(i)
|
||||
vifs.append(vif)
|
||||
return vifs
|
||||
|
||||
class OvmVif(OvmObject):
|
||||
name = ''
|
||||
mac = ''
|
||||
bridge = ''
|
||||
type = ''
|
||||
mode = ''
|
||||
|
||||
def toXenString(self):
|
||||
return "%s,%s,%s"%(self.mac, self.bridge, self.type)
|
||||
|
|
@ -0,0 +1,497 @@
|
|||
'''
|
||||
Created on May 17, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
from OvmCommonModule import *
|
||||
from OvmDiskModule import *
|
||||
from OvmVifModule import *
|
||||
from OvmHostModule import OvmHost
|
||||
from string import Template
|
||||
from OVSXXenVMConfig import *
|
||||
from OVSSiteVM import start_vm, stop_vm, reset_vm
|
||||
from OVSSiteCluster import *
|
||||
from OvmStoragePoolModule import OvmStoragePool
|
||||
from OVSXXenStore import xen_get_vm_path, xen_get_vnc_port
|
||||
from OVSDB import db_get_vm
|
||||
from OVSXMonitor import xen_get_vm_perf_metrics, xen_get_xm_info
|
||||
from OVSXXenVM import xen_migrate_vm
|
||||
from OVSSiteRMVM import unregister_vm, register_vm
|
||||
from OVSSiteVMInstall import install_vm_hvm
|
||||
from OVSSiteRMServer import get_master_ip
|
||||
from OVSXXenVMInstall import xen_change_vm_cdrom
|
||||
from OVSXAPIUtil import XenAPIObject, session_login, session_logout
|
||||
|
||||
|
||||
logger = OvmLogger("OvmVm")
|
||||
|
||||
class OvmVmDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDict = asciiLoads(jStr)
|
||||
vm = OvmVm()
|
||||
setAttrFromDict(vm, 'cpuNum', deDict, int)
|
||||
setAttrFromDict(vm, 'memory', deDict, long)
|
||||
setattr(vm, 'rootDisk', toOvmDisk(deDict['rootDisk']))
|
||||
setattr(vm, 'vifs', toOvmVifList(deDict['vifs']))
|
||||
setattr(vm, 'disks', toOvmDiskList(deDict['disks']))
|
||||
setAttrFromDict(vm, 'name', deDict)
|
||||
setAttrFromDict(vm, 'uuid', deDict)
|
||||
setAttrFromDict(vm, 'bootDev', deDict)
|
||||
setAttrFromDict(vm, 'type', deDict)
|
||||
return vm
|
||||
|
||||
class OvmVmEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmVm): raise Exception("%s is not instance of OvmVm"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'cpuNum')
|
||||
safeDictSet(obj, dct, 'memory')
|
||||
safeDictSet(obj, dct, 'powerState')
|
||||
safeDictSet(obj, dct, 'name')
|
||||
safeDictSet(obj, dct, 'type')
|
||||
vifs = fromOvmVifList(obj.vifs)
|
||||
dct['vifs'] = vifs
|
||||
rootDisk = fromOvmDisk(obj.rootDisk)
|
||||
dct['rootDisk'] = rootDisk
|
||||
disks = fromOvmDiskList(obj.disks)
|
||||
dct['disks'] = disks
|
||||
return dct
|
||||
|
||||
def toOvmVm(jStr):
|
||||
return json.loads(jStr, cls=OvmVmDecoder)
|
||||
|
||||
def fromOvmVm(vm):
|
||||
return normalizeToGson(json.dumps(vm, cls=OvmVmEncoder))
|
||||
|
||||
class OvmVm(OvmObject):
|
||||
cpuNum = 0
|
||||
memory = 0
|
||||
rootDisk = None
|
||||
vifs = []
|
||||
disks = []
|
||||
powerState = ''
|
||||
name = ''
|
||||
bootDev = ''
|
||||
type = ''
|
||||
|
||||
def _getVifs(self, vmName):
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
domId = OvmHost()._getDomainIdByName(vmName)
|
||||
vifs = successToMap(xen_get_vifs(vmPath))
|
||||
lst = []
|
||||
for k in vifs:
|
||||
v = vifs[k]
|
||||
vifName = 'vif' + domId + '.' + k[len('vif'):]
|
||||
vif = OvmVif()
|
||||
(mac, bridge, type) = v.split(',')
|
||||
safeSetAttr(vif, 'name', vifName)
|
||||
safeSetAttr(vif, 'mac', mac)
|
||||
safeSetAttr(vif, 'bridge', bridge)
|
||||
safeSetAttr(vif, 'type', type)
|
||||
lst.append(vif)
|
||||
|
||||
return lst
|
||||
|
||||
def _getVifsFromConfig(self, vmPath):
|
||||
vifs = successToMap(xen_get_vifs(vmPath))
|
||||
lst = []
|
||||
for k in vifs:
|
||||
v = vifs[k]
|
||||
vif = OvmVif()
|
||||
(mac, bridge, type) = v.split(',')
|
||||
safeSetAttr(vif, 'name', k)
|
||||
safeSetAttr(vif, 'mac', mac)
|
||||
safeSetAttr(vif, 'bridge', bridge)
|
||||
safeSetAttr(vif, 'type', type)
|
||||
lst.append(vif)
|
||||
return lst
|
||||
|
||||
def _getIsoMountPath(self, vmPath):
|
||||
vmName = basename(vmPath)
|
||||
priStoragePath = vmPath.rstrip(join('running_pool', vmName))
|
||||
return join(priStoragePath, 'iso_pool', vmName)
|
||||
|
||||
def _getVmTypeFromConfigFile(self, vmPath):
|
||||
vmType = successToMap(xen_get_vm_type(vmPath))['type']
|
||||
return vmType.replace('hvm', 'HVM').replace('para', 'PV')
|
||||
|
||||
@staticmethod
|
||||
def create(jsonString):
|
||||
def dumpCfg(vmName, cfgPath):
|
||||
cfgFd = open(cfgPath, 'r')
|
||||
cfg = cfgFd.readlines()
|
||||
cfgFd.close()
|
||||
logger.info(OvmVm.create, "Start %s with configure:\n\n%s\n"%(vmName, "".join(cfg)))
|
||||
|
||||
def setVifsType(vifs, type):
|
||||
for vif in vifs:
|
||||
vif.type = type
|
||||
|
||||
def hddBoot(vm, vmPath):
|
||||
vmType = vm.type
|
||||
if vmType == "FROMCONFIGFILE":
|
||||
vmType = OvmVm()._getVmTypeFromConfigFile(vmPath)
|
||||
|
||||
cfgDict = {}
|
||||
if vmType == "HVM":
|
||||
cfgDict['builder'] = "'hvm'"
|
||||
cfgDict['acpi'] = "1"
|
||||
cfgDict['apic'] = "1"
|
||||
cfgDict['device_model'] = "'/usr/lib/xen/bin/qemu-dm'"
|
||||
cfgDict['kernel'] = "'/usr/lib/xen/boot/hvmloader'"
|
||||
vifType = 'ioemu'
|
||||
else:
|
||||
cfgDict['bootloader'] = "'/usr/bin/pygrub'"
|
||||
vifType = 'netfront'
|
||||
|
||||
cfgDict['name'] = "'%s'"%vm.name
|
||||
cfgDict['disk'] = "[]"
|
||||
cfgDict['vcpus'] = "''"
|
||||
cfgDict['memory'] = "''"
|
||||
cfgDict['on_crash'] = "'destroy'"
|
||||
cfgDict['on_reboot'] = "'restart'"
|
||||
cfgDict['vif'] = "[]"
|
||||
|
||||
items = []
|
||||
for k in cfgDict.keys():
|
||||
item = " = ".join([k, cfgDict[k]])
|
||||
items.append(item)
|
||||
vmSpec = "\n".join(items)
|
||||
|
||||
vmCfg = open(join(vmPath, 'vm.cfg'), 'w')
|
||||
vmCfg.write(vmSpec)
|
||||
vmCfg.close()
|
||||
|
||||
setVifsType(vm.vifs, vifType)
|
||||
raiseExceptionIfFail(xen_set_vcpus(vmPath, vm.cpuNum))
|
||||
raiseExceptionIfFail(xen_set_memory(vmPath, BytesToM(vm.memory)))
|
||||
raiseExceptionIfFail(xen_add_disk(vmPath, vm.rootDisk.path, mode=vm.rootDisk.type))
|
||||
vifs = [OvmVif.toXenString(v) for v in vm.vifs]
|
||||
for vif in vifs:
|
||||
raiseExceptionIfFail(xen_set_vifs(vmPath, vif))
|
||||
|
||||
for disk in vm.disks:
|
||||
raiseExceptionIfFail(xen_add_disk(vmPath, disk.path, mode=disk.type))
|
||||
|
||||
raiseExceptionIfFail(xen_set_vm_vnc_password(vmPath, ""))
|
||||
cfgFile = join(vmPath, 'vm.cfg')
|
||||
# only HVM supports attaching cdrom
|
||||
if vmType == 'HVM':
|
||||
# Add an empty "hdc:cdrom" entry in config. Fisrt we set boot order to 'd' that is cdrom boot,
|
||||
# then 'hdc:cdrom' entry will be in disk list. Second, change boot order to 'c' which
|
||||
# is harddisk boot. VM can not start with an empty 'hdc:cdrom' when boot order is 'd'.
|
||||
# it's tricky !
|
||||
raiseExceptionIfFail(xen_config_boot_sequence(vmPath, 'd'))
|
||||
raiseExceptionIfFail(xen_config_boot_sequence(vmPath, 'c'))
|
||||
|
||||
raiseExceptionIfFail(xen_correct_cfg(cfgFile, vmPath))
|
||||
xen_correct_qos_cfg(cfgFile)
|
||||
dumpCfg(vm.name, cfgFile)
|
||||
server = successToMap(get_master_ip())['ip']
|
||||
raiseExceptionIfFail(start_vm(vmPath, server))
|
||||
rs = SUCC()
|
||||
return rs
|
||||
|
||||
def cdBoot(vm, vmPath):
|
||||
isoMountPath = None
|
||||
try:
|
||||
cdrom = None
|
||||
for disk in vm.disks:
|
||||
if disk.isIso == True:
|
||||
cdrom = disk
|
||||
break
|
||||
if not cdrom: raise Exception("Cannot find Iso in disks")
|
||||
|
||||
isoOnSecStorage = dirname(cdrom.path)
|
||||
isoName = basename(cdrom.path)
|
||||
isoMountPath = OvmVm()._getIsoMountPath(vmPath)
|
||||
OvmStoragePool()._mount(isoOnSecStorage, isoMountPath)
|
||||
isoPath = join(isoMountPath, isoName)
|
||||
if not exists(isoPath):
|
||||
raise Exception("Cannot found iso %s at %s which mounts to %s"%(isoName, isoOnSecStorage, isoMountPath))
|
||||
|
||||
stdout = run_cmd(args=['file', isoPath])
|
||||
if not stdout.strip().endswith("(bootable)"): raise Exception("ISO %s is not bootable"%cdrom.path)
|
||||
|
||||
#now alter cdrom to correct path
|
||||
cdrom.path = isoPath
|
||||
if len(vm.vifs) != 0:
|
||||
vif = vm.vifs[0]
|
||||
#ISO boot must be HVM
|
||||
vifCfg = ','.join([vif.mac, vif.bridge, 'ioemu'])
|
||||
else:
|
||||
vifCfg = ''
|
||||
|
||||
rootDiskSize = os.path.getsize(vm.rootDisk.path)
|
||||
rooDiskCfg = ':'.join([join(vmPath, basename(vm.rootDisk.path)), str(BytesToG(rootDiskSize)), 'True'])
|
||||
disks = [rooDiskCfg]
|
||||
for d in vm.disks:
|
||||
if d.isIso: continue
|
||||
size = os.path.getsize(d.path)
|
||||
cfg = ':'.join([d.path, str(BytesToG(size)), 'True'])
|
||||
disks.append(cfg)
|
||||
disksCfg = ','.join(disks)
|
||||
server = successToMap(get_master_ip())['ip']
|
||||
|
||||
raiseExceptionIfFail(install_vm_hvm(vmPath, BytesToM(vm.memory), vm.cpuNum, vifCfg, disksCfg, cdrom.path, vncpassword='', dedicated_server=server))
|
||||
rs = SUCC()
|
||||
return rs
|
||||
except Exception, e:
|
||||
if isoMountPath and OvmStoragePool()._isMounted(isoMountPath):
|
||||
doCmd(['umount', '-f', isoMountPath])
|
||||
errmsg = fmt_err_msg(e)
|
||||
raise Exception(errmsg)
|
||||
|
||||
try:
|
||||
vm = toOvmVm(jsonString)
|
||||
logger.debug(OvmVm.create, "creating vm, spec:%s"%jsonString)
|
||||
rootDiskPath = vm.rootDisk.path
|
||||
if not exists(rootDiskPath): raise Exception("Cannot find root disk %s"%rootDiskPath)
|
||||
|
||||
rootDiskDir = dirname(rootDiskPath)
|
||||
vmPath = join(dirname(rootDiskDir), vm.name)
|
||||
if not exists(vmPath):
|
||||
doCmd(['ln', '-s', rootDiskDir, vmPath])
|
||||
vmNameFile = open(join(rootDiskDir, 'vmName'), 'w')
|
||||
vmNameFile.write(vm.name)
|
||||
vmNameFile.close()
|
||||
|
||||
if vm.bootDev == "HDD":
|
||||
return hddBoot(vm, vmPath)
|
||||
elif vm.bootDev == "CD":
|
||||
return cdBoot(vm, vmPath)
|
||||
else:
|
||||
raise Exception("Unkown bootdev %s for %s"%(vm.bootDev, vm.name))
|
||||
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.create, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.create), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def stop(vmName):
|
||||
try:
|
||||
try:
|
||||
OvmHost()._getDomainIdByName(vmName)
|
||||
except NoVmFoundException, e:
|
||||
logger.info(OvmVm.stop, "vm %s is already stopped"%vmName)
|
||||
return SUCC()
|
||||
|
||||
logger.info(OvmVm.stop, "Stop vm %s"%vmName)
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
raiseExceptionIfFail(stop_vm(vmPath))
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.stop, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.stop), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def reboot(vmName):
|
||||
try:
|
||||
#===================================================================
|
||||
# Xend has a bug of reboot. If reboot vm too quick, xend return success
|
||||
# but actually it refused reboot (seen from log)
|
||||
# vmPath = successToMap(xen_get_vm_path(vmName))['path']
|
||||
# raiseExceptionIfFail(reset_vm(vmPath))
|
||||
#===================================================================
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
OvmVm.stop(vmName)
|
||||
raiseExceptionIfFail(start_vm(vmPath))
|
||||
vncPort= successToMap(xen_get_vnc_port(vmName))['vnc_port']
|
||||
logger.info(OvmVm.stop, "reboot vm %s, new vncPort is %s"%(vmName, vncPort))
|
||||
return toGson({"vncPort":str(vncPort)})
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.reboot, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.reboot), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getDetails(vmName):
|
||||
try:
|
||||
vm = OvmVm()
|
||||
|
||||
try:
|
||||
OvmHost()._getDomainIdByName(vmName)
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
vifsFromConfig = False
|
||||
except NoVmFoundException, e:
|
||||
vmPath = OvmHost()._getVmPathFromPrimaryStorage(vmName)
|
||||
vifsFromConfig = True
|
||||
|
||||
|
||||
if not isdir(vmPath):
|
||||
# The case is, when vm starting was not completed at primaryStroageDownload or createVolume(e.g. mgmt server stop), the mgmt
|
||||
# server will keep vm state in staring, then a stop command will be sent. The stop command will delete bridges that vm attaches,
|
||||
# by retriving birdge info by OvmVm.getDetails(). In this case, the vm doesn't exists, so returns a fake object here.
|
||||
fakeDisk = OvmDisk()
|
||||
vm.rootDisk = fakeDisk
|
||||
else:
|
||||
if vifsFromConfig:
|
||||
vm.vifs.extend(vm._getVifsFromConfig(vmPath))
|
||||
else:
|
||||
vm.vifs.extend(vm._getVifs(vmName))
|
||||
|
||||
safeSetAttr(vm, 'name', vmName)
|
||||
disks = successToMap(xen_get_vdisks(vmPath))['vdisks'].split(',')
|
||||
rootDisk = None
|
||||
#BUG: there is no way to get type of disk, assume all are "w"
|
||||
for d in disks:
|
||||
if vmName in d:
|
||||
rootDisk = OvmDisk()
|
||||
safeSetAttr(rootDisk, 'path', d)
|
||||
safeSetAttr(rootDisk, 'type', "w")
|
||||
continue
|
||||
disk = OvmDisk()
|
||||
safeSetAttr(disk, 'path', d)
|
||||
safeSetAttr(disk, 'type', "w")
|
||||
vm.disks.append(disk)
|
||||
if not rootDisk: raise Exception("Cannot find root disk for vm %s"%vmName)
|
||||
safeSetAttr(vm, 'rootDisk', rootDisk)
|
||||
vcpus = int(successToMap(xen_get_vcpus(vmPath))['vcpus'])
|
||||
safeSetAttr(vm, 'cpuNum', vcpus)
|
||||
memory = MtoBytes(int(successToMap(xen_get_memory(vmPath))['memory']))
|
||||
safeSetAttr(vm, 'memory', memory)
|
||||
vmStatus = db_get_vm(vmPath)
|
||||
safeSetAttr(vm, 'powerState', vmStatus['status'])
|
||||
vmType = successToMap(xen_get_vm_type(vmPath))['type'].replace('hvm', 'HVM').replace('para', 'PV')
|
||||
safeSetAttr(vm, 'type', vmType)
|
||||
|
||||
rs = fromOvmVm(vm)
|
||||
logger.info(OvmVm.getDetails, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.getDetails, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.getDetails), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getVmStats(vmName):
|
||||
def getVcpuNumAndUtils():
|
||||
try:
|
||||
session = session_login()
|
||||
refs = session.xenapi.VM.get_by_name_label(vmName)
|
||||
if len(refs) == 0:
|
||||
raise Exception("No ref for %s found in xenapi VM objects"%vmName)
|
||||
vm = XenAPIObject('VM', session, refs[0])
|
||||
VM_metrics = XenAPIObject("VM_metrics", session, vm.get_metrics())
|
||||
items = VM_metrics.get_VCPUs_utilisation().items()
|
||||
nvCpus = len(items)
|
||||
if nvCpus == 0:
|
||||
raise Exception("vm %s has 0 vcpus !!!"%vmName)
|
||||
|
||||
xmInfo = successToMap(xen_get_xm_info())
|
||||
nCpus = int(xmInfo['nr_cpus'])
|
||||
totalUtils = 0.0
|
||||
# CPU utlization of VM = (total cpu utilization of each vcpu) / number of physical cpu
|
||||
for num, util in items:
|
||||
totalUtils += float(util)
|
||||
avgUtils = float(totalUtils/nCpus) * 100
|
||||
return (nvCpus, avgUtils)
|
||||
finally:
|
||||
session_logout()
|
||||
|
||||
|
||||
try:
|
||||
try:
|
||||
OvmHost()._getDomainIdByName(vmName)
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
(nvcpus, avgUtils) = getVcpuNumAndUtils()
|
||||
vifs = successToMap(xen_get_vifs(vmPath))
|
||||
rxBytes = 0
|
||||
txBytes = 0
|
||||
vifs = OvmVm()._getVifs(vmName)
|
||||
for vif in vifs:
|
||||
rxp = join('/sys/class/net', vif.name, 'statistics/rx_bytes')
|
||||
txp = join("/sys/class/net/", vif.name, "statistics/tx_bytes")
|
||||
if not exists(rxp): raise Exception('can not find %s'%rxp)
|
||||
if not exists(txp): raise Exception('can not find %s'%txp)
|
||||
rxBytes += long(doCmd(['cat', rxp])) / 1000
|
||||
txBytes += long(doCmd(['cat', txp])) / 1000
|
||||
except NoVmFoundException, e:
|
||||
vmPath = OvmHost()._getVmPathFromPrimaryStorage(vmName)
|
||||
nvcpus = int(successToMap(xen_get_vcpus(vmPath))['vcpus'])
|
||||
avgUtils = 0
|
||||
rxBytes = 0
|
||||
txBytes = 0
|
||||
|
||||
rs = toGson({"cpuNum":nvcpus, "cpuUtil":avgUtils, "rxBytes":rxBytes, "txBytes":txBytes})
|
||||
logger.debug(OvmVm.getVmStats, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.getVmStats, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.getVmStats), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def migrate(vmName, targetHost):
|
||||
try:
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
raiseExceptionIfFail(xen_migrate_vm(vmPath, targetHost))
|
||||
unregister_vm(vmPath)
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.migrate, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.migrate), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def register(vmName):
|
||||
try:
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
raiseExceptionIfFail(register_vm(vmPath))
|
||||
vncPort= successToMap(xen_get_vnc_port(vmName))['vnc_port']
|
||||
rs = toGson({"vncPort":str(vncPort)})
|
||||
logger.debug(OvmVm.register, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.register, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.register), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def getVncPort(vmName):
|
||||
try:
|
||||
vncPort= successToMap(xen_get_vnc_port(vmName))['vnc_port']
|
||||
rs = toGson({"vncPort":vncPort})
|
||||
logger.debug(OvmVm.getVncPort, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.getVncPort, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.getVncPort), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def detachOrAttachIso(vmName, iso, isAttach):
|
||||
try:
|
||||
if vmName in OvmHost.getAllVms():
|
||||
scope = 'both'
|
||||
vmPath = OvmHost()._vmNameToPath(vmName)
|
||||
else:
|
||||
scope = 'cfg'
|
||||
vmPath = OvmHost()._getVmPathFromPrimaryStorage(vmName)
|
||||
|
||||
vmType = OvmVm()._getVmTypeFromConfigFile(vmPath)
|
||||
if vmType != 'HVM':
|
||||
raise Exception("Only HVM supports attaching/detaching ISO")
|
||||
|
||||
if not isAttach:
|
||||
iso = ''
|
||||
else:
|
||||
isoName = basename(iso)
|
||||
isoMountPoint = OvmVm()._getIsoMountPath(vmPath)
|
||||
isoOnSecStorage = dirname(iso)
|
||||
OvmStoragePool()._mount(isoOnSecStorage, isoMountPoint)
|
||||
iso = join(isoMountPoint, isoName)
|
||||
|
||||
exceptionIfNoSuccess(xen_change_vm_cdrom(vmPath, iso, scope))
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVm.detachOrAttachIso, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVm, OvmVm.detachOrAttachIso), errmsg)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
print OvmVm.getDetails(sys.argv[1])
|
||||
#print OvmVm.getVmStats(sys.argv[1])
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
'''
|
||||
Created on June 2, 2011
|
||||
|
||||
@author: frank
|
||||
'''
|
||||
from OvmCommonModule import *
|
||||
from OvmStoragePoolModule import OvmStoragePool
|
||||
from OVSXUtility import xen_create_disk
|
||||
from OvmHostModule import OvmHost
|
||||
import os
|
||||
|
||||
logger = OvmLogger("OvmVolume")
|
||||
|
||||
class OvmVolumeDecoder(json.JSONDecoder):
|
||||
def decode(self, jStr):
|
||||
deDict = asciiLoads(jStr)
|
||||
vol = OvmVolume()
|
||||
setAttrFromDict(vol, 'uuid', deDict)
|
||||
setAttrFromDict(vol, 'size', deDict, long)
|
||||
setAttrFromDict(vol, 'poolUuid', deDict)
|
||||
return vol
|
||||
|
||||
class OvmVolumeEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if not isinstance(obj, OvmVolume): raise Exception("%s is not instance of OvmVolume"%type(obj))
|
||||
dct = {}
|
||||
safeDictSet(obj, dct, 'name')
|
||||
safeDictSet(obj, dct, 'uuid')
|
||||
safeDictSet(obj, dct, 'poolUuid')
|
||||
safeDictSet(obj, dct, 'path')
|
||||
safeDictSet(obj, dct, 'size')
|
||||
return dct
|
||||
|
||||
def toOvmVolume(jStr):
|
||||
return json.loads(jStr, cls=OvmVolumeDecoder)
|
||||
|
||||
def fromOvmVlolume(vol):
|
||||
return normalizeToGson(json.dumps(vol, cls=OvmVolumeEncoder))
|
||||
|
||||
class OvmVolume(OvmObject):
|
||||
name = ''
|
||||
uuid = ''
|
||||
poolUuid = ''
|
||||
path = ''
|
||||
size = 0
|
||||
|
||||
@staticmethod
|
||||
def createDataDisk(poolUuid, size, isRoot):
|
||||
try:
|
||||
vol = OvmVolume()
|
||||
vol.size = long(size)
|
||||
vol.poolUuid = poolUuid
|
||||
pool = OvmStoragePool()
|
||||
sr = pool._getSrByNameLable(vol.poolUuid)
|
||||
if isRoot:
|
||||
path = join(sr.mountpoint, 'running_pool', get_uuid())
|
||||
else:
|
||||
path = join(sr.mountpoint, 'shareDisk')
|
||||
if not exists(path): os.makedirs(path)
|
||||
freeSpace = pool._getSpaceinfoOfDir(path)
|
||||
if freeSpace < vol.size:
|
||||
raise Exception("%s has not enough space (available:%s, required:%s"%(path, freeSpace, vol.size))
|
||||
|
||||
vol.uuid = get_uuid()
|
||||
vol.name = vol.uuid + '.raw'
|
||||
filePath = join(path, vol.name)
|
||||
exceptionIfNoSuccess(xen_create_disk(filePath, BytesToM(vol.size)), "Create datadisk %s failed"%filePath)
|
||||
vol.path = filePath
|
||||
rs = fromOvmVlolume(vol)
|
||||
logger.debug(OvmVolume.createDataDisk, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVolume.createDataDisk, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.createDataDisk, errmsg))
|
||||
|
||||
@staticmethod
|
||||
def createFromTemplate(poolUuid, templateUrl):
|
||||
try:
|
||||
if not exists(templateUrl):
|
||||
raise Exception("Cannot find template:%s"%templateUrl)
|
||||
sr = OvmStoragePool()._getSrByNameLable(poolUuid)
|
||||
volDirUuid = get_uuid()
|
||||
volUuid = get_uuid()
|
||||
priStorageMountPoint = sr.mountpoint
|
||||
volDir = join(priStorageMountPoint, 'running_pool', volDirUuid)
|
||||
if exists(volDir):
|
||||
raise Exception("Volume dir %s alreay existed, can not override"%volDir)
|
||||
os.makedirs(volDir)
|
||||
OvmStoragePool()._checkDirSizeForImage(volDir, templateUrl)
|
||||
volName = volUuid + '.raw'
|
||||
tgt = join(volDir, volName)
|
||||
cpVolCmd = ['cp', templateUrl, tgt]
|
||||
doCmd(cpVolCmd)
|
||||
volSize = os.path.getsize(tgt)
|
||||
vol = OvmVolume()
|
||||
vol.name = volName
|
||||
vol.path = tgt
|
||||
vol.size = volSize
|
||||
vol.uuid = volUuid
|
||||
vol.poolUuid = poolUuid
|
||||
rs = fromOvmVlolume(vol)
|
||||
logger.debug(OvmVolume.createFromTemplate, rs)
|
||||
return rs
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVolume.createFromTemplate, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.createFromTemplate), errmsg)
|
||||
|
||||
@staticmethod
|
||||
def destroy(poolUuid, path):
|
||||
try:
|
||||
OvmStoragePool()._getSrByNameLable(poolUuid)
|
||||
if not exists(path): raise Exception("Cannot find %s"%path)
|
||||
dir = dirname(path)
|
||||
if exists(join(dir, 'vm.cfg')):
|
||||
# delete root disk
|
||||
vmNamePath = join(dir, 'vmName')
|
||||
if exists(vmNamePath):
|
||||
vmNameFd = open(vmNamePath, 'r')
|
||||
vmName = vmNameFd.readline()
|
||||
vmName = vmName.rstrip('\n')
|
||||
link = join(dirname(dir), vmName)
|
||||
doCmd(['rm', '-rf', link])
|
||||
vmNameFd.close()
|
||||
else:
|
||||
logger.warning(OvmVolume.destroy, "Can not find vmName file in %s"%dir)
|
||||
doCmd(['rm','-rf', dir])
|
||||
else:
|
||||
doCmd(['rm', path])
|
||||
return SUCC()
|
||||
except Exception, e:
|
||||
errmsg = fmt_err_msg(e)
|
||||
logger.error(OvmVolume.destroy, errmsg)
|
||||
raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.destroy), errmsg)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print OvmVolume.detachOrAttachIso(sys.argv[1], '', False)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/sh
|
||||
|
||||
errExit() {
|
||||
echo $@
|
||||
exit 1
|
||||
}
|
||||
|
||||
stopHeartbeat() {
|
||||
pidFile="/var/run/ovs-agent/heartbeat.pid"
|
||||
if [ -f $pidFile ]; then
|
||||
pid=`cat $pidFile`
|
||||
ps -p $pid &>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
kill $pid &>/dev/null
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
openPortOnIptables() {
|
||||
port="$1"
|
||||
protocol="$2"
|
||||
chkconfig --list iptables | grep "on"
|
||||
if [ $? -eq 0 ]; then
|
||||
iptables-save | grep "A INPUT -p $protocol -m $protocol --dport $port -j ACCEPT" >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
iptables -I INPUT 1 -p $protocol --dport $port -j ACCEPT
|
||||
if [ $? -ne 0 ]; then
|
||||
exit_with_error "iptables -I INPUT 1 -p $protocol --dport $port -j ACCEPT failed"
|
||||
fi
|
||||
echo "iptables:Open $protocol port $port for DHCP"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
applyPatch() {
|
||||
patchFile="$1"
|
||||
level="$2"
|
||||
|
||||
[ ! -f $patchFile ] && errExit "Can not find $patchFile"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
pushd /opt/ovs-agent-latest &>/dev/null
|
||||
test=`patch -p$level --dry-run -N < $patchFile`
|
||||
if [ $? -ne 0 ]; then
|
||||
tmp=`mktemp`
|
||||
echo $test > $tmp
|
||||
grep "Reversed (or previously applied) patch detected" $tmp &>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# The file has been patched
|
||||
rm $tmp -f
|
||||
popd &>/dev/null
|
||||
return
|
||||
else
|
||||
rm $tmp -f
|
||||
popd &>/dev/null
|
||||
errExit "Can not apply $patchFile beacuse $test"
|
||||
fi
|
||||
fi
|
||||
patch -p$level < $patchFile
|
||||
[ $? -ne 0 ] && errExit "Patch to $target failed"
|
||||
popd &>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
postSetup() {
|
||||
openPortOnIptables 7777 tcp
|
||||
openPortOnIptables 7777 udp
|
||||
applyPatch "/opt/ovs-agent-latest/OvmPatch.patch" 2
|
||||
applyPatch "/opt/ovs-agent-latest/OvmDontTouchOCFS2ClusterWhenAgentStart.patch" 1
|
||||
|
||||
stopHeartbeat
|
||||
|
||||
/etc/init.d/ovs-agent restart --disable-nowayout
|
||||
[ $? -ne 0 ] && errExit "Restart ovs agent failed"
|
||||
exit 0
|
||||
}
|
||||
|
||||
preSetup() {
|
||||
agentConfig="/etc/ovs-agent/agent.ini"
|
||||
agentInitScript="/etc/init.d/ovs-agent"
|
||||
|
||||
[ ! -f $agentConfig ] && errExit "Can not find $agentConfig"
|
||||
[ ! -f $agentInitScript ] && errExit "Can not find $agentInitScript"
|
||||
|
||||
version=`grep "version=" $agentInitScript | cut -d "=" -f 2`
|
||||
[ x"$version" != x"2.3" ] && errExit "The OVS agent version is $version, we only support 2.3 now"
|
||||
|
||||
# disable SSL
|
||||
sed -i 's/ssl=enable/ssl=disable/g' $agentConfig
|
||||
[ $? -ne 0 ] && errExit "configure ovs agent to non ssl failed"
|
||||
|
||||
if [ ! -L /opt/ovs-agent-latest ]; then
|
||||
eval $agentInitScript status | grep 'down' && $agentInitScript start
|
||||
[ $? -ne 0 ] && errExit "Start ovs agent failed"
|
||||
[ ! -L /opt/ovs-agent-latest ] && errExit "No link at /opt/ovs-agent-latest"
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
[ $# -ne 1 ] && errExit "Usage: configureOvm.sh command"
|
||||
|
||||
case "$1" in
|
||||
preSetup)
|
||||
preSetup
|
||||
;;
|
||||
postSetup)
|
||||
postSetup
|
||||
;;
|
||||
*)
|
||||
errExit "Valid commands: preSetup postSetup"
|
||||
esac
|
||||
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
package com.cloud.ovm.hypervisor;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.host.HostInfo;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.ovm.object.Connection;
|
||||
import com.cloud.ovm.object.OvmHost;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import com.cloud.resource.DiscovererBase;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||
|
||||
@Local(value=Discoverer.class)
|
||||
public class OvmDiscoverer extends DiscovererBase implements Discoverer {
|
||||
private static final Logger s_logger = Logger.getLogger(OvmDiscoverer.class);
|
||||
|
||||
@Inject ClusterDao _clusterDao;
|
||||
|
||||
protected OvmDiscoverer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>> find(long dcId,
|
||||
Long podId, Long clusterId, URI url, String username,
|
||||
String password, List<String> hostTags) throws DiscoveryException {
|
||||
Connection conn = null;
|
||||
|
||||
if (!url.getScheme().equals("http")) {
|
||||
String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
|
||||
s_logger.debug(msg);
|
||||
return null;
|
||||
}
|
||||
if (clusterId == null) {
|
||||
String msg = "must specify cluster Id when add host";
|
||||
s_logger.debug(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
|
||||
if (podId == null) {
|
||||
String msg = "must specify pod Id when add host";
|
||||
s_logger.debug(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||
if(cluster == null || (cluster.getHypervisorType() != HypervisorType.Ovm)) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("invalid cluster id or cluster is not for Ovm hypervisors");
|
||||
return null;
|
||||
}
|
||||
|
||||
String agentUsername = _params.get("agentusername");
|
||||
if (agentUsername == null) {
|
||||
throw new CloudRuntimeException("Agent user name must be specified");
|
||||
}
|
||||
|
||||
String agentPassword = _params.get("agentpassword");
|
||||
if (agentPassword == null) {
|
||||
throw new CloudRuntimeException("Agent password must be specified");
|
||||
}
|
||||
|
||||
try {
|
||||
String hostname = url.getHost();
|
||||
InetAddress ia = InetAddress.getByName(hostname);
|
||||
String hostIp = ia.getHostAddress();
|
||||
String guid = UUID.nameUUIDFromBytes(hostIp.getBytes()).toString();
|
||||
|
||||
|
||||
ClusterVO clu = _clusterDao.findById(clusterId);
|
||||
if (clu.getGuid() == null) {
|
||||
clu.setGuid("/root");
|
||||
_clusterDao.update(clusterId, clu);
|
||||
}
|
||||
|
||||
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hostIp, 22);
|
||||
sshConnection.connect(null, 60000, 60000);
|
||||
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(hostIp, username, password);
|
||||
if (sshConnection == null) {
|
||||
throw new DiscoveryException(
|
||||
String.format("Cannot connect to ovm host(IP=%1$s, username=%2$s, password=%3$s, discover failed", hostIp, username, password));
|
||||
}
|
||||
|
||||
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/etc/ovs-agent/agent.ini' ]")) {
|
||||
throw new DiscoveryException("Can not find /etc/ovs-agent/agent.ini " + hostIp);
|
||||
}
|
||||
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
OvmResourceBase ovmResource = new OvmResourceBase();
|
||||
details.put("ip", hostIp);
|
||||
details.put("username", username);
|
||||
details.put("password", password);
|
||||
details.put("zone", Long.toString(dcId));
|
||||
details.put("guid", guid);
|
||||
details.put("pod", Long.toString(podId));
|
||||
details.put("cluster", Long.toString(clusterId));
|
||||
details.put("agentusername", agentUsername);
|
||||
details.put("agentpassword", agentPassword);
|
||||
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.putAll(details);
|
||||
ovmResource.configure("Ovm Server", params);
|
||||
ovmResource.start();
|
||||
|
||||
conn = new Connection(hostIp, "oracle", agentPassword);
|
||||
/* After resource start, we are able to execute our agent api*/
|
||||
OvmHost.Details d = OvmHost.getDetails(conn);
|
||||
details.put("agentVersion", d.agentVersion);
|
||||
details.put(HostInfo.HOST_OS_KERNEL_VERSION, d.dom0KernelVersion);
|
||||
details.put(HostInfo.HYPERVISOR_VERSION, d.hypervisorVersion);
|
||||
|
||||
Map<OvmResourceBase, Map<String, String>> resources = new HashMap<OvmResourceBase, Map<String, String>>();
|
||||
resources.put(ovmResource, details);
|
||||
return resources;
|
||||
} catch (XmlRpcException e) {
|
||||
s_logger.debug("XmlRpc exception, Unable to discover OVM: " + url, e);
|
||||
return null;
|
||||
} catch (UnknownHostException e) {
|
||||
s_logger.debug("Host name resolve failed exception, Unable to discover OVM: " + url, e);
|
||||
return null;
|
||||
} catch (ConfigurationException e) {
|
||||
s_logger.debug("Configure resource failed, Unable to discover OVM: " + url, e);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Unable to discover OVM: " + url, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDiscovery(List<HostVO> hosts, long msId)
|
||||
throws DiscoveryException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHypervisor(String hypervisor) {
|
||||
return HypervisorType.Ovm.toString().equalsIgnoreCase(hypervisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return HypervisorType.Ovm;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.cloud.ovm.hypervisor;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import com.cloud.hypervisor.HypervisorGuruBase;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value=HypervisorGuru.class)
|
||||
public class OvmGuru extends HypervisorGuruBase implements HypervisorGuru {
|
||||
@Inject GuestOSDao _guestOsDao;
|
||||
protected OvmGuru() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return HypervisorType.Ovm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VirtualMachine> VirtualMachineTO implement(
|
||||
VirtualMachineProfile<T> vm) {
|
||||
VirtualMachineTO to = toVirtualMachineTO(vm);
|
||||
to.setBootloader(vm.getBootLoaderType());
|
||||
|
||||
// Determine the VM's OS description
|
||||
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
|
||||
to.setOs(guestOS.getDisplayName());
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackVmHostChange() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.cloud.ovm.hypervisor;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class OvmHelper {
|
||||
private static final HashMap<String, String> _ovmMap = new HashMap<String, String>();
|
||||
|
||||
public static final String ORACLE_LINUX = "Oracle Linux";
|
||||
public static final String WINDOWS = "Windows";
|
||||
|
||||
static {
|
||||
_ovmMap.put("Oracle Enterprise Linux 6.0 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 6.0 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.0 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.0 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.1 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.1 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.2 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.2 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.3 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.3 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.4 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.4 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.5 (32-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Oracle Enterprise Linux 5.5 (64-bit)", ORACLE_LINUX);
|
||||
_ovmMap.put("Windows 7 (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows 7 (64-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Server 2003 (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Server 2003 (64-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Server 2008 (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Server 2008 (64-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Server 2008 R2 (64-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows 2000 SP4 (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows Vista (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows XP SP2 (32-bit)", WINDOWS);
|
||||
_ovmMap.put("Windows XP SP3 (32-bit)", WINDOWS);
|
||||
}
|
||||
|
||||
public static String getOvmGuestType(String stdType) {
|
||||
return _ovmMap.get(stdType);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,69 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.cloud.ovm.object.OvmHost.Details;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
public class Coder {
|
||||
private static Gson _gson;
|
||||
private static Gson _mapGson;
|
||||
|
||||
public static Object[] EMPTY_PARAMS = new Object[0];
|
||||
|
||||
private static class MapDecoder implements JsonDeserializer<Map<String, String>> {
|
||||
@Override
|
||||
public Map<String, String> deserialize(JsonElement arg0, Type arg1,
|
||||
JsonDeserializationContext arg2) throws JsonParseException {
|
||||
if (!arg0.isJsonObject()) {
|
||||
throw new JsonParseException(arg0.toString() + " is not Json Object, cannot convert to map");
|
||||
}
|
||||
JsonObject objs = arg0.getAsJsonObject();
|
||||
Map<String, String> map = new HashMap<String ,String>();
|
||||
for (Entry<String, JsonElement> e : objs.entrySet()) {
|
||||
if (!e.getValue().isJsonPrimitive()) {
|
||||
throw new JsonParseException(e.getValue().toString() + " is not a Json primitive," + arg0 + " can not convert to map");
|
||||
}
|
||||
map.put(e.getKey(), e.getValue().getAsString());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static {
|
||||
GsonBuilder _builder = new GsonBuilder();
|
||||
_builder.registerTypeAdapter(Map.class, new MapDecoder());
|
||||
_mapGson = _builder.create();
|
||||
_gson = new Gson();
|
||||
}
|
||||
|
||||
public static String toJson(Object obj) {
|
||||
return _gson.toJson(obj);
|
||||
}
|
||||
|
||||
public static <T> T fromJson(String str, Class<T> clz) {
|
||||
return (T)_gson.fromJson(str, clz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, String> mapFromJson(String str) {
|
||||
return _mapGson.fromJson(str, Map.class);
|
||||
}
|
||||
|
||||
public static List<String> listFromJson(String str) {
|
||||
Type listType = new TypeToken<List<String>>() {}.getType();
|
||||
return _gson.fromJson(str, listType);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
import org.apache.xmlrpc.client.TimingOutCallback;
|
||||
import org.apache.xmlrpc.client.XmlRpcClient;
|
||||
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class Connection {
|
||||
private static final Logger s_logger = Logger.getLogger(Connection.class);
|
||||
private XmlRpcClientConfigImpl _config = new XmlRpcClientConfigImpl();
|
||||
XmlRpcClient _client;
|
||||
String _username;
|
||||
String _password;
|
||||
String _ip;
|
||||
Integer _port = 8899;
|
||||
Boolean _isSsl = false;
|
||||
|
||||
private XmlRpcClient getXmlClient() {
|
||||
XmlRpcClient client = new XmlRpcClient();
|
||||
|
||||
URL url;
|
||||
try {
|
||||
url = new URL("http://" + _ip + ":" + _port.toString());
|
||||
_config.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
_config.setServerURL(url);
|
||||
_config.setReplyTimeout(0); // disable, we use asyncexecute to control timeout
|
||||
_config.setConnectionTimeout(6000);
|
||||
_config.setBasicUserName(_username);
|
||||
_config.setBasicPassword(_password);
|
||||
client.setConfig(_config);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
public Connection(String ip, Integer port, String username, String password) {
|
||||
_ip = ip;
|
||||
_port = port;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_client = getXmlClient();
|
||||
}
|
||||
|
||||
public Connection(String ip, String username, String password) {
|
||||
_ip = ip;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_client = getXmlClient();
|
||||
}
|
||||
|
||||
public Object call(String method, Object[] params) throws XmlRpcException {
|
||||
/* default timeout is 10 mins */
|
||||
return callTimeoutInSec(method, params, 600);
|
||||
}
|
||||
|
||||
public Object callTimeoutInSec(String method, Object[] params, int timeout) throws XmlRpcException {
|
||||
TimingOutCallback callback = new TimingOutCallback(timeout * 1000);
|
||||
Object[] mParams = new Object[params.length + 1];
|
||||
mParams[0] = method;
|
||||
for (int i=0; i<params.length; i++) {
|
||||
mParams[i+1] = params[i];
|
||||
}
|
||||
|
||||
s_logger.debug("Call Ovm agent: " + Coder.toJson(mParams));
|
||||
long startTime = System.currentTimeMillis();
|
||||
_client.executeAsync("OvmDispatch", mParams, callback);
|
||||
try {
|
||||
return callback.waitForResponse();
|
||||
} catch (TimingOutCallback.TimeoutException to) {
|
||||
throw to;
|
||||
} catch (Throwable e) {
|
||||
throw new XmlRpcException(-2, e.getMessage());
|
||||
} finally {
|
||||
long endTime = System.currentTimeMillis();
|
||||
float during = (endTime - startTime) / 1000; // in secs
|
||||
s_logger.debug("Ovm call " + method + " finished in " + during + " secs");
|
||||
}
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return _ip;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return _port;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return _username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return _password;
|
||||
}
|
||||
|
||||
public Boolean getIsSsl() {
|
||||
return _isSsl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
public class OvmBridge extends OvmObject {
|
||||
public static class Details {
|
||||
public String name;
|
||||
public String attach;
|
||||
public List<String> interfaces;
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static void create(Connection c, Details d) throws XmlRpcException {
|
||||
Object[] params = {d.toJson()};
|
||||
c.call("OvmNetwork.createBridge", params);
|
||||
}
|
||||
|
||||
public static void delete(Connection c, String name) throws XmlRpcException {
|
||||
Object[] params = {name};
|
||||
c.call("OvmNetwork.deleteBridge", params);
|
||||
}
|
||||
|
||||
public static List<String> getAllBridges(Connection c) throws XmlRpcException {
|
||||
String res = (String) c.call("OvmNetwork.getAllBridges", Coder.EMPTY_PARAMS);
|
||||
return Coder.listFromJson(res);
|
||||
}
|
||||
|
||||
public static String getBridgeByIp(Connection c, String ip) throws XmlRpcException {
|
||||
Object[] params = {ip};
|
||||
String res = (String) c.call("OvmNetwork.getBridgeByIp", params);
|
||||
return Coder.mapFromJson(res).get("bridge");
|
||||
}
|
||||
|
||||
public static void createVlanBridge(Connection c, OvmBridge.Details bDetails, OvmVlan.Details vDetails) throws XmlRpcException {
|
||||
Object[] params = {bDetails.toJson(), vDetails.toJson()};
|
||||
c.call("OvmNetwork.createVlanBridge", params);
|
||||
}
|
||||
|
||||
public static void deleteVlanBridge(Connection c, String name) throws XmlRpcException {
|
||||
Object[] params = {name};
|
||||
c.call("OvmNetwork.deleteVlanBridge", params);
|
||||
}
|
||||
|
||||
public static Details getDetails(Connection c, String name) throws XmlRpcException {
|
||||
Object[] params = {name};
|
||||
String res = (String) c.call("OvmNetwork.getBridgeDetails", params);
|
||||
return Coder.fromJson(res, Details.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
|
||||
public class OvmDisk extends OvmObject {
|
||||
public static final String WRITE = "w";
|
||||
public static final String READ = "r";
|
||||
public static final String SHAREDWRITE = "w!";
|
||||
public static final String SHAREDREAD = "r!";
|
||||
|
||||
public static class Details {
|
||||
public String type;
|
||||
public String path;
|
||||
public Boolean isIso;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
public class OvmHost extends OvmObject {
|
||||
public static final String SITE = "site";
|
||||
public static final String UTILITY = "utility";
|
||||
public static final String XEN = "xen";
|
||||
|
||||
public static class Details {
|
||||
public String masterIp;
|
||||
public Integer cpuNum;
|
||||
public Integer cpuSpeed;
|
||||
public Long totalMemory;
|
||||
public Long freeMemory;
|
||||
public Long dom0Memory;
|
||||
public String agentVersion;
|
||||
public String name;
|
||||
public String dom0KernelVersion;
|
||||
public String hypervisorVersion;
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerAsMaster(Connection c) throws XmlRpcException {
|
||||
Object[] params = {c.getIp(), c.getUserName(), c.getPassword(), c.getPort(), c.getIsSsl()};
|
||||
c.call("OvmHost.registerAsMaster", params);
|
||||
}
|
||||
|
||||
public static void registerAsVmServer(Connection c) throws XmlRpcException {
|
||||
Object[] params = {c.getIp(), c.getUserName(), c.getPassword(), c.getPort(), c.getIsSsl()};
|
||||
c.call("OvmHost.registerAsVmServer", params);
|
||||
}
|
||||
|
||||
public static Details getDetails(Connection c) throws XmlRpcException {
|
||||
String res = (String)c.call("OvmHost.getDetails", Coder.EMPTY_PARAMS);
|
||||
return Coder.fromJson(res, OvmHost.Details.class);
|
||||
}
|
||||
|
||||
public static void ping(Connection c) throws XmlRpcException {
|
||||
Object[] params = {c.getIp()};
|
||||
c.call("OvmHost.ping", params);
|
||||
}
|
||||
|
||||
public static Map<String, String> getPerformanceStats(Connection c, String bridge) throws XmlRpcException {
|
||||
Object[] params = {bridge};
|
||||
String res = (String) c.call("OvmHost.getPerformanceStats", params);
|
||||
return Coder.mapFromJson(res);
|
||||
}
|
||||
|
||||
public static Map<String, String> getAllVms(Connection c) throws XmlRpcException {
|
||||
String res = (String) c.call("OvmHost.getAllVms", Coder.EMPTY_PARAMS);
|
||||
return Coder.mapFromJson(res);
|
||||
}
|
||||
|
||||
public static void setupHeartBeat(Connection c, String poolUuid, String ip) throws XmlRpcException {
|
||||
Object[] params = {poolUuid, ip};
|
||||
c.call("OvmHost.setupHeartBeat", params);
|
||||
}
|
||||
|
||||
public static Boolean fence(Connection c, String ip) throws XmlRpcException {
|
||||
Object[] params = {ip};
|
||||
String res = (String)c.call("OvmHost.fence", params);
|
||||
Map<String, String> result = Coder.mapFromJson(res);
|
||||
return Boolean.parseBoolean(result.get("isLive"));
|
||||
}
|
||||
|
||||
public static void pingAnotherHost(Connection c, String ip) throws XmlRpcException {
|
||||
Object[] params = {ip};
|
||||
c.call("OvmHost.pingAnotherHost", params);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
public class OvmObject {
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
public class OvmSecurityGroup extends OvmObject {
|
||||
|
||||
// canBridgeFirewall
|
||||
// cleanupRules
|
||||
// defaultNetworkRulesUserVm
|
||||
// addNetworkRules
|
||||
// deleteAllNetworkRulesForVm
|
||||
|
||||
public static boolean canBridgeFirewall(Connection c) throws XmlRpcException {
|
||||
Object[] params = {};
|
||||
return (Boolean) c.call("OvmSecurityGroup.can_bridge_firewall", params);
|
||||
}
|
||||
|
||||
public static boolean cleanupNetworkRules(Connection c) throws XmlRpcException {
|
||||
Object[] params = {};
|
||||
return (Boolean) c.call("OvmSecurityGroup.cleanup_rules", params);
|
||||
}
|
||||
|
||||
public static boolean defaultNetworkRulesForUserVm(Connection c, String vmName, String vmId, String ipAddress, String macAddress, String vifName, String bridgeName) throws XmlRpcException {
|
||||
Object[] params = {vmName, vmId, ipAddress, macAddress, vifName, bridgeName};
|
||||
return (Boolean) c.call("OvmSecurityGroup.default_network_rules_user_vm", params);
|
||||
}
|
||||
|
||||
public static boolean addNetworkRules(Connection c, String vmName, String vmId, String guestIp, String signature, String seqno, String vifMacAddress, String newRules, String vifDeviceName, String bridgeName) throws XmlRpcException {
|
||||
Object[] params = {vmName, vmId, guestIp, signature, seqno, vifMacAddress, newRules, vifDeviceName, bridgeName};
|
||||
return (Boolean) c.call("OvmSecurityGroup.add_network_rules", params);
|
||||
}
|
||||
|
||||
public static boolean deleteAllNetworkRulesForVm(Connection c, String vmName, String vif) throws XmlRpcException {
|
||||
Object[] params = {vmName, vif};
|
||||
return (Boolean) c.call("OvmSecurityGroup.delete_all_network_rules_for_vm", params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public class OvmStoragePool extends OvmObject {
|
||||
public static final String NFS = "OVSSPNFS";
|
||||
public static final String OCFS2 = "OVSSPOCFS2";
|
||||
public static final String PARTITION = "OVSSPPartition";
|
||||
|
||||
public static class Details {
|
||||
public String uuid;
|
||||
public String type;
|
||||
public String path;
|
||||
public String mountPoint;
|
||||
public Long totalSpace;
|
||||
public Long freeSpace;
|
||||
public Long usedSpace;
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c: connection
|
||||
* @param d: includes three fields {uuid, type, path}
|
||||
* @throws XmlRpcException
|
||||
*/
|
||||
public static void create(Connection c, Details d) throws XmlRpcException {
|
||||
Object[] params = {d.toJson()};
|
||||
c.callTimeoutInSec("OvmStoragePool.create", params, 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param c: connection
|
||||
* @param uuid: uuid of primary storage
|
||||
* @return: Details with full fields
|
||||
* @throws XmlRpcException
|
||||
*/
|
||||
public static Details getDetailsByUuid(Connection c, String uuid) throws XmlRpcException {
|
||||
Object[] params = {uuid};
|
||||
String res = (String)c.call("OvmStoragePool.getDetailsByUuid", params);
|
||||
return Coder.fromJson(res, Details.class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param c: Connection
|
||||
* @param uuid: Pool uuid
|
||||
* @param from: secondary storage download path
|
||||
* @return: <destenation path, size of template>
|
||||
* @throws XmlRpcException
|
||||
*/
|
||||
public static Pair<String, Long> downloadTemplate(Connection c, String uuid, String from) throws XmlRpcException {
|
||||
Object[] params = {uuid, from};
|
||||
String res = (String) c.callTimeoutInSec("OvmStoragePool.downloadTemplate", params, 3600);
|
||||
Map pair = Coder.mapFromJson(res);
|
||||
return new Pair<String, Long>((String)pair.get("installPath"), Long.parseLong((String)pair.get("templateSize")));
|
||||
}
|
||||
|
||||
public static void prepareOCFS2Nodes(Connection c, String clusterName, String nodes) throws XmlRpcException {
|
||||
Object[] params = {clusterName, nodes};
|
||||
c.call("OvmStoragePool.prepareOCFS2Nodes", params);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
public class OvmVif extends OvmObject {
|
||||
public static final String NETFRONT = "netfront";
|
||||
public static final String IOEMU = "ioemu";
|
||||
|
||||
public static class Details {
|
||||
public String name;
|
||||
public String mac;
|
||||
public String bridge;
|
||||
public String type;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
public class OvmVlan extends OvmObject {
|
||||
public static class Details {
|
||||
public String name;
|
||||
public int vid;
|
||||
public String pif;
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static String create(Connection c, Details d) throws XmlRpcException {
|
||||
Object[] params = {d.toJson()};
|
||||
String res = (String)c.call("OvmNetwork.createVlan", params);
|
||||
Details ret = Coder.fromJson(res, Details.class);
|
||||
return ret.name;
|
||||
}
|
||||
|
||||
public static void delete(Connection c, String name) throws XmlRpcException {
|
||||
Object[] params = {name};
|
||||
c.call("OvmNetwork.deleteVlan", params);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.ovm.object.OvmHost.Details;
|
||||
|
||||
public class OvmVm extends OvmObject {
|
||||
public static final String CD = "CD";
|
||||
public static final String HDD = "HDD";
|
||||
public static final String HVM = "HVM";
|
||||
public static final String PV = "PV";
|
||||
public static final String FROMCONFIGFILE = "FROMCONFIGFILE";
|
||||
|
||||
public static class Details {
|
||||
public int cpuNum;
|
||||
public long memory;
|
||||
public OvmDisk.Details rootDisk;
|
||||
public List<OvmDisk.Details> disks;
|
||||
public List<OvmVif.Details> vifs;
|
||||
public String name;
|
||||
public String uuid;
|
||||
public String powerState;
|
||||
public String bootDev;
|
||||
public String type;
|
||||
|
||||
public Details() {
|
||||
disks = new ArrayList<OvmDisk.Details>();
|
||||
vifs = new ArrayList<OvmVif.Details>();
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
public OvmVm() {
|
||||
}
|
||||
|
||||
/*********** XML RPC Call **************/
|
||||
public static void create(Connection c, Details d) throws XmlRpcException {
|
||||
Object[] params = {d.toJson()};
|
||||
c.call("OvmVm.create", params);
|
||||
}
|
||||
|
||||
public static Map<String, String> reboot(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
String res = (String) c.call("OvmVm.reboot", params);
|
||||
return Coder.mapFromJson(res);
|
||||
}
|
||||
|
||||
public static void stop(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
/* Agent will destroy vm if vm shutdowns failed due to timout after 10 mins, so we set timeout to 20 mins here*/
|
||||
c.callTimeoutInSec("OvmVm.stop", params, 1200);
|
||||
}
|
||||
|
||||
public static Details getDetails(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
String res = (String)c.call("OvmVm.getDetails", params);
|
||||
return Coder.fromJson(res, OvmVm.Details.class);
|
||||
}
|
||||
|
||||
public static Map<String, String> getVmStats(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
String res = (String)c.call("OvmVm.getVmStats", params);
|
||||
return Coder.mapFromJson(res);
|
||||
}
|
||||
|
||||
public static void migrate(Connection c, String vmName, String dest) throws XmlRpcException {
|
||||
Object[] params = {vmName, dest};
|
||||
c.call("OvmVm.migrate", params);
|
||||
}
|
||||
|
||||
public static Map<String, String> register(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
String res = (String) c.call("OvmVm.register", params);
|
||||
return Coder.mapFromJson(res);
|
||||
}
|
||||
|
||||
public static Integer getVncPort(Connection c, String vmName) throws XmlRpcException {
|
||||
Object[] params = {vmName};
|
||||
String res = (String) c.call("OvmVm.getVncPort", params);
|
||||
Map<String, String> result = Coder.mapFromJson(res);
|
||||
return Integer.parseInt(result.get("vncPort"));
|
||||
}
|
||||
|
||||
public static void detachOrAttachIso(Connection c, String vmName, String iso, Boolean isAttach) throws XmlRpcException {
|
||||
Object[] params = {vmName, iso, isAttach};
|
||||
c.call("OvmVm.detachOrAttachIso", params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
public class OvmVolume extends OvmObject {
|
||||
public static class Details {
|
||||
public String name;
|
||||
public String uuid;
|
||||
public String poolUuid;
|
||||
public Long size;
|
||||
public String path;
|
||||
|
||||
public String toJson() {
|
||||
return Coder.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static Details createDataDsik(Connection c, String poolUuid, String size, Boolean isRoot) throws XmlRpcException {
|
||||
Object[] params = {poolUuid, size, isRoot};
|
||||
String res = (String) c.call("OvmVolume.createDataDisk", params);
|
||||
Details result = Coder.fromJson(res, Details.class);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Details createFromTemplate(Connection c, String poolUuid, String templateUrl) throws XmlRpcException {
|
||||
Object[] params = {poolUuid, templateUrl};
|
||||
String res = (String) c.callTimeoutInSec("OvmVolume.createFromTemplate", params, 3600*3);
|
||||
Details result = Coder.fromJson(res, Details.class);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void destroy(Connection c, String poolUuid, String path) throws XmlRpcException {
|
||||
Object[] params = {poolUuid, path};
|
||||
c.call("OvmVolume.destroy", params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
package com.cloud.ovm.object;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
/*Connection c = new Connection("192.168.105.155", "oracle", "password");
|
||||
Utils util = new UtilsImpl(c);
|
||||
Storage storage = new StorageImpl(c);
|
||||
String[] res = util.listDir("/etc", 1);
|
||||
for (String s : res) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
|
||||
Pool pool = new PoolImpl(c);
|
||||
|
||||
//pool.registerServer("192.168.105.155", Pool.ServerType.SITE);
|
||||
//pool.registerServer("192.168.105.155", Pool.ServerType.UTILITY);
|
||||
//pool.registerServer("192.168.105.155", Pool.ServerType.XEN);
|
||||
System.out.println("Is:" + pool.isServerRegistered());
|
||||
//String ip = pool.getMasterIp();
|
||||
//System.out.println("IP:" + ip);
|
||||
System.out.println(pool.getServerConfig());
|
||||
System.out.println(pool.getServerXmInfo());
|
||||
System.out.println(pool.getHostInfo());
|
||||
System.out.println(pool.getAgentVersion());
|
||||
String[] srs = storage.listSr();
|
||||
for (int i=0; i<srs.length; i++) {
|
||||
System.out.println(srs[i]);
|
||||
}
|
||||
String spuuid = storage.createSp(StorageType.OVSSPNFS, "192.168.110.232:/export/frank/nfs");
|
||||
System.out.println(spuuid);
|
||||
String sruuid = storage.createSr(spuuid, "hi");
|
||||
System.out.println(sruuid);
|
||||
storage.initSr();
|
||||
Pair<Long, Long> spaceInfo = storage.getSrSpaceInfo("192.168.110.232:/export/frank/nfs");
|
||||
System.out.println("Total:" + spaceInfo.first());
|
||||
System.out.println("Free:" + spaceInfo.second());*/
|
||||
OvmVm.Details vm = new OvmVm.Details();
|
||||
vm.cpuNum = 1;
|
||||
vm.memory = 512;
|
||||
vm.name = "Test";
|
||||
vm.uuid = "This-is-a-test";
|
||||
OvmDisk.Details rootDisk = new OvmDisk.Details();
|
||||
rootDisk.path = "/root/root.raw";
|
||||
rootDisk.type = OvmDisk.WRITE;
|
||||
vm.rootDisk = rootDisk;
|
||||
OvmDisk.Details dataDisk = new OvmDisk.Details();
|
||||
dataDisk.path = "/tmp/data.raw";
|
||||
dataDisk.type = OvmDisk.SHAREDWRITE;
|
||||
vm.disks.add(dataDisk);
|
||||
vm.disks.add(dataDisk);
|
||||
vm.disks.add(dataDisk);
|
||||
vm.disks.add(dataDisk);
|
||||
vm.disks.add(dataDisk);
|
||||
OvmVif.Details vif = new OvmVif.Details();
|
||||
vif.mac = "00:ff:ff:ff:ff:ee";
|
||||
vif.bridge = "xenbr0";
|
||||
vif.type = OvmVif.NETFRONT;
|
||||
vm.vifs.add(vif);
|
||||
vm.vifs.add(vif);
|
||||
vm.vifs.add(vif);
|
||||
vm.vifs.add(vif);
|
||||
vm.vifs.add(vif);
|
||||
//System.out.println(vm.toJson());
|
||||
Connection c = new Connection("192.168.189.12", "oracle", "password");
|
||||
//System.out.println(Coder.toJson(OvmHost.getDetails(c)));
|
||||
String txt = "{\"MasterIp\": \"192.168.189.12\", \"dom0Memory\": 790626304, \"freeMemory\": 16378757120, \"totalMemory\": 17169383424, \"cpuNum\": 4, \"agentVersion\": \"2.3-38\", \"cpuSpeed\": 2261}";
|
||||
//OvmHost.Details d = new GsonBuilder().create().fromJson(txt, OvmHost.Details.class);
|
||||
//OvmHost.Details d = Coder.fromJson(txt, OvmHost.Details.class);
|
||||
//OvmHost.Details d = OvmHost.getDetails(c);
|
||||
//System.out.println(Coder.toJson(d));
|
||||
// OvmStoragePool.Details pool = new OvmStoragePool.Details();
|
||||
// pool.path = "192.168.110.232:/export/frank/ovs";
|
||||
// pool.type = OvmStoragePool.NFS;
|
||||
// pool.uuid = "123";
|
||||
// System.out.println(pool.toJson());
|
||||
|
||||
String cmd = null;
|
||||
System.out.println(args.length);
|
||||
if (args.length >= 1) {
|
||||
cmd = args[0];
|
||||
OvmVm.Details d = new OvmVm.Details();
|
||||
d.cpuNum = 1;
|
||||
d.memory = 512 * 1024 * 1024;
|
||||
d.name = "MyTest";
|
||||
d.uuid = "1-2-3-4-5";
|
||||
OvmDisk.Details r = new OvmDisk.Details();
|
||||
r.path = "/var/ovs/mount/60D0985974CA425AAF5D01A1F161CC8B/running_pool/36_systemvm/System.img";
|
||||
r.type = OvmDisk.WRITE;
|
||||
d.rootDisk = r;
|
||||
OvmVif.Details v = new OvmVif.Details();
|
||||
v.mac = "00:16:3E:5C:B1:D1";
|
||||
v.bridge = "xenbr0";
|
||||
v.type = OvmVif.NETFRONT;
|
||||
d.vifs.add(v);
|
||||
System.out.println(d.toJson());
|
||||
|
||||
if (cmd.equalsIgnoreCase("create")) {
|
||||
// String s =
|
||||
// "{\"cpuNum\":1,\"memory\":512,\"rootDisk\":{\"type\":\"w\",\"path\":\"/var/ovs/mount/60D0985974CA425AAF5D01A1F161CC8B/running_pool/36_systemvm/System.img\"},\"disks\":[],\"vifs\":[{\"mac\":\"00:16:3E:5C:B1:D1\",\"bridge\":\"xenbr0\",\"type\":\"netfront\"}],\"name\":\"MyTest\",\"uuid\":\"1-2-3-4-5\"}";
|
||||
OvmVm.create(c, d);
|
||||
// c.call("OvmVm.echo", new Object[]{s});
|
||||
} else if (cmd.equalsIgnoreCase("reboot")) {
|
||||
Map<String, String> res = OvmVm.reboot(c, "MyTest");
|
||||
System.out.println(res.get("vncPort"));
|
||||
//OvmVm.stop(c, "MyTest");
|
||||
//OvmVm.create(c, d);
|
||||
} else if (cmd.equalsIgnoreCase("stop")) {
|
||||
OvmVm.stop(c, "MyTest");
|
||||
} else if (cmd.equalsIgnoreCase("details")) {
|
||||
OvmVm.Details ddd = OvmVm.getDetails(c, "MyTest");
|
||||
System.out.println(ddd.vifs.size());
|
||||
System.out.println(ddd.rootDisk.path);
|
||||
System.out.println(ddd.powerState);
|
||||
} else if (cmd.equalsIgnoreCase("all")) {
|
||||
System.out.println(OvmHost.getAllVms(c));
|
||||
} else if (cmd.equalsIgnoreCase("createBridge")) {
|
||||
OvmBridge.Details bd = new OvmBridge.Details();
|
||||
bd.name = "xenbr10";
|
||||
bd.attach = args[1];
|
||||
OvmBridge.create(c, bd);
|
||||
} else if (cmd.equalsIgnoreCase("createVlan")) {
|
||||
OvmVlan.Details vd = new OvmVlan.Details();
|
||||
vd.pif = "eth0";
|
||||
vd.vid = 1000;
|
||||
String vname = OvmVlan.create(c, vd);
|
||||
System.out.println(vname);
|
||||
} else if (cmd.equalsIgnoreCase("delVlan")) {
|
||||
OvmVlan.delete(c, args[1]);
|
||||
} else if (cmd.equalsIgnoreCase("delBr")) {
|
||||
OvmBridge.delete(c, args[1]);
|
||||
} else if (cmd.equalsIgnoreCase("getBrs")) {
|
||||
List<String> brs = OvmBridge.getAllBridges(c);
|
||||
System.out.println(brs);
|
||||
} else if (cmd.equalsIgnoreCase("getBrDetails")) {
|
||||
OvmBridge.Details brd = OvmBridge.getDetails(c, args[1]);
|
||||
System.out.println(brd.interfaces);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<String> l = new ArrayList<String>();
|
||||
l.add("4b4d8951-f0b6-36c5-b4f3-a82ff2611c65");
|
||||
System.out.println(Coder.toJson(l));
|
||||
|
||||
// Map<String, String> res = OvmHost.getPerformanceStats(c, "xenbr0");
|
||||
// System.out.println(res.toString());
|
||||
// String stxt = "{\"vifs\": [{\"bridge\": \"xenbr0\", \"mac\": \"00:16:3E:5C:B1:D1\", \"type\": \"netfront\"}], \"powerState\": \"RUNNING\", \"disks\": [], \"cpuNum\": 1, \"memory\": 536870912, \"rootDisk\": {\"path\": \"/var/ovs/mount/60D0985974CA425AAF5D01A1F161CC8B/running_pool/MyTest/System.img\", \"type\": \"w\"}}";
|
||||
// OvmVm.Details ddd = Coder.fromJson(stxt, OvmVm.Details.class);
|
||||
// System.out.println(ddd.vifs.size());
|
||||
// System.out.println(ddd.rootDisk.path);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<profile>
|
||||
<name>%access-profile-name%</name>
|
||||
<client>
|
||||
<name>%username%</name>
|
||||
<firewall-user>
|
||||
<password>%password%</password>
|
||||
</firewall-user>
|
||||
</client>
|
||||
<address-assignment>
|
||||
<pool>%address-pool-name%</pool>
|
||||
</address-assignment>
|
||||
</profile>
|
||||
</access>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<profile>
|
||||
</profile>
|
||||
</access>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<profile %delete%>
|
||||
<name>%access-profile-name%</name>
|
||||
</profile>
|
||||
</access>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<zones>
|
||||
<security-zone>
|
||||
<name>%zone%</name>
|
||||
<address-book>
|
||||
<address>
|
||||
<name>%entry-name%</name>
|
||||
<ip-prefix>%ip%</ip-prefix>
|
||||
</address>
|
||||
</address-book>
|
||||
</security-zone>
|
||||
</zones>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<zones>
|
||||
<security-zone>
|
||||
<name>%zone%</name>
|
||||
<address-book>
|
||||
</address-book>
|
||||
</security-zone>
|
||||
</zones>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<zones>
|
||||
<security-zone>
|
||||
<name>%zone%</name>
|
||||
<address-book>
|
||||
<address %delete%>
|
||||
<name>%entry-name%</name>
|
||||
</address>
|
||||
</address-book>
|
||||
</security-zone>
|
||||
</zones>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<address-assignment>
|
||||
<pool>
|
||||
<name>%address-pool-name%</name>
|
||||
<family>
|
||||
<inet>
|
||||
<network>%guest-network-cidr%</network>
|
||||
<range>
|
||||
<name>%address-range-name%</name>
|
||||
<low>%low-address%</low>
|
||||
<high>%high-address%</high>
|
||||
</range>
|
||||
<xauth-attributes>
|
||||
<primary-dns>%primary-dns-address%</primary-dns>
|
||||
</xauth-attributes>
|
||||
</inet>
|
||||
</family>
|
||||
</pool>
|
||||
</address-assignment>
|
||||
</access>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<address-assignment>
|
||||
<pool>
|
||||
</pool>
|
||||
</address-assignment>
|
||||
</access>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<access>
|
||||
<address-assignment>
|
||||
<pool %delete%>
|
||||
<name>%address-pool-name%</name>
|
||||
</pool>
|
||||
</address-assignment>
|
||||
</access>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<applications>
|
||||
<application>
|
||||
<name>%name%</name>
|
||||
<protocol>%protocol%</protocol>
|
||||
<destination-port>%dest-port%</destination-port>
|
||||
</application>
|
||||
</applications>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<applications>
|
||||
<application %delete%>
|
||||
<name>%name%</name>
|
||||
</application>
|
||||
</applications>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<rpc>
|
||||
<close-configuration/>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<rpc>
|
||||
<commit-configuration>
|
||||
</commit-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
<pool>
|
||||
<name>%pool-name%</name>
|
||||
<address>
|
||||
<ipaddr>%private-address%</ipaddr>
|
||||
<port>%dest-port%</port>
|
||||
</address>
|
||||
</pool>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
<pool %delete%>
|
||||
<name>%pool-name%</name>
|
||||
</pool>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
<rule-set>
|
||||
<name>%rule-set%</name>
|
||||
<from><zone>%from-zone%</zone></from>
|
||||
<rule>
|
||||
<name>%rule-name%</name>
|
||||
<dest-nat-rule-match>
|
||||
<destination-address>
|
||||
<dst-addr>%public-address%</dst-addr>
|
||||
</destination-address>
|
||||
<destination-port>
|
||||
<dst-port>%src-port%</dst-port>
|
||||
</destination-port>
|
||||
</dest-nat-rule-match>
|
||||
<then>
|
||||
<destination-nat>
|
||||
<pool>
|
||||
<pool-name>%pool-name%</pool-name>
|
||||
</pool>
|
||||
</destination-nat>
|
||||
</then>
|
||||
</rule>
|
||||
</rule-set>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
<rule-set>
|
||||
<name>%rule-set%</name>
|
||||
</rule-set>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<nat>
|
||||
<destination>
|
||||
<rule-set>
|
||||
<name>%from-zone%</name>
|
||||
<rule %delete%>
|
||||
<name>%rule-name%</name>
|
||||
</rule>
|
||||
</rule-set>
|
||||
</destination>
|
||||
</nat>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<dynamic-vpn>
|
||||
<clients>
|
||||
<name>%client-name%</name>
|
||||
<remote-protected-resources>
|
||||
<name>%guest-network-cidr%</name>
|
||||
</remote-protected-resources>
|
||||
<remote-exceptions>
|
||||
<name>0.0.0.0/0</name>
|
||||
</remote-exceptions>
|
||||
<remote-exceptions>
|
||||
<name>0.0.0.0/32</name>
|
||||
</remote-exceptions>
|
||||
<remote-exceptions>
|
||||
<name>1.1.1.1/24</name>
|
||||
</remote-exceptions>
|
||||
<ipsec-vpn>%ipsec-vpn-name%</ipsec-vpn>
|
||||
<user>
|
||||
<name>%username%</name>
|
||||
</user>
|
||||
</clients>
|
||||
</dynamic-vpn>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<dynamic-vpn>
|
||||
<clients>
|
||||
</clients>
|
||||
</dynamic-vpn>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<dynamic-vpn>
|
||||
<clients %delete%>
|
||||
<name>%client-name%</name>
|
||||
</clients>
|
||||
</dynamic-vpn>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<firewall>
|
||||
<filter %delete%>
|
||||
<name>%filter-name%</name>
|
||||
</filter>
|
||||
</firewall>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<firewall>
|
||||
<filter>
|
||||
<name>%filter-name%</name>
|
||||
<term %delete%>
|
||||
<name>%term-name%</name>
|
||||
</term>
|
||||
</filter>
|
||||
</firewall>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<rpc>
|
||||
<get-firewall-information>
|
||||
</get-firewall-information>
|
||||
</rpc>
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<firewall>
|
||||
<filter>
|
||||
<name>%filter-name%</name>
|
||||
<term>
|
||||
<name>%term-name%</name>
|
||||
<then>
|
||||
<count>%term-name%</count>
|
||||
<accept/>
|
||||
</then>
|
||||
</term>
|
||||
</filter>
|
||||
</firewall>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<gateway>
|
||||
<name>%gateway-name%</name>
|
||||
<ike-policy>%ike-policy-name%</ike-policy>
|
||||
<dynamic>
|
||||
<hostname>%ike-gateway-hostname%</hostname>
|
||||
</dynamic>
|
||||
<external-interface>%public-interface-name%</external-interface>
|
||||
<xauth>
|
||||
<access-profile>%access-profile-name%</access-profile>
|
||||
</xauth>
|
||||
</gateway>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<gateway>
|
||||
</gateway>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<gateway %delete%>
|
||||
<name>%gateway-name%</name>
|
||||
</gateway>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<policy>
|
||||
<name>%policy-name%</name>
|
||||
<mode>aggressive</mode>
|
||||
<proposals>%proposal-name%</proposals>
|
||||
<pre-shared-key>
|
||||
<ascii-text>%pre-shared-key%</ascii-text>
|
||||
</pre-shared-key>
|
||||
</policy>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<policy>
|
||||
</policy>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ike>
|
||||
<policy %delete%>
|
||||
<name>%policy-name%</name>
|
||||
</policy>
|
||||
</ike>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ipsec>
|
||||
<vpn>
|
||||
<name>%ipsec-vpn-name%</name>
|
||||
<ike>
|
||||
<gateway>%ike-gateway%</gateway>
|
||||
<ipsec-policy>%ipsec-policy-name%</ipsec-policy>
|
||||
</ike>
|
||||
<establish-tunnels>on-traffic</establish-tunnels>
|
||||
</vpn>
|
||||
</ipsec>
|
||||
</security>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ipsec>
|
||||
<vpn>
|
||||
</vpn>
|
||||
</ipsec>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<security>
|
||||
<ipsec>
|
||||
<vpn %delete%>
|
||||
<name>%ipsec-vpn-name%</name>
|
||||
</vpn>
|
||||
</ipsec>
|
||||
</security>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="us-ascii"?>
|
||||
<junoscript version="1.0">
|
||||
<rpc>
|
||||
<request-login>
|
||||
<username>
|
||||
%username%
|
||||
</username>
|
||||
<challenge-response>
|
||||
%password%
|
||||
</challenge-response>
|
||||
</request-login>
|
||||
</rpc>
|
||||
</junoscript>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<rpc>
|
||||
<open-configuration>
|
||||
<private/>
|
||||
</open-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<rpc>
|
||||
<load-configuration>
|
||||
<configuration>
|
||||
<interfaces>
|
||||
<interface>
|
||||
<name>%private-interface-name%</name>
|
||||
<vlan-tagging/>
|
||||
<unit>
|
||||
<name>%vlan-id%</name>
|
||||
<vlan-id>%vlan-id%</vlan-id>
|
||||
<family>
|
||||
<inet>
|
||||
<address>
|
||||
<name>%private-interface-ip%</name>
|
||||
</address>
|
||||
</inet>
|
||||
</family>
|
||||
</unit>
|
||||
</interface>
|
||||
</interfaces>
|
||||
</configuration>
|
||||
</load-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<interfaces>
|
||||
<interface>
|
||||
<name>%private-interface-name%</name>
|
||||
</interface>
|
||||
</interfaces>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<rpc>
|
||||
<get-configuration>
|
||||
<configuration>
|
||||
<interfaces>
|
||||
<interface>
|
||||
<name>%private-interface-name%</name>
|
||||
<vlan-tagging/>
|
||||
<unit %delete%>
|
||||
<name>%vlan-id%</name>
|
||||
</unit>
|
||||
</interface>
|
||||
</interfaces>
|
||||
</configuration>
|
||||
</get-configuration>
|
||||
</rpc>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue