diff --git a/.gitignore b/.gitignore index 01a43f2fb9a..6bc922c7d86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +build/replace.properties build/build.number bin/ cloudstack-proprietary/ diff --git a/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in b/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in new file mode 100644 index 00000000000..e6fc5f8cca3 --- /dev/null +++ b/agent/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-agent.in @@ -0,0 +1,81 @@ +#!/bin/bash + +# chkconfig: 35 99 10 +# description: Cloud Agent + +# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well + +. /etc/rc.d/init.d/functions + +whatami=cloud-agent + +# set environment variables + +SHORTNAME="$whatami" +PIDFILE=@PIDDIR@/"$whatami".pid +LOCKFILE=@LOCKDIR@/"$SHORTNAME" +LOGFILE=@AGENTLOG@ +PROGNAME="Cloud Agent" + +unset OPTIONS +[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" +DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize +PROG=@LIBEXECDIR@/agent-runner + +start() { + echo -n $"Starting $PROGNAME: " + if hostname --fqdn >/dev/null 2>&1 ; then + daemon --check=$SHORTNAME --pidfile=${PIDFILE} "$DAEMONIZE" \ + -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS + RETVAL=$? + echo + else + failure + echo + echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr + RETVAL=9 + fi + [ $RETVAL = 0 ] && touch ${LOCKFILE} + return $RETVAL +} + +stop() { + echo -n $"Stopping $PROGNAME: " + killproc -p ${PIDFILE} $SHORTNAME # -d 10 $SHORTNAME + RETVAL=$? + echo + [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} +} + + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status -p ${PIDFILE} $SHORTNAME + RETVAL=$? + ;; + restart) + stop + sleep 3 + start + ;; + condrestart) + if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then + stop + sleep 3 + start + fi + ;; + *) + echo $"Usage: $whatami {start|stop|restart|condrestart|status|help}" + RETVAL=3 +esac + +exit $RETVAL + diff --git a/agent/src/com/cloud/agent/Agent.java b/agent/src/com/cloud/agent/Agent.java index 821cf6de5f8..25b1df31d69 100755 --- a/agent/src/com/cloud/agent/Agent.java +++ b/agent/src/com/cloud/agent/Agent.java @@ -77,8 +77,7 @@ import com.cloud.utils.script.Script; * **/ public class Agent implements HandlerFactory, IAgentControl { - private static final Logger s_logger = Logger.getLogger(Agent.class.getName()); - + private static final Logger s_logger = Logger.getLogger(Agent.class.getName()); public enum ExitStatus { Normal(0), // Normal status = 0. Upgrade(65), // Exiting for upgrade. diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java b/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java index f99adcb063d..d9a063b920b 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtCapXMLParser.java @@ -36,7 +36,7 @@ public class LibvirtCapXMLParser extends LibvirtXMLParser { private boolean _osType = false; private boolean _domainTypeKVM = false; private boolean _emulatorFlag = false; - private String _emulator ; + private final StringBuffer _emulator = new StringBuffer() ; private final StringBuffer _capXML = new StringBuffer(); private static final Logger s_logger = Logger.getLogger(LibvirtCapXMLParser.class); private final ArrayList guestOsTypes = new ArrayList(); @@ -53,6 +53,7 @@ public class LibvirtCapXMLParser extends LibvirtXMLParser { _domainTypeKVM = false; } else if (qName.equalsIgnoreCase("emulator")) { _emulatorFlag = false; + } else if (_host) { _capXML.append("<").append("/").append(qName).append(">"); } @@ -65,7 +66,7 @@ public class LibvirtCapXMLParser extends LibvirtXMLParser { } else if (_osType) { guestOsTypes.add(new String(ch, start, length)); } else if (_emulatorFlag) { - _emulator = new String(ch, start, length); + _emulator.append(ch, start, length); } } @@ -90,6 +91,7 @@ public class LibvirtCapXMLParser extends LibvirtXMLParser { } } else if (qName.equalsIgnoreCase("emulator") && _domainTypeKVM) { _emulatorFlag = true; + _emulator.delete(0, _emulator.length()); } else if (_host) { _capXML.append("<").append(qName); for (int i=0; i < attributes.getLength(); i++) { @@ -120,7 +122,7 @@ public class LibvirtCapXMLParser extends LibvirtXMLParser { } public String getEmulator() { - return _emulator; + return _emulator.toString(); } public static void main(String [] args) { diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index 91b1fb19177..46f381ff6ed 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -109,6 +109,8 @@ import com.cloud.agent.api.MirrorCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolAnswer; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; @@ -1110,6 +1112,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return _virtRouterResource.executeRequest(cmd); } else if (cmd instanceof CheckSshCommand) { return execute((CheckSshCommand) cmd); + } else if (cmd instanceof NetworkUsageCommand) { + return execute((NetworkUsageCommand) cmd); } else { s_logger.warn("Unsupported command "); return Answer.createUnsupportedCommandAnswer(cmd); @@ -2114,19 +2118,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } long totMem = Long.parseLong(totMemparser.getLine()); - double rx = 0.0; - OutputInterpreter.OneLineParser rxParser = new OutputInterpreter.OneLineParser(); - result = executeBashScript("cat /sys/class/net/" + _publicBridgeName + "/statistics/rx_bytes", rxParser); - if (result == null && rxParser.getLine() != null) { - rx = Double.parseDouble(rxParser.getLine())/1000; - } - - double tx = 0.0; - OutputInterpreter.OneLineParser txParser = new OutputInterpreter.OneLineParser(); - result = executeBashScript("cat /sys/class/net/" + _publicBridgeName + "/statistics/tx_bytes", txParser); - if (result == null && txParser.getLine() != null) { - tx = Double.parseDouble(txParser.getLine())/1000; - } + Pair nicStats = getNicStats(_publicBridgeName); int numCpus = 0; try { @@ -2136,9 +2128,29 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } - HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), cpuUtil, rx, tx, "host", totMem, freeMem, 0, 0); + HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), cpuUtil, nicStats.first()/1000, nicStats.second()/1000, "host", totMem, freeMem, 0, 0); return new GetHostStatsAnswer(cmd, hostStats); } + + private Answer execute(NetworkUsageCommand cmd) { + String vmName = cmd.getDomRName(); + try { + Domain dm = getDomain(vmName); + LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); + String xml = dm.getXMLDesc(0); + parser.parseDomainXML(xml); + List nics = parser.getInterfaces(); + if (nics.size() != 3) { + return new Answer(cmd, false, vmName + " doesn't have public nic"); + } + String pubNic = nics.get(2); + Pair nicStats = getNicStats(pubNic); + /*Note: received means bytes received by all the vms, but from host kernel's pov, it's tx*/ + return new NetworkUsageAnswer(cmd, "", nicStats.first().longValue(), nicStats.second().longValue()); + } catch (LibvirtException e) { + return new Answer(cmd, false, e.toString()); + } + } private Answer execute(RebootCommand cmd) { Long bytesReceived = null; @@ -3003,7 +3015,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv long speed = 0; long cpus = 0; long ram = 0; - String osType = null; + String cap = null; try { final NodeInfo hosts = _conn.nodeInfo(); @@ -3016,17 +3028,21 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv for(String s : oss) { /*Even host supports guest os type more than hvm, we only report hvm to management server*/ if (s.equalsIgnoreCase("hvm")) { - osType = "hvm"; + cap = "hvm"; } } } catch (LibvirtException e) { } + + if (isSnapshotSupported()) { + cap = cap + ",snapshot"; + } info.add((int)cpus); info.add(speed); info.add(ram); - info.add(osType); + info.add(cap); long dom0ram = Math.min(ram/10, 768*1024*1024L);//save a maximum of 10% of system ram or 768M dom0ram = Math.max(dom0ram, _dom0MinMem); info.add(dom0ram); @@ -3270,6 +3286,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (f.exists()) { return "/usr/bin/cloud-qemu-system-x86_64"; } else { + f = new File("/usr/libexec/cloud-qemu-kvm"); + if (f.exists()) { + return "/usr/libexec/cloud-qemu-kvm"; + } + if (_conn == null) { return null; } @@ -3841,5 +3862,37 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } return states; } + + /*online snapshot supported by enhanced qemu-kvm*/ + private boolean isSnapshotSupported() { + File f =new File("/usr/bin/cloud-qemu-system-x86_64"); + if (f.exists()) { + return true; + } else { + f = new File("/usr/libexec/cloud-qemu-kvm"); + if (f.exists()) { + return true; + } + } + return false; + } + + private Pair getNicStats(String nicName) { + double rx = 0.0; + OutputInterpreter.OneLineParser rxParser = new OutputInterpreter.OneLineParser(); + String result = executeBashScript("cat /sys/class/net/" + nicName + "/statistics/rx_bytes", rxParser); + if (result == null && rxParser.getLine() != null) { + rx = Double.parseDouble(rxParser.getLine()); + } + + double tx = 0.0; + OutputInterpreter.OneLineParser txParser = new OutputInterpreter.OneLineParser(); + result = executeBashScript("cat /sys/class/net/" + nicName + "/statistics/tx_bytes", txParser); + if (result == null && txParser.getLine() != null) { + tx = Double.parseDouble(txParser.getLine()); + } + + return new Pair(rx, tx); + } } diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index 9fda4e46446..0e2be2bc31d 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -38,7 +38,6 @@ public class VirtualMachineTO { String bootArgs; String[] bootupScripts; boolean rebootOnCrash; - Monitor monitor; VolumeTO[] disks; NicTO[] nics; @@ -70,14 +69,6 @@ public class VirtualMachineTO { return name; } - public Monitor getMonitor() { - return monitor; - } - - public void setMonitor(Monitor monitor) { - this.monitor = monitor; - } - public void setName(String name) { this.name = name; } @@ -187,26 +178,4 @@ public class VirtualMachineTO { public void setNics(NicTO[] nics) { this.nics = nics; } - - public static interface Monitor { - - } - - public static class SshMonitor implements Monitor { - String ip; - int port; - - public String getIp() { - return ip; - } - - public int getPort() { - return port; - } - - public SshMonitor(String ip, int port) { - this.ip = ip; - this.port = port; - } - } } diff --git a/api/src/com/cloud/api/Implementation.java b/api/src/com/cloud/api/Implementation.java index ff28bc2cfe0..8a6aa4abb19 100644 --- a/api/src/com/cloud/api/Implementation.java +++ b/api/src/com/cloud/api/Implementation.java @@ -9,9 +9,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE}) public @interface Implementation { -// String createMethod() default ""; -// String method() default ""; -// Class manager() default ManagementServer.class; Class responseObject(); String description() default ""; } diff --git a/api/src/com/cloud/api/commands/AddHostCmd.java b/api/src/com/cloud/api/commands/AddHostCmd.java index a1f7b02754d..e73eb037864 100644 --- a/api/src/com/cloud/api/commands/AddHostCmd.java +++ b/api/src/com/cloud/api/commands/AddHostCmd.java @@ -63,7 +63,7 @@ public class AddHostCmd extends BaseCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=true, description="the Zone ID for the host") private Long zoneId; - @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=false, description="hypervisor type of the host") + @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="hypervisor type of the host") private String hypervisor; diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java index 008f4fe8a0d..1dc774b402b 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java @@ -40,8 +40,7 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.utils.StringUtils; -//FIXME - add description -@Implementation(responseObject=IngressRuleResponse.class) @SuppressWarnings("rawtypes") +@Implementation(responseObject=IngressRuleResponse.class, description="Authorizes a particular ingress rule for this security group") @SuppressWarnings("rawtypes") public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName()); @@ -54,40 +53,31 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, description="TCP is default. UDP is the other supported protocol") private String protocol; - //FIXME - add description - @Parameter(name=ApiConstants.START_PORT, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.START_PORT, type=CommandType.INTEGER, description="start port for this ingress rule") private Integer startPort; - //FIXME - add description - @Parameter(name=ApiConstants.END_PORT, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.END_PORT, type=CommandType.INTEGER, description="end port for this ingress rule") private Integer endPort; - //FIXME - add description - @Parameter(name=ApiConstants.ICMP_TYPE, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.ICMP_TYPE, type=CommandType.INTEGER, description="type of the icmp message being sent") private Integer icmpType; - //FIXME - add description - @Parameter(name=ApiConstants.ICMP_CODE, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.ICMP_CODE, type=CommandType.INTEGER, description="error code for this icmp message") private Integer icmpCode; - //FIXME - add description - @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, required=true) + @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, required=true, description="the security group name") private String securityGroupName; - //FIXME - add description - @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.LIST, collectionType=CommandType.STRING) + @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.LIST, collectionType=CommandType.STRING, description="the cidr list associated") private List cidrList; - //FIXME - add description - @Parameter(name=ApiConstants.USER_SECURITY_GROUP_LIST, type=CommandType.MAP) + @Parameter(name=ApiConstants.USER_SECURITY_GROUP_LIST, type=CommandType.MAP, description="user to security group mapping") private Map userSecurityGroupList; - //FIXME - add description - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING) + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the security group. Must be used with domainId.") private String accountName; - //FIXME - add description - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG) + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="an optional domainId for the security group. If the account parameter is used, domainId must also be used.") private Long domainId; diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index e1375abe297..c033afbc02f 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -65,14 +65,17 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the VLAN. Default is an \"untagged\" VLAN.") private String vlan; - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account who will own the VLAN. If VLAN is Zone wide, this parameter should be ommited") + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account who will own the network") private String accountName; - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="domain ID of the account owning a VLAN") + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="domain ID of the account owning a network") private Long domainId; @Parameter(name=ApiConstants.IS_SHARED, type=CommandType.BOOLEAN, description="true is network offering supports vlans") private Boolean isShared; + + @Parameter(name=ApiConstants.IS_DEFAULT, type=CommandType.BOOLEAN, description="true if network is default, false otherwise") + private Boolean isDefault; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -124,6 +127,10 @@ public class CreateNetworkCmd extends BaseCmd { public boolean getIsShared() { return isShared == null ? false : isShared; } + + public Boolean isDefault() { + return isDefault; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java b/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java index 2d3cfdb985d..2c6822254f5 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkOfferingCmd.java @@ -26,8 +26,8 @@ import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.NetworkOfferingResponse; -import com.cloud.network.Networks.Availability; import com.cloud.offering.NetworkOffering; +import com.cloud.offering.NetworkOffering.Availability; @Implementation(description="Creates a network offering.", responseObject=NetworkOfferingResponse.class) public class CreateNetworkOfferingCmd extends BaseCmd { @@ -44,9 +44,6 @@ public class CreateNetworkOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the network offering") private String displayText; - @Parameter(name=ApiConstants.TYPE, type=CommandType.STRING, required=true, description="type of the network. Supported types Virtual, Direct") - private String type; - @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, required=true, description="the traffic type for the network offering, supported types are Public, Management, Control, Guest, Vlan or Storage.") private String traffictype; @@ -78,10 +75,6 @@ public class CreateNetworkOfferingCmd extends BaseCmd { return tags; } - public String getType() { - return type; - } - public String getTraffictype() { return traffictype; } diff --git a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java index 17bc361f43c..2686617a9fb 100644 --- a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java @@ -74,11 +74,11 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements @Override public String getProtocol() { - return protocol; + return protocol.trim(); } public String getPublicPort() { - return publicPort; + return publicPort.trim(); } @Override @@ -133,17 +133,17 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements @Override public Ip getSourceIpAddress() { - return new Ip(ipAddress); + return new Ip(ipAddress.trim()); } @Override public int getSourcePortStart() { - return Integer.parseInt(publicPort); + return Integer.parseInt(publicPort.trim()); } @Override public int getSourcePortEnd() { - return Integer.parseInt(publicPort); + return Integer.parseInt(publicPort.trim()); } @Override diff --git a/api/src/com/cloud/api/commands/CreateSecurityGroupCmd.java b/api/src/com/cloud/api/commands/CreateSecurityGroupCmd.java index faf271c0a62..49ab8416e03 100644 --- a/api/src/com/cloud/api/commands/CreateSecurityGroupCmd.java +++ b/api/src/com/cloud/api/commands/CreateSecurityGroupCmd.java @@ -27,8 +27,7 @@ import com.cloud.api.ServerApiException; import com.cloud.api.response.SecurityGroupResponse; import com.cloud.network.security.SecurityGroup; -//TODO - add description to implementation -@Implementation(responseObject=SecurityGroupResponse.class) +@Implementation(responseObject=SecurityGroupResponse.class, description="Creates a security group") public class CreateSecurityGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSecurityGroupCmd.class.getName()); diff --git a/api/src/com/cloud/api/commands/CreateTemplateCmd.java b/api/src/com/cloud/api/commands/CreateTemplateCmd.java index 2dc17f684da..6e30653d24c 100644 --- a/api/src/com/cloud/api/commands/CreateTemplateCmd.java +++ b/api/src/com/cloud/api/commands/CreateTemplateCmd.java @@ -47,7 +47,7 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.BITS, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.BITS, type=CommandType.INTEGER, description="32 or 64 bit") private Integer bits; @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the template. This is usually used for display purposes.") diff --git a/api/src/com/cloud/api/commands/CreateUserCmd.java b/api/src/com/cloud/api/commands/CreateUserCmd.java index debb5cf2e1a..ca26a7baca6 100644 --- a/api/src/com/cloud/api/commands/CreateUserCmd.java +++ b/api/src/com/cloud/api/commands/CreateUserCmd.java @@ -41,7 +41,7 @@ public class CreateUserCmd extends BaseCmd { @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="Creates the user under the specified account. If no account is specified, the username will be used as the account name.") private String accountName; - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="Creates the user under the specified domain.") + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="Creates the user under the specified domain. Has to be accompanied with the account parameter") private Long domainId; @Parameter(name=ApiConstants.EMAIL, type=CommandType.STRING, required=true, description="email") diff --git a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java b/api/src/com/cloud/api/commands/DeleteVolumeCmd.java index c0919c7895c..bd23f442885 100644 --- a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java +++ b/api/src/com/cloud/api/commands/DeleteVolumeCmd.java @@ -26,6 +26,7 @@ import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.SuccessResponse; +import com.cloud.exception.ConcurrentOperationException; @Implementation(description="Deletes a detached disk volume.", responseObject=SuccessResponse.class) public class DeleteVolumeCmd extends BaseCmd { @@ -63,7 +64,7 @@ public class DeleteVolumeCmd extends BaseCmd { } @Override - public void execute(){ + public void execute() throws ConcurrentOperationException { boolean result = _storageService.deleteVolume(this); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); diff --git a/api/src/com/cloud/api/commands/ListNetworkOfferingsCmd.java b/api/src/com/cloud/api/commands/ListNetworkOfferingsCmd.java index 1864b4e06b9..64c726bd64f 100644 --- a/api/src/com/cloud/api/commands/ListNetworkOfferingsCmd.java +++ b/api/src/com/cloud/api/commands/ListNetworkOfferingsCmd.java @@ -49,9 +49,6 @@ public class ListNetworkOfferingsCmd extends BaseListCmd { @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="list network offerings by display text") private String displayText; - @Parameter(name=ApiConstants.TYPE, type=CommandType.STRING, description="list by type of the network") - private String type; - @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, description="list by traffic type") private String trafficType; @@ -78,11 +75,7 @@ public class ListNetworkOfferingsCmd extends BaseListCmd { public String getDisplayText() { return displayText; } - - public String getType() { - return type; - } - + public String getTrafficType() { return trafficType; } diff --git a/api/src/com/cloud/api/commands/ListNetworksCmd.java b/api/src/com/cloud/api/commands/ListNetworksCmd.java index 0b959f55098..b9400f9b444 100644 --- a/api/src/com/cloud/api/commands/ListNetworksCmd.java +++ b/api/src/com/cloud/api/commands/ListNetworksCmd.java @@ -57,6 +57,15 @@ public class ListNetworksCmd extends BaseListCmd { @Parameter(name=ApiConstants.IS_SYSTEM, type=CommandType.BOOLEAN, description="true if network is system, false otherwise") private Boolean isSystem; + + @Parameter(name=ApiConstants.IS_SHARED, type=CommandType.BOOLEAN, description="true if network is shared, false otherwise") + private Boolean isShared; + + @Parameter(name=ApiConstants.IS_DEFAULT, type=CommandType.BOOLEAN, description="true if network is default, false otherwise") + private Boolean isDefault; + + @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, description="type of the traffic") + private String trafficType; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -86,6 +95,18 @@ public class ListNetworksCmd extends BaseListCmd { return isSystem; } + public Boolean getIsShared() { + return isShared; + } + + public Boolean isDefault() { + return isDefault; + } + + public String getTrafficType() { + return trafficType; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/ListPreallocatedLunsCmd.java b/api/src/com/cloud/api/commands/ListPreallocatedLunsCmd.java index 645f0a6ca5b..981c155c3ed 100644 --- a/api/src/com/cloud/api/commands/ListPreallocatedLunsCmd.java +++ b/api/src/com/cloud/api/commands/ListPreallocatedLunsCmd.java @@ -30,7 +30,7 @@ import com.cloud.api.Parameter; import com.cloud.api.response.ListResponse; import com.cloud.api.response.PreallocatedLunResponse; -@Implementation(responseObject=PreallocatedLunResponse.class) +@Implementation(description="List PreallocatedLuns",responseObject=PreallocatedLunResponse.class) public class ListPreallocatedLunsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListPreallocatedLunsCmd.class.getName()); diff --git a/api/src/com/cloud/api/commands/RegisterPreallocatedLunCmd.java b/api/src/com/cloud/api/commands/RegisterPreallocatedLunCmd.java index e7d7f72d118..1fb47e40d5b 100644 --- a/api/src/com/cloud/api/commands/RegisterPreallocatedLunCmd.java +++ b/api/src/com/cloud/api/commands/RegisterPreallocatedLunCmd.java @@ -24,8 +24,7 @@ import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.PreallocatedLunResponse; -//TODO - add description to @Implementation -@Implementation(responseObject=PreallocatedLunResponse.class) +@Implementation(description="Registers PreallocatedLun", responseObject=PreallocatedLunResponse.class) public class RegisterPreallocatedLunCmd extends BaseCmd { private static final String s_name = "registerPreallocatedLunsResponse"; @@ -33,20 +32,17 @@ public class RegisterPreallocatedLunCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - //FIXME - add description - @Parameter(name=ApiConstants.DISK_SIZE, type=CommandType.LONG, required=true) + @Parameter(name=ApiConstants.DISK_SIZE, type=CommandType.LONG, required=true, description="Volume size") private Long diskSize; - //FIXME - add description - @Parameter(name=ApiConstants.LUN, type=CommandType.INTEGER, required=true) + @Parameter(name=ApiConstants.LUN, type=CommandType.INTEGER, required=true, description="Lun id") private Integer lun; //FIXME - add description @Parameter(name=ApiConstants.PORTAL, type=CommandType.STRING, required=true) private String portal; - //FIXME - add description - @Parameter(name=ApiConstants.TAGS, type=CommandType.STRING) + @Parameter(name=ApiConstants.TAGS, type=CommandType.STRING, description="tags for the volume") private String tags; @Parameter(name=ApiConstants.TARGET_IQN, type=CommandType.STRING, required=true, description="the target IQN on the storage host where LUN is created") diff --git a/api/src/com/cloud/api/commands/RestartNetworkCmd.java b/api/src/com/cloud/api/commands/RestartNetworkCmd.java index 72ba23414b5..b03c5d73ca9 100644 --- a/api/src/com/cloud/api/commands/RestartNetworkCmd.java +++ b/api/src/com/cloud/api/commands/RestartNetworkCmd.java @@ -17,8 +17,6 @@ */ package com.cloud.api.commands; -import java.util.List; - import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -32,10 +30,10 @@ import com.cloud.api.response.SuccessResponse; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.user.UserContext; @Implementation(description="Reapplies all ip addresses for the particular network", responseObject=IPAddressResponse.class) public class RestartNetworkCmd extends BaseAsyncCmd { @@ -46,12 +44,6 @@ public class RestartNetworkCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account to associate with this IP address") - private String accountName; - - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the ID of the domain to associate with this IP address") - private Long domainId; - @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=true, description="the ID of the availability zone you want to acquire an public IP address from") private Long zoneId; @@ -63,20 +55,6 @@ public class RestartNetworkCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getAccountName() { - if (accountName != null) { - return accountName; - } - return UserContext.current().getCaller().getAccountName(); - } - - public long getDomainId() { - if (domainId != null) { - return domainId; - } - return UserContext.current().getCaller().getDomainId(); - } - public long getZoneId() { return zoneId; } @@ -90,26 +68,16 @@ public class RestartNetworkCmd extends BaseAsyncCmd { } public long getEntityOwnerId() { - List networks = _networkService.getVirtualNetworksOwnedByAccountInZone(getAccountName(), getDomainId(), getZoneId()); - if (networks.size() == 0) { - assert (networks.size() <= 1) : "No virtual network is found"; - } - assert (networks.size() <= 1) : "Too many virtual networks. This logic should be obsolete"; - - return networks.get(0).getAccountId(); + return _networkService.getNetwork(networkId).getAccountId(); } public Long getNetworkId() { - if (networkId != null) { - return networkId; + Network network = _networkService.getNetwork(networkId); + if (network == null) { + throw new InvalidParameterValueException("Unable to find network by id " + networkId); + } else { + return network.getId(); } - - List networks = _networkService.getVirtualNetworksOwnedByAccountInZone(getAccountName(), getDomainId(), getZoneId()); - if (networks.size() == 0) { - return null; - } - assert (networks.size() <= 1) : "Too many virtual networks. This logic should be obsolete"; - return networks.get(0).getId(); } diff --git a/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java index 321f2f4b2a1..916a72153f1 100644 --- a/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java @@ -19,7 +19,7 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; @SuppressWarnings("rawtypes") -@Implementation(responseObject=SuccessResponse.class) +@Implementation(responseObject=SuccessResponse.class, description="Deletes a particular ingress rule from this security group") public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupIngressCmd.class.getName()); @@ -29,44 +29,34 @@ public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - //FIXME - add description - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING) + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the security group. Must be used with domainId.") private String accountName; - //FIXME - add description - @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.STRING) + @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.STRING, description="the cidr list associated") private String cidrList; - //FIXME - add description - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG) + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="an optional domainId for the security group. If the account parameter is used, domainId must also be used.") private Long domainId; - //FIXME - add description - @Parameter(name=ApiConstants.END_PORT, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.END_PORT, type=CommandType.INTEGER, description="end port for this ingress rule") private Integer endPort; - //FIXME - add description - @Parameter(name=ApiConstants.ICMP_CODE, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.ICMP_CODE, type=CommandType.INTEGER, description="error code for this icmp message") private Integer icmpCode; - //FIXME - add description - @Parameter(name=ApiConstants.ICMP_TYPE, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.ICMP_TYPE, type=CommandType.INTEGER, description="type for this icmp message") private Integer icmpType; - //FIXME - add description - @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, required=true) + @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, required=true, description="name of the security group") private String securityGroupName; - //FIXME - add description - @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING) + @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, description="protocol used") private String protocol; - //FIXME - add description - @Parameter(name=ApiConstants.START_PORT, type=CommandType.INTEGER) + @Parameter(name=ApiConstants.START_PORT, type=CommandType.INTEGER,description="start port for this ingress rule") private Integer startPort; - //FIXME - add description - @Parameter(name=ApiConstants.USER_SECURITY_GROUP_LIST, type=CommandType.MAP) + @Parameter(name=ApiConstants.USER_SECURITY_GROUP_LIST, type=CommandType.MAP, description="user to security group mapping") private Map userSecurityGroupList; ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java index 980010b7d95..901a841240d 100644 --- a/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java @@ -26,8 +26,8 @@ import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.NetworkOfferingResponse; -import com.cloud.network.Networks.Availability; import com.cloud.offering.NetworkOffering; +import com.cloud.offering.NetworkOffering.Availability; @Implementation(description="Updates a network offering.", responseObject=NetworkOfferingResponse.class) public class UpdateNetworkOfferingCmd extends BaseCmd { diff --git a/api/src/com/cloud/api/response/DiskOfferingResponse.java b/api/src/com/cloud/api/response/DiskOfferingResponse.java index 8d20d06c5ab..32c123431ad 100644 --- a/api/src/com/cloud/api/response/DiskOfferingResponse.java +++ b/api/src/com/cloud/api/response/DiskOfferingResponse.java @@ -45,10 +45,7 @@ public class DiskOfferingResponse extends BaseResponse { @SerializedName(ApiConstants.CREATED) @Param(description="the date this disk offering was created") private Date created; - @SerializedName("ismirrored") - private Boolean mirrored; - - @SerializedName("iscustomized") + @SerializedName("iscustomized") @Param(description="true if disk offering uses custom size, false otherwise") private Boolean customized; @SerializedName(ApiConstants.TAGS) @Param(description="the tags for the disk offering") @@ -110,14 +107,6 @@ public class DiskOfferingResponse extends BaseResponse { this.created = created; } - public Boolean isMirrored() { - return mirrored; - } - - public void setMirrored(Boolean mirrored) { - this.mirrored = mirrored; - } - public String getTags() { return tags; } diff --git a/api/src/com/cloud/api/response/ExtractResponse.java b/api/src/com/cloud/api/response/ExtractResponse.java index 6c9f2dae1b9..2190a6b4863 100755 --- a/api/src/com/cloud/api/response/ExtractResponse.java +++ b/api/src/com/cloud/api/response/ExtractResponse.java @@ -42,7 +42,7 @@ public class ExtractResponse extends BaseResponse { @SerializedName("accountid") @Param(description="the account id to which the extracted object belongs") private Long accountId; - @SerializedName("resultstring") @Param(description="") + @SerializedName("resultstring") @Param(expose=false) private String resultString; @SerializedName(ApiConstants.CREATED) @Param(description="the time and date the object was created") @@ -51,11 +51,9 @@ public class ExtractResponse extends BaseResponse { @SerializedName(ApiConstants.STATE) @Param(description="the state of the extracted object") private String state; - //FIXME - add description - @SerializedName("storagetype") + @SerializedName("storagetype") @Param(description="type of the storage") private String storageType; - //FIXME - add description @SerializedName("storage") private String storage; diff --git a/api/src/com/cloud/api/response/HypervisorResponse.java b/api/src/com/cloud/api/response/HypervisorResponse.java index 3fd675e98b2..ff9d52a10a0 100644 --- a/api/src/com/cloud/api/response/HypervisorResponse.java +++ b/api/src/com/cloud/api/response/HypervisorResponse.java @@ -1,10 +1,11 @@ package com.cloud.api.response; import com.cloud.api.ApiConstants; +import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; public class HypervisorResponse extends BaseResponse { - @SerializedName(ApiConstants.NAME) + @SerializedName(ApiConstants.NAME) @Param(description="Hypervisor name") private String name; public String getName() { diff --git a/api/src/com/cloud/api/response/IngressRuleResponse.java b/api/src/com/cloud/api/response/IngressRuleResponse.java index ed4bbc248d6..9fa12f3ee09 100644 --- a/api/src/com/cloud/api/response/IngressRuleResponse.java +++ b/api/src/com/cloud/api/response/IngressRuleResponse.java @@ -28,12 +28,10 @@ public class IngressRuleResponse extends BaseResponse { @SerializedName("protocol") @Param(description="the protocol of the ingress rule") private String protocol; - //FIXME - add description - @SerializedName(ApiConstants.ICMP_TYPE) + @SerializedName(ApiConstants.ICMP_TYPE) @Param(description="the type of the ICMP message response") private Integer icmpType; - //FIXME - add description - @SerializedName(ApiConstants.ICMP_CODE) + @SerializedName(ApiConstants.ICMP_CODE) @Param(description="the code for the ICMP message response") private Integer icmpCode; @SerializedName(ApiConstants.START_PORT) @Param(description="the starting IP of the ingress rule") diff --git a/api/src/com/cloud/api/response/NetworkOfferingResponse.java b/api/src/com/cloud/api/response/NetworkOfferingResponse.java index 56d75410578..47bf6e98436 100644 --- a/api/src/com/cloud/api/response/NetworkOfferingResponse.java +++ b/api/src/com/cloud/api/response/NetworkOfferingResponse.java @@ -24,9 +24,6 @@ public class NetworkOfferingResponse extends BaseResponse{ @SerializedName("maxconnections") @Param(description="the max number of concurrent connection the network offering supports") private Integer maxConnections; - @SerializedName("type") @Param(description="type of the network. Supported types are Virtualized, DirectSingle, DirectDual") - private String type; - @SerializedName("traffictype") @Param(description="the traffic type for the network offering, supported types are Public, Management, Control, Guest, Vlan or Storage.") private String trafficType; @@ -87,14 +84,6 @@ public class NetworkOfferingResponse extends BaseResponse{ this.maxConnections = maxConnections; } - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - public String getTrafficType() { return trafficType; } diff --git a/api/src/com/cloud/api/response/NetworkResponse.java b/api/src/com/cloud/api/response/NetworkResponse.java index 0c1df19f4e9..aed50cae27a 100644 --- a/api/src/com/cloud/api/response/NetworkResponse.java +++ b/api/src/com/cloud/api/response/NetworkResponse.java @@ -17,20 +17,16 @@ public class NetworkResponse extends BaseResponse{ @SerializedName("displaytext") @Param(description="the displaytext of the network") private String displaytext; - //TODO - add description - @SerializedName("broadcastdomaintype") + @SerializedName("broadcastdomaintype") @Param(description="Broadcast domain type of the network") private String broadcastDomainType; - //TODO - add description - @SerializedName("traffictype") + @SerializedName("traffictype") @Param(description="the traffic type of the network") private String trafficType; - //TODO - add description - @SerializedName("gateway") + @SerializedName("gateway") @Param(description="the network's gateway") private String gateway; - //TODO - add description - @SerializedName("netmask") + @SerializedName("netmask") @Param(description="the network's netmask") private String netmask; @SerializedName("startip") @Param(description="the start ip of the network") @@ -39,61 +35,46 @@ public class NetworkResponse extends BaseResponse{ @SerializedName("endip") @Param(description="the end ip of the network") private String endIp; - //TODO - add description - @SerializedName("zoneid") + @SerializedName("zoneid") @Param(description="zone id of the network") private Long zoneId; - //TODO - add description - @SerializedName("networkofferingid") + @SerializedName("networkofferingid") @Param(description="network offering id the network is created from") private Long networkOfferingId; - //TODO - add description - @SerializedName("networkofferingname") + @SerializedName("networkofferingname") @Param(description="name of the network offering the network is created from") private String networkOfferingName; - //TODO - add description - @SerializedName("networkofferingdisplaytext") + @SerializedName("networkofferingdisplaytext") @Param(description="display text of the network offering the network is created from") private String networkOfferingDisplayText; - //TODO - add description - @SerializedName("networkofferingavailability") + @SerializedName("networkofferingavailability") @Param(description="availability of the network offering the network is created from") private String networkOfferingAvailability; - - //TODO - add description - @SerializedName("isshared") + @SerializedName("isshared") @Param(description="true if network is shared, false otherwise") private Boolean isShared; - //TODO - add description - @SerializedName("issystem") + @SerializedName("issystem") @Param(description="true if network is system, false otherwise") private Boolean isSystem; - //TODO - add description - @SerializedName("state") + @SerializedName("state") @Param(description="state of the network") private String state; - - //TODO - add description - @SerializedName("related") + + @SerializedName("related") @Param(description="related to what other network configuration") private Long related; - //TODO - add description - @SerializedName("broadcasturi") + @SerializedName("broadcasturi") @Param(description="broadcast uri of the network") private String broadcastUri; - //TODO - add description - @SerializedName("dns1") + @SerializedName("dns1") @Param(description="the first dns for the network") private String dns1; - //TODO - add description - @SerializedName("dns2") + @SerializedName("dns2") @Param(description="the second dns for the network") private String dns2; - //TODO - add description - @SerializedName("type") + @SerializedName("type") @Param(description="the type of the network") private String type; - //TODO - add description - @SerializedName("vlan") + @SerializedName("vlan") @Param(description="the vlan of the network") private String vlan; @SerializedName(ApiConstants.ACCOUNT) @Param(description="the account associated with the network") @@ -105,7 +86,10 @@ public class NetworkResponse extends BaseResponse{ @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain associated with the network") private String domain; - @SerializedName("service") @Param(description="the list of services") + @SerializedName("isdefault") @Param(description="true if network is default, false otherwise") + private Boolean isDefault; + + @SerializedName("service") @Param(description="the list of services", responseObject = ServiceResponse.class) private List services; public Long getId() { @@ -323,4 +307,12 @@ public class NetworkResponse extends BaseResponse{ public void setServices(List services) { this.services = services; } + + public Boolean getIsDefault() { + return isDefault; + } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } } diff --git a/api/src/com/cloud/api/response/NicResponse.java b/api/src/com/cloud/api/response/NicResponse.java index d68fa797ddb..b69f0449d11 100644 --- a/api/src/com/cloud/api/response/NicResponse.java +++ b/api/src/com/cloud/api/response/NicResponse.java @@ -43,13 +43,14 @@ public class NicResponse extends BaseResponse { @SerializedName("broadcasturi") @Param(description="the broadcast uri of the nic") private String broadcastUri; - //TODO - add description - @SerializedName("traffictype") + @SerializedName("traffictype") @Param(description="the traffic type of the nic") private String trafficType; - //TODO - add description - @SerializedName("type") + @SerializedName("type") @Param(description="the type of the nic") private String type; + + @SerializedName("isdefault") @Param(description="true if nic is default, false otherwise") + private Boolean isDefault; public Long getId() { return id; @@ -122,4 +123,12 @@ public class NicResponse extends BaseResponse { public void setType(String type) { this.type = type; } + + public Boolean getIsDefault() { + return isDefault; + } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } } diff --git a/api/src/com/cloud/api/response/SecurityGroupResponse.java b/api/src/com/cloud/api/response/SecurityGroupResponse.java index aeddef21b93..705ac8addec 100644 --- a/api/src/com/cloud/api/response/SecurityGroupResponse.java +++ b/api/src/com/cloud/api/response/SecurityGroupResponse.java @@ -41,7 +41,7 @@ public class SecurityGroupResponse extends BaseResponse { @SerializedName("domain") @Param(description="the domain name of the security group") private String domainName; - @SerializedName("ingressrule") @Param(description="the list of ingress rules associated with the security group") + @SerializedName("ingressrule") @Param(description="the list of ingress rules associated with the security group", responseObject = IngressRuleResponse.class) private List ingressRules; public Long getId() { diff --git a/api/src/com/cloud/api/response/ServiceResponse.java b/api/src/com/cloud/api/response/ServiceResponse.java index d28c9f496ec..2f75de3529b 100644 --- a/api/src/com/cloud/api/response/ServiceResponse.java +++ b/api/src/com/cloud/api/response/ServiceResponse.java @@ -28,7 +28,7 @@ public class ServiceResponse extends BaseResponse { @SerializedName(ApiConstants.NAME) @Param(description="the service name") private String name; - @SerializedName("capability") @Param(description="the list of capabilities") + @SerializedName("capability") @Param(description="the list of capabilities", responseObject = CapabilityResponse.class) private List capabilities; public String getName() { diff --git a/api/src/com/cloud/api/response/UserVmResponse.java b/api/src/com/cloud/api/response/UserVmResponse.java index 40625421b9c..113c49f2ec8 100644 --- a/api/src/com/cloud/api/response/UserVmResponse.java +++ b/api/src/com/cloud/api/response/UserVmResponse.java @@ -142,7 +142,7 @@ public class UserVmResponse extends BaseResponse { @SerializedName("jobstatus") @Param(description="shows the current pending asynchronous job status") private Integer jobStatus; - @SerializedName("nic") @Param(description="the list of nics associated with vm") + @SerializedName("nic") @Param(description="the list of nics associated with vm", responseObject = NicResponse.class) private List nics; public Long getObjectId() { diff --git a/api/src/com/cloud/api/response/VolumeResponse.java b/api/src/com/cloud/api/response/VolumeResponse.java index 481b0a640f3..f415077a648 100644 --- a/api/src/com/cloud/api/response/VolumeResponse.java +++ b/api/src/com/cloud/api/response/VolumeResponse.java @@ -81,13 +81,13 @@ public class VolumeResponse extends BaseResponse { @SerializedName("storagetype") @Param(description="shared or local storage") private String storageType; - @SerializedName("sourceid") + @SerializedName("sourceid") @Param(description="Id of the snapshot or diskOffering volume is created from") private Long sourceId; - @SerializedName("sourcetype") + @SerializedName("sourcetype") @Param(description="Type of the source the volume is created from. Can be: Snapshot,DiskOffering") private String sourceType; - @SerializedName(ApiConstants.HYPERVISOR) + @SerializedName(ApiConstants.HYPERVISOR) @Param(description="Hypervisor the volume belongs to") private String hypervisor; @SerializedName(ApiConstants.DISK_OFFERING_ID) @Param(description="ID of the disk offering") diff --git a/api/src/com/cloud/api/response/ZoneResponse.java b/api/src/com/cloud/api/response/ZoneResponse.java index daa40c07483..efbd044d892 100644 --- a/api/src/com/cloud/api/response/ZoneResponse.java +++ b/api/src/com/cloud/api/response/ZoneResponse.java @@ -42,19 +42,18 @@ public class ZoneResponse extends BaseResponse { @SerializedName(ApiConstants.INTERNAL_DNS2) @Param(description="the second internal DNS for the Zone") private String internalDns2; - - //FIXME - add description. This parameter is called "vnet" in updateZone, and vlan in createZone - figure out which one is right. - @SerializedName(ApiConstants.VLAN) + + @SerializedName(ApiConstants.VLAN) @Param(description="the vlan range of the zone") private String vlan; @SerializedName(ApiConstants.GUEST_CIDR_ADDRESS) @Param(description="the guest CIDR address for the Zone") private String guestCidrAddress; - //FIXME - do we need 2 parameters below at all? + //TODO - generate description @SerializedName("status") private String status; - @SerializedName(ApiConstants.DISPLAY_TEXT) + @SerializedName(ApiConstants.DISPLAY_TEXT) @Param(description="the display text of the zone") private String displayText; @SerializedName(ApiConstants.DOMAIN) @Param(description="Domain name for the Vms in the zone") diff --git a/api/src/com/cloud/deploy/DeploymentPlanner.java b/api/src/com/cloud/deploy/DeploymentPlanner.java index 668b6952f6a..c010d5a7ff6 100644 --- a/api/src/com/cloud/deploy/DeploymentPlanner.java +++ b/api/src/com/cloud/deploy/DeploymentPlanner.java @@ -10,6 +10,7 @@ import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.Host; import com.cloud.org.Cluster; import com.cloud.storage.StoragePool; @@ -50,11 +51,11 @@ public interface DeploymentPlanner extends Adapter { Set _hostIds; Set _poolIds; - public void add(InsufficientCapacityException e) { + public boolean add(InsufficientCapacityException e) { Class scope = e.getScope(); if (scope == null) { - return; + return false; } if (Host.class.isAssignableFrom(scope)) { @@ -67,7 +68,35 @@ public interface DeploymentPlanner extends Adapter { addCluster(e.getId()); } else if (StoragePool.class.isAssignableFrom(scope)) { addPool(e.getId()); + } else { + return false; } + + return true; + } + + public boolean add(ResourceUnavailableException e) { + Class scope = e.getScope(); + + if (scope == null) { + return false; + } + + if (Host.class.isAssignableFrom(scope)) { + addHost(e.getResourceId()); + } else if (Pod.class.isAssignableFrom(scope)) { + addPod(e.getResourceId()); + } else if (DataCenter.class.isAssignableFrom(scope)) { + addDataCenter(e.getResourceId()); + } else if (Cluster.class.isAssignableFrom(scope)) { + addCluster(e.getResourceId()); + } else if (StoragePool.class.isAssignableFrom(scope)) { + addPool(e.getResourceId()); + } else { + return false; + } + + return true; } public void addPool(long poolId) { diff --git a/api/src/com/cloud/event/ActionEvent.java b/api/src/com/cloud/event/ActionEvent.java new file mode 100644 index 00000000000..b890172ec77 --- /dev/null +++ b/api/src/com/cloud/event/ActionEvent.java @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2010 Cloud.com, 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 . + * + */ +package com.cloud.event; + +public @interface ActionEvent { +} diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index ed62bb57b6d..92301a31a6d 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -11,7 +11,6 @@ import com.cloud.acl.ControlledEntity; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.fsm.FiniteState; import com.cloud.utils.fsm.StateMachine; @@ -21,6 +20,11 @@ import com.cloud.utils.fsm.StateMachine; */ public interface Network extends ControlledEntity { + public enum GuestIpType { + Virtual, + Direct, + } + public static class Service { public static final Service Vpn = new Service("Vpn", Capability.SupportedVpnTypes); @@ -197,5 +201,7 @@ public interface Network extends ControlledEntity { boolean isShared(); String getReservationId(); + + boolean isDefault(); } diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index fdcdae253d1..5b0a9da8860 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -55,4 +55,6 @@ public interface NetworkService { int getActiveNicsInNetwork(long networkId); + Network getNetwork(long networkId); + } diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java index 9286ece6d51..889ca567047 100644 --- a/api/src/com/cloud/network/Networks.java +++ b/api/src/com/cloud/network/Networks.java @@ -36,12 +36,6 @@ public class Networks { Firewall } - public enum Availability { - Required, - Optional, - Unavailable; - } - /** * Different ways to assign ip address to this network. */ diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index 07863b7c6b2..5505f7d34fc 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -61,5 +61,7 @@ public interface LoadBalancingRulesService { * @return list of load balancers that match the criteria */ List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd); + + List listByNetworkId(long networkId); } diff --git a/api/src/com/cloud/network/ovs/OvsCreateGreTunnelAnswer.java b/api/src/com/cloud/network/ovs/OvsCreateGreTunnelAnswer.java new file mode 100644 index 00000000000..bd541d9c1af --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsCreateGreTunnelAnswer.java @@ -0,0 +1,65 @@ +package com.cloud.network.ovs; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class OvsCreateGreTunnelAnswer extends Answer { + String hostIp; + String remoteIp; + String bridge; + String key; + long from; + long to; + int port; + + public OvsCreateGreTunnelAnswer(Command cmd, boolean success, String details) { + super(cmd, success, details); + } + + public OvsCreateGreTunnelAnswer(Command cmd, boolean success, + String details, String hostIp, String bridge) { + super(cmd, success, details); + OvsCreateGreTunnelCommand c = (OvsCreateGreTunnelCommand)cmd; + this.hostIp = hostIp; + this.bridge = bridge; + this.remoteIp = c.getRemoteIp(); + this.key = c.getKey(); + this.port = -1; + this.from = c.getFrom(); + this.to = c.getTo(); + } + + public OvsCreateGreTunnelAnswer(Command cmd, boolean success, + String details, String hostIp, String bridge, int port) { + this(cmd, success, details, hostIp, bridge); + this.port = port; + } + + public String getHostIp() { + return hostIp; + } + + public String getRemoteIp() { + return remoteIp; + } + + public String getBridge() { + return bridge; + } + + public String getKey() { + return key; + } + + public long getFrom() { + return from; + } + + public long getTo() { + return to; + } + + public int getPort() { + return port; + } +} diff --git a/api/src/com/cloud/network/ovs/OvsCreateGreTunnelCommand.java b/api/src/com/cloud/network/ovs/OvsCreateGreTunnelCommand.java new file mode 100644 index 00000000000..3c504a769df --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsCreateGreTunnelCommand.java @@ -0,0 +1,38 @@ +package com.cloud.network.ovs; + +import com.cloud.agent.api.Command; + +public class OvsCreateGreTunnelCommand extends Command { + String remoteIp; + String key; + long from; + long to; + + @Override + public boolean executeInSequence() { + return true; + } + + public OvsCreateGreTunnelCommand(String remoteIp, String key, long from, long to) { + this.remoteIp = remoteIp; + this.key = key; + this.from = from; + this.to = to; + } + + public String getRemoteIp() { + return remoteIp; + } + + public String getKey() { + return key; + } + + public long getFrom() { + return from; + } + + public long getTo() { + return to; + } +} diff --git a/api/src/com/cloud/network/ovs/OvsDeleteFlowCommand.java b/api/src/com/cloud/network/ovs/OvsDeleteFlowCommand.java new file mode 100644 index 00000000000..2765eb789db --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsDeleteFlowCommand.java @@ -0,0 +1,20 @@ +package com.cloud.network.ovs; + +import com.cloud.agent.api.Command; + +public class OvsDeleteFlowCommand extends Command { + String vmName; + + @Override + public boolean executeInSequence() { + return true; + } + + public String getVmName() { + return vmName; + } + + public OvsDeleteFlowCommand(String vmName) { + this.vmName = vmName; + } +} diff --git a/api/src/com/cloud/network/ovs/OvsSetTagAndFlowAnswer.java b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowAnswer.java new file mode 100644 index 00000000000..5b495c7cdec --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowAnswer.java @@ -0,0 +1,24 @@ +package com.cloud.network.ovs; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class OvsSetTagAndFlowAnswer extends Answer { + Long vmId; + Long seqno; + + public OvsSetTagAndFlowAnswer(Command cmd, boolean success, String details) { + super(cmd, success, details); + OvsSetTagAndFlowCommand c = (OvsSetTagAndFlowCommand)cmd; + this.vmId = c.getVmId(); + this.seqno = Long.parseLong(c.getSeqNo()); + } + + public Long getVmId() { + return vmId; + } + + public Long getSeqNo() { + return seqno; + } +} diff --git a/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java new file mode 100644 index 00000000000..6ff8934a7ae --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java @@ -0,0 +1,44 @@ +package com.cloud.network.ovs; + +import com.cloud.agent.api.Command; + +public class OvsSetTagAndFlowCommand extends Command { + String vlans; + String vmName; + String seqno; + String tag; + Long vmId; + + @Override + public boolean executeInSequence() { + return true; + } + + public String getSeqNo() { + return seqno; + } + + public String getVlans() { + return vlans; + } + + public String getVmName() { + return vmName; + } + + public Long getVmId() { + return vmId; + } + + public String getTag() { + return tag; + } + + public OvsSetTagAndFlowCommand(String vmName, String tag, String vlans, String seqno, Long vmId) { + this.vmName = vmName; + this.tag = tag; + this.vlans = vlans; + this.seqno = seqno; + this.vmId = vmId; + } +} diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index d4c09737b6e..62bbaa221f6 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -17,7 +17,6 @@ */ package com.cloud.offering; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.TrafficType; /** @@ -26,16 +25,21 @@ import com.cloud.network.Networks.TrafficType; */ public interface NetworkOffering { - public enum GuestIpType { - Virtual, - Direct, - DirectPodBased, + public enum Availability { + Required, + Optional, + Unavailable; } - public final String DefaultVirtualizedNetworkOffering = "DefaultVirtualizedNetworkOffering"; - public final String DefaultDirectNetworkOffering = "DefaultDirectNetworkOffering"; - public final String DefaultDirectPodBasedNetworkOffering = "DefaultDirectPodBasedNetworkOffering"; - public final String DefaultDirectChooseVlanNetworkOffering = "DefaultDirectChooseVlanNetworkOffering"; + public final static String SystemPublicNetwork = "System-Public-Network"; + public final static String SystemControlNetwork = "System-Control-Network"; + public final static String SystemManagementNetwork = "System-Management-Network"; + public final static String SystemStorageNetwork = "System-Storage-Network"; + public final static String SysteGuestNetwork = "System-Guest-Network"; + + public final static String DefaultVirtualizedNetworkOffering = "DefaultVirtualizedNetworkOffering"; + public final static String DefaultDirectNetworkOffering = "DefaultDirectNetworkOffering"; + public final static String DefaultDirectChooseVlanNetworkOffering = "DefaultDirectChooseVlanNetworkOffering"; long getId(); @@ -59,11 +63,6 @@ public interface NetworkOffering { */ Integer getMulticastRateMbps(); - /** - * @return the type of IP address to allocate as the primary ip address to a guest - */ - GuestIpType getGuestIpType(); - /** * @return concurrent connections to be supported. */ @@ -81,6 +80,7 @@ public interface NetworkOffering { Availability getAvailability(); + boolean isDnsService(); boolean isGatewayService(); diff --git a/api/src/com/cloud/offering/ServiceOffering.java b/api/src/com/cloud/offering/ServiceOffering.java index aa9c97c1b8c..c9ca5ba3272 100755 --- a/api/src/com/cloud/offering/ServiceOffering.java +++ b/api/src/com/cloud/offering/ServiceOffering.java @@ -19,6 +19,8 @@ package com.cloud.offering; import java.util.Date; +import com.cloud.network.Network; + /** * ServiceOffering models the different types of service contracts to be * offered. @@ -70,7 +72,7 @@ public interface ServiceOffering { /** * @return the type of IP address to allocate as the primary ip address to a guest */ - NetworkOffering.GuestIpType getGuestIpType(); + Network.GuestIpType getGuestIpType(); /** * @return whether or not the service offering requires local storage diff --git a/api/src/com/cloud/serializer/Param.java b/api/src/com/cloud/serializer/Param.java index da3579e3125..ebc0fb62e9f 100644 --- a/api/src/com/cloud/serializer/Param.java +++ b/api/src/com/cloud/serializer/Param.java @@ -18,12 +18,16 @@ package com.cloud.serializer; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface Param { String name() default ""; String propName() default ""; - String description() default ""; + String description() default ""; + + // 2 parameters below are used by cloudstack api + boolean expose() default true; + Class responseObject() default Object.class; } diff --git a/api/src/com/cloud/storage/StorageService.java b/api/src/com/cloud/storage/StorageService.java index f8fd6d290dc..e51e7392a6d 100644 --- a/api/src/com/cloud/storage/StorageService.java +++ b/api/src/com/cloud/storage/StorageService.java @@ -27,6 +27,7 @@ import com.cloud.api.commands.DeletePoolCmd; import com.cloud.api.commands.DeleteVolumeCmd; import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd; import com.cloud.api.commands.UpdateStoragePoolCmd; +import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; @@ -60,7 +61,7 @@ public interface StorageService { */ Volume createVolume(CreateVolumeCmd cmd); - boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException; + boolean deleteVolume(DeleteVolumeCmd cmd) throws ConcurrentOperationException; /** * Delete the storage pool * @param cmd - the command specifying poolId diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index 397d9e9173d..2e650fb5179 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -38,8 +38,7 @@ public interface Volume extends ControlledEntity, BasedOn { Creating("The volume is being created. getPoolId() should reflect the pool where it is being created."), Ready("The volume is ready to be used."), Used("The volume is used"), - Destroy("The volume is set to be desctroyed but can be recovered."), - Destroyed("The volume is destroyed. Should be removed."); + Destroy("The volume is set to be destroyed but can be recovered."); String _description; @@ -75,16 +74,13 @@ public interface Volume extends ControlledEntity, BasedOn { private final static StateMachine s_fsm = new StateMachine(); static { s_fsm.addTransition(Allocated, Event.Create, Creating); - s_fsm.addTransition(Allocated, Event.Destroy, Destroyed); + s_fsm.addTransition(Allocated, Event.Destroy, Destroy); s_fsm.addTransition(Creating, Event.OperationRetry, Creating); s_fsm.addTransition(Creating, Event.OperationFailed, Allocated); s_fsm.addTransition(Creating, Event.OperationSucceeded, Ready); s_fsm.addTransition(Creating, Event.Destroy, Destroy); s_fsm.addTransition(Ready, Event.Destroy, Destroy); s_fsm.addTransition(Ready, Event.Start, Used); - s_fsm.addTransition(Destroy, Event.OperationSucceeded, Destroyed); - s_fsm.addTransition(Destroy, Event.OperationFailed, Destroy); - s_fsm.addTransition(Destroy, Event.OperationRetry, Destroy); } } @@ -156,7 +152,6 @@ public interface Volume extends ControlledEntity, BasedOn { Date getCreated(); AsyncInstanceCreateStatus getStatus(); - boolean getDestroyed(); long getDiskOfferingId(); diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index 3a0baa6df74..4858a285797 100644 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -104,7 +104,6 @@ public interface AccountService { * @param cmd - the LockAccount command defining the accountId to be locked. * @return account object */ - //Account lockAccount(LockAccountCmd cmd); Account lockAccount(DisableAccountCmd cmd); /** @@ -139,6 +138,14 @@ public interface AccountService { User createUser(CreateUserCmd cmd); boolean deleteUser(DeleteUserCmd deleteUserCmd); - + + boolean isAdmin(short accountType); + + Account finalizeOwner(Account caller, String accountName, Long domainId); + + Account getActiveAccount(String accountName, Long domainId); + + Account getAccount(Long accountId); + } diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index b6ccd7724e2..de435368305 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Set; import com.cloud.acl.ControlledEntity; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.fsm.FiniteState; import com.cloud.utils.fsm.StateMachine; @@ -223,4 +224,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { public long getServiceOfferingId(); Type getType(); + + HypervisorType getHypervisorType(); } diff --git a/client/WEB-INF/classes/resources/messages_zh.properties b/client/WEB-INF/classes/resources/messages_zh.properties index 1cb4c4780fa..dd2c0a69705 100644 --- a/client/WEB-INF/classes/resources/messages_zh.properties +++ b/client/WEB-INF/classes/resources/messages_zh.properties @@ -1,6 +1,8 @@ #Titles label.cloud.console=Cloud Management Console[zh] +label.menu.dashboard=儀器板 + #Labels #Messages \ No newline at end of file diff --git a/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in b/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in new file mode 100644 index 00000000000..d61cb7b8088 --- /dev/null +++ b/client/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-management.in @@ -0,0 +1,41 @@ +#!/bin/bash +# +# @PACKAGE@-management This shell script takes care of starting and stopping Tomcat +# +# chkconfig: - 80 20 +# +### BEGIN INIT INFO +# Provides: tomcat6 +# Required-Start: $network $syslog +# Required-Stop: $network $syslog +# Default-Start: +# Default-Stop: +# Description: Release implementation for Servlet 2.5 and JSP 2.1 +# Short-Description: start and stop tomcat +### END INIT INFO +# +# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot +# - heavily rewritten by Deepak Bhole and Jason Corley +# + +if [ -r /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi +if [ -r /lib/lsb/init-functions ]; then + . /lib/lsb/init-functions +fi + + +NAME="$(basename $0)" + +# See how we were called. +case "$1" in + status) + status ${NAME} + RETVAL=$? + ;; + *) + . /etc/rc.d/init.d/tomcat6 +esac + +exit $RETVAL diff --git a/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in b/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in new file mode 100644 index 00000000000..2d4b22f4bff --- /dev/null +++ b/client/distro/rhel/SYSCONFDIR/sysconfig/cloud-management.in @@ -0,0 +1,6 @@ +# This file is loaded in /etc/init.d/vmopsmanagement +# ATM we only do two things here: + +dummy=1 ; export TOMCAT_CFG=@MSCONF@/tomcat6.conf ; . @MSCONF@/tomcat6.conf +#-------------------------- + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index fd403afbcef..f0c9608dd6e 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -103,7 +103,6 @@ listVlanIpRanges=com.cloud.api.commands.ListVlanIpRangesCmd;1 associateIpAddress=com.cloud.api.commands.AssociateIPAddrCmd;15 disassociateIpAddress=com.cloud.api.commands.DisassociateIPAddrCmd;15 listPublicIpAddresses=com.cloud.api.commands.ListPublicIpAddressesCmd;15 -restartNetwork=com.cloud.api.commands.RestartNetworkCmd;15 #### firewall commands listPortForwardingRules=com.cloud.api.commands.ListPortForwardingRulesCmd;15 @@ -169,7 +168,6 @@ listCapacity=com.cloud.api.commands.ListCapacityCmd;1 addHost=com.cloud.api.commands.AddHostCmd;1 addCluster=com.cloud.api.commands.AddClusterCmd;1 deleteCluster=com.cloud.api.commands.DeleteClusterCmd;1 -add=com.cloud.api.commands.AddHostCmd;1 reconnectHost=com.cloud.api.commands.ReconnectHostCmd;1 updateHost=com.cloud.api.commands.UpdateHostCmd;1 deleteHost=com.cloud.api.commands.DeleteHostCmd;1 @@ -247,11 +245,11 @@ listNetworkOfferings=com.cloud.api.commands.ListNetworkOfferingsCmd;15 #### network commands createNetwork=com.cloud.api.commands.CreateNetworkCmd;15 deleteNetwork=com.cloud.api.commands.DeleteNetworkCmd;15 -listNetworks=com.cloud.api.commands.ListNetworksCmd;15 +listNetworks=com.cloud.api.commands.ListNetworksCmd;15 +restartNetwork=com.cloud.api.commands.RestartNetworkCmd;15 #### SSH key pair commands registerSSHKeyPair=com.cloud.api.commands.RegisterSSHKeyPairCmd;15 createSSHKeyPair=com.cloud.api.commands.CreateSSHKeyPairCmd;15 deleteSSHKeyPair=com.cloud.api.commands.DeleteSSHKeyPairCmd;15 listSSHKeyPairs=com.cloud.api.commands.ListSSHKeyPairsCmd;15 - diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index 61052977b66..5f1d7fd299e 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -23,6 +23,7 @@ documented, please contact the author. --> + @@ -45,6 +46,7 @@ + diff --git a/cloud.spec b/cloud.spec index f74a7ef541e..931b2b1d1fb 100644 --- a/cloud.spec +++ b/cloud.spec @@ -223,6 +223,12 @@ Requires: kvm Requires: qemu-cloud-system-x86 Requires: qemu-cloud-img %endif + +%if 0%{?rhel} >= 6 +Requires: cloud-qemu-kvm +Requires: cloud-qemu-img +%endif + Requires: libcgroup Requires: /usr/bin/uuidgen Requires: augeas >= 0.7.1 @@ -302,6 +308,8 @@ Obsoletes: %{name}-premium-vendor-zynga < %{version}-%{release} Requires: java >= 1.6.0 Requires: %{name}-utils = %{version}-%{release} Requires: %{name}-premium-deps +# there is a fsimage.so in the source code, which adds xen-libs as a dependence, needs to supress it, as rhel doesn't have this pacakge +AutoReqProv: no License: CSL 1.1 Group: System Environment/Libraries %description premium @@ -431,8 +439,8 @@ fi %defattr(0644,root,root,0755) %{_javadir}/%{name}-utils.jar %{_javadir}/%{name}-api.jar -%attr(755,root,root) %{_bindir}/cloud-sccs -%attr(755,root,root) %{_bindir}/cloud-gitrevs +%attr(0755,root,root) %{_bindir}/cloud-sccs +%attr(0755,root,root) %{_bindir}/cloud-gitrevs %doc %{_docdir}/%{name}-%{version}/sccs-info %doc %{_docdir}/%{name}-%{version}/version-info %doc %{_docdir}/%{name}-%{version}/configure-info @@ -457,7 +465,7 @@ fi %files daemonize %defattr(-,root,root,-) -%attr(755,root,root) %{_bindir}/%{name}-daemonize +%attr(0755,root,root) %{_bindir}/%{name}-daemonize %files deps %defattr(0644,root,root,0755) @@ -497,7 +505,7 @@ fi %{_prefix}/lib*/python*/site-packages/%{name}* %attr(0755,root,root) %{_bindir}/cloud-external-ipallocator.py %attr(0755,root,root) %{_initrddir}/cloud-ipallocator -%dir %attr(770,root,root) %{_localstatedir}/log/%{name}/ipallocator +%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator %files setup %attr(0755,root,root) %{_bindir}/%{name}-setup-databases @@ -508,30 +516,30 @@ fi %{_datadir}/%{name}/setup/server-setup.xml %files client -%defattr(0644,root,root,0755) +%defattr(0644,root,root,0775) %{_sysconfdir}/%{name}/management/* %if %{_premium} %exclude %{_sysconfdir}/%{name}/management/*premium* %endif -%config(noreplace) %attr(640,root,%{name}) %{_sysconfdir}/%{name}/management/db.properties +%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 -%dir %attr(770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina -%dir %attr(770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina/localhost -%dir %attr(770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina/localhost/client +%dir %attr(0770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina +%dir %attr(0770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina/localhost +%dir %attr(0770,root,%{name}) %{_sysconfdir}/%{name}/management/Catalina/localhost/client %config %{_sysconfdir}/sysconfig/%{name}-management %attr(0755,root,root) %{_initrddir}/%{name}-management %dir %{_datadir}/%{name}/management %{_datadir}/%{name}/management/* -%attr(755,root,root) %{_bindir}/%{name}-setup-management -%attr(755,root,root) %{_bindir}/%{name}-update-xenserver-licenses -%dir %attr(770,root,%{name}) %{_sharedstatedir}/%{name}/mnt -%dir %attr(770,%{name},%{name}) %{_sharedstatedir}/%{name}/management -%dir %attr(770,root,%{name}) %{_localstatedir}/cache/%{name}/management -%dir %attr(770,root,%{name}) %{_localstatedir}/cache/%{name}/management/work -%dir %attr(770,root,%{name}) %{_localstatedir}/cache/%{name}/management/temp -%dir %attr(770,root,%{name}) %{_localstatedir}/log/%{name}/management -%dir %attr(770,root,%{name}) %{_localstatedir}/log/%{name}/agent +%attr(0755,root,root) %{_bindir}/%{name}-setup-management +%attr(0755,root,root) %{_bindir}/%{name}-update-xenserver-licenses +%dir %attr(0770,root,%{name}) %{_sharedstatedir}/%{name}/mnt +%dir %attr(0770,%{name},%{name}) %{_sharedstatedir}/%{name}/management +%dir %attr(0770,root,%{name}) %{_localstatedir}/cache/%{name}/management +%dir %attr(0770,root,%{name}) %{_localstatedir}/cache/%{name}/management/work +%dir %attr(0770,root,%{name}) %{_localstatedir}/cache/%{name}/management/temp +%dir %attr(0770,root,%{name}) %{_localstatedir}/log/%{name}/management +%dir %attr(0770,root,%{name}) %{_localstatedir}/log/%{name}/agent %files agent-libs %defattr(0644,root,root,0755) @@ -550,7 +558,7 @@ fi %{_libdir}/%{name}/agent/js %{_libdir}/%{name}/agent/images %attr(0755,root,root) %{_bindir}/%{name}-setup-agent -%dir %attr(770,root,root) %{_localstatedir}/log/%{name}/agent +%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/agent %files console-proxy @@ -561,7 +569,7 @@ fi %attr(0755,root,root) %{_libexecdir}/console-proxy-runner %{_libdir}/%{name}/console-proxy/* %attr(0755,root,root) %{_bindir}/%{name}-setup-console-proxy -%dir %attr(770,root,root) %{_localstatedir}/log/%{name}/console-proxy +%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/console-proxy %files cli %{_bindir}/%{name}-tool @@ -574,7 +582,7 @@ fi %files test %defattr(0644,root,root,0755) -%attr(755,root,root) %{_bindir}/%{name}-run-test +%attr(0755,root,root) %{_bindir}/%{name}-run-test %{_javadir}/%{name}-test.jar %{_sharedstatedir}/%{name}/test/* %{_libdir}/%{name}/test/* @@ -597,14 +605,14 @@ fi %{_libdir}/%{name}/agent/premium-scripts/* %files usage -%defattr(0644,root,root,0755) +%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(770,root,%{name}) %{_localstatedir}/log/%{name}/usage +%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(640,root,%{name}) %{_sysconfdir}/%{name}/usage/db.properties +%config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/%{name}/usage/db.properties %endif diff --git a/console-proxy/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-console-proxy.in b/console-proxy/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-console-proxy.in new file mode 100644 index 00000000000..488df568f02 --- /dev/null +++ b/console-proxy/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-console-proxy.in @@ -0,0 +1,81 @@ +#!/bin/bash + +# chkconfig: 35 99 10 +# description: Cloud Console Proxy + +# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well + +. /etc/rc.d/init.d/functions + +whatami=cloud-console-proxy + +# set environment variables + +SHORTNAME="$whatami" +PIDFILE=@PIDDIR@/"$whatami".pid +LOCKFILE=@LOCKDIR@/"$SHORTNAME" +LOGFILE=@CPLOG@ +PROGNAME="Cloud Console Proxy" + +unset OPTIONS +[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" +DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize +PROG=@LIBEXECDIR@/console-proxy-runner + +start() { + echo -n $"Starting $PROGNAME: " + if hostname --fqdn >/dev/null 2>&1 ; then + daemon --check=$SHORTNAME --pidfile=${PIDFILE} "$DAEMONIZE" \ + -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS + RETVAL=$? + echo + else + failure + echo + echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr + RETVAL=9 + fi + [ $RETVAL = 0 ] && touch ${LOCKFILE} + return $RETVAL +} + +stop() { + echo -n $"Stopping $PROGNAME: " + killproc -p ${PIDFILE} $SHORTNAME # -d 10 $SHORTNAME + RETVAL=$? + echo + [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} +} + + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status -p ${PIDFILE} $SHORTNAME + RETVAL=$? + ;; + restart) + stop + sleep 3 + start + ;; + condrestart) + if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then + stop + sleep 3 + start + fi + ;; + *) + echo $"Usage: $whatami {start|stop|restart|condrestart|status|help}" + RETVAL=3 +esac + +exit $RETVAL + diff --git a/console-proxy/scripts/ipfirewall.sh b/console-proxy/scripts/ipfirewall.sh new file mode 100755 index 00000000000..47ac5bd9dca --- /dev/null +++ b/console-proxy/scripts/ipfirewall.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +BASE_DIR="/var/www/html/copy/" +HTACCESS="$BASE_DIR/.htaccess" + +config_htaccess() { + mkdir -p $BASE_DIR + result=$? + echo "Options -Indexes" > $HTACCESS + let "result=$result+$?" + echo "order deny,allow" >> $HTACCESS + let "result=$result+$?" + echo "deny from all" >> $HTACCESS + let "result=$result+$?" + return $result +} + +ips(){ + echo "allow from $1" >> $HTACCESS + result=$? + return $result +} + + +config_htaccess +for i in $@ +do + ips "$i" +done +exit $? + diff --git a/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java b/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java new file mode 100644 index 00000000000..0912a926e3a --- /dev/null +++ b/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java @@ -0,0 +1,26 @@ +package com.cloud.agent.api; + +import java.util.List; +import java.util.Map; + +import com.cloud.host.Host; +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine.State; + +public class PingRoutingWithOvsCommand extends PingRoutingCommand { + List> states; + + protected PingRoutingWithOvsCommand() { + super(); + } + + public PingRoutingWithOvsCommand(Host.Type type, long id, + Map states, List> ovsStates) { + super(type, id, states); + this.states = ovsStates; + } + + public List> getStates() { + return states; + } +} diff --git a/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java b/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java old mode 100644 new mode 100755 index da77cea9c4e..f84adc3f00c --- a/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java +++ b/core/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java @@ -4,15 +4,17 @@ import com.cloud.agent.api.Command; public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { - public CreateEntityDownloadURLCommand(String installPath) { + public CreateEntityDownloadURLCommand(String installPath, String uuid) { super(); this.installPath = installPath; + this.extractLinkUUID = uuid; } public CreateEntityDownloadURLCommand() { } private String installPath; + private String extractLinkUUID; @Override public boolean executeInSequence() { @@ -27,4 +29,12 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { this.installPath = installPath; } + public String getExtractLinkUUID() { + return extractLinkUUID; + } + + public void setExtractLinkUUID(String extractLinkUUID) { + this.extractLinkUUID = extractLinkUUID; + } + } diff --git a/core/src/com/cloud/agent/api/storage/DeleteEntityDownloadURLCommand.java b/core/src/com/cloud/agent/api/storage/DeleteEntityDownloadURLCommand.java index cd4007e829c..f9dd0142b0d 100755 --- a/core/src/com/cloud/agent/api/storage/DeleteEntityDownloadURLCommand.java +++ b/core/src/com/cloud/agent/api/storage/DeleteEntityDownloadURLCommand.java @@ -4,13 +4,15 @@ import com.cloud.storage.Upload; public class DeleteEntityDownloadURLCommand extends AbstractDownloadCommand { - String path; - Upload.Type type; + private String path; + private String extractUrl; + private Upload.Type type; - public DeleteEntityDownloadURLCommand(String path, Upload.Type type) { + public DeleteEntityDownloadURLCommand(String path, Upload.Type type, String url) { super(); this.path = path; this.type = type; + this.extractUrl = url; } public DeleteEntityDownloadURLCommand() { @@ -33,4 +35,12 @@ public class DeleteEntityDownloadURLCommand extends AbstractDownloadCommand { this.type = type; } + public String getExtractUrl() { + return extractUrl; + } + + public void setExtractUrl(String extractUrl) { + this.extractUrl = extractUrl; + } + } diff --git a/core/src/com/cloud/event/UsageEventVO.java b/core/src/com/cloud/event/UsageEventVO.java index 4ed67fe527f..bc21f2c283b 100644 --- a/core/src/com/cloud/event/UsageEventVO.java +++ b/core/src/com/cloud/event/UsageEventVO.java @@ -63,6 +63,9 @@ public class UsageEventVO implements UsageEvent { @Column(name="size") private Long size; + + @Column(name="processed") + boolean processed; public UsageEventVO() { @@ -163,4 +166,12 @@ public class UsageEventVO implements UsageEvent { return size; } + public boolean isProcessed() { + return processed; + } + + public void setProcessed(boolean processed) { + this.processed = processed; + } + } diff --git a/core/src/com/cloud/event/dao/UsageEventDao.java b/core/src/com/cloud/event/dao/UsageEventDao.java index 271856b2f5d..acd6099cca1 100644 --- a/core/src/com/cloud/event/dao/UsageEventDao.java +++ b/core/src/com/cloud/event/dao/UsageEventDao.java @@ -29,13 +29,9 @@ import com.cloud.utils.db.SearchCriteria; public interface UsageEventDao extends GenericDao { - public List searchAllUsageEvents(SearchCriteria sc, Filter filter); + public List listLatestEvents(Date endDate); - public List listLatestEvents(Date recentEventDate, Date endDate); - - public List listAllEvents(Date endDate); - - public List getLatestEventDate(); + public List getLatestEvent(); List getRecentEvents(Date endDate) throws UsageServerException; diff --git a/core/src/com/cloud/event/dao/UsageEventDaoImpl.java b/core/src/com/cloud/event/dao/UsageEventDaoImpl.java index 170892dd95e..70dce7d6dcb 100644 --- a/core/src/com/cloud/event/dao/UsageEventDaoImpl.java +++ b/core/src/com/cloud/event/dao/UsageEventDaoImpl.java @@ -19,7 +19,6 @@ package com.cloud.event.dao; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.util.Date; import java.util.List; import java.util.TimeZone; @@ -31,6 +30,7 @@ import org.apache.log4j.Logger; import com.cloud.event.UsageEventVO; import com.cloud.exception.UsageServerException; import com.cloud.utils.DateUtil; +import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -42,58 +42,40 @@ public class UsageEventDaoImpl extends GenericDaoBase implem public static final Logger s_logger = Logger.getLogger(UsageEventDaoImpl.class.getName()); private final SearchBuilder latestEventsSearch; - private final SearchBuilder allEventsSearch; - private static final String GET_LATEST_EVENT_DATE = "SELECT created FROM usage_event ORDER BY created DESC LIMIT 1"; - private static final String COPY_EVENTS = "INSERT INTO cloud_usage.usage_event SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size FROM cloud.usage_event vmevt WHERE vmevt.created > ? and vmevt.created <= ? "; - private static final String COPY_ALL_EVENTS = "INSERT INTO cloud_usage.usage_event SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size FROM cloud.usage_event where created <= ? "; + private static final String COPY_EVENTS = "INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size) " + + "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.created <= ? "; + private static final String COPY_ALL_EVENTS = "INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size) " + + "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size FROM cloud.usage_event where id <= ? "; public UsageEventDaoImpl () { latestEventsSearch = createSearchBuilder(); - latestEventsSearch.and("recentEventDate", latestEventsSearch.entity().getCreateDate(), SearchCriteria.Op.GT); + latestEventsSearch.and("processed", latestEventsSearch.entity().isProcessed(), SearchCriteria.Op.EQ); latestEventsSearch.and("enddate", latestEventsSearch.entity().getCreateDate(), SearchCriteria.Op.LTEQ); latestEventsSearch.done(); - - allEventsSearch = createSearchBuilder(); - allEventsSearch.and("enddate", allEventsSearch.entity().getCreateDate(), SearchCriteria.Op.LTEQ); - allEventsSearch.done(); - } @Override - public List listLatestEvents(Date recentEventDate, Date endDate) { + public List listLatestEvents(Date endDate) { Filter filter = new Filter(UsageEventVO.class, "createDate", Boolean.TRUE, null, null); SearchCriteria sc = latestEventsSearch.create(); - sc.setParameters("recentEventDate", recentEventDate); + sc.setParameters("processed", false); sc.setParameters("enddate", endDate); return listBy(sc, filter); } @Override - public List listAllEvents(Date endDate) { - Filter filter = new Filter(UsageEventVO.class, "createDate", Boolean.TRUE, null, null); - SearchCriteria sc = latestEventsSearch.create(); - sc.setParameters("enddate", endDate); - return listBy(sc, filter); - } - - @Override - public List getLatestEventDate() { - Filter filter = new Filter(UsageEventVO.class, "createDate", Boolean.FALSE, null, 1L); + public List getLatestEvent() { + Filter filter = new Filter(UsageEventVO.class, "id", Boolean.FALSE, Long.valueOf(0), Long.valueOf(1)); return listAll(filter); } - - @Override - public List searchAllUsageEvents(SearchCriteria sc, Filter filter) { - return listIncludingRemovedBy(sc, filter); - } - + @DB public synchronized List getRecentEvents(Date endDate) throws UsageServerException { Transaction txn = Transaction.open(Transaction.USAGE_DB); - Date recentEventDate = getMostRecentEventDate(); + long recentEventId = getMostRecentEventId(); String sql = COPY_EVENTS; - if (recentEventDate == null) { + if (recentEventId == 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("no recent event date, copying all events"); } @@ -105,13 +87,13 @@ public class UsageEventDaoImpl extends GenericDaoBase implem txn.start(); pstmt = txn.prepareAutoCloseStatement(sql); int i = 1; - if (recentEventDate != null) { - pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), recentEventDate)); + if (recentEventId != 0) { + pstmt.setLong(i++, recentEventId); } pstmt.setString(i, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate)); pstmt.executeUpdate(); txn.commit(); - return findRecentEvents(recentEventDate, endDate); + return findRecentEvents(endDate); } catch (Exception ex) { txn.rollback(); s_logger.error("error copying events from cloud db to usage db", ex); @@ -121,37 +103,31 @@ public class UsageEventDaoImpl extends GenericDaoBase implem } } - private Date getMostRecentEventDate() throws UsageServerException { + @DB + private long getMostRecentEventId() throws UsageServerException { Transaction txn = Transaction.open(Transaction.USAGE_DB); - PreparedStatement pstmt = null; - String sql = GET_LATEST_EVENT_DATE; try { - pstmt = txn.prepareAutoCloseStatement(sql); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) { - String mostRecentTimestampStr = rs.getString(1); - if (mostRecentTimestampStr != null) { - return DateUtil.parseDateString(s_gmtTimeZone, mostRecentTimestampStr); + List latestEvents = getLatestEvent(); + + if(latestEvents !=null && latestEvents.size() == 1){ + UsageEventVO latestEvent = latestEvents.get(0); + if(latestEvent != null){ + return latestEvent.getId(); } } + return 0; } catch (Exception ex) { - s_logger.error("error getting most recent event date", ex); + s_logger.error("error getting most recent event id", ex); throw new UsageServerException(ex.getMessage()); } finally { txn.close(); } - return null; } - private List findRecentEvents(Date recentEventDate, Date endDate) throws UsageServerException { + private List findRecentEvents(Date endDate) throws UsageServerException { Transaction txn = Transaction.open(Transaction.USAGE_DB); try { - int i = 1; - if (recentEventDate == null) { - return listAllEvents(endDate); - } else { - return listLatestEvents(recentEventDate, endDate); - } + return listLatestEvents(endDate); } catch (Exception ex) { s_logger.error("error getting most recent event date", ex); throw new UsageServerException(ex.getMessage()); diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 2b9c9d6f911..ce63fd67fa6 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -94,6 +94,7 @@ import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; +import com.cloud.agent.api.PingRoutingWithOvsCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PoolEjectCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; @@ -148,17 +149,22 @@ import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VirtualMachineTO.Monitor; -import com.cloud.agent.api.to.VirtualMachineTO.SshMonitor; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.dc.Vlan; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.HAProxyConfigurator; import com.cloud.network.LoadBalancerConfigurator; +import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.ovs.OvsCreateGreTunnelAnswer; +import com.cloud.network.ovs.OvsCreateGreTunnelCommand; +import com.cloud.network.ovs.OvsDeleteFlowCommand; +import com.cloud.network.ovs.OvsSetTagAndFlowAnswer; +import com.cloud.network.ovs.OvsSetTagAndFlowCommand; import com.cloud.resource.ServerResource; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; @@ -245,6 +251,7 @@ public abstract class CitrixResourceBase implements ServerResource { protected StorageLayer _storage; protected boolean _canBridgeFirewall = false; + protected boolean _isOvs = false; protected HashMap _pools = new HashMap(5); public enum SRType { @@ -443,6 +450,12 @@ public abstract class CitrixResourceBase implements ServerResource { return execute((CheckSshCommand)cmd); } else if (cmd instanceof SecurityIngressRulesCmd) { return execute((SecurityIngressRulesCmd) cmd); + } else if (cmd instanceof OvsCreateGreTunnelCommand) { + return execute((OvsCreateGreTunnelCommand)cmd); + } else if (cmd instanceof OvsSetTagAndFlowCommand) { + return execute((OvsSetTagAndFlowCommand)cmd); + } else if (cmd instanceof OvsDeleteFlowCommand) { + return execute((OvsDeleteFlowCommand)cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -467,6 +480,86 @@ public abstract class CitrixResourceBase implements ServerResource { throw new CloudRuntimeException("Unsupported network type: " + type); } + /** + * This is a tricky to create network in xenserver. + * if you create a network then create bridge by brctl or openvswitch yourself, + * then you will get an expection that is "REQUIRED_NETWROK" when you start a + * vm with this network. The soultion is, create a vif of dom0 and plug it in + * network, xenserver will create the bridge on behalf of you + * @throws XmlRpcException + * @throws XenAPIException + */ + private void enableXenServerNetwork(Connection conn, Network nw, + String vifNameLabel, String networkDesc) throws XenAPIException, XmlRpcException { + /* Make sure there is a physical bridge on this network */ + VIF dom0vif = null; + Pair vm = getControlDomain(conn); + VM dom0 = vm.first(); + Set vifs = dom0.getVIFs(conn); + if (vifs.size() != 0) { + for (VIF vif : vifs) { + Map otherConfig = vif.getOtherConfig(conn); + if (otherConfig != null) { + String nameLabel = otherConfig.get("nameLabel"); + if ((nameLabel != null) && nameLabel.equalsIgnoreCase(vifNameLabel)) { + dom0vif = vif; + } + } + } + } + /* create temp VIF0 */ + if (dom0vif == null) { + s_logger.debug("Can't find a vif on dom0 for " + networkDesc + ", creating a new one"); + VIF.Record vifr = new VIF.Record(); + vifr.VM = dom0; + vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0); + if (vifr.device == null) { + s_logger.debug("Failed to create " + networkDesc + ", no vif available"); + return; + } + Map config = new HashMap(); + config.put("nameLabel", vifNameLabel); + vifr.otherConfig = config; + vifr.MAC = "FE:FF:FF:FF:FF:FF"; + vifr.network = nw; + dom0vif = VIF.create(conn, vifr); + dom0vif.plug(conn); + } else { + s_logger.debug("already have a vif on dom0 for " + networkDesc); + if (!dom0vif.getCurrentlyAttached(conn)) { + dom0vif.plug(conn); + } + } + } + + private synchronized Network setupvSwitchNetwork(Connection conn) { + try { + if (_host.vswitchNetwork == null) { + Network vswitchNw = null; + Network.Record rec = new Network.Record(); + String nwName = Networks.BroadcastScheme.VSwitch.toString(); + Set networks = Network.getByNameLabel(conn, nwName); + + if (networks.size() == 0) { + rec.nameDescription = "vswitch network for " + nwName; + rec.nameLabel = nwName; + vswitchNw = Network.create(conn, rec); + } else { + vswitchNw = networks.iterator().next(); + } + + enableXenServerNetwork(conn, vswitchNw, "vswitch", + "vswicth network"); + _host.vswitchNetwork = vswitchNw; + } + return _host.vswitchNetwork; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException { Pair network = getNativeNetworkForTraffic(conn, nic.getType()); if (nic.getBroadcastUri() != null && nic.getBroadcastUri().toString().contains("untagged")) { @@ -478,7 +571,9 @@ public abstract class CitrixResourceBase implements ServerResource { return enableVlanNetwork(conn, vlan, network.first(), network.second()); } else if (nic.getBroadcastType() == BroadcastDomainType.Native || nic.getBroadcastType() == BroadcastDomainType.LinkLocal) { return network.first(); - } + } else if (nic.getBroadcastType() == BroadcastDomainType.Vswitch) { + return setupvSwitchNetwork(conn); + } throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri()); } @@ -828,25 +923,6 @@ public abstract class CitrixResourceBase implements ServerResource { } } } - - Monitor monitor = vmSpec.getMonitor(); - if (monitor != null && monitor instanceof SshMonitor) { - SshMonitor sshMon = (SshMonitor)monitor; - String privateIp = sshMon.getIp(); - int cmdPort = sshMon.getPort(); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); - } - - String result = connect(conn, vmName, privateIp, cmdPort); - if (result != null) { - throw new CloudRuntimeException("Can not ping System vm " + vmName + "due to:" + result); - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Ping command port succeeded for vm " + vmName); - } - } state = State.Running; return new StartAnswer(cmd); @@ -2163,6 +2239,18 @@ public abstract class CitrixResourceBase implements ServerResource { } s_logger.warn(logX(sr, "Unable to remove SR")); } + + private boolean isPVInstalled(Connection conn, VM vm) throws BadServerResponse, XenAPIException, XmlRpcException { + VMGuestMetrics vmmetric = vm.getGuestMetrics(conn); + if (isRefNull(vmmetric)) { + return false; + } + Map PVversion = vmmetric.getPVDriversVersion(conn); + if (PVversion != null && PVversion.containsKey("major")) { + return true; + } + return false; + } protected MigrateAnswer execute(final MigrateCommand cmd) { Connection conn = getConnection(); @@ -2186,15 +2274,18 @@ public abstract class CitrixResourceBase implements ServerResource { break; } } - // if it is windows, we will not fake it is migrateable, - // windows requires PV driver to migrate - + if ( dsthost == null ) { + String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + _host.pool; + s_logger.warn(msg); + return new MigrateAnswer(cmd, false, msg, null); + } for (VM vm : vms) { - if (!cmd.isWindows()) { + if (vm.getPVBootloader(conn).equals("pygrub") && !isPVInstalled(conn, vm)) { + // Only fake PV driver for PV kernel, the PV driver is installed, but XenServer doesn't think it is installed String uuid = vm.getUuid(conn); String result = callHostPlugin(conn, "vmops", "preparemigration", "uuid", uuid); if (result == null || result.isEmpty()) { - return new MigrateAnswer(cmd, false, "migration failed", null); + return new MigrateAnswer(cmd, false, "migration failed due to preparemigration failed", null); } // check if pv version is successfully set up int i = 0; @@ -2203,45 +2294,34 @@ public abstract class CitrixResourceBase implements ServerResource { Thread.sleep(1000); } catch (final InterruptedException ex) { } - VMGuestMetrics vmmetric = vm.getGuestMetrics(conn); - - if (isRefNull(vmmetric)) { - continue; - } - - Map PVversion = vmmetric.getPVDriversVersion(conn); - if (PVversion != null && PVversion.containsKey("major")) { - break; - } - - } - Set vbds = vm.getVBDs(conn); - for( VBD vbd : vbds) { - VBD.Record vbdRec = vbd.getRecord(conn); - if( vbdRec.type.equals(Types.VbdType.CD.toString()) && !vbdRec.empty ) { - vbd.eject(conn); + if( isPVInstalled(conn, vm) ) { break; } } - if (i >= 20) { - String msg = "migration failed due to can not fake PV driver for " + vmName; - s_logger.warn(msg); - return new MigrateAnswer(cmd, false, msg, null); + s_logger.warn("Can not fake PV driver for " + vmName); } } - final Map options = new HashMap(); - vm.poolMigrate(conn, dsthost, options); + Set vbds = vm.getVBDs(conn); + for( VBD vbd : vbds) { + VBD.Record vbdRec = vbd.getRecord(conn); + if( vbdRec.type.equals(Types.VbdType.CD.toString()) && !vbdRec.empty ) { + vbd.eject(conn); + break; + } + } + try { + vm.poolMigrate(conn, dsthost, new HashMap()); + } catch (Types.VmMissingPvDrivers e1) { + // if PV driver is missing, just shutdown the VM + s_logger.warn("VM " + vmName + " is stopped when trying to migrate it because PV driver is missing, Please install PV driver for this VM"); + vm.hardShutdown(conn); + } state = State.Stopping; - } return new MigrateAnswer(cmd, true, "migration succeeded", null); - } catch (XenAPIException e) { - String msg = "migration failed due to " + e.toString(); - s_logger.warn(msg, e); - return new MigrateAnswer(cmd, false, msg, null); - } catch (XmlRpcException e) { - String msg = "migration failed due to " + e.getMessage(); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + ": Migration failed due to " + e.toString(); s_logger.warn(msg, e); return new MigrateAnswer(cmd, false, msg, null); } finally { @@ -2603,7 +2683,7 @@ public abstract class CitrixResourceBase implements ServerResource { } } - void startVM(Connection conn, Host host, VM vm, String vmName) { + void startVM(Connection conn, Host host, VM vm, String vmName) throws XmlRpcException { try { vm.startOn(conn, host, false, true); } catch (Exception e) { @@ -2942,7 +3022,7 @@ public abstract class CitrixResourceBase implements ServerResource { Set routerVIFs = router.getVIFs(conn); for (VIF vif : routerVIFs) { Network vifNetwork = vif.getNetwork(conn); - if (vlanId.equals("untagged")) { + if (vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { if (vifNetwork.getUuid(conn).equals(_host.publicNetwork)) { return vif; } @@ -3237,9 +3317,12 @@ public abstract class CitrixResourceBase implements ServerResource { if (newStates == null) { newStates = new HashMap(); } - if (!_canBridgeFirewall) { + if (!_canBridgeFirewall && !_isOvs) { return new PingRoutingCommand(getType(), id, newStates); - } else { + } else if (_isOvs) { + List>ovsStates = ovsFullSyncStates(); + return new PingRoutingWithOvsCommand(getType(), id, newStates, ovsStates); + }else { HashMap> nwGrpStates = syncNetworkGroups(conn, id); return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, nwGrpStates); } @@ -3745,6 +3828,112 @@ public abstract class CitrixResourceBase implements ServerResource { return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid)); } + private Answer execute(OvsDeleteFlowCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + try { + Network nw = setupvSwitchNetwork(conn); + String bridge = nw.getBridge(conn); + String result = callHostPlugin(conn, "ovsgre", "ovs_delete_flow", "bridge", bridge, + "vmName", cmd.getVmName()); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new Answer(cmd, true, "success to delete flows for " + cmd.getVmName()); + } else { + return new Answer(cmd, false, result); + } + } catch (Exception e) { + e.printStackTrace(); + } + return new Answer(cmd, false, "failed to delete flow for " + cmd.getVmName()); + } + + private List> ovsFullSyncStates() { + Connection conn = getConnection(); + try { + String result = callHostPlugin(conn, "ovsgre", "ovs_get_vm_log", "host_uuid", _host.uuid); + String [] logs = result != null ?result.split(";"): new String [0]; + List> states = new ArrayList>(); + for (String log: logs){ + String [] info = log.split(","); + if (info.length != 5) { + s_logger.warn("Wrong element number in ovs log(" + log +")"); + continue; + } + + //','.join([bridge, vmName, vmId, seqno, tag]) + try { + states.add(new Pair(info[0], Long.parseLong(info[3]))); + } catch (NumberFormatException nfe) { + states.add(new Pair(info[0], -1L)); + } + } + + return states; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + private OvsSetTagAndFlowAnswer execute(OvsSetTagAndFlowCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + try { + Network nw = setupvSwitchNetwork(conn); + String bridge = nw.getBridge(conn); + + /*If VM is domainRouter, this will try to set flow and tag on its + * none guest network nic. don't worry, it will fail silently at host + * plugin side + */ + String result = callHostPlugin(conn, "ovsgre", "ovs_set_tag_and_flow", "bridge", bridge, + "vmName", cmd.getVmName(), "tag", cmd.getTag(), + "vlans", cmd.getVlans(), "seqno", cmd.getSeqNo()); + s_logger.debug("set flow for " + cmd.getVmName() + " " + result); + + if (result.equalsIgnoreCase("SUCCESS")) { + return new OvsSetTagAndFlowAnswer(cmd, true, result); + } else { + return new OvsSetTagAndFlowAnswer(cmd, false, result); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return new OvsSetTagAndFlowAnswer(cmd, false, "EXCEPTION"); + } + + + private OvsCreateGreTunnelAnswer execute(OvsCreateGreTunnelCommand cmd) { + _isOvs = true; + + Connection conn = getConnection(); + String bridge = "unkonwn"; + try { + Network nw = setupvSwitchNetwork(conn); + bridge = nw.getBridge(conn); + + String result = callHostPlugin(conn, "ovsgre", "ovs_create_gre", "bridge", bridge, + "remoteIP", cmd.getRemoteIp(), "greKey", cmd.getKey(), "from", + Long.toString(cmd.getFrom()), "to", Long.toString(cmd.getTo())); + String[] res = result.split(":"); + if (res.length != 2 || (res.length == 2 && res[1] == "[]")) { + return new OvsCreateGreTunnelAnswer(cmd, false, result, + _host.ip, bridge); + } else { + return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.ip, bridge, Integer.parseInt(res[1])); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge); + } + private Answer execute(SecurityIngressRulesCmd cmd) { Connection conn = getConnection(); if (s_logger.isTraceEnabled()) { @@ -3846,7 +4035,8 @@ public abstract class CitrixResourceBase implements ServerResource { } } // assume the memory Virtualization overhead is 1/64 - ram = (ram - dom0Ram) * 63/64; + // xen hypervisor used 128 M + ram = (ram - dom0Ram - (128 * 1024 * 1024)) * 63/64; cmd.setMemory(ram); cmd.setDom0MinMemory(dom0Ram); @@ -5521,6 +5711,7 @@ public abstract class CitrixResourceBase implements ServerResource { public String publicNetwork; public String privateNetwork; public String linkLocalNetwork; + public Network vswitchNetwork; public String storageNetwork1; public String storageNetwork2; public String guestNetwork; diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index f18c81f0372..7285e65411c 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -45,7 +45,6 @@ import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; -import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer; import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteTemplateCommand; @@ -94,6 +93,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S UploadManager _upldMgr; private String _configSslScr; private String _configAuthScr; + private String _configIpFirewallScr; private String _publicIp; private String _hostname; private String _localgw; @@ -189,26 +189,21 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S if (!_inSystemVM){ return new Answer(cmd, true, null); } - List iptablesCfg = new ArrayList(); - iptablesCfg.add("iptables -F HTTP"); + + List ipList = new ArrayList(); + for (PortConfig pCfg:cmd.getPortConfigs()){ if (pCfg.isAdd()) { - iptablesCfg.add("iptables -A HTTP -i " + pCfg.getIntf() + " -s " + pCfg.getSourceIp() + " -p tcp -m state --state NEW -m tcp --dport " + pCfg.getPort() + " -j ACCEPT"); + ipList.add(pCfg.getSourceIp()); } } boolean success = true; - StringBuilder result = new StringBuilder(); - for (String rule: iptablesCfg) { - Script command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add(rule); - String tmpresult = command.execute(); - if (tmpresult != null) { - result.append(tmpresult); - success = false; - } - } - return new Answer(cmd, success, result.toString()); + String result; + result = configureIpFirewall(ipList); + if (result !=null) + success = false; + + return new Answer(cmd, success, result); } protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { @@ -351,6 +346,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S s_logger.info("config_auth.sh found in " + _configAuthScr); } + _configIpFirewallScr = Script.findScript(getDefaultScriptsDir(), "ipfirewall.sh"); + if (_configIpFirewallScr != null) { + s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr); + } + _guid = (String)params.get("guid"); if (_guid == null) { throw new ConfigurationException("Unable to find the guid"); @@ -525,6 +525,19 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return result; } + private String configureIpFirewall(List ipList){ + Script command = new Script(_configIpFirewallScr); + for (String ip : ipList){ + command.add(ip); + } + + String result = command.execute(); + if (result != null) { + s_logger.warn("Unable to configure firewall for command : " +command); + } + return result; + } + protected String mount(String path, String parent) { String mountPoint = null; for (int i = 0; i < 10; i++) { diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java old mode 100644 new mode 100755 index be24a04edf5..f141a2610e9 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java @@ -873,17 +873,8 @@ public class DownloadManagerImpl implements DownloadManager { command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j DROP;" + - "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j HTTP;" + - "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j DROP;" + - "iptables -D INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j HTTP;" + - "iptables -F HTTP;" + - "iptables -X HTTP;" + - "iptables -N HTTP;" + - "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j DROP;" + - "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j DROP;" + - "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j HTTP;" + - "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j HTTP;"); + command.add("iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + port + " -j ACCEPT;" + + "iptables -I INPUT -i " + intf + " -p tcp -m state --state NEW -m tcp --dport " + "443" + " -j ACCEPT;"); result = command.execute(); if (result != null) { diff --git a/core/src/com/cloud/storage/template/UploadManagerImpl.java b/core/src/com/cloud/storage/template/UploadManagerImpl.java index 46dbc23a265..98b902191e1 100755 --- a/core/src/com/cloud/storage/template/UploadManagerImpl.java +++ b/core/src/com/cloud/storage/template/UploadManagerImpl.java @@ -331,9 +331,10 @@ public class UploadManagerImpl implements UploadManager { return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE); } // Create the directory structure so that its visible under apache server root + String extractDir = "/var/www/html/userdata/"; Script command = new Script("mkdir", s_logger); command.add("-p"); - command.add("/var/www/html/copy"); + command.add(extractDir); String result = command.execute(); if (result != null) { String errorString = "Error in creating directory =" + result; @@ -341,11 +342,23 @@ public class UploadManagerImpl implements UploadManager { return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE); } - // Create a symbolic link from the actual directory to the template location. The entity would be directly visible under /var/www/html/ + // Create a random file under the directory for security reasons. + String uuid = cmd.getExtractLinkUUID(); + command = new Script("touch", s_logger); + command.add(extractDir + uuid); + result = command.execute(); + if (result != null) { + String errorString = "Error in creating file " +uuid+ " ,error: " + result; + s_logger.warn(errorString); + return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE); + } + + + // Create a symbolic link from the actual directory to the template location. The entity would be directly visible under /var/www/html/userdata cmd.getInstallPath(); command = new Script("/bin/bash", s_logger); command.add("-c"); - command.add("ln -sf " + extractMountPoint + File.separator + cmd.getInstallPath() + " /var/www/html/copy/"); + command.add("ln -sf " + extractMountPoint + File.separator + cmd.getInstallPath() + " " + extractDir + uuid); result = command.execute(); if (result != null) { String errorString = "Error in linking err=" + result; @@ -365,8 +378,10 @@ public class UploadManagerImpl implements UploadManager { String path = cmd.getPath(); Script command = new Script("/bin/bash", s_logger); command.add("-c"); - //We just need to remove the UUID.vhd - command.add("unlink /var/www/html/copy/" +path.substring(path.lastIndexOf(File.separator) + 1)); + + //We just need to remove the UUID.vhd + String extractUrl = cmd.getExtractUrl(); + command.add("unlink /var/www/html/userdata/" +extractUrl.substring(extractUrl.lastIndexOf(File.separator) + 1)); String result = command.execute(); if (result != null) { String errorString = "Error in deleting =" + result; @@ -617,7 +632,7 @@ public class UploadManagerImpl implements UploadManager { //Apache Server is not running. Try to start it. if (result != null) { - s_logger.warn("Apache server not running, trying to start it"); + /*s_logger.warn("Apache server not running, trying to start it"); String port = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT); String intf = TemplateConstants.DEFAULT_TMPLT_COPY_INTF; @@ -639,7 +654,7 @@ public class UploadManagerImpl implements UploadManager { if (result != null) { s_logger.warn("Error in opening up httpd port err=" + result ); return false; - } + }*/ command = new Script("/bin/bash", s_logger); command.add("-c"); diff --git a/core/src/com/cloud/vm/ConsoleProxyVO.java b/core/src/com/cloud/vm/ConsoleProxyVO.java index 0fd99fc9978..e863cb2d233 100644 --- a/core/src/com/cloud/vm/ConsoleProxyVO.java +++ b/core/src/com/cloud/vm/ConsoleProxyVO.java @@ -28,6 +28,8 @@ import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; /** * ConsoleProxyVO domain object @@ -97,64 +99,11 @@ public class ConsoleProxyVO extends VMInstanceVO implements ConsoleProxy { /** * Correct constructor to use. */ - public ConsoleProxyVO(long id, long serviceOfferingId, String name, long templateId, long guestOSId, long dataCenterId, long domainId, long accountId, int activeSession) { - super(id, serviceOfferingId, name, name, Type.ConsoleProxy, templateId, guestOSId, domainId, accountId, false); + public ConsoleProxyVO(long id, long serviceOfferingId, String name, long templateId, HypervisorType hypervisorType, long guestOSId, long dataCenterId, long domainId, long accountId, int activeSession) { + super(id, serviceOfferingId, name, name, Type.ConsoleProxy, templateId, hypervisorType, guestOSId, domainId, accountId, false); this.activeSession = activeSession; } - public ConsoleProxyVO(ConsoleProxyVO that) { - this(that.id, that.serviceOfferingId, that.instanceName, that.guestMacAddress, that.guestIpAddress, that.guestNetmask, that.privateMacAddress, that.privateIpAddress, that.privateNetmask, that.templateId, that.guestOSId, that.publicMacAddress, that.publicIpAddress, that.publicNetmask, that.vlanDbId, that.vlanId, that.podId, that.dataCenterId, that.domainId, that.accountId, that.gateway, that.hostId, that.dns1, that.dns2, that.domain, that.ramSize, that.activeSession); - this.vncPassword = that.vncPassword; - this.sslEnabled = that.sslEnabled; - this.sessionDetails = that.sessionDetails; - } - - public ConsoleProxyVO( - long id, - long serviceOfferingId, - String name, - String guestMacAddress, - String guestIpAddress, - String guestNetMask, - String privateMacAddress, - String privateIpAddress, - String privateNetmask, - long templateId, - long guestOSId, - String publicMacAddress, - String publicIpAddress, - String publicNetmask, - Long vlanDbId, - String vlanId, - long podId, - long dataCenterId, - long domainId, - long accountId, - String gateway, - Long hostId, - String dns1, - String dns2, - String domain, - int ramSize, - int activeSession) { - super(id, serviceOfferingId, name, name, Type.ConsoleProxy, templateId, guestOSId, - privateMacAddress, privateIpAddress, privateNetmask, dataCenterId, podId, domainId, accountId, true, hostId); - this.gateway = gateway; - this.publicIpAddress = publicIpAddress; - this.publicNetmask = publicNetmask; - this.publicMacAddress = publicMacAddress; - this.guestIpAddress = guestIpAddress; - this.guestMacAddress = guestMacAddress; - this.guestNetmask = guestNetMask; - this.vlanDbId = vlanDbId; - this.vlanId = vlanId; - this.dns1 = dns1; - this.dns2 = dns2; - this.domain = domain; - this.ramSize = ramSize; - this.activeSession = activeSession; - } - protected ConsoleProxyVO() { super(); } diff --git a/core/src/com/cloud/vm/DomainRouterVO.java b/core/src/com/cloud/vm/DomainRouterVO.java index 3eb47f2aa19..3daa59d5838 100755 --- a/core/src/com/cloud/vm/DomainRouterVO.java +++ b/core/src/com/cloud/vm/DomainRouterVO.java @@ -26,6 +26,7 @@ import javax.persistence.Enumerated; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.router.VirtualRouter; import com.cloud.utils.net.NetUtils; @@ -92,66 +93,17 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter { @Enumerated(EnumType.STRING) private Role role = Role.DHCP_FIREWALL_LB_PASSWD_USERDATA; - public DomainRouterVO(DomainRouterVO that) { - this(that.id, that.serviceOfferingId, that.instanceName, that.privateMacAddress, that.privateIpAddress, that.privateNetmask, that.templateId, that.guestOSId, that.guestMacAddress, that.guestIpAddress, that.guestNetmask, that.accountId, that.domainId, that.publicMacAddress, that.publicIpAddress, that.publicNetmask, that.vlanDbId, that.vlanId, that.podId, that.dataCenterId, that.ramSize, that.gateway, that.domain, that.dns1, that.dns2); - this.vnet = that.vnet; - this.role = that.role; - } - - public DomainRouterVO(long id, - long serviceOfferingId, - String name, - String privateMacAddress, - String privateIpAddress, - String privateNetmask, - long templateId, - long guestOSId, - String guestMacAddress, - String guestIpAddress, - String guestNetmask, - long accountId, - long domainId, - String publicMacAddress, - String publicIpAddress, - String publicNetMask, - Long vlanDbId, String vlanId, - long podId, - long dataCenterId, - int ramSize, - String gateway, - String domain, - String dns1, - String dns2) { - super(id, serviceOfferingId, name, name, Type.DomainRouter, templateId, guestOSId, privateMacAddress, privateIpAddress, privateNetmask, dataCenterId, podId, domainId, accountId, true, null); - this.privateMacAddress = privateMacAddress; - this.guestMacAddress = guestMacAddress; - this.guestIpAddress = guestIpAddress; - this.publicIpAddress = publicIpAddress; - this.publicMacAddress = publicMacAddress; - this.publicNetmask = publicNetMask; - this.vlanDbId = vlanDbId; - this.vlanId = vlanId; - this.ramSize = ramSize; - this.gateway = gateway; - this.domain = domain; - this.dns1 = dns1; - this.dns2 = dns2; - this.dataCenterId = dataCenterId; - this.accountId = accountId; - this.domainId = domainId; - this.guestNetmask = guestNetmask; - } - public DomainRouterVO(long id, long serviceOfferingId, String name, long templateId, + HypervisorType hypervisorType, long guestOSId, long domainId, long accountId, long networkConfigurationId, boolean haEnabled) { - super(id, serviceOfferingId, name, name, Type.DomainRouter, templateId, guestOSId, domainId, accountId, haEnabled); + super(id, serviceOfferingId, name, name, Type.DomainRouter, templateId, hypervisorType, guestOSId, domainId, accountId, haEnabled); this.networkId = networkConfigurationId; } diff --git a/core/src/com/cloud/vm/SecondaryStorageVmVO.java b/core/src/com/cloud/vm/SecondaryStorageVmVO.java index 5afb42c8633..c4d2e6ecad5 100644 --- a/core/src/com/cloud/vm/SecondaryStorageVmVO.java +++ b/core/src/com/cloud/vm/SecondaryStorageVmVO.java @@ -26,6 +26,8 @@ import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; /** * SecondaryStorageVmVO domain object @@ -89,63 +91,11 @@ public class SecondaryStorageVmVO extends VMInstanceVO implements SecondaryStora - public SecondaryStorageVmVO(long id, long serviceOfferingId, String name, long templateId, long guestOSId, long dataCenterId, + public SecondaryStorageVmVO(long id, long serviceOfferingId, String name, long templateId, HypervisorType hypervisorType, long guestOSId, long dataCenterId, long domainId, long accountId) { - super(id, serviceOfferingId, name, name, Type.SecondaryStorageVm, templateId, guestOSId, domainId, accountId, true); + super(id, serviceOfferingId, name, name, Type.SecondaryStorageVm, templateId, hypervisorType, guestOSId, domainId, accountId, true); } - public SecondaryStorageVmVO( - long id, - long serviceOfferingId, - String name, - String guestMacAddress, - String guestIpAddress, - String guestNetMask, - String privateMacAddress, - String privateIpAddress, - String privateNetmask, - long templateId, - long guestOSId, - String publicMacAddress, - String publicIpAddress, - String publicNetmask, - Long vlanDbId, - String vlanId, - long podId, - long dataCenterId, - long domainId, - long accountId, - String gateway, - Long hostId, - String dns1, - String dns2, - String domain, - int ramSize, - String guid, - String nfsShare) { - super(id, serviceOfferingId, name, name, Type.SecondaryStorageVm, templateId, guestOSId, - privateMacAddress, privateIpAddress, privateNetmask, dataCenterId, podId, domainId, accountId, true, hostId); - this.gateway = gateway; - this.publicIpAddress = publicIpAddress; - this.publicNetmask = publicNetmask; - this.publicMacAddress = publicMacAddress; - this.guestIpAddress = guestIpAddress; - this.guestMacAddress = guestMacAddress; - this.guestNetmask = guestNetMask; - this.vlanDbId = vlanDbId; - this.vlanId = vlanId; - this.dns1 = dns1; - this.dns2 = dns2; - this.domain = domain; - this.ramSize = ramSize; - this.setGuid(guid); - this.nfsShare = nfsShare; - } - - public SecondaryStorageVmVO(SecondaryStorageVmVO that) { - this(that.id, that.serviceOfferingId, that.instanceName, that.guestMacAddress, that.guestIpAddress, that.guestNetmask, that.privateMacAddress, that.privateIpAddress, that.privateNetmask, that.templateId, that.guestOSId, that.publicMacAddress, that.publicIpAddress, that.publicNetmask, that.vlanDbId, that.vlanId, that.podId, that.dataCenterId, that.domainId, that.accountId, that.gateway, that.hostId, that.dns1, that.dns2, that.domain, that.ramSize, that.guid, that.nfsShare); - } - protected SecondaryStorageVmVO() { super(); } diff --git a/core/src/com/cloud/vm/UserVmVO.java b/core/src/com/cloud/vm/UserVmVO.java index d79cec6d3b6..80e7b8f66f0 100755 --- a/core/src/com/cloud/vm/UserVmVO.java +++ b/core/src/com/cloud/vm/UserVmVO.java @@ -23,6 +23,7 @@ import javax.persistence.Entity; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.uservm.UserVm; @Entity @@ -68,7 +69,8 @@ public class UserVmVO extends VMInstanceVO implements UserVm { private String sshPublicKey; transient String password; - + + @Override public String getPassword() { return password; } @@ -152,6 +154,7 @@ public class UserVmVO extends VMInstanceVO implements UserVm { String instanceName, String displayName, long templateId, + HypervisorType hypervisorType, long guestOsId, boolean haEnabled, long domainId, @@ -160,44 +163,12 @@ public class UserVmVO extends VMInstanceVO implements UserVm { String userData, String name, String sshPublicKey) { - super(id, serviceOfferingId, name, instanceName, Type.User, templateId, guestOsId, domainId, accountId, haEnabled); + super(id, serviceOfferingId, name, instanceName, Type.User, templateId, hypervisorType, guestOsId, domainId, accountId, haEnabled); this.userData = userData; this.displayName = displayName != null ? displayName : null; this.sshPublicKey = sshPublicKey; } - public UserVmVO(long id, - String name, - long templateId, - long guestOSId, - long accountId, - long domainId, - long serviceOfferingId, - String guestMacAddress, - String guestIpAddress, - String guestNetMask, - String externalIpAddress, - String externalMacAddress, - Long vlanDbId, - Long routerId, - long podId, - long dcId, - boolean haEnabled, - String displayName, - String userData) { - super(id, serviceOfferingId, name, name, Type.User, templateId, guestOSId, guestMacAddress, guestIpAddress, guestNetMask, dcId, podId, domainId, accountId, haEnabled, null); - this.domainRouterId = routerId; - this.guestIpAddress = guestIpAddress; - this.guestNetmask = guestNetMask; - this.guestMacAddress = guestMacAddress; - this.externalIpAddress = externalIpAddress; - this.externalMacAddress = externalMacAddress; - this.setUserData(userData); - this.setExternalVlanDbId(vlanDbId); - this.isoId = null; - this.displayName = displayName; - } - protected UserVmVO() { super(); } diff --git a/core/src/com/cloud/vm/VMInstanceVO.java b/core/src/com/cloud/vm/VMInstanceVO.java index 3714f5778ee..bd22f50feb2 100644 --- a/core/src/com/cloud/vm/VMInstanceVO.java +++ b/core/src/com/cloud/vm/VMInstanceVO.java @@ -35,6 +35,7 @@ import javax.persistence.TableGenerator; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.StateMachine; import com.cloud.utils.fsm.FiniteStateObject; @@ -139,12 +140,17 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject -1) { - this.templateId = vmTemplateId; - } else { - this.templateId = null; - } - this.guestOSId = guestOSId; - this.privateIpAddress = privateIpAddress; - this.privateMacAddress = privateMacAddress; - this.privateNetmask = privateNetmask; - this.hostId = hostId; - this.dataCenterId = dataCenterId; - this.podId = podId; - this.type = type; - this.haEnabled = haEnabled; - this.instanceName = instanceName; - this.updated = 0; - this.updateTime = new Date(); - this.vncPassword = Long.toHexString(new Random().nextLong()); - this.state = State.Creating; - this.serviceOfferingId = serviceOfferingId; - this.domainId = domainId; - this.accountId = accountId; - } - protected VMInstanceVO() { } @@ -239,6 +202,11 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject ${MOUNTPOINT}/usr/share/cloud/cloud-scripts.tgz md5sum ${MOUNTPOINT}/usr/share/cloud/cloud-scripts.tgz |awk '{print $1}' > ${MOUNTPOINT}/var/cache/cloud/cloud-scripts-signature - echo "Cloudstack Release 2.2 $(date)" > ${MOUNTPOINT}/etc/cloudstack-release + echo "Cloudstack Release $CLOUDSTACK_RELEASE $(date)" > ${MOUNTPOINT}/etc/cloudstack-release } mkdir -p $IMAGENAME diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index 2cd6aaeb86f..1c4fbd6cde1 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -180,8 +180,13 @@ setup_common() { ip route add $MGMTNET via $LOCAL_GW dev eth1 fi - ip route delete default - ip route add default via $GW dev eth2 + ip route delete default + if [ -n "$3" ] + then + ip route add default via $GW dev $3 + else + ip route add default via $GW dev eth0 + fi } setup_dnsmasq() { diff --git a/patches/systemvm/debian/config/etc/iptables/iptables-secstorage b/patches/systemvm/debian/config/etc/iptables/iptables-secstorage old mode 100644 new mode 100755 index ffdf116be15..5326589d5ea --- a/patches/systemvm/debian/config/etc/iptables/iptables-secstorage +++ b/patches/systemvm/debian/config/etc/iptables/iptables-secstorage @@ -12,8 +12,6 @@ COMMIT -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth2 -m state --state RELATED,ESTABLISHED -j ACCEPT --A INPUT -i eth2 -p tcp -m state --state NEW -m tcp --dport 80 -j HTTP --A INPUT -i eth2 -p tcp -m state --state NEW -m tcp --dport 80 -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i eth0 -p tcp -m state --state NEW --dport 3922 -j ACCEPT diff --git a/python/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-ipallocator.in b/python/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-ipallocator.in new file mode 100644 index 00000000000..e0b6b613253 --- /dev/null +++ b/python/distro/rhel/SYSCONFDIR/rc.d/init.d/cloud-ipallocator.in @@ -0,0 +1,82 @@ +#!/bin/bash + +# chkconfig: 35 99 10 +# description: Cloud Agent + +# WARNING: if this script is changed, then all other initscripts MUST BE changed to match it as well + +. /etc/rc.d/init.d/functions + +whatami=cloud-external-ipallocator + +# set environment variables + +SHORTNAME="$whatami" +PIDFILE=@PIDDIR@/"$whatami".pid +LOCKFILE=@LOCKDIR@/"$SHORTNAME" +LOGFILE=@AGENTLOG@ +PROGNAME="Cloud Agent" + +unset OPTIONS +[ -r @SYSCONFDIR@/sysconfig/"$SHORTNAME" ] && source @SYSCONFDIR@/sysconfig/"$SHORTNAME" +DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize +PROG=@BINDIR@/@PACKAGE@-external-ipallocator.py +OPTIONS=8083 + +start() { + echo -n $"Starting $PROGNAME: " + if hostname --fqdn >/dev/null 2>&1 ; then + daemon --check=$SHORTNAME --pidfile=${PIDFILE} "$DAEMONIZE" \ + -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS + RETVAL=$? + echo + else + failure + echo + echo The host name does not resolve properly to an IP address. Cannot start "$PROGNAME". > /dev/stderr + RETVAL=9 + fi + [ $RETVAL = 0 ] && touch ${LOCKFILE} + return $RETVAL +} + +stop() { + echo -n $"Stopping $PROGNAME: " + killproc -p ${PIDFILE} $SHORTNAME # -d 10 $SHORTNAME + RETVAL=$? + echo + [ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE} +} + + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status -p ${PIDFILE} $SHORTNAME + RETVAL=$? + ;; + restart) + stop + sleep 3 + start + ;; + condrestart) + if status -p ${PIDFILE} $SHORTNAME >&/dev/null; then + stop + sleep 3 + start + fi + ;; + *) + echo $"Usage: $whatami {start|stop|restart|condrestart|status|help}" + RETVAL=3 +esac + +exit $RETVAL + diff --git a/python/lib/cloud_utils.py b/python/lib/cloud_utils.py index 3bfc62976a9..d9a825913ef 100644 --- a/python/lib/cloud_utils.py +++ b/python/lib/cloud_utils.py @@ -34,6 +34,7 @@ Unknown = 0 Fedora = 1 CentOS = 2 Ubuntu = 3 +RHEL6 = 4 IPV4 = 4 IPV6 = 6 @@ -42,10 +43,14 @@ IPV6 = 6 if os.path.exists("/etc/fedora-release"): distro = Fedora elif os.path.exists("/etc/centos-release"): distro = CentOS -elif os.path.exists("/etc/redhat-release") and not os.path.exists("/etc/fedora-release"): distro = CentOS +elif os.path.exists("/etc/redhat-release"): + version = file("/etc/redhat-release").readline() + if version.find("Red Hat Enterprise Linux Server release 6") != -1: + distro = RHEL6 + elif version.find("CentOS release") != -1: + distro = CentOS elif os.path.exists("/etc/legal") and "Ubuntu" in file("/etc/legal").read(-1): distro = Ubuntu else: distro = Unknown - logFileName=None # ================== LIBRARY UTILITY CODE============= def setLogFile(logFile): @@ -264,7 +269,7 @@ def check_hostname(): #check function def check_kvm(): - if distro in (Fedora,CentOS): + if distro in (Fedora,CentOS,RHEL6): if os.path.exists("/dev/kvm"): return True raise CheckFailed("KVM is not correctly installed on this system, or support for it is not enabled in the BIOS") else: @@ -284,7 +289,7 @@ def check_cgroups(): #check function def check_selinux(): - if distro not in [Fedora,CentOS]: return # no selinux outside of those + if distro not in [Fedora,CentOS,RHEL6]: return # no selinux outside of those enforcing = False try: output = getenforce().stdout.strip() @@ -365,7 +370,7 @@ class SetupNetworking(ConfigTask): self.runtime_state_changed = False self.was_nm_service_running = None self.was_net_service_running = None - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): self.nmservice = 'NetworkManager' self.netservice = 'network' else: @@ -376,7 +381,7 @@ class SetupNetworking(ConfigTask): def done(self): try: alreadysetup = False - if distro in (Fedora,CentOS): + if distro in (Fedora,CentOS, RHEL6): if self.pubNic != None: alreadysetup = alreadysetup or augtool._print("/files/etc/sysconfig/network-scripts/ifcfg-%s"%self.pubNic).stdout.strip() if self.prvNic != None: @@ -463,12 +468,12 @@ class SetupNetworking(ConfigTask): self.old_net_device = dev - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): inconfigfile = "/".join(augtool.match("/files/etc/sysconfig/network-scripts/*/DEVICE",dev).stdout.strip().split("/")[:-1]) if not inconfigfile: raise TaskFailed("Device %s has not been set up in /etc/sysconfig/network-scripts"%dev) pathtoconfigfile = inconfigfile[6:] - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): automatic = augtool.match("%s/ONBOOT"%inconfigfile,"yes").stdout.strip() else: automatic = augtool.match("/files/etc/network/interfaces/auto/*/",dev).stdout.strip() @@ -476,17 +481,17 @@ class SetupNetworking(ConfigTask): if distro is Fedora: raise TaskFailed("Device %s has not been set up in %s as automatic on boot"%dev,pathtoconfigfile) else: raise TaskFailed("Device %s has not been set up in /etc/network/interfaces as automatic on boot"%dev) - if distro not in (Fedora , CentOS): + if distro not in (Fedora , CentOS, RHEL6): inconfigfile = augtool.match("/files/etc/network/interfaces/iface",dev).stdout.strip() if not inconfigfile: raise TaskFailed("Device %s has not been set up in /etc/network/interfaces"%dev) - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): isstatic = augtool.match(inconfigfile + "/BOOTPROTO","none").stdout.strip() if not isstatic: isstatic = augtool.match(inconfigfile + "/BOOTPROTO","static").stdout.strip() else: isstatic = augtool.match(inconfigfile + "/method","static").stdout.strip() if not isstatic: - if distro in (Fedora, CentOS): raise TaskFailed("Device %s has not been set up as a static device in %s"%(dev,pathtoconfigfile)) + if distro in (Fedora, CentOS, RHEL6): raise TaskFailed("Device %s has not been set up as a static device in %s"%(dev,pathtoconfigfile)) else: raise TaskFailed("Device %s has not been set up as a static device in /etc/network/interfaces"%dev) if is_service_running(self.nmservice): @@ -503,7 +508,7 @@ class SetupNetworking(ConfigTask): yield "Creating Cloud bridging device and making device %s member of this bridge"%dev - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): ifcfgtext = file(pathtoconfigfile).read() newf = "/etc/sysconfig/network-scripts/ifcfg-%s"%self.brname #def restore(): @@ -687,7 +692,7 @@ class SetupLibvirt(ConfigTask): cfgline = "export CGROUP_DAEMON='cpu:/virt'" def done(self): try: - if distro in (Fedora,CentOS): libvirtfile = "/etc/sysconfig/libvirtd" + if distro in (Fedora,CentOS, RHEL6): libvirtfile = "/etc/sysconfig/libvirtd" elif distro is Ubuntu: libvirtfile = "/etc/default/libvirt-bin" else: raise AssertionError, "We should not reach this" return self.cfgline in file(libvirtfile,"r").read(-1) @@ -696,14 +701,14 @@ class SetupLibvirt(ConfigTask): raise def execute(self): - if distro in (Fedora,CentOS): libvirtfile = "/etc/sysconfig/libvirtd" + if distro in (Fedora,CentOS, RHEL6): libvirtfile = "/etc/sysconfig/libvirtd" elif distro is Ubuntu: libvirtfile = "/etc/default/libvirt-bin" else: raise AssertionError, "We should not reach this" libvirtbin = file(libvirtfile,"r").read(-1) libvirtbin = libvirtbin + "\n" + self.cfgline + "\n" file(libvirtfile,"w").write(libvirtbin) - if distro in (CentOS, Fedora): svc = "libvirtd" + if distro in (CentOS, Fedora, RHEL6): svc = "libvirtd" else: svc = "libvirt-bin" stop_service(svc) enable_service(svc) @@ -731,7 +736,7 @@ class SetupLiveMigration(ConfigTask): startswith = stanza.split("=")[0] + '=' replace_or_add_line("/etc/libvirt/libvirtd.conf",startswith,stanza) - if distro is Fedora: + if distro in (Fedora, RHEL6): replace_or_add_line("/etc/sysconfig/libvirtd","LIBVIRTD_ARGS=","LIBVIRTD_ARGS=-l") elif distro is Ubuntu: @@ -743,7 +748,7 @@ class SetupLiveMigration(ConfigTask): else: raise AssertionError("Unsupported distribution") - if distro in (CentOS, Fedora): svc = "libvirtd" + if distro in (CentOS, Fedora, RHEL6): svc = "libvirtd" else: svc = "libvirt-bin" stop_service(svc) enable_service(svc) @@ -753,14 +758,14 @@ class SetupRequiredServices(ConfigTask): name = "required services setup" def done(self): - if distro is Fedora: nfsrelated = "rpcbind nfslock" + if distro in (Fedora, RHEL6): nfsrelated = "rpcbind nfslock" elif distro is CentOS: nfsrelated = "portmap nfslock" else: return True return all( [ is_service_running(svc) for svc in nfsrelated.split() ] ) def execute(self): - if distro is Fedora: nfsrelated = "rpcbind nfslock" + if distro in (Fedora, RHEL6): nfsrelated = "rpcbind nfslock" elif distro is CentOS: nfsrelated = "portmap nfslock" else: raise AssertionError("Unsupported distribution") @@ -772,7 +777,7 @@ class SetupFirewall(ConfigTask): def done(self): - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS,RHEL6): if not os.path.exists("/etc/sysconfig/iptables"): return True if ":on" not in chkconfig("--list","iptables").stdout: return True else: @@ -784,7 +789,7 @@ class SetupFirewall(ConfigTask): def execute(self): ports = "22 1798 16509".split() - if distro in (Fedora , CentOS): + if distro in (Fedora , CentOS, RHEL6): for p in ports: iptables("-I","INPUT","1","-p","tcp","--dport",p,'-j','ACCEPT') o = service.iptables.save() ; print o.stdout + o.stderr else: @@ -800,7 +805,7 @@ class SetupFirewall2(ConfigTask): def done(self): - if distro in (Fedora, CentOS): + if distro in (Fedora, CentOS, RHEL6): if not os.path.exists("/etc/sysconfig/iptables"): return True if ":on" not in chkconfig("--list","iptables").stdout: return True rule = "FORWARD -i %s -o %s -j ACCEPT"%(self.brname,self.brname) @@ -817,7 +822,7 @@ class SetupFirewall2(ConfigTask): yield "Permitting traffic in the bridge interface, migration port and for VNC ports" - if distro in (Fedora , CentOS): + if distro in (Fedora , CentOS, RHEL6): for rule in ( "-I FORWARD -i %s -o %s -j ACCEPT"%(self.brname,self.brname), @@ -856,7 +861,7 @@ def config_tasks(brname, pubNic, prvNic): SetupFirewall(), SetupFirewall2(brname), ) - elif distro in (Ubuntu,Fedora): + elif distro in (Ubuntu,Fedora, RHEL6): config_tasks = ( SetupNetworking(brname, pubNic, prvNic), SetupCgConfig(), @@ -929,7 +934,7 @@ def prompt_for_hostpods(zonespods): def device_exist(devName): try: alreadysetup = False - if distro in (Fedora,CentOS): + if distro in (Fedora,CentOS, RHEL6): alreadysetup = augtool._print("/files/etc/sysconfig/network-scripts/ifcfg-%s"%devName).stdout.strip() else: alreadysetup = augtool.match("/files/etc/network/interfaces/iface",devName).stdout.strip() diff --git a/scripts/vm/hypervisor/xenserver/ovsgre b/scripts/vm/hypervisor/xenserver/ovsgre new file mode 100755 index 00000000000..99804ae63df --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/ovsgre @@ -0,0 +1,777 @@ +#!/usr/bin/python +# +# A plugin for executing script needed by vmops cloud + +import os, sys, time +import XenAPIPlugin +sys.path.append("/opt/xensource/sm/") +import util +from util import CommandException +import hostvmstats +import socket +import stat +import base64 +import tempfile +from os.path import exists as _exists +from time import localtime as _localtime, asctime as _asctime + +vSwitchDBPidFile = "/var/run/openvswitch/ovsdb-server.pid" +vSwitchDBDaemonName = "ovsdb-server" +vSwitchPidFile = "/var/run/openvswitch/ovs-vswitchd.pid" +vsctlPath = "/usr/bin/ovs-vsctl" +vSwitchDaemonName = "ovs-vswitchd" + +logFile = "/var/log/ovsgre.log" +fLog = None + +global result + +errors = \ + {"NO_DB_PID_FILE" : "NO_DB_PID_FILE", \ + "DB_NOT_RUN" : "DB_NOT_RUN", \ + "NO_SWITCH_PID_FILE" : "NO_SWITCH_PID_FILE", \ + "SWITCH_NOT_RUN" : "SWITCH_NOT_RUN", \ + "NO_VSCTL" : "NO_VSCTL", \ + "COMMAND_FAILED" : "COMMAND_FAILED", \ + "TUNNEL_EXISTED" : "TUNNEL_EXISTED", \ + "NO_INPORT" : "NO_INPORT", \ + "NO_OFPORT" : "NO_OFPORT", \ + + "ERR_ARGS_NUM" : "ERR_ARGS_NUM", \ + "ERROR_OP" : "ERROR_OP", \ + "SUCCESS" : "SUCCESS", \ + } + +class ovs_log(object): + def __init__(self, name): + n = "ovs-%s" % name; + logfilename = "/var/run/cloud/" + n +".log" + + self.name = logfilename + self.vmName = name + self.bridge = "" + self.domId = "" + self.seqno = "" + self.tag = "" + self.vifs = "" + self.macs = "" + self.vlans = "" + self.ofports = "" + + def write(self): + log = open(self.name, "w") + log.write("vmName=%s" % self.vmName) + log.write("\n") + log.write("bridge=%s" % self.bridge) + log.write("\n") + log.write("domId=%s" % self.domId) + log.write("\n") + log.write("seqno=%s" % self.seqno) + log.write("\n") + log.write("tag=%s" % self.tag) + log.write("\n") + log.write("vifs=%s" % self.vifs) + log.write("\n") + log.write("macs=%s" % self.macs) + log.write("\n") + log.write("vlans=%s" % self.vlans) + log.write("\n") + log.write("ofports=%s" % self.ofports) + log.close() + + def read(self): + try: + lines = [line.rstrip() for line in open(self.name)] + for i in lines: + if "=" not in i: + util.SMlog("invalid line(%s) in %s" % (i, self.name)) + continue + + (key,value) = i.split("=") + if key == "vmName": + self.vmName = value + elif key == "bridge": + self.bridge = value + elif key == "domId": + self.domId = value + elif key == "seqno": + self.seqno = value + elif key == "tag": + self.tag = value + elif key == "vifs": + self.vifs = value + elif key == "macs": + self.macs = value + elif key == "vlans": + self.vlans = value + elif key == "ofports": + self.ofports = value + except Exception, e: + util.SMlog(e.__str__()) + util.SMlog("Failed to open ovs log %s" % self.name); + + def get_common_info(self): + self.read() + return "%s,%s,%s,%s,%s" % (self.vmName, self.bridge, self.domId, + self.seqno, self.tag) + + def remove(self): + try: + os.remove(self.name) + except: + util.SMlog("Failed to delete ovs log file " + self.name) + +def open_log (): + global fLog + + try: + if fLog == None: + fLog = open (logFile, "a") + except IOError, e: + #print e + pass + +def pr (str): + global fLog + + if fLog != None: + str = "[%s]:" % _asctime (_localtime()) + str + "\n" + fLog.write (str) + +def close_log (): + global fLog + + if fLog != None: + fLog.close () + +def is_process_run (pidFile, name): + try: + fpid = open (pidFile, "r") + pid = fpid.readline () + fpid.close () + except IOError, e: + return -1 + + pid = pid[:-1] + ps = os.popen ("ps -ae") + for l in ps: + if pid in l and name in l: + ps.close () + return 0 + + ps.close () + return -2 + +def is_tool_exist (name): + if _exists (name): + return 0 + return -1 + + +def check_switch (): + global result + + ret = is_process_run (vSwitchDBPidFile, vSwitchDBDaemonName); + if ret < 0: + if ret == -1: result = errors["NO_DB_PID_FILE"] + if ret == -2: result = errors["DB_NOT_RUN"] + return -1 + + ret = is_process_run (vSwitchPidFile, vSwitchDaemonName) + if ret < 0: + if ret == -1: result = errors["NO_SWITCH_PID_FILE"] + if ret == -2: result = errors["SWITCH_NOT_RUN"] + return -1 + + if is_tool_exist (vsctlPath) < 0: + result = errors["NO_VSCTL"] + return -1 + + return 0 + +def do_cmd (cmds, lines=False): + cmd = "" + for i in cmds: + cmd += " " + cmd += i + + pr("do command '%s'" % cmd) + f = os.popen (cmd) + if lines == True: + res = f.readlines () + else: + res = f.readline () + res = res[:-1] + f.close () + + if lines == False: + pr("command output '%s'" % res) + return res + +######################## GRE creation utils ########################## +# UUID's format is 8-4-4-4-12 +def is_uuid (uuid): + list = uuid.split ("-") + + if len (list) != 5: + return -1 + + if len (list[0]) != 8 or len (list[1]) != 4 \ + or len (list[2]) != 4 or len (list[3]) != 4 \ + or len (list[4]) != 12: + return -1 + + return 0 + +def check_gre (bridge, remoteIP, greKey): + ports = get_ports_on_bridge(bridge) + if ports == None: + return "[]" + + for i in ports: + ifaces = get_interface_on_port(i) + if ifaces == None: + continue + + for j in ifaces: + if j == '[]': + continue + options = get_field_of_interface(j, "options") + if remoteIP in options and greKey in options: + pr("WARNING: GRE tunnel for remote_ip=%s key=%s already here, \ +interface(%s)" % (remoteIP, greKey, j)) + return get_field_of_interface(j, "ofport") + + return "[]" + +def ovs_create_gre (session, args): + global result + bridge = args.pop("bridge") + remoteIP = args.pop("remoteIP") + greKey = args.pop("greKey") + srcHost = args.pop("from") + dstHost = args.pop("to") + + name = "%s-%s" % (srcHost, dstHost) + res = check_gre(bridge, remoteIP, greKey) + if res != "[]": + result = "SUCCESS:%s" % res + return result + + wait = [vsctlPath, "--timeout=30 wait-until bridge %s -- get bridge %s name" % \ + (bridge, bridge)] + res = do_cmd(wait) + if bridge not in res: + pr("WARNIING:Can't find bridge %s for creating tunnel!" % bridge) + result = errors["COMMAND_FAILED"] + return result + + createInterface = [vsctlPath, "create interface", "name=%s" % name, \ + 'type=gre options:"remote_ip=%s key=%s"' % (remoteIP, greKey)] + ifaceUUID = do_cmd (createInterface) + if is_uuid (ifaceUUID) < 0: + result = errors["COMMAND_FAILED"]; + return result + + createPort = [vsctlPath, "create port", "name=%s" % name, \ + "interfaces=[%s]" % ifaceUUID] + portUUID = do_cmd (createPort) + if is_uuid (portUUID) < 0: + result = errors["COMMAND_FAILED"]; + return result + + addBridge = [vsctlPath, "add bridge %s" % bridge, "ports %s" % portUUID] + do_cmd (addBridge) + + wait = [vsctlPath, "--timeout=5 wait-until port %s -- get port %s name" % \ + (name, name)] + res = do_cmd(wait) + if name in res: + port = get_field_of_interface(name, "ofport"); + result = "SUCCESS:%s" % port + else: + result = errors["COMMAND_FAILED"] + + return result +######################## End GRE creation utils ########################## + +######################## Flow creation utils ########################## +def get_ports_on_bridge(bridge): + listBr = [vsctlPath, "list br", bridge] + res = do_cmd(listBr, True) + + for i in res: + if "ports" in i: + (x, str) = i.split(":") + str = str.lstrip().rstrip() + str = str[1:] + str = str[:-1] + return str.split(",") + return None + +def get_filed_of_port(nameOruuid, field): + listport = [vsctlPath, "list port", nameOruuid] + res = do_cmd(listport, True) + + for i in res: + if field in i: + (x, r) = i.split(":") + return r.lstrip().rstrip() + return None + +def get_field_of_interface(nameOruuid, field): + listIface = [vsctlPath, "list interface", nameOruuid] + res = do_cmd(listIface, True) + + for i in res: + if field in i: + (x, r) = i.split(":") + return r.lstrip().rstrip() + return None + +def strip(str, direction="default"): + str = str.lstrip().rstrip() + if direction == "left": + return str[1:] + if direction == "right": + return str[:-1] + if direction == "both": + str = str[1:] + str = str[:-1] + return str + return str + +def get_vif_port(bridge, vifName): + portUuids = get_ports_on_bridge(bridge) + if portUuids == None: + pr("No ports on bridge %s" % bridge) + return None + + for i in portUuids: + name = get_filed_of_port(i, "name") + if name == None: + pr("WARNING: no name found for %s" % name) + continue + + name = strip(name, "both") + if name == vifName: + return get_field_of_interface(vifName, "ofport") + return None + +def get_interface_on_port(nameOruuid): + listPort = [vsctlPath, "list port", nameOruuid] + res = do_cmd(listPort, True) + + for i in res: + if "interfaces" in i: + (x, str) = i.split(":") + str = strip(str, "both") + return str.split(",") + return None + +def get_ofports_by_tag(bridge, tag): + portUuids = get_ports_on_bridge(bridge) + if portUuids == None: + pr("WARNING:No ports on bridge %s" % bridge) + return [] + + OfPorts = [] + for i in portUuids: + t = get_filed_of_port(i, "tag") + if t != tag: + pr("Skip port %s with tag=%s" % (i, t)) + continue + + iface = get_filed_of_port(i, "interfaces") + iface = strip(iface, "both") + port = get_field_of_interface(iface, "ofport") + if port != '[]': + OfPorts.append(port) + + return OfPorts + +def format_flow(inPort, vlan, mac, outPut): + flow = "in_port=%s dl_vlan=%s dl_dst=%s idle_timeout=0 hard_timeout=0 \ + priority=10000 actions=strip_vlan,output:%s" % (inPort, vlan, mac, outPut) + return flow + +def format_drop_flow(inPort, vlan): + flow = "in_port=%s dl_vlan=%s priority=0 idle_timeout=0 hard_timeout=0 \ + actions=drop" % (inPort, vlan) + return flow + +def del_flow(bridge, mac): + param = "dl_dst=%s" % mac + flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + do_cmd(flow) + +def del_arp_and_dhcp_flow(bridge, vlan, inPort): + param = "dl_type=0x0806 dl_vlan=%s in_port=%s" % (vlan, inPort) + flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + do_cmd(flow) + + param = "dl_type=0x0800 nw_proto=17 tp_dst=68 dl_vlan=%s, in_port=%s" % (vlan, inPort) + flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + do_cmd(flow) + + param = "dl_type=0x0800 nw_proto=17 tp_dst=67 dl_vlan=%s, in_port=%s" % (vlan, inPort) + flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + do_cmd(flow) + +def del_drop_flow(bridge, vlan): + param = "priority=0 dl_vlan=%s" % vlan + flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + do_cmd(flow) + +def format_normal_flow(): + flow = "priority=0 idle_timeout=0 hard_timeout=0 actions=normal" + return flow + +def format_dhcp_flow(bridge, inPort, vlan, ports): + outputs = '' + for i in ports: + str = "output:%s," % i + outputs += str + outputs = outputs[:-1] + flow = "in_port=%s dl_vlan=%s dl_type=0x0800 nw_proto=17 tp_dst=67 idle_timeout=0 hard_timeout=0 \ + priority=10000 actions=strip_vlan,%s" % (inPort, vlan, outputs) + return flow + +def format_dhcp_client_flow(bridge, inPort, vlan, ports): + outputs = '' + for i in ports: + str = "output:%s," % i + outputs += str + outputs = outputs[:-1] + flow = "in_port=%s dl_vlan=%s dl_type=0x0800 nw_proto=17 tp_dst=68 idle_timeout=0 hard_timeout=0 \ + priority=10000 actions=strip_vlan,%s" % (inPort, vlan, outputs) + return flow + +def format_arp_flow(bridge, inPort, vlan, ports): + outputs = '' + for i in ports: + str = "output:%s," % i + outputs += str + + outputs = outputs[:-1] + flow = "in_port=%s dl_vlan=%s dl_type=0x0806 idle_timeout=0 hard_timeout=0 \ + priority=10000 actions=strip_vlan,%s" % (inPort, vlan, outputs) + return flow + +def create_flow (bridge, vifName, mac, vlans): + global result + + output = get_vif_port(bridge, vifName) + if output == None: + pr("WARNING: cannot find ofport for %s" % vifName) + return errors["NO_OFPORT"] + return -1 + if output == '[]': + pr("WARNING: ofport is [] for %s" % vifName) + return errors["NO_OFPORT"] + return -1 + + #set remap here, remap has format e.g. 1/22/200/13/16 + pr("") + pr("Create flow for vlans=%s" % vlans) + for v in vlans.split(","): + try: + (vlan, inPort) = v.split(":") + flow = format_drop_flow(inPort, vlan) + add_flow(bridge, flow) + + flow = format_flow(inPort, vlan, mac, output) + add_flow(bridge, flow) + except Exception, e: + pr(e.__str__()) + pr("invalid map") + + # add normal flow make switch work as L2/L3 switch + flow = format_normal_flow() + add_flow(bridge, flow) + + return errors["SUCCESS"] +######################## End Flow creation utils ########################## + +def set_tag(bridge, vifName, vlan): + # The startVM command is slow, we may wait for a while for it creates vif on + # open vswitch + pr("Waiting for %s ..." % vifName) + waitPortCmd = [vsctlPath, "--timeout=10 wait-until port %s -- get port %s name" % \ + (vifName, vifName)] + do_cmd (waitPortCmd) + pr("%s is here" % vifName) + + if get_vif_port(bridge, vifName) == None: + pr("WARNING: %s is not on bridge %s" % (vifName, bridge)) + return 0 + + pr("Set tag") + set_tagCmd = [vsctlPath, "set port", vifName, "tag=%s"%vlan] + do_cmd (set_tagCmd) + return 0 + +def ask_ports(bridge, vifNames): + vifs = vifNames.split(",") + if len(vifs) == 0: + return ' ' + + ofports = [] + for vif in vifs: + op = get_vif_port(bridge, vif) + if op == None: + pr("ask_ports: no port(bridge:%s, vif:%s)" % (bridge, vif)) + continue + ofports.append(op) + + return ",".join(ofports) + +def delete_vm_flows(bridge, vmName, reCreate=True): + log = ovs_log(vmName) + log.read() + + macs = log.macs; + for i in macs.split(","): + del_flow(bridge, i) + pr("Delete flows for %s" % i) + + vlans = log.vlans + for v in vlans.split(","): + try: + (vlan, inPort) = v.split(":") + del_arp_and_dhcp_flow(bridge, vlan, inPort) + except Exception, e: + pr(e.__str__()) + pr("invalid map") + + for v in vlans: + try: + (vlan, inport) = v.split(":") + del_drop_flow(bridge, vlan) + except Exception, e: + pr(e.__str__()) + pr("invalid map") + + if reCreate == False: + return + + bridge = log.bridge + tag = log.tag + noneGreOfPorts = get_ofports_by_tag(bridge, tag) + + try: + noneGreOfPorts.remove(log.ofports) + except Exception, e: + pr(e.__str__()) + pr("ofport %s of %s is not on bridge %s" % (log.ofports, log.vmName, + bridge)) + + if len(noneGreOfPorts) != 0: + set_arp_and_dhcp_flow(bridge, vlans, tag, noneGreOfPorts) + + # add normal flow make switch work as L2/L3 switch + flow = format_normal_flow() + add_flow(bridge, flow) + + log.remove() + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name ) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name ) + return res + return wrapped + + +def ovs_handle_rebooted_vm(session, vmName): + curr_domid = '-1' + log = ovs_log(vmName) + log.read() + + (curr_domid, vifrs, hostuuid) = ovs_get_domid_vifrs_hostuuid(session, vmName) + + old_id = log.domId; + if curr_domid == old_id: + util.SMlog("OvsInfo:%s is normal" % vmName) + return True + + util.SMlog("%s rebooted, reset flow for it" % vmName) + vlans = log.vlans; + bridge = log.bridge + tag = log.tag + for vifr in vifrs: + vifName = "vif" + curr_domid + "." + vifr[0] + set_tag(bridge, vifName, tag) + create_flow(bridge, vifName, vifr[1], vlans) + + log.domId = curr_domid + log.write() + + return True + +@echo +def ovs_get_vm_log(session, args): + host_uuid = args.pop('host_uuid') + try: + thishost = session.xenapi.host.get_by_uuid(host_uuid) + hostrec = session.xenapi.host.get_record(thishost) + vms = hostrec.get('resident_VMs') + except Exception, e: + util.SMlog("Failed to get host from uuid %s, exception: %s" % (host_uuid, e.__str__())) + return ' ' + + result = [] + try: + for name in [session.xenapi.VM.get_name_label(x) for x in vms]: + if 1 not in [ name.startswith(c) for c in ['r-', 'i-'] ]: + continue + ovs_handle_rebooted_vm(session, name) + if name.startswith('i-'): + log = ovs_log(name) + info = log.get_common_info() + result.append(info) + except Exception, e: + util.SMlog(e.__str__()) + util.SMlog("OVs failed to get logs, better luck next time!") + + return ";".join(result) + +def ovs_write_vm_log(bridge, vmName, vmId, seqno, vifNames, macs, tag, vlans, ofports): + log = ovs_log(vmName) + log.read() + log.bridge = bridge + log.vmName = vmName + log.domId = vmId + log.seqno = seqno + log.vifs = vifNames + log.macs = macs + log.tag = tag + log.vlans = vlans + log.ofports = ofports + log.write() + + util.SMlog("Writing ovs log to " + log.name) + +@echo +def ovs_delete_flow(session, args): + bridge = args.pop('bridge') + vmName = args.pop('vmName') + + delete_vm_flows(bridge, vmName) + return 'SUCCESS' + +def ovs_get_domid_vifrs_hostuuid(session, vmName): + def get_vif_field(name, field): + return session.xenapi.VIF.get_record(name).get(field) + + try: + vm = session.xenapi.VM.get_by_name_label(vmName) + if len(vm) != 1: + return 'NO_VM' + vm_rec = session.xenapi.VM.get_record(vm[0]) + vm_vifs = vm_rec.get('VIFs') + vifrs = [] + for vif in vm_vifs: + rec = (get_vif_field(vif, 'device'), get_vif_field(vif, 'MAC')) + vifrs.append(rec) + domid = vm_rec.get('domid') + host = vm_rec.get('resident_on') + host_rec = session.xenapi.host.get_record(host) + uuid = host_rec.get('uuid') + util.SMlog("OVSINFO: (domid:%s, uuid:%s)" % (domid, uuid)) + return (domid, vifrs, uuid) + + except: + util.SMlog("### Failed to get domid or vif list for vm ##" + vmName) + return (-1, [], "-1") + +def add_flow(bridge, flow): + param = bridge + ' "%s"' % flow + addflow = ["ovs-ofctl add-flow", param] + do_cmd (addflow) + +def set_arp_and_dhcp_flow(bridge, vlans, tag, ofports): + for v in vlans.split(","): + try: + (vlan, inPort) = v.split(":") + arpFlow = format_arp_flow(bridge, inPort, vlan, ofports) + add_flow(bridge, arpFlow) + + dhcpFlow = format_dhcp_flow(bridge, inPort, vlan, ofports) + add_flow(bridge, dhcpFlow) + + dhcpClientFlow = format_dhcp_client_flow(bridge, inPort, vlan, ofports) + add_flow(bridge, dhcpClientFlow) + except Exception, e: + pr(e.__str__()) + pr("invalid map") + +@echo +def ovs_set_arp_and_dhcp_flow(session, args): + vlans = args.pop('vlans') + bridge = args.pop('bridge') + tag = args.pop('tag') + + pr("ovs_set_arp_and_dhcp_flow: bridge=%s, vlans=%s, tag=%s" % (bridge, + vlans, tag)) + if vlans == '[]': + pr("No need to create arp and dhcp flow") + return 'SUCCESS' + + ofports = get_ofports_by_tag(bridge, tag) + if len(ofports) == 0: + pr("No VMs, skip set arp and dhcp flow for tag=%s" % tag) + return 'SUCCESS' + + set_arp_and_dhcp_flow(bridge, vlans, tag, ofports) + return 'SUCCESS' + +@echo +def ovs_set_tag_and_flow(session, args): + bridge = args.pop('bridge') + vmName = args.pop('vmName') + vlans = args.pop('vlans') + tag = args.pop('tag') + seqno = args.pop('seqno') + + (domid, vifrs, hostuuid) = ovs_get_domid_vifrs_hostuuid(session, vmName) + + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vmName) + return 'NO_DOMID' + + if len(vifrs) == 0: + return 'SUCCESS' + + pr("ovs_set_tag_and_flow: bridge=%s, vmName=%s, vlans=%s, tag=%s, seqno=%s" % + (bridge, vmName, vlans, tag, seqno)) + #delete old flows first + delete_vm_flows(bridge, vmName, False) + + vifNames = [] + vlans = strip(vlans, "both") + macs = [] + for vifr in vifrs: + vifName = "vif" + domid + "." + vifr[0] + vifNames.append(vifName) + mac = vifr[1] + macs.append(mac) + set_tag(bridge, vifName, tag) + create_flow(bridge, vifName, mac, vlans) + + vifs = ",".join(vifNames) + ofports = ask_ports(bridge, vifs) + ovs_write_vm_log(bridge, vmName, domid, seqno, vifs, ",".join(macs), tag, vlans, ofports) + + #see if there is rebooted vm to handle + ovs_get_vm_log(session, {"host_uuid":hostuuid}) + ovs_set_arp_and_dhcp_flow(session, {"bridge":bridge, "tag":tag, "vlans":vlans}) + return 'SUCCESS' + +if __name__ == "__main__": + open_log() + XenAPIPlugin.dispatch({"ovs_create_gre":ovs_create_gre, "ovs_set_tag_and_flow":ovs_set_tag_and_flow, "ovs_get_vm_log":ovs_get_vm_log,"ovs_delete_flow":ovs_delete_flow}) + close_log() + diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 91a35007047..02e7702cf87 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -358,7 +358,7 @@ def can_bridge_firewall(session, args): util.pread2(['iptables', '-D', 'FORWARD', '-j', 'RH-Firewall-1-INPUT']) except: util.SMlog('Chain BRIDGE-FIREWALL already exists') - privnic = get_private_nic(session,args) + privnic = get_private_nic(session, args) result = 'true' try: util.pread2(['/bin/bash', '-c', 'iptables -n -L FORWARD | grep BRIDGE-FIREWALL']) @@ -374,7 +374,7 @@ def can_bridge_firewall(session, args): os.makedirs('/var/run/cloud') cleanup_rules_for_dead_vms(session) - cleanup_rules(session) + cleanup_rules(session, args) return result @@ -414,13 +414,13 @@ def destroy_network_rules_for_vm(session, args): vmchain = '-'.join(vm_name.split('-')[:-1]) vmchain_default = '-'.join(vm_name.split('-')[:-2]) + "-def" - destroy_ebtables_rules(vmchain) + try: + util.pread2(['iptables', '-F', vmchain_default]) + util.pread2(['iptables', '-X', vmchain_default]) + except: + util.SMlog("Ignoring failure to delete chain " + vmchain_default) - try: - util.pread2(['iptables', '-F', vmchain_default]) - util.pread2(['iptables', '-X', vmchain_default]) - except: - util.SMlog("Ignoring failure to delete chain " + vmchain_default) + destroy_ebtables_rules(vmchain) try: util.pread2(['iptables', '-F', vmchain]) @@ -518,8 +518,7 @@ def default_ebtables_rules(vm_name, vif, vm_ip, vm_mac): except: util.SMlog("Failed to program default ebtables OUT rules") return 'false' - - + @echo def default_network_rules_systemvm(session, args): vm_name = args.pop('vmName') @@ -591,15 +590,21 @@ def default_network_rules(session, args): return 'false' vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - vm_name = '-'.join(vm_name.split('-')[:-1]) - vmchain = vm_name - vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def" + vmchain = '-'.join(vm_name.split('-')[:-1]) + vmchain_default = '-'.join(vm_name.split('-')[:-2]) + "-def" - destroy_ebtables_rules(vm_name) + destroy_ebtables_rules(vmchain) try: @@ -630,7 +635,8 @@ def default_network_rules(session, args): util.SMlog("Failed to program default rules for vm " + vm_name) return 'false' - default_ebtables_rules(vm_name, vif, vm_ip, vm_mac) + for v in vifs: + default_ebtables_rules(vm_name, v, vm_ip, vm_mac) if write_rule_log_for_vm(vmName, vm_id, vm_ip, domid, '_initial_', '-1') == False: util.SMlog("Failed to log default network rules, ignoring") @@ -666,10 +672,9 @@ def check_domid_changed(session, vmName): def delete_rules_for_vm_in_bridge_firewall_chain(vmName): vm_name = vmName - if vm_name.startswith('i-') or vm_name.startswith('r-'): - vm_name = '-'.join(vm_name.split('-')[:-2]) - vmchain = vm_name + if vm_name.startswith('i-') or vm_name.startswith('r-'): + vmchain = '-'.join(vm_name.split('-')[:-1]) delcmd = "iptables -S BRIDGE-FIREWALL | grep " + vmchain + " | sed 's/-A/-D/'" delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') @@ -726,7 +731,7 @@ def network_rules_for_rebooted_vm(session, vmName): inscmd2 = "iptables -S " + vmchain_default + " | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'" ipts = [] - for cmd in [delcmd, inscmd]: + for cmd in [delcmd, inscmd, inscmd2]: cmds = util.pread2(['/bin/bash', '-c', cmd]).split('\n') cmds.pop() for c in cmds: @@ -824,7 +829,7 @@ def cleanup_rules_for_dead_vms(session): @echo -def cleanup_rules(session): +def cleanup_rules(session, args): try: chainscmd = "iptables-save | grep '^:' | grep -v '.*-def' | awk '{print $1}' | cut -d':' -f2" chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') @@ -851,9 +856,12 @@ def cleanup_rules(session): for vmname in cleanup: destroy_network_rules_for_vm(session, {'vmName':vmname}) - util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") + util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") + return str(len(cleanup)) except: util.SMlog("Failed to cleanup rules !") + return '-1'; + @echo def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): @@ -939,6 +947,13 @@ def network_rules(session, args): return 'false' vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass vm_name = '-'.join(vm_name.split('-')[:-1]) vmchain = vm_name @@ -1017,5 +1032,5 @@ def network_rules(session, args): if __name__ == "__main__": - XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn}) + XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, "cleanup_rules":cleanup_rules}) diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 9c95ab4847f..8042e30d103 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -12,6 +12,7 @@ NFSSR.py=/opt/xensource/sm nfs.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins +ovsgre=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index b908ae4d341..d6ef574a7e6 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -486,7 +486,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, final ServiceOfferingVO offering, final VMTemplateVO template, VMInstanceVO vm, Host currentHost, final Set avoid) { VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl( - vm, template, offering, null, null, null); + vm, template, offering, null, null); DeployDestination dest = null; DataCenterDeployment plan = new DataCenterDeployment(dc.getId(), pod.getId(), sp.getClusterId(), null); @@ -1531,7 +1531,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Long dcId = host.getDataCenterId(); ReadyCommand ready = new ReadyCommand(dcId); Answer answer = easySend(hostId, ready); - if (answer == null) { + if (answer == null || !answer.getResult()) { // this is tricky part for secondary storage // make it as disconnected, wait for secondary storage VM to be up // return the attache instead of null, even it is disconnectede diff --git a/server/src/com/cloud/agent/manager/Commands.java b/server/src/com/cloud/agent/manager/Commands.java index 50a9aa1a997..100ea6d0268 100644 --- a/server/src/com/cloud/agent/manager/Commands.java +++ b/server/src/com/cloud/agent/manager/Commands.java @@ -60,6 +60,10 @@ public class Commands { addCommand(null, cmd); } + public void addCommand(int index, Command cmd) { + _cmds.add(index, cmd); + } + public Answer getAnswer(String id) { int i = _ids.indexOf(id); return i == -1 ? null : _answers[i]; diff --git a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java index 6dcab9892d8..a45e8891551 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/UserConcentratedAllocator.java @@ -38,7 +38,7 @@ import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; import com.cloud.dc.dao.HostPodDao; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -250,14 +250,14 @@ public class UserConcentratedAllocator implements PodAllocator { so = _offeringDao.findById(userVm.getServiceOfferingId()); } else if(vm.getType() == VirtualMachine.Type.ConsoleProxy) { so = new ServiceOfferingVO("Fake Offering For DomP", 1, - _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + _proxyRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.SecondaryStorageVm) { - so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.DomainRouter) { - so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else { assert(false) : "Unsupported system vm type"; - so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } if(capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) { diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 3fe4c16a3ef..b397cbd5adf 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -509,7 +509,7 @@ public class ApiDBUtils { } public static long getPublicNetworkIdByZone(long zoneId) { - return _networkMgr.getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(zoneId, TrafficType.Public, null); + return _networkMgr.getSystemNetworkByZoneAndTrafficType(zoneId, TrafficType.Public).getId(); } public static Long getVlanNetworkId(long vlanId) { diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 1875b520dd3..e8baf8d2065 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -113,7 +113,6 @@ import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupRules; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; import com.cloud.server.Criteria; @@ -740,7 +739,7 @@ public class ApiResponseHelper implements ResponseGenerator { volResponse.setDeviceId(volume.getDeviceId()); Long instanceId = volume.getInstanceId(); - if (instanceId != null) { + if (instanceId != null && volume.getState() != Volume.State.Destroy) { VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId); volResponse.setVirtualMachineId(vm.getId()); volResponse.setVirtualMachineName(vm.getName()); @@ -1084,16 +1083,11 @@ public class ApiResponseHelper implements ResponseGenerator { if (singleNic.getIsolationUri() != null) { nicResponse.setIsolationUri(singleNic.getIsolationUri().toString()); } - } - //Set traffic type + } Network network = ApiDBUtils.findNetworkById(singleNic.getNetworkId()); nicResponse.setTrafficType(network.getTrafficType().toString()); - - //Set type - NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId()); - if (networkOffering.getGuestIpType() != null) { - nicResponse.setType(networkOffering.getGuestIpType().toString()); - } + nicResponse.setType(network.getGuestType().toString()); + nicResponse.setIsDefault(singleNic.isDefaultNic()); nicResponse.setObjectName("nic"); @@ -2174,9 +2168,6 @@ public class ApiResponseHelper implements ResponseGenerator { response.setDisplayText(offering.getDisplayText()); response.setTags(offering.getTags()); response.setTrafficType(offering.getTrafficType().toString()); - if (offering.getGuestIpType() != null) { - response.setType(offering.getGuestIpType().toString()); - } response.setMaxconnections(offering.getConcurrentConnections()); response.setIsDefault(offering.isDefault()); response.setSpecifyVlan(offering.getSpecifyVlan()); @@ -2232,6 +2223,7 @@ public class ApiResponseHelper implements ResponseGenerator { } response.setIsShared(network.isShared()); + response.setIsDefault(network.isDefault()); response.setState(network.getState().toString()); response.setRelated(network.getRelated()); response.setDns1(network.getDns1()); diff --git a/server/src/com/cloud/api/doc/ApiXmlDocReader.java b/server/src/com/cloud/api/doc/ApiXmlDocReader.java index b5b19937073..54f9627478d 100644 --- a/server/src/com/cloud/api/doc/ApiXmlDocReader.java +++ b/server/src/com/cloud/api/doc/ApiXmlDocReader.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import com.thoughtworks.xstream.XStream; @@ -39,8 +40,8 @@ public class ApiXmlDocReader { String oldFile = null; String dirName = ""; - HashMap commands = new HashMap(); - HashMap oldCommands = new HashMap(); + LinkedHashMap commands = new LinkedHashMap(); + LinkedHashMap oldCommands = new LinkedHashMap(); ArrayList addedCommands = new ArrayList(); ArrayList removedCommands = new ArrayList(); HashMap stableCommands = new HashMap(); @@ -117,13 +118,23 @@ public class ApiXmlDocReader { //Print added commands out.write("Added commands:\n"); for (Command c : addedCommands) { - out.write("\n " + c.getName() + " (" + c.getDescription() + "\n"); + if (c.getDescription() != null && !c.getDescription().isEmpty()) { + out.write("\n " + c.getName() + " (" + c.getDescription() + ")\n"); + } else { + out.write("\n " + c.getName() + "\n"); + } + } //Print removed commands out.write("\nRemoved commands:\n"); for (Command c : removedCommands) { - out.write("\n " + c.getName() + " (" + c.getDescription() + ")\n"); + if (c.getDescription() != null && !c.getDescription().isEmpty()) { + out.write("\n " + c.getName() + " (" + c.getDescription() + ")\n"); + } else { + out.write("\n " + c.getName() + "\n"); + } + } //Print differences between commands arguments @@ -167,18 +178,21 @@ public class ApiXmlDocReader { } //Check if any response arguments were added in new version - for (Argument arg : newCommand.getResponse()) { - if (oldCommand.getResArgByName(arg.getName()) == null) { - newRespArgs.add(arg); - } + if (newCommand.getResponse() != null && oldCommand.getResponse() != null) { + for (Argument arg : newCommand.getResponse()) { + if (oldCommand.getResArgByName(arg.getName()) == null) { + newRespArgs.add(arg); + } + } + + //Check if any response arguments were removed in new version + for (Argument arg : oldCommand.getResponse()) { + if (newCommand.getResArgByName(arg.getName()) == null) { + removedRespArgs.add(arg); + } + } } - //Check if any response arguments were removed in new version - for (Argument arg : oldCommand.getResponse()) { - if (newCommand.getResArgByName(arg.getName()) == null) { - removedRespArgs.add(arg); - } - } if (newReqArgs.size() != 0 || newRespArgs.size() != 0 || removedReqArgs.size() != 0 || removedRespArgs.size() != 0 || stableReqArgs.size() != 0 || stableReqArgs.size() != 0) { out.write("\n\t" + key); @@ -186,21 +200,33 @@ public class ApiXmlDocReader { if (newReqArgs.size() != 0 || removedReqArgs.size() != 0 || stableReqArgs.size() != 0) { out.write("\n\t\tRequest"); if (newReqArgs.size() != 0){ - out.write("\n\t\t\tNew parameters: "); + StringBuffer newParameters = new StringBuffer(); + newParameters.append("\n\t\t\tNew parameters: "); for (Argument newArg: newReqArgs) { - out.write(newArg.getName()); + String isRequiredParam = "optional"; + if (newArg.isRequired()) { + isRequiredParam = "required"; + } + newParameters.append(newArg.getName() + " (" + isRequiredParam + "), "); } + newParameters.delete(newParameters.length()-2, newParameters.length()-1); + out.write(newParameters.toString()); out.write("\n"); } if (removedReqArgs.size() != 0){ - out.write("\n\t\t\tRemoved parameters: "); + StringBuffer removedParameters = new StringBuffer(); + removedParameters.append("\n\t\t\tRemoved parameters: "); for (Argument removedArg: removedReqArgs) { - out.write(removedArg.getName()); + removedParameters.append(removedArg.getName() + ", "); } + removedParameters.delete(removedParameters.length()-2, removedParameters.length()-1); + out.write(removedParameters.toString()); + out.write("\n"); } - out.write("\n"); + if (stableReqArgs.size() != 0){ - out.write("\n\t\t\tChanged parameters: "); + StringBuffer changedParameters = new StringBuffer(); + changedParameters.append("\n\t\t\tChanged parameters: "); for (Argument stableArg: stableReqArgs.values()) { String newRequired = "optional"; String oldRequired = "optional"; @@ -208,29 +234,37 @@ public class ApiXmlDocReader { oldRequired = "required"; if (newCommand.getReqArgByName(stableArg.getName()).isRequired() == true) newRequired = "required"; - - out.write(stableArg.getName() + " (old version - " + oldRequired + ", new version - " + newRequired + ") "); + changedParameters.append(stableArg.getName() + " (old version - " + oldRequired + ", new version - " + newRequired + "), "); } + changedParameters.delete(changedParameters.length() - 2, changedParameters.length() - 1); + out.write(changedParameters.toString()); + out.write("\n"); } - out.write("\n"); + } //Response if (newRespArgs.size() != 0 || removedRespArgs.size() != 0 || stableRespArgs.size() != 0) { - out.write("\n\t\tResponse:"); + StringBuffer changedResponseParams = new StringBuffer(); + changedResponseParams.append("\n\t\tResponse:"); if (newRespArgs.size() != 0){ + changedResponseParams.append("\n\t\t\tNew parameters: "); out.write("\n\t\t\tNew parameters: "); for (Argument newArg: newRespArgs) { - out.write(newArg.getName()); + changedResponseParams.append(newArg.getName() + ", "); } + changedResponseParams.delete(changedResponseParams.length() - 2, changedResponseParams.length() - 1); out.write("\n"); } if (removedRespArgs.size() != 0){ - out.write("\n\t\t\tRemoved parameters: "); + changedResponseParams.append("\n\t\t\tRemoved parameters: "); for (Argument removedArg: removedRespArgs) { + changedResponseParams.append(removedArg.getName()); out.write(removedArg.getName()); } } + changedResponseParams.delete(changedResponseParams.length() - 2, changedResponseParams.length() - 1); + out.write(changedResponseParams.toString()); out.write("\n"); } } diff --git a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java index ad1e5624286..95ed8945228 100644 --- a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java +++ b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java @@ -18,18 +18,26 @@ package com.cloud.api.doc; +import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.TreeMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.apache.log4j.Logger; @@ -39,21 +47,27 @@ import com.cloud.api.BaseCmd; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; +import com.cloud.api.response.BaseResponse; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; import com.thoughtworks.xstream.XStream; public class ApiXmlDocWriter { - public static final Logger s_logger = Logger - .getLogger(ApiXmlDocWriter.class.getName()); - private static Properties api_commands = new Properties(); + public static final Logger s_logger = Logger.getLogger(ApiXmlDocWriter.class.getName()); + + private static final short DOMAIN_ADMIN_COMMAND = 2; + private static final short USER_COMMAND = 8; + private static LinkedHashMap all_api_commands = new LinkedHashMap(); + private static LinkedHashMap domain_admin_api_commands = new LinkedHashMap(); + private static LinkedHashMap regular_user_api_commands = new LinkedHashMap(); + private static TreeMap all_api_commands_sorted = new TreeMap(); + private static TreeMap domain_admin_api_commands_sorted = new TreeMap(); + private static TreeMap regular_user_api_commands_sorted = new TreeMap(); private static String dirName=""; public static void main (String[] args) { - Properties preProcessedCommands = new Properties(); - Enumeration command = null; + LinkedProperties preProcessedCommands = new LinkedProperties(); String[] fileNames = null; - ArrayList commands = new ArrayList(); List argsList = Arrays.asList(args); Iterator iter = argsList.iterator(); @@ -86,98 +100,273 @@ public class ApiXmlDocWriter { } } + Iterator propertiesIterator = preProcessedCommands.keys.iterator(); //Get command classes and response object classes - for (Object key : preProcessedCommands.keySet()) { - String preProcessedCommand = preProcessedCommands.getProperty((String)key); + while (propertiesIterator.hasNext()) { + String key = (String)propertiesIterator.next(); + String preProcessedCommand = preProcessedCommands.getProperty(key); String[] commandParts = preProcessedCommand.split(";"); - api_commands.put(key, commandParts[0]); + String commandName = commandParts[0]; + all_api_commands.put(key, commandName); + + short cmdPermissions = 1; + if (commandParts.length > 1 && commandParts[1] != null) { + cmdPermissions = Short.parseShort(commandParts[1]); + } + + if ((cmdPermissions & DOMAIN_ADMIN_COMMAND) != 0) { + domain_admin_api_commands.put(key, commandName); + } + if ((cmdPermissions & USER_COMMAND) != 0) { + regular_user_api_commands.put(key, commandName); + } } - command = api_commands.propertyNames(); + all_api_commands_sorted.putAll(all_api_commands); + domain_admin_api_commands_sorted.putAll(domain_admin_api_commands); + regular_user_api_commands_sorted.putAll(regular_user_api_commands); try { //Create object writer XStream xs = new XStream(); xs.alias("command", Command.class); xs.alias("arg", Argument.class); + String xmlDocDir = dirName + "/xmldoc"; + String rootAdminDirName = xmlDocDir + "/root_admin"; + String domainAdminDirName = xmlDocDir + "/domain_admin"; + String regularUserDirName = xmlDocDir + "/regular_user"; + (new File(rootAdminDirName)).mkdirs(); + (new File(domainAdminDirName)).mkdirs(); + (new File(regularUserDirName)).mkdirs(); ObjectOutputStream out = xs.createObjectOutputStream(new FileWriter(dirName + "/commands.xml"), "commands"); + ObjectOutputStream rootAdmin = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "rootAdminSummary.xml"), "commands"); + ObjectOutputStream rootAdminSorted = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "rootAdminSummarySorted.xml"), "commands"); + ObjectOutputStream domainAdmin = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + "domainAdminSummary.xml"), "commands"); + ObjectOutputStream outDomainAdminSorted = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + "domainAdminSummarySorted.xml"), "commands"); + ObjectOutputStream regularUser = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/regularUserSummary.xml"), "commands"); + ObjectOutputStream regularUserSorted = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/regularUserSummarySorted.xml"), "commands"); - while (command.hasMoreElements()) { - String key = (String) command.nextElement(); - Class clas = Class.forName(api_commands.getProperty(key)); - ArrayList request = new ArrayList(); - ArrayList response = new ArrayList(); + //Write commands in the order they are represented in commands.properties.in file + Iterator it = all_api_commands.keySet().iterator(); + while (it.hasNext()) { + String key = (String)it.next(); - //Create a new command, set name and description - Command apiCommand = new Command(); - apiCommand.setName(key); + //Write admin commands + writeCommand(out, key); + writeCommand(rootAdmin, key); + + //Write single commands to separate xml files + ObjectOutputStream singleRootAdminCommandOs = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + key + ".xml"), "command"); + writeCommand(singleRootAdminCommandOs, key); + singleRootAdminCommandOs.close(); - - Implementation impl = (Implementation)clas.getAnnotation(Implementation.class); - if (impl == null) - impl = (Implementation)clas.getSuperclass().getAnnotation(Implementation.class); - String commandDescription = impl.description(); - if (commandDescription != null) - apiCommand.setDescription(commandDescription); - else - System.out.println("Command " + apiCommand.getName() + " misses description"); - - //Get request parameters - Field[] fields = clas.getDeclaredFields(); - - //Get fields from superclass - Class superClass = clas.getSuperclass(); - String superName = superClass.getName(); - if (!superName.equals(BaseCmd.class.getName()) && !superName.equals(BaseAsyncCmd.class.getName()) && !superName.equals(BaseAsyncCreateCmd.class.getName())) { - Field[] superClassFields = superClass.getDeclaredFields(); - if (superClassFields != null && !superClass.getName().equals(BaseListCmd.class.getName())) { - Field[] tmpFields = new Field[fields.length + superClassFields.length]; - System.arraycopy(fields, 0, tmpFields, 0, fields.length); - System.arraycopy(superClassFields, 0, tmpFields, fields.length, superClassFields.length); - fields = tmpFields; - } - superClass = superClass.getSuperclass(); - } - - for (Field f : fields) { - Parameter parameterAnnotation = f.getAnnotation(Parameter.class); - if (parameterAnnotation != null) { - Argument reqArg = new Argument(parameterAnnotation.name()); - reqArg.setRequired(parameterAnnotation.required()); - if (!parameterAnnotation.description().isEmpty() && parameterAnnotation.expose()) - reqArg.setDescription(parameterAnnotation.description()); - else if (parameterAnnotation.expose()) { - //System.out.println("Description is missing for the parameter " + parameterAnnotation.name() + " of the command " + apiCommand.getName() ); - } - request.add(reqArg); - } + if (domain_admin_api_commands.containsKey(key)){ + writeCommand(domainAdmin, key); + ObjectOutputStream singleDomainAdminCommandOs = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + key + ".xml"), "command"); + writeCommand(singleDomainAdminCommandOs, key); + singleDomainAdminCommandOs.close(); } - - Class responseClas = impl.responseObject(); - //Get response parameters - Field[] responseFields = responseClas.getDeclaredFields(); - for (Field responseField : responseFields) { - SerializedName nameAnnotation = responseField.getAnnotation(SerializedName.class); - Param descAnnotation = responseField.getAnnotation(Param.class); - Argument respArg = new Argument(nameAnnotation.value()); - if (descAnnotation != null) - respArg.setDescription(descAnnotation.description()); - response.add(respArg); + if (regular_user_api_commands.containsKey(key)){ + writeCommand(regularUser, key); + ObjectOutputStream singleRegularUserCommandOs = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/" + key + ".xml"), "command"); + writeCommand(singleRegularUserCommandOs, key); + singleRegularUserCommandOs.close(); } - - apiCommand.setRequest(request); - apiCommand.setResponse(response); - commands.add(apiCommand); - - //Write command to xml file - out.writeObject(apiCommand); } + + //Write sorted commands + it = all_api_commands_sorted.keySet().iterator(); + while (it.hasNext()) { + String key = (String)it.next(); + writeCommand(rootAdminSorted, key); + + + if (domain_admin_api_commands.containsKey(key)){ + writeCommand(outDomainAdminSorted, key); + } + + if (regular_user_api_commands.containsKey(key)){ + writeCommand(regularUserSorted, key); + } + } + out.close(); + rootAdmin.close(); + rootAdminSorted.close(); + domainAdmin.close(); + outDomainAdminSorted.close(); + regularUser.close(); + regularUserSorted.close(); + + //gzip directory with xml doc + zipDir(dirName + "xmldoc.zip", xmlDocDir); + + //Delete directory + deleteDir(new File(xmlDocDir)); + } catch (Exception ex) { ex.printStackTrace(); System.exit(2); - } + } } + + + private static void writeCommand(ObjectOutputStream out, String command) throws ClassNotFoundException, IOException{ + Class clas = Class.forName(all_api_commands.get(command)); + ArrayList request = new ArrayList(); + ArrayList response = new ArrayList(); + + //Create a new command, set name and description + Command apiCommand = new Command(); + apiCommand.setName(command); + + Implementation impl = (Implementation)clas.getAnnotation(Implementation.class); + if (impl == null) + impl = (Implementation)clas.getSuperclass().getAnnotation(Implementation.class); + String commandDescription = impl.description(); + if (commandDescription != null) + apiCommand.setDescription(commandDescription); + else + System.out.println("Command " + apiCommand.getName() + " misses description"); + + //Set request parameters + Field[] fields = clas.getDeclaredFields(); + + //Get fields from superclass + Class superClass = clas.getSuperclass(); + String superName = superClass.getName(); + if (!superName.equals(BaseCmd.class.getName()) && !superName.equals(BaseAsyncCmd.class.getName()) && !superName.equals(BaseAsyncCreateCmd.class.getName())) { + Field[] superClassFields = superClass.getDeclaredFields(); + if (superClassFields != null && !superClass.getName().equals(BaseListCmd.class.getName())) { + Field[] tmpFields = new Field[fields.length + superClassFields.length]; + System.arraycopy(fields, 0, tmpFields, 0, fields.length); + System.arraycopy(superClassFields, 0, tmpFields, fields.length, superClassFields.length); + fields = tmpFields; + } + superClass = superClass.getSuperclass(); + } + request = setRequestFields(fields); + + + //Get response parameters + Class responseClas = impl.responseObject(); + Field[] responseFields = responseClas.getDeclaredFields(); + response = setResponseFields(responseFields); + + apiCommand.setRequest(request); + apiCommand.setResponse(response); + + out.writeObject(apiCommand); + } + + + private static ArrayList setRequestFields(Field[] fields) { + ArrayList arguments = new ArrayList(); + for (Field f : fields) { + Parameter parameterAnnotation = f.getAnnotation(Parameter.class); + if (parameterAnnotation != null && parameterAnnotation.expose()) { + Argument reqArg = new Argument(parameterAnnotation.name()); + reqArg.setRequired(parameterAnnotation.required()); + if (!parameterAnnotation.description().isEmpty()) { + reqArg.setDescription(parameterAnnotation.description()); + } + arguments.add(reqArg); + } + } + return arguments; + } + + private static ArrayList setResponseFields(Field[] responseFields) { + ArrayList arguments = new ArrayList(); + for (Field responseField : responseFields) { + SerializedName nameAnnotation = responseField.getAnnotation(SerializedName.class); + Param paramAnnotation = responseField.getAnnotation(Param.class); + Argument respArg = new Argument(nameAnnotation.value()); + boolean toExpose = true; + if (paramAnnotation != null) { + String description = paramAnnotation.description(); + Class fieldClass = paramAnnotation.responseObject(); + toExpose = paramAnnotation.expose(); + if (description != null && !description.isEmpty()) { + respArg.setDescription(description); + } + + if (fieldClass != null) { + Class superClass = fieldClass.getSuperclass(); + if (superClass != null) { + String superName = superClass.getName(); + if (superName.equals(BaseResponse.class.getName())) { + ArrayList fieldArguments = new ArrayList(); + Field[] fields = fieldClass.getDeclaredFields(); + fieldArguments = setResponseFields(fields); + respArg.setArguments(fieldArguments); + } + } + } + } + + if (toExpose) { + arguments.add(respArg); + } + + + } + return arguments; + } + + private static void zipDir(String zipFileName, String dir) throws Exception { + File dirObj = new File(dir); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName)); + addDir(dirObj, out); + out.close(); + } + + static void addDir(File dirObj, ZipOutputStream out) throws IOException { + File[] files = dirObj.listFiles(); + byte[] tmpBuf = new byte[1024]; + String pathToDir = dirName; + + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + addDir(files[i], out); + continue; + } + FileInputStream in = new FileInputStream(files[i].getPath()); + out.putNextEntry(new ZipEntry(files[i].getPath().substring(pathToDir.length()))); + int len; + while ((len = in.read(tmpBuf)) > 0) { + out.write(tmpBuf, 0, len); + } + out.closeEntry(); + in.close(); + } + } + + private static void deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i=0; i keys = new LinkedList(); + + public Enumeration keys() { + return Collections.enumeration(keys); + } + + public Object put(Object key, Object value) { + //System.out.println("Adding key" + key); + keys.add(key); + return super.put(key, value); + } + } + } \ No newline at end of file diff --git a/server/src/com/cloud/api/doc/Argument.java b/server/src/com/cloud/api/doc/Argument.java index c3927842c2b..2846bb550b4 100644 --- a/server/src/com/cloud/api/doc/Argument.java +++ b/server/src/com/cloud/api/doc/Argument.java @@ -18,10 +18,13 @@ package com.cloud.api.doc; +import java.util.List; + public class Argument{ private String name; private String description; private Boolean required; + private List arguments; public Argument(String name) { this.name = name; @@ -45,5 +48,12 @@ public class Argument{ public void setRequired(Boolean required) { this.required = required; } - + + public List getArguments() { + return arguments; + } + + public void setArguments(List arguments) { + this.arguments = arguments; + } } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java old mode 100644 new mode 100755 index 57cfce0d2a8..5ef73d33490 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -60,6 +60,7 @@ public enum Config { NetworkThrottlingRate("Network", ManagementServer.class, Integer.class, "network.throttling.rate", "200", "Default data transfer rate in megabits per second allowed.", null), GuestDomainSuffix("Network", AgentManager.class, String.class, "guest.domain.suffix", "cloud-test.cloud.internal", "Default domain name for vms inside virtualized networks fronted by router", null), DirectNetworkNoDefaultRoute("Network", ManagementServer.class, Boolean.class, "direct.network.no.default.route", "false", "Direct Network Dhcp Server should not send a default route", "true/false"), + OvsNetwork("Network", ManagementServer.class, Boolean.class, "open.vswitch.network", "false", "enable/disable open vswitch network", null), //VPN RemoteAccessVpnPskLength("Network", AgentManager.class, Integer.class, "remote.access.vpn.psk.length", "24", "The length of the ipsec preshared key (minimum 8, maximum 256)", null), @@ -120,6 +121,7 @@ public enum Config { ExpungeDelay("Advanced", UserVmManager.class, Integer.class, "expunge.delay", "86400", "Determines how long to wait before actually expunging destroyed vm. The default value = the default value of expunge.interval", null), ExpungeInterval("Advanced", UserVmManager.class, Integer.class, "expunge.interval", "86400", "The interval to wait before running the expunge thread.", null), ExpungeWorkers("Advanced", UserVmManager.class, Integer.class, "expunge.workers", "1", "Number of workers performing expunge ", null), + ExtractURLCleanUpInterval("Advanced", ManagementServer.class, Integer.class, "extract.url.cleanup.interval", "120", "The interval to wait before cleaning up the extract URL's ", null), HostStatsInterval("Advanced", ManagementServer.class, Integer.class, "host.stats.interval", "60000", "The interval in milliseconds when host stats are retrieved from agents.", null), HostRetry("Advanced", AgentManager.class, Integer.class, "host.retry", "2", "Number of times to retry hosts for creating a volume", null), IntegrationAPIPort("Advanced", ManagementServer.class, Integer.class, "integration.api.port", "8096", "Defaul API port", null), @@ -154,7 +156,7 @@ public enum Config { MaxTemplateAndIsoSize("Advanced", ManagementServer.class, Long.class, "max.template.iso.size", "50", "The maximum size for a downloaded template or ISO (in GB).", null), SecStorageAllowedInternalDownloadSites("Advanced", ManagementServer.class, String.class, "secstorage.allowed.internal.sites", null, "Comma separated list of cidrs internal to the datacenter that can host template download servers", null), SecStorageEncryptCopy("Advanced", ManagementServer.class, Boolean.class, "secstorage.encrypt.copy", "false", "Use SSL method used to encrypt copy traffic between zones", "true,false"), - SecStorageSecureCopyCert("Advanced", ManagementServer.class, Boolean.class, "secstorage.ssl.cert.domain", "realhostip.com", "SSL certificate used to encrypt copy traffic between zones", "realhostip.com"), + SecStorageSecureCopyCert("Advanced", ManagementServer.class, String.class, "secstorage.ssl.cert.domain", "realhostip.com", "SSL certificate used to encrypt copy traffic between zones", null), DirectAttachSecurityGroupsEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.security.groups.enabled", "false", "Ec2-style distributed firewall for direct-attach VMs", "true,false"), DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled", "false", "Direct-attach VMs using external DHCP server", "true,false"), DirectAttachNetworkExternalAPIURL("Advanced", ManagementServer.class, String.class, "direct.attach.network.externalIpAllocator.url", null, "Direct-attach VMs using external DHCP server (API url)", null), @@ -212,7 +214,13 @@ public enum Config { SSOKey("Hidden", ManagementServer.class, String.class, "security.singlesignon.key", null, "A Single Sign-On key used for logging into the cloud", null), SSOAuthTolerance("Advanced", ManagementServer.class, Long.class, "security.singlesignon.tolerance.millis", "300000", "The allowable clock difference in milliseconds between when an SSO login request is made and when it is received.", null), //NetworkType("Hidden", ManagementServer.class, String.class, "network.type", "vlan", "The type of network that this deployment will use.", "vlan,direct"), - HashKey("Hidden", ManagementServer.class, String.class, "security.hash.key", null, "for generic key-ed hash", null); + HashKey("Hidden", ManagementServer.class, String.class, "security.hash.key", null, "for generic key-ed hash", null), + + VmOpWaitInterval("Advanced", ManagementServer.class, Integer.class, "vm.op.wait.interval", "120", "Seconds to wait before checking if a previous operation has succeeded", null), + VmOpLockStateRetry("Advanced", ManagementServer.class, Integer.class, "vm.op.lock.state.retry", "5", "Times to retry locking the state of a VM for operations", "-1 means try forever"), + VmOpCleanupInterval("Advanced", ManagementServer.class, Long.class, "vm.op.cleanup.interval", "86400", "Interval to run the thread that cleans up the vm operations in seconds", "Seconds"), + VmOpCleanupWait("Advanced", ManagementServer.class, Long.class, "vm.op.cleanup.wait", "3600", "Seconds to wait before cleanuping up any vm work items", "Seconds"), + VmOpCancelInterval("Advanced", ManagementServer.class, Long.class, "vm.op.cancel.interval", "3600", "Seconds to wait before cancelling a operation", "Seconds"); private final String _category; private final Class _componentClass; diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index a9b254436d6..a9163cbeb63 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -29,10 +29,9 @@ import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.DiskOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offering.NetworkOffering.Availability; import com.cloud.offering.ServiceOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.service.ServiceOfferingVO; @@ -172,15 +171,14 @@ public interface ConfigurationManager extends Manager { * Creates a new network offering * @param name * @param displayText - * @param type * @param trafficType * @param tags * @param maxConnections * @param id - * @param specifyVlan; + * @param specifyVlan; * @return network offering object */ - NetworkOfferingVO createNetworkOffering(long userId, String name, String displayText, GuestIpType type, TrafficType trafficType, String tags, Integer maxConnections, boolean specifyVlan, Availability availability); + NetworkOfferingVO createNetworkOffering(long userId, String name, String displayText, TrafficType trafficType, String tags, Integer maxConnections, boolean specifyVlan, Availability availability); Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; @@ -188,4 +186,5 @@ public interface ConfigurationManager extends Manager { Long saveConfigurationEvent(long userId, Long accountId, String type, String description, String... paramsList); + DataCenterVO getZone(long id); } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 67bc0fcd483..b666a28da25 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -91,16 +91,17 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IPAddressVO; +import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offering.NetworkOffering.Availability; import com.cloud.offering.ServiceOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; @@ -285,7 +286,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (type.equals(Boolean.class)) { if (!(value.equals("true") || value.equals("false"))) { s_logger.error("Configuration variable " + name + " is expecting true or false in stead of " + value); - return "Please enter either \"true\" or \"false\"."; + return "Please enter either 'true' or 'false'."; } return null; } @@ -523,7 +524,15 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (!(_LinkLocalIpAllocDao.deleteIpAddressByPod(podId))) { throw new CloudRuntimeException("Failed to cleanup private ip addresses for pod " + podId); } - + + //Delete vlans associated with the pod + List vlans = _networkMgr.listPodVlans(podId); + if (vlans != null && !vlans.isEmpty()) { + for (Vlan vlan: vlans) { + _vlanDao.remove(vlan.getId()); + } + } + //Delete the pod if (!(_podDao.expunge(podId))) { throw new CloudRuntimeException("Failed to delete pod " + podId); @@ -1207,36 +1216,29 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Account systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); BroadcastDomainType broadcastDomainType = null; - if (offering.getGuestIpType() != GuestIpType.DirectPodBased) { - if (offering.getTrafficType() == TrafficType.Management) { - broadcastDomainType = BroadcastDomainType.Native; - } else if (offering.getTrafficType() == TrafficType.Public) { + boolean isNetworkDefault = false; + if (offering.getTrafficType() == TrafficType.Management) { + broadcastDomainType = BroadcastDomainType.Native; + } else if (offering.getTrafficType() == TrafficType.Control) { + broadcastDomainType = BroadcastDomainType.LinkLocal; + } else if (offering.getTrafficType() == TrafficType.Public) { + if (zone.getNetworkType() == NetworkType.Advanced) { broadcastDomainType = BroadcastDomainType.Vlan; - } else if (offering.getTrafficType() == TrafficType.Control) { - broadcastDomainType = BroadcastDomainType.LinkLocal; - } - userNetwork.setBroadcastDomainType(broadcastDomainType); - _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, true); - } + } else { + continue; + } + } else if (offering.getTrafficType() == TrafficType.Guest) { + if (zone.getNetworkType() == NetworkType.Basic) { + isNetworkDefault = true; + broadcastDomainType = BroadcastDomainType.Native; + } else { + continue; + } + } + userNetwork.setBroadcastDomainType(broadcastDomainType); + _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, true, isNetworkDefault); } } - - //if zone is basic, create a untagged network - if (zone != null && zone.getNetworkType() == NetworkType.Basic) { - //Create network - DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null); - NetworkVO userNetwork = new NetworkVO(); - userNetwork.setBroadcastDomainType(BroadcastDomainType.Native); - - Account systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); - - List networkOffering = _networkOfferingDao.findByType(GuestIpType.DirectPodBased); - if (networkOffering == null || networkOffering.isEmpty()) { - throw new CloudRuntimeException("No default DirectPodBased network offering is found"); - } - - _networkMgr.setupNetwork(systemAccount, networkOffering.get(0), userNetwork, plan, null, null, true); - } } @Override @@ -1361,7 +1363,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr)); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); - NetworkOffering.GuestIpType guestIpType = useVirtualNetwork ? NetworkOffering.GuestIpType.Virtual : NetworkOffering.GuestIpType.Direct; + Network.GuestIpType guestIpType = useVirtualNetwork ? Network.GuestIpType.Virtual : Network.GuestIpType.Direct; tags = cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, multicastRate, offerHA, displayText, guestIpType, localStorageRequired, false, tags, false,domainId); @@ -1443,7 +1445,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (_serviceOfferingDao.update(id, offering)) { offering = _serviceOfferingDao.findById(id); saveConfigurationEvent(userId, null, EventTypes.EVENT_SERVICE_OFFERING_EDIT, "Successfully updated service offering with name: " + offering.getName() + ".", "soId=" + offering.getId(), "name=" + offering.getName(), - "displayText=" + offering.getDisplayText(), "offerHA=" + offering.getOfferHA(), "useVirtualNetwork=" + (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtual), "tags=" + offering.getTags(), "domainId=" + offering.getDomainId()); + "displayText=" + offering.getDisplayText(), "offerHA=" + offering.getOfferHA(), "useVirtualNetwork=" + (offering.getGuestIpType() == Network.GuestIpType.Virtual), "tags=" + offering.getTags(), "domainId=" + offering.getDomainId()); return offering; } else { return null; @@ -1661,14 +1663,14 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (forVirtualNetwork){ if (network == null) { //find default public network in the zone - networkId = _networkMgr.getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(zoneId, TrafficType.Public, null); + networkId = _networkMgr.getSystemNetworkByZoneAndTrafficType(zoneId, TrafficType.Public).getId(); } else if (network.getGuestType() != null || network.getTrafficType() != TrafficType.Public){ throw new InvalidParameterValueException("Can't find Public network by id=" + networkId); } } else { if (network == null) { if (zone.getNetworkType() == DataCenter.NetworkType.Basic) { - networkId = _networkMgr.getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(zoneId, TrafficType.Public, GuestIpType.DirectPodBased); + networkId = _networkMgr.getSystemNetworkByZoneAndTrafficType(zoneId, TrafficType.Guest).getId(); } else { throw new InvalidParameterValueException("Nework id is required for Direct vlan creation "); } @@ -1690,11 +1692,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura //check if startIp and endIp belong to network Cidr String networkCidr = network.getCidr(); String networkGateway = network.getGateway(); - Long networkZoneId = network.getDataCenterId(); - String[] splitResult = networkCidr.split("\\/"); - long size = Long.valueOf(splitResult[1]); - String networkNetmask = NetUtils.getCidrNetmask(size); + String networkNetmask = NetUtils.getCidrNetmask(networkCidr); //Check if ip addresses are in network range if (!NetUtils.sameSubnet(startIP, networkGateway, networkNetmask)) { @@ -1732,7 +1731,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Please specify a valid pod."); } - if (podId != null && _podDao.findById(podId).getDataCenterId() != zoneId) { throw new InvalidParameterValueException("Pod id=" + podId + " doesn't belong to zone id=" + zoneId); } @@ -1766,7 +1764,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if(hypervisorType.equalsIgnoreCase("xenserver")) { //check for the vlan being added before going to db, to see if it is untagged - if(vlanType.toString().equalsIgnoreCase("VirtualNetwork") && vlanId.equalsIgnoreCase("untagged")) + if(vlanType.toString().equalsIgnoreCase("VirtualNetwork") && vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { if(_configDao.getValue("xen.public.network.device") == null || _configDao.getValue("xen.public.network.device").equals("")) { @@ -1787,13 +1785,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } - - -// //check if the account's domain is a child of the zone's domain, for adding vlan ip ranges -// if(domainId != null && !_domainDao.isChildDomain(zone.getDomainId(), domainId)){ -// //this is for account specific case, as domainId != null -// throw new PermissionDeniedException("The account associated with specific domain id:"+domainId+" doesn't have permissions to add vlan ip ranges for the zone:"+zone.getId()); -// } //ACL check checkAccess(account, zone); @@ -1922,6 +1913,19 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for the guest network in zone " + zone.getName()); } + //For untagged vlan check if vlan per pod already exists. If yes, verify that new vlan range has the same netmask and gateway + if (zone.getNetworkType() == NetworkType.Basic && vlanId.equalsIgnoreCase(Vlan.UNTAGGED) && podId != null){ + List podVlans = _vlanDao.listVlansForPodByType(podId, VlanType.DirectAttached); + if (podVlans != null && !podVlans.isEmpty()) { + VlanVO podVlan = podVlans.get(0); + if (!podVlan.getVlanNetmask().equals(vlanNetmask)) { + throw new InvalidParameterValueException("Vlan netmask is different from the netmask of Untagged vlan id=" + podVlan.getId() + " existing in the pod " + podId); + } else if (!podVlan.getVlanGateway().equals(vlanGateway)) { + throw new InvalidParameterValueException("Vlan gateway is different from the gateway of Untagged vlan id=" + podVlan.getId() + " existing in the pod " + podId); + } + } + } + // Everything was fine, so persist the VLAN String ipRange = startIP; if (endIP != null) { @@ -2678,13 +2682,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura String name = cmd.getNetworkOfferingName(); String displayText = cmd.getDisplayText(); String tags = cmd.getTags(); - String typeString = cmd.getType(); String trafficTypeString = cmd.getTraffictype(); Boolean specifyVlan = cmd.getSpecifyVlan(); String availabilityStr = cmd.getAvailability(); TrafficType trafficType = null; - GuestIpType type = null; Availability availability = null; @@ -2698,16 +2700,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Invalid value for traffictype. Supported traffic types: Public, Management, Control, Guest, Vlan or Storage"); } - //Verify type - for (GuestIpType gType : GuestIpType.values()) { - if (gType.name().equalsIgnoreCase(typeString)) { - type = gType; - } - } - if (type == null || type == GuestIpType.DirectPodBased) { - throw new InvalidParameterValueException("Invalid value for type. Supported types: Virtual, Direct"); - } - //Verify availability for (Availability avlb : Availability.values()) { if (avlb.name().equalsIgnoreCase(availabilityStr)) { @@ -2720,17 +2712,17 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } Integer maxConnections = cmd.getMaxconnections(); - return createNetworkOffering(userId, name, displayText, type, trafficType, tags, maxConnections, specifyVlan, availability); + return createNetworkOffering(userId, name, displayText, trafficType, tags, maxConnections, specifyVlan, availability); } @Override - public NetworkOfferingVO createNetworkOffering(long userId, String name, String displayText, GuestIpType type, TrafficType trafficType, String tags, Integer maxConnections, boolean specifyVlan, Availability availability) { + public NetworkOfferingVO createNetworkOffering(long userId, String name, String displayText, TrafficType trafficType, String tags, Integer maxConnections, boolean specifyVlan, Availability availability) { String networkRateStr = _configDao.getValue("network.throttling.rate"); String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr)); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); tags = cleanupTags(tags); - NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, type, false, specifyVlan, networkRate, multicastRate, maxConnections, false, availability, false, false, false, false, false, false, false); + NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, false, specifyVlan, networkRate, multicastRate, maxConnections, false, availability, false, false, false, false, false, false, false); if ((offering = _networkOfferingDao.persist(offering)) != null) { saveConfigurationEvent(userId, null, EventTypes.EVENT_NETWORK_OFFERING_CREATE, "Successfully created new network offering with name: " + name + ".", "noId=" + offering.getId(), "name=" + name, @@ -2749,7 +2741,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Object id = cmd.getId(); Object name = cmd.getNetworkOfferingName(); Object displayText = cmd.getDisplayText(); - Object type = cmd.getType(); Object trafficType = cmd.getTrafficType(); Object isDefault = cmd.getIsDefault(); Object specifyVlan = cmd.getSpecifyVlan(); @@ -2775,9 +2766,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (displayText != null) { sc.addAnd("displayText", SearchCriteria.Op.LIKE, "%" + displayText + "%"); } - if (type != null) { - sc.addAnd("guestIpType", SearchCriteria.Op.EQ, type); - } if (trafficType != null) { sc.addAnd("trafficType", SearchCriteria.Op.EQ, trafficType); @@ -2896,4 +2884,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } } + + @Override + public DataCenterVO getZone(long id){ + return _zoneDao.findById(id); + } } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index 7d79725d1c1..6ba6c5edf5c 100644 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -72,6 +72,12 @@ import com.cloud.network.dao.NetworkRuleConfigDaoImpl; import com.cloud.network.dao.RemoteAccessVpnDaoImpl; import com.cloud.network.dao.VpnUserDaoImpl; import com.cloud.network.lb.LoadBalancingRulesManagerImpl; +import com.cloud.network.ovs.OvsNetworkManagerImpl; +import com.cloud.network.ovs.dao.GreTunnelDaoImpl; +import com.cloud.network.ovs.dao.OvsWorkDaoImpl; +import com.cloud.network.ovs.dao.VlanMappingDaoImpl; +import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl; +import com.cloud.network.ovs.dao.VmFlowLogDaoImpl; import com.cloud.network.router.VirtualNetworkApplianceManagerImpl; import com.cloud.network.rules.RulesManagerImpl; import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl; @@ -240,7 +246,11 @@ public class DefaultComponentLibrary implements ComponentLibrary { addDao("UsageEventDao", UsageEventDaoImpl.class); addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class); addDao("UserVmDetailsDao", UserVmDetailsDaoImpl.class); - + addDao("VlanMappingDao", VlanMappingDaoImpl.class); + addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class); + addDao("OvsWorkDao", OvsWorkDaoImpl.class); + addDao("VmFlowLogDao", VmFlowLogDaoImpl.class); + addDao("GreTunnelDao", GreTunnelDaoImpl.class); } Map> _managers = new HashMap>(); @@ -295,6 +305,7 @@ public class DefaultComponentLibrary implements ComponentLibrary { addManager("LoadBalancingRulesManager", LoadBalancingRulesManagerImpl.class); addManager("RulesManager", RulesManagerImpl.class); addManager("RemoteAccessVpnManager", RemoteAccessVpnManagerImpl.class); + addManager("OvsNetworkManager", OvsNetworkManagerImpl.class); } protected List> addAdapterChain(Class interphace, List>> adapters) { @@ -339,4 +350,5 @@ public class DefaultComponentLibrary implements ComponentLibrary { factories.put(EntityManager.class, EntityManagerImpl.class); return factories; } + } diff --git a/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java new file mode 100644 index 00000000000..846f8d0533b --- /dev/null +++ b/server/src/com/cloud/configuration/DefaultInterceptorLibrary.java @@ -0,0 +1,32 @@ +/** + * Copyright (C) 2010 Cloud.com, 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 . + * + */ +package com.cloud.configuration; + +import java.util.List; + +import com.cloud.utils.component.AnnotationInterceptor; +import com.cloud.utils.component.InterceptorLibrary; +import com.cloud.utils.db.DatabaseCallback; + +public class DefaultInterceptorLibrary implements InterceptorLibrary { + + @Override + public void addInterceptors(List> interceptors) { + interceptors.add(new DatabaseCallback()); + } +} diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index c953144543c..e77fec8d2e4 100644 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -91,7 +91,7 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu return -1; } GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getName())); - return answer == null ? -1 : answer.getPort(); + return (answer == null || !answer.getResult()) ? -1 : answer.getPort(); } @Override diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 0f248e55ae4..4e3ad207872 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -72,6 +72,8 @@ import com.cloud.certificate.dao.CertificateDao; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.DataCenterDao; @@ -102,11 +104,11 @@ import com.cloud.info.RunningHostInfoAgregator; import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.maid.StackMaid; import com.cloud.network.IpAddrAllocator; +import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.NetworkDao; -import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.service.ServiceOfferingVO; @@ -560,7 +562,10 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); Account systemAcct = _accountMgr.getSystemAccount(); User systemUser = _accountMgr.getSystemUser(); - return _itMgr.start(proxy, null, systemUser, systemAcct, null); + if (proxy.getState() == VirtualMachine.State.Running) { + return proxy; + } + return _itMgr.start(proxy, null, systemUser, systemAcct); } public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) { @@ -697,17 +702,21 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); - List defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmPublicNetwork); - List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork); + List defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork); + if (dc.getNetworkType() == NetworkType.Basic) { + defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SysteGuestNetwork); + } + + List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork); List> networks = new ArrayList>(offerings.size() + 1); NicProfile defaultNic = new NicProfile(); defaultNic.setDefaultNic(true); defaultNic.setDeviceId(2); - networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false).get(0), defaultNic)); + networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false, false).get(0), defaultNic)); for (NetworkOfferingVO offering : offerings) { - networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false).get(0), null)); + networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false, false).get(0), null)); } - ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), 0); + ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getHypervisorType(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), 0); try { proxy = _itMgr.allocate(proxy, _template, _serviceOffering, networks, plan, null, systemAcct); } catch (InsufficientCapacityException e) { @@ -1525,7 +1534,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx final RebootCommand cmd = new RebootCommand(proxy.getInstanceName()); final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd); - if (answer != null) { + if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully reboot console proxy " + proxy.getName()); } @@ -1551,64 +1560,13 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx } @Override - @DB public boolean destroyProxy(long vmId) { - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId()); - } - _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId); - } - - ConsoleProxyVO vm = _consoleProxyDao.findById(vmId); - if (vm == null || vm.getState() == State.Destroyed) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find vm or vm is destroyed: " + vmId); - } - return true; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Destroying console proxy vm " + vmId); - } - - if (!_itMgr.stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, null)) { - s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId); - return false; - } - - Transaction txn = Transaction.currentTxn(); - List vols = null; + ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId); try { - vols = _volsDao.findByInstance(vmId); - if (vols.size() != 0) { - _storageMgr.destroy(vm, vols); - } - - return true; - } finally { - try { - txn.start(); - // release critical system resources used by the VM before we - // delete them - if (vm.getPublicIpAddress() != null) { -// freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId()); - } - vm.setPublicIpAddress(null); - - _consoleProxyDao.remove(vm.getId()); - - txn.commit(); - } catch (Exception e) { - s_logger.error("Caught this error: ", e); - txn.rollback(); - return false; - } finally { - s_logger.debug("console proxy vm is destroyed : " + vm.getName()); - } + return _itMgr.expunge(proxy, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + } catch (ResourceUnavailableException e) { + s_logger.warn("Unable to expunge " + proxy, e); + return false; } } @@ -1702,7 +1660,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false); Answer answer = _agentMgr.easySend(fromHost.getId(), cmd); - if (answer == null) { + if (answer == null || !answer.getResult()) { return false; } @@ -1905,7 +1863,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key())); - _serviceOffering = new ServiceOfferingVO("System Offering For Console Proxy", 1, _proxyRamSize, 0, 0, 0, true, null, NetworkOffering.GuestIpType.Virtual, + _serviceOffering = new ServiceOfferingVO("System Offering For Console Proxy", 1, _proxyRamSize, 0, 0, 0, true, null, Network.GuestIpType.Virtual, useLocalStorage, true, null, true); _serviceOffering.setUniqueName("Cloud.com-ConsoleProxy"); _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); @@ -2020,10 +1978,11 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx cmds.addCommand("checkSsh", check); ConsoleProxyVO proxy = profile.getVirtualMachine(); + DataCenter dc = dest.getDataCenter(); List nics = _nicDao.listBy(proxy.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); - if (network.getTrafficType() == TrafficType.Public) { + if ((network.getTrafficType() == TrafficType.Public && dc.getNetworkType() == NetworkType.Advanced) || (network.getTrafficType() == TrafficType.Guest && dc.getNetworkType() == NetworkType.Basic)) { proxy.setPublicIpAddress(nic.getIp4Address()); proxy.setPublicNetmask(nic.getNetmask()); proxy.setPublicMacAddress(nic.getMacAddress()); diff --git a/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java b/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java index 38728608fb6..4dd5ce8582d 100644 --- a/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java +++ b/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java @@ -58,10 +58,10 @@ public class DataCenterDaoImpl extends GenericDaoBase implem protected SearchBuilder PublicZonesSearch; protected SearchBuilder ChildZonesSearch; - protected static final DataCenterIpAddressDaoImpl _ipAllocDao = ComponentLocator.inject(DataCenterIpAddressDaoImpl.class); - protected static final DataCenterLinkLocalIpAddressDaoImpl _LinkLocalIpAllocDao = ComponentLocator.inject(DataCenterLinkLocalIpAddressDaoImpl.class); - protected static final DataCenterVnetDaoImpl _vnetAllocDao = ComponentLocator.inject(DataCenterVnetDaoImpl.class); - protected static final PodVlanDaoImpl _podVlanAllocDao = ComponentLocator.inject(PodVlanDaoImpl.class); + protected final DataCenterIpAddressDaoImpl _ipAllocDao = ComponentLocator.inject(DataCenterIpAddressDaoImpl.class); + protected final DataCenterLinkLocalIpAddressDaoImpl _LinkLocalIpAllocDao = ComponentLocator.inject(DataCenterLinkLocalIpAddressDaoImpl.class); + protected final DataCenterVnetDaoImpl _vnetAllocDao = ComponentLocator.inject(DataCenterVnetDaoImpl.class); + protected final PodVlanDaoImpl _podVlanAllocDao = ComponentLocator.inject(PodVlanDaoImpl.class); protected long _prefix; protected Random _rand = new Random(System.currentTimeMillis()); protected TableGenerator _tgMacAddress; diff --git a/server/src/com/cloud/dc/dao/VlanDao.java b/server/src/com/cloud/dc/dao/VlanDao.java index a0bf95e7067..c4c028b1f74 100644 --- a/server/src/com/cloud/dc/dao/VlanDao.java +++ b/server/src/com/cloud/dc/dao/VlanDao.java @@ -40,13 +40,9 @@ public interface VlanDao extends GenericDao { List listVlansForPodByType(long podId, Vlan.VlanType vlanType); void addToPod(long podId, long vlanDbId); - -// Pair assignIpAddress(long zoneId, long accountId, long domainId, VlanType vlanType, boolean sourceNat); List listVlansForAccountByType(Long zoneId, long accountId, VlanType vlanType); -// Pair assignPodDirectAttachIpAddress(long zoneId, long podId, long accountId, long domainId); - boolean zoneHasDirectAttachUntaggedVlans(long zoneId); List listZoneWideVlans(long zoneId, VlanType vlanType, String vlanId); diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index b6622300529..9a49ca11c0f 100644 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -381,8 +381,10 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao if( event.equals(Event.Ping) || event.equals(Event.AgentConnected)) { ub.set(host, _pingTimeAttr, System.currentTimeMillis() >> 10); } + } + if ( event.equals(Event.ManagementServerDown)) { + ub.set(host, _pingTimeAttr, (( System.currentTimeMillis() >> 10) - ( 10 * 60 ))); } - int result = update(ub, sc, null); assert result <= 1 : "How can this update " + result + " rows? "; diff --git a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 0907ade3a7c..a1d30d5ff16 100644 --- a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -148,8 +148,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L Pool pool = pools.iterator().next(); Pool.Record pr = pool.getRecord(conn); String poolUuid = pr.uuid; - Host master = pr.master; - Map thosts = Host.getAllRecords(conn); + Map hosts = Host.getAllRecords(conn); /*set cluster hypervisor type to xenserver*/ ClusterVO clu = _clusterDao.findById(clusterId); @@ -157,7 +156,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L clu.setGuid(poolUuid); } else { if( !clu.getGuid().equals(poolUuid)) { - if (thosts.size() == 1 ) { + if (hosts.size() == 1 ) { if( !addHostsToPool(conn, hostIp, clusterId)){ String msg = "Unable to add host(" + hostIp + ") to cluster " + clusterId; s_logger.warn(msg); @@ -170,17 +169,20 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } } } + // can not use this conn after this point, because this host may join a pool, this conn is retired + if (conn != null) { + try{ + Session.logout(conn); + } catch (Exception e ) { + } + conn.dispose(); + conn = null; + } + poolUuid = clu.getGuid(); _clusterDao.update(clusterId, clu); - LinkedHashMap hosts = new LinkedHashMap(20); - hosts.put(master, master.getRecord(conn)); - for (Map.Entry entry : thosts.entrySet()) { - if( !master.equals(entry.getKey()) ) { - hosts.put(entry.getKey(), entry.getValue()); - } - } - + if (_checkHvm) { for (Map.Entry entry : hosts.entrySet()) { Host.Record record = entry.getValue(); @@ -293,15 +295,6 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L s_logger.debug("other exceptions: " + e.toString(), e); return null; } - finally { - if (conn != null) { - try{ - Session.logout(conn); - } catch (Exception e ) { - } - conn.dispose(); - } - } return resources; } diff --git a/server/src/com/cloud/migration/Db20to21MigrationUtil.java b/server/src/com/cloud/migration/Db20to21MigrationUtil.java index d95036a9a7e..9d141fef251 100644 --- a/server/src/com/cloud/migration/Db20to21MigrationUtil.java +++ b/server/src/com/cloud/migration/Db20to21MigrationUtil.java @@ -38,7 +38,7 @@ import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.migration.DiskOffering21VO.Type; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePoolVO; import com.cloud.storage.Volume.VolumeType; @@ -306,7 +306,7 @@ public class Db20to21MigrationUtil { _configDao.getValue(Config.ConsoleProxyRamSize.key()), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE); ServiceOffering21VO soConsoleProxy = new ServiceOffering21VO("Fake Offering For DomP", 1, - proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, + proxyRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, useLocalStorage, true, null); soConsoleProxy.setId(seq++); soConsoleProxy.setUniqueName("Cloud.com-ConsoleProxy"); @@ -317,7 +317,7 @@ public class Db20to21MigrationUtil { _configDao.getValue(Config.SecStorageVmRamSize.key()), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE); ServiceOffering21VO soSecondaryVm = new ServiceOffering21VO("Fake Offering For Secondary Storage VM", 1, - secStorageVmRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, useLocalStorage, true, null); + secStorageVmRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, useLocalStorage, true, null); soSecondaryVm.setId(seq++); soSecondaryVm.setUniqueName("Cloud.com-SecondaryStorage"); soSecondaryVm = _serviceOffering21Dao.persist(soSecondaryVm); @@ -325,7 +325,7 @@ public class Db20to21MigrationUtil { int routerRamSize = NumbersUtil.parseInt(_configDao.getValue("router.ram.size"), 128); ServiceOffering21VO soDomainRouter = new ServiceOffering21VO("Fake Offering For DomR", 1, - routerRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, useLocalStorage, true, null); + routerRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, useLocalStorage, true, null); soDomainRouter.setId(seq++); soDomainRouter.setUniqueName("Cloud.Com-SoftwareRouter"); soDomainRouter = _serviceOffering21Dao.persist(soDomainRouter); diff --git a/server/src/com/cloud/migration/Db21to22MigrationUtil.java b/server/src/com/cloud/migration/Db21to22MigrationUtil.java index 78007068c3c..3216e28f3e3 100644 --- a/server/src/com/cloud/migration/Db21to22MigrationUtil.java +++ b/server/src/com/cloud/migration/Db21to22MigrationUtil.java @@ -1,7 +1,6 @@ package com.cloud.migration; import java.io.File; -import java.net.InetAddress; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.List; @@ -9,13 +8,12 @@ import java.util.List; import org.apache.log4j.xml.DOMConfigurator; import com.cloud.configuration.ResourceCount.ResourceType; -import com.cloud.configuration.ConfigurationVO; import com.cloud.configuration.ResourceCountVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceCountDao; import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.domain.DomainVO; @@ -28,7 +26,6 @@ import com.cloud.user.Account; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.ComponentLocator; -import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; diff --git a/server/src/com/cloud/migration/ServiceOffering20VO.java b/server/src/com/cloud/migration/ServiceOffering20VO.java index 7d31fbb7ede..60e8115b8fa 100644 --- a/server/src/com/cloud/migration/ServiceOffering20VO.java +++ b/server/src/com/cloud/migration/ServiceOffering20VO.java @@ -11,8 +11,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.network.Network; import com.cloud.utils.db.GenericDao; @Entity @@ -52,7 +51,7 @@ public class ServiceOffering20VO { @Column(name="guest_ip_type") @Enumerated(EnumType.STRING) - private NetworkOffering.GuestIpType guestIpType = NetworkOffering.GuestIpType.Virtual; + private Network.GuestIpType guestIpType = Network.GuestIpType.Virtual; @Column(name="use_local_storage") private boolean useLocalStorage; @@ -67,10 +66,10 @@ public class ServiceOffering20VO { } public ServiceOffering20VO(Long id, String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, boolean localStorageRequired) { - this(id, name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, displayText, NetworkOffering.GuestIpType.Virtual, localStorageRequired); + this(id, name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, displayText, Network.GuestIpType.Virtual, localStorageRequired); } - public ServiceOffering20VO(Long id, String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, NetworkOffering.GuestIpType guestIpType, boolean useLocalStorage) { + public ServiceOffering20VO(Long id, String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, Network.GuestIpType guestIpType, boolean useLocalStorage) { this.id = id; this.name = name; this.cpu = cpu; @@ -168,11 +167,11 @@ public class ServiceOffering20VO { return multicastRateMbps; } - public void setGuestIpType(NetworkOffering.GuestIpType guestIpType) { + public void setGuestIpType(Network.GuestIpType guestIpType) { this.guestIpType = guestIpType; } - public NetworkOffering.GuestIpType getGuestIpType() { + public Network.GuestIpType getGuestIpType() { return guestIpType; } diff --git a/server/src/com/cloud/migration/ServiceOffering21VO.java b/server/src/com/cloud/migration/ServiceOffering21VO.java index 95b4fee3584..12385fbf30f 100644 --- a/server/src/com/cloud/migration/ServiceOffering21VO.java +++ b/server/src/com/cloud/migration/ServiceOffering21VO.java @@ -9,7 +9,7 @@ import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import javax.persistence.Transient; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; import com.cloud.offering.ServiceOffering; @Entity @@ -37,13 +37,13 @@ public class ServiceOffering21VO extends DiskOffering21VO implements ServiceOffe @Column(name="guest_ip_type") @Enumerated(EnumType.STRING) - private NetworkOffering.GuestIpType guestIpType; + private Network.GuestIpType guestIpType; protected ServiceOffering21VO() { super(); } - public ServiceOffering21VO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, NetworkOffering.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags) { + public ServiceOffering21VO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, Network.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags) { super(name, displayText, false, tags, recreatable, useLocalStorage); this.cpu = cpu; this.ramSize = ramSize; @@ -119,12 +119,12 @@ public class ServiceOffering21VO extends DiskOffering21VO implements ServiceOffe return multicastRateMbps; } - public void setGuestIpType(NetworkOffering.GuestIpType guestIpType) { + public void setGuestIpType(Network.GuestIpType guestIpType) { this.guestIpType = guestIpType; } @Override - public NetworkOffering.GuestIpType getGuestIpType() { + public Network.GuestIpType getGuestIpType() { return guestIpType; } public String gethypervisorType() { diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index d4fa6f4b45d..37b1562a2be 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -20,6 +20,7 @@ package com.cloud.network; import java.util.List; import java.util.Map; +import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; @@ -31,11 +32,10 @@ import com.cloud.network.Network.Capability; import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; +import com.cloud.network.guru.NetworkGuru; import com.cloud.network.rules.FirewallRule; import com.cloud.network.vpn.RemoteAccessVpnElement; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.service.ServiceOfferingVO; import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.utils.Pair; @@ -59,13 +59,14 @@ public interface NetworkManager extends NetworkService { * Assigns a new public ip address. * * @param dcId + * @param podId TODO * @param owner * @param type * @param networkId * @return * @throws InsufficientAddressCapacityException */ - PublicIp assignPublicIpAddress(long dcId, Account owner, VlanType type, Long networkId) throws InsufficientAddressCapacityException; + PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId) throws InsufficientAddressCapacityException; /** * assigns a source nat ip address to an account within a network. @@ -107,8 +108,8 @@ public interface NetworkManager extends NetworkService { */ List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat); - List setupNetwork(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared) throws ConcurrentOperationException; - List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared) throws ConcurrentOperationException; + List setupNetwork(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault) throws ConcurrentOperationException; + List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault) throws ConcurrentOperationException; List getSystemAccountNetworkOfferings(String... offeringNames); @@ -119,27 +120,28 @@ public interface NetworkManager extends NetworkService { void cleanupNics(VirtualMachineProfile vm); - List getNics (VirtualMachine vm); + List getNics(VirtualMachine vm); List getAccountsUsingNetwork(long configurationId); AccountVO getNetworkOwner(long configurationId); List getNetworksforOffering(long offeringId, long dataCenterId, long accountId); - - List setupNetwork(Account owner, ServiceOfferingVO offering, DeploymentPlan plan) throws ConcurrentOperationException; - Network getNetwork(long id); String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException; boolean applyRules(List rules, boolean continueOnError) throws ResourceUnavailableException; Map> getZoneCapabilities(long zoneId); - long getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(long zoneId, TrafficType trafficType, GuestIpType guestType); + Network getSystemNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType); List getRemoteAccessVpnElements(); PublicIpAddress getPublicIpAddress(Ip ipAddress); - Network getBasicZoneDefaultPublicNetwork(long zoneId); + List listPodVlans(long podId); + + Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + List listNetworksUsedByVm(long vmId, boolean isSystem); + } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 1af653a815b..4100d407fcd 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -20,8 +20,6 @@ package com.cloud.network; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -36,14 +34,9 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import com.cloud.agent.AgentManager; -import com.cloud.agent.AgentManager.OnError; -import com.cloud.agent.api.Answer; import com.cloud.agent.api.to.NicTO; -import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.api.BaseCmd; -import com.cloud.api.ServerApiException; import com.cloud.api.commands.AssociateIPAddrCmd; import com.cloud.api.commands.CreateNetworkCmd; import com.cloud.api.commands.DisassociateIPAddrCmd; @@ -58,15 +51,18 @@ import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.PodVlanMapDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; +import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; import com.cloud.event.EventTypes; import com.cloud.event.EventUtils; @@ -75,47 +71,36 @@ import com.cloud.event.UsageEventVO; import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.AccountLimitException; -import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network.Capability; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.Service; import com.cloud.network.Networks.AddressFormat; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.RemoteAccessVpnDao; -import com.cloud.network.dao.VpnUserDao; import com.cloud.network.element.NetworkElement; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.lb.LoadBalancingRule; -import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRulesManager; -import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.RulesManager; -import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpn.RemoteAccessVpnElement; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offering.NetworkOffering.Availability; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.Resource; import com.cloud.resource.Resource.ReservationStrategy; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; @@ -149,6 +134,7 @@ import com.cloud.vm.ReservationContext; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; @@ -172,25 +158,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Inject UserVmDao _vmDao = null; @Inject ResourceLimitDao _limitDao = null; @Inject CapacityDao _capacityDao = null; - @Inject AgentManager _agentMgr; @Inject AlertManager _alertMgr; @Inject AccountManager _accountMgr; @Inject ConfigurationManager _configMgr; - @Inject ServiceOfferingDao _serviceOfferingDao = null; @Inject AccountVlanMapDao _accountVlanMapDao; - @Inject UserStatisticsDao _statsDao = null; @Inject NetworkOfferingDao _networkOfferingDao = null; @Inject NetworkDao _networksDao = null; @Inject NicDao _nicDao = null; - @Inject RemoteAccessVpnDao _remoteAccessVpnDao = null; - @Inject VpnUserDao _vpnUsersDao = null; - @Inject VirtualNetworkApplianceManager _routerMgr; @Inject RulesManager _rulesMgr; @Inject LoadBalancingRulesManager _lbMgr; - @Inject FirewallRulesDao _firewallRulesDao; - @Inject LoadBalancerDao _lbDao; - @Inject PortForwardingRulesDao _pfRulesDao; @Inject UsageEventDao _usageEventDao; + @Inject PodVlanMapDao _podVlanMapDao; @Inject(adapter=NetworkGuru.class) Adapters _networkGurus; @@ -203,7 +181,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag SearchBuilder AccountsUsingNetworkSearch; SearchBuilder AssignIpAddressSearch; + SearchBuilder AssignIpAddressFromPodVlanSearch; SearchBuilder IpAddressSearch; + int _networkGcWait; int _networkGcInterval; @@ -212,15 +192,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag HashMap _lastNetworkIdsToFree = new HashMap(); @Override - public PublicIp assignPublicIpAddress(long dcId, Account owner, VlanType type, Long networkId) throws InsufficientAddressCapacityException { - return fetchNewPublicIp(dcId, owner, type, networkId, false, true); + public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId) throws InsufficientAddressCapacityException { + return fetchNewPublicIp(dcId, podId, owner, type, networkId, false, true); } @DB - public PublicIp fetchNewPublicIp(long dcId, Account owner, VlanType vlanUse, Long networkId, boolean sourceNat, boolean assign) throws InsufficientAddressCapacityException { + public PublicIp fetchNewPublicIp(long dcId, Long podId, Account owner, VlanType vlanUse, Long networkId, boolean sourceNat, boolean assign) throws InsufficientAddressCapacityException { Transaction txn = Transaction.currentTxn(); txn.start(); - SearchCriteria sc = AssignIpAddressSearch.create(); + SearchCriteria sc = null; + if (podId != null) { + sc = AssignIpAddressFromPodVlanSearch.create(); + sc.setJoinParameters("podVlanMapSB", "podId", podId); + } else { + sc = AssignIpAddressSearch.create(); + } + sc.setParameters("dc", dcId); //for direct network take ip addresses only from the vlans belonging to the network @@ -266,6 +253,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override + @DB public PublicIp assignSourceNatIpAddress(Account owner, Network network, long callerId) throws ConcurrentOperationException, InsufficientAddressCapacityException { assert (network.getTrafficType() != null) : "You're asking for a source nat but your network can't participate in source nat. What do you have to say for yourself?"; @@ -303,7 +291,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("assigning a new ip address in " + dcId + " to " + owner); } - ip = fetchNewPublicIp(dcId, owner, VlanType.VirtualNetwork, network.getId(), true, false); + ip = fetchNewPublicIp(dcId, null, owner, VlanType.VirtualNetwork, network.getId(), true, false); sourceNat = ip.ip(); sourceNat.setState(IpAddress.State.Allocated); _ipAddressDao.update(sourceNat.getAddress(), sourceNat); @@ -358,77 +346,77 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public boolean associateIP(final DomainRouterVO router, final List ipAddrList, final boolean add, long vmId) { - Commands cmds = new Commands(OnError.Continue); - boolean sourceNat = false; - Map> vlanIpMap = new HashMap>(); - for (final String ipAddress: ipAddrList) { - IPAddressVO ip = _ipAddressDao.findById(new Ip(ipAddress)); - - VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - ArrayList ipList = vlanIpMap.get(vlan.getId()); - if (ipList == null) { - ipList = new ArrayList(); - } - ipList.add(ip); - vlanIpMap.put(vlan, ipList); - } - for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { - boolean firstIP = true; - ArrayList ipList = vlanAndIp.getValue(); - Collections.sort(ipList, new Comparator() { - @Override - public int compare(IPAddressVO o1, IPAddressVO o2) { - return o1.getAddress().compareTo(o2.getAddress()); - } }); - - for (final IPAddressVO ip: ipList) { - sourceNat = ip.isSourceNat(); - VlanVO vlan = vlanAndIp.getKey(); - String vlanId = vlan.getVlanTag(); - String vlanGateway = vlan.getVlanGateway(); - String vlanNetmask = vlan.getVlanNetmask(); - - String vifMacAddress = null; - if (firstIP && add) { - String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); - vifMacAddress = macAddresses[1]; - } - String vmGuestAddress = null; - if(vmId!=0){ - vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); - } - - //cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); - - firstIP = false; - } - } - - Answer[] answers = null; - try { - answers = _agentMgr.send(router.getHostId(), cmds); - } catch (final AgentUnavailableException e) { - s_logger.warn("Agent unavailable", e); - return false; - } catch (final OperationTimedoutException e) { - s_logger.warn("Timed Out", e); - return false; - } - - if (answers == null) { - return false; - } - - if (answers.length != ipAddrList.size()) { - return false; - } - - // FIXME: this used to be a loop for all answers, but then we always returned the - // first one in the array, so what should really be done here? - if (answers.length > 0) { - Answer ans = answers[0]; - return ans.getResult(); - } +// Commands cmds = new Commands(OnError.Continue); +// boolean sourceNat = false; +// Map> vlanIpMap = new HashMap>(); +// for (final String ipAddress: ipAddrList) { +// IPAddressVO ip = _ipAddressDao.findById(new Ip(ipAddress)); +// +// VlanVO vlan = _vlanDao.findById(ip.getVlanId()); +// ArrayList ipList = vlanIpMap.get(vlan.getId()); +// if (ipList == null) { +// ipList = new ArrayList(); +// } +// ipList.add(ip); +// vlanIpMap.put(vlan, ipList); +// } +// for (Map.Entry> vlanAndIp: vlanIpMap.entrySet()) { +// boolean firstIP = true; +// ArrayList ipList = vlanAndIp.getValue(); +// Collections.sort(ipList, new Comparator() { +// @Override +// public int compare(IPAddressVO o1, IPAddressVO o2) { +// return o1.getAddress().compareTo(o2.getAddress()); +// } }); +// +// for (final IPAddressVO ip: ipList) { +// sourceNat = ip.isSourceNat(); +// VlanVO vlan = vlanAndIp.getKey(); +// String vlanId = vlan.getVlanTag(); +// String vlanGateway = vlan.getVlanGateway(); +// String vlanNetmask = vlan.getVlanNetmask(); +// +// String vifMacAddress = null; +// if (firstIP && add) { +// String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(ip.getDataCenterId()); +// vifMacAddress = macAddresses[1]; +// } +// String vmGuestAddress = null; +// if(vmId!=0){ +// vmGuestAddress = _vmDao.findById(vmId).getGuestIpAddress(); +// } +// +// //cmds.addCommand(new IPAssocCommand(router.getInstanceName(), router.getPrivateIpAddress(), ip.getAddress(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, vmGuestAddress)); +// +// firstIP = false; +// } +// } +// +// Answer[] answers = null; +// try { +// answers = _agentMgr.send(router.getHostId(), cmds); +// } catch (final AgentUnavailableException e) { +// s_logger.warn("Agent unavailable", e); +// return false; +// } catch (final OperationTimedoutException e) { +// s_logger.warn("Timed Out", e); +// return false; +// } +// +// if (answers == null) { +// return false; +// } +// +// if (answers.length != ipAddrList.size()) { +// return false; +// } +// +// // FIXME: this used to be a loop for all answers, but then we always returned the +// // first one in the array, so what should really be done here? +// if (answers.length > 0) { +// Answer ans = answers[0]; +// return ans.getResult(); +// } return true; } @@ -441,26 +429,24 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag protected Account getAccountForApiCommand(String accountName, Long domainId) throws InvalidParameterValueException, PermissionDeniedException{ Account account = UserContext.current().getCaller(); - if ((account == null) || isAdmin(account.getType())) { + if (_accountMgr.isAdmin(account.getType())) { //The admin is making the call, determine if it is for someone else or for himself if (domainId != null) { if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) { throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, , permission denied"); } if (accountName != null) { - Account userAccount = _accountDao.findActiveAccount(accountName, domainId); + Account userAccount = _accountMgr.getActiveAccount(accountName, domainId); if (userAccount != null) { account = userAccount; } else { throw new PermissionDeniedException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); } } - } else if (account != null) { + } else { // the admin is calling the api on his own behalf return account; - } else { - throw new InvalidParameterValueException("Account information is not specified."); - } + } } return account; } @@ -506,7 +492,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public List getVirtualNetworksOwnedByAccountInZone(String accountName, long domainId, long zoneId) { - Account owner = _accountDao.findActiveAccount(accountName, domainId); + Account owner = _accountMgr.getActiveAccount(accountName, domainId); if (owner == null) { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); } @@ -522,7 +508,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Account caller = UserContext.current().getCaller(); long userId = UserContext.current().getCallerUserId(); - Account owner = _accountDao.findActiveAccount(accountName, domainId); + Account owner = _accountMgr.getActiveAccount(accountName, domainId); if (owner == null) { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); } @@ -572,7 +558,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } txn.start(); - ip = fetchNewPublicIp(zoneId, owner, VlanType.VirtualNetwork, network.getId(), false, false); + ip = fetchNewPublicIp(zoneId, null, owner, VlanType.VirtualNetwork, network.getId(), false, false); if (ip == null) { throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId); @@ -701,26 +687,27 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _networkGcWait = NumbersUtil.parseInt(_configs.get(Config.NetworkGcWait.key()), 600); _networkGcInterval = NumbersUtil.parseInt(_configs.get(Config.NetworkGcInterval.key()), 600); - NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmPublicNetwork, TrafficType.Public, null); + NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemPublicNetwork, TrafficType.Public); publicNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(publicNetworkOffering); - _systemNetworks.put(NetworkOfferingVO.SystemVmPublicNetwork, publicNetworkOffering); - NetworkOfferingVO managementNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmManagementNetwork, TrafficType.Management, null); + _systemNetworks.put(NetworkOfferingVO.SystemPublicNetwork, publicNetworkOffering); + NetworkOfferingVO managementNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemManagementNetwork, TrafficType.Management); managementNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(managementNetworkOffering); - _systemNetworks.put(NetworkOfferingVO.SystemVmManagementNetwork, managementNetworkOffering); - NetworkOfferingVO controlNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmControlNetwork, TrafficType.Control, null); + _systemNetworks.put(NetworkOfferingVO.SystemManagementNetwork, managementNetworkOffering); + NetworkOfferingVO controlNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemControlNetwork, TrafficType.Control); controlNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(controlNetworkOffering); - _systemNetworks.put(NetworkOfferingVO.SystemVmControlNetwork, controlNetworkOffering); - NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmStorageNetwork, TrafficType.Storage, null); + _systemNetworks.put(NetworkOfferingVO.SystemControlNetwork, controlNetworkOffering); + NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemStorageNetwork, TrafficType.Storage); storageNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(storageNetworkOffering); - _systemNetworks.put(NetworkOfferingVO.SystemVmStorageNetwork, storageNetworkOffering); - - NetworkOfferingVO defaultGuestNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultVirtualizedNetworkOffering, "Virtual Vlan", TrafficType.Guest, GuestIpType.Virtual, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); - defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering); - NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Public, GuestIpType.Direct, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); - defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering); - NetworkOfferingVO defaultGuestDirectPodBasedNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectPodBasedNetworkOffering, "DirectPodBased", TrafficType.Public, GuestIpType.DirectPodBased, true, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); - defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectPodBasedNetworkOffering); + _systemNetworks.put(NetworkOfferingVO.SystemStorageNetwork, storageNetworkOffering); + NetworkOfferingVO guestNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SysteGuestNetwork, TrafficType.Guest); + guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering); + _systemNetworks.put(NetworkOfferingVO.SysteGuestNetwork, guestNetworkOffering); + NetworkOfferingVO defaultGuestNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultVirtualizedNetworkOffering, "Virtual Vlan", TrafficType.Guest, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); + defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering); + NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Public, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); + defaultGuestDirectNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering); + AccountsUsingNetworkSearch = _accountDao.createSearchBuilder(); SearchBuilder networkAccountSearch = _networksDao.createSearchBuilderForAccount(); AccountsUsingNetworkSearch.join("nc", networkAccountSearch, AccountsUsingNetworkSearch.entity().getId(), networkAccountSearch.entity().getAccountId(), JoinType.INNER); @@ -729,14 +716,26 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag AccountsUsingNetworkSearch.done(); AssignIpAddressSearch = _ipAddressDao.createSearchBuilder(); - SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); AssignIpAddressSearch.and("dc", AssignIpAddressSearch.entity().getDataCenterId(), Op.EQ); AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL); - AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER); + SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ); + AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER); AssignIpAddressSearch.done(); + AssignIpAddressFromPodVlanSearch = _ipAddressDao.createSearchBuilder(); + AssignIpAddressFromPodVlanSearch.and("dc", AssignIpAddressFromPodVlanSearch.entity().getDataCenterId(), Op.EQ); + AssignIpAddressFromPodVlanSearch.and("allocated", AssignIpAddressFromPodVlanSearch.entity().getAllocatedTime(), Op.NULL); + SearchBuilder podVlanSearch = _vlanDao.createSearchBuilder(); + podVlanSearch.and("type", podVlanSearch.entity().getVlanType(), Op.EQ); + podVlanSearch.and("networkId", podVlanSearch.entity().getNetworkId(), Op.EQ); + SearchBuilder podVlanMapSB = _podVlanMapDao.createSearchBuilder(); + podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ); + AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER); + AssignIpAddressFromPodVlanSearch.join("vlan", podVlanSearch, podVlanSearch.entity().getId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER); + AssignIpAddressFromPodVlanSearch.done(); + IpAddressSearch = _ipAddressDao.createSearchBuilder(); IpAddressSearch.and("accountId", IpAddressSearch.entity().getAllocatedToAccountId(), Op.EQ); IpAddressSearch.and("dataCenterId", IpAddressSearch.entity().getDataCenterId(), Op.EQ); @@ -785,12 +784,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public List setupNetwork(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared) throws ConcurrentOperationException { - return setupNetwork(owner, offering, null, plan, name, displayText, isShared); + public List setupNetwork(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault) throws ConcurrentOperationException { + return setupNetwork(owner, offering, null, plan, name, displayText, isShared, isDefault); } @Override @DB - public List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared) throws ConcurrentOperationException { + public List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault) throws ConcurrentOperationException { Transaction.currentTxn(); Account locked = _accountDao.acquireInLockTable(owner.getId()); if (locked == null) { @@ -832,7 +831,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag related = id; } - NetworkVO vo = new NetworkVO(id, config, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared); + NetworkVO vo = new NetworkVO(id, config, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared, isDefault); configs.add(_networksDao.persist(vo, vo.getGuestType() != null)); } @@ -881,6 +880,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag requested.setMode(config.getMode()); } NicProfile profile = concierge.allocate(config, requested, vm); + + if (vm != null && vm.getVirtualMachine().getType() == Type.User && config.isDefault()) { + profile.setDefaultNic(true); + } + if (profile == null) { continue; } @@ -987,8 +991,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return to; } + @Override @DB - protected Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Transaction.currentTxn(); Pair implemented = new Pair(null, null); @@ -1056,7 +1061,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _nicDao.update(nic.getId(), nic); URI broadcastUri = nic.getBroadcastUri(); if (broadcastUri == null) { - network.getBroadcastUri(); + broadcastUri = network.getBroadcastUri(); } URI isolationUri = nic.getIsolationUri(); @@ -1114,16 +1119,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return _nicDao.listBy(vm.getId()); } - public static boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); - } - private Account findAccountByIpAddress(Ip ipAddress) { IPAddressVO address = _ipAddressDao.findById(ipAddress); if ((address != null) && (address.getAllocatedToAccountId() != null)) { - return _accountDao.findById(address.getAllocatedToAccountId()); + return _accountMgr.getAccount(address.getAllocatedToAccountId()); } return null; } @@ -1133,29 +1132,23 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd) throws PermissionDeniedException, IllegalArgumentException { Long userId = UserContext.current().getCallerUserId(); - Account account = UserContext.current().getCaller(); + Account caller = UserContext.current().getCaller(); Ip ipAddress = cmd.getIpAddress(); // Verify input parameters Account accountByIp = findAccountByIpAddress(ipAddress); if(accountByIp == null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find account owner for ip " + ipAddress); + throw new InvalidParameterValueException("Unable to find account owner for ip " + ipAddress); } Long accountId = accountByIp.getId(); - if (account != null) { - if (!isAdmin(account.getType())) { - if (account.getId() != accountId.longValue()) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + ipAddress); - } - } else if (!_domainDao.isChildDomain(account.getDomainId(), accountByIp.getDomainId())) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to disassociate IP address " + ipAddress + ", permission denied."); + if (!_accountMgr.isAdmin(caller.getType())) { + if (caller.getId() != accountId.longValue()) { + throw new PermissionDeniedException("account " + caller.getAccountName() + " doesn't own ip address " + ipAddress); } - } - - // If command is executed via 8096 port, set userId to the id of System account (1) - if (userId == null) { - userId = Long.valueOf(1); + } else { + Domain domain = _domainDao.findById(accountByIp.getDomainId()); + _accountMgr.checkAccess(caller, domain); } try { @@ -1168,7 +1161,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return true; } - Account Account = _accountDao.findById(accountId); + Account Account = _accountMgr.getAccount(accountId); if (Account == null) { return false; } @@ -1240,12 +1233,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return _networksDao.getNetworksForOffering(offeringId, dataCenterId, accountId); } - @Override - public List setupNetwork(Account owner, ServiceOfferingVO offering, DeploymentPlan plan) throws ConcurrentOperationException { - NetworkOfferingVO networkOffering = _networkOfferingDao.findByServiceOffering(offering); - return setupNetwork(owner, networkOffering, plan, null, null, false); - } - @Override public List listNetworkOfferings() { return _networkOfferingDao.listNonSystemNetworkOfferings(); @@ -1303,6 +1290,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag String endIP = cmd.getEndIp(); String netmask = cmd.getNetmask(); String cidr = null; + Boolean isDefault = cmd.isDefault(); if (gateway != null && netmask != null) { cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); } @@ -1312,8 +1300,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag String name = cmd.getNetworkName(); String displayText = cmd.getDisplayText(); Boolean isShared = cmd.getIsShared(); - Account owner = null; - Long ownerId = null; //if end ip is not specified, default it to startIp if (endIP == null && startIP != null) { @@ -1326,68 +1312,40 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Unable to find network offeirng by id " + networkOfferingId); } + //allow isDefault to be set only for Virtual network + if (networkOffering.getTrafficType() == TrafficType.Guest) { + if (isDefault != null) { + throw new InvalidParameterValueException("Can specify isDefault parameter only for Public network. "); + } else { + isDefault = true; + } + } else { + if (isDefault == null) { + isDefault = false; + } + } + //Check if zone exists if (zoneId == null || ((_dcDao.findById(zoneId)) == null)) { throw new InvalidParameterValueException("Please specify a valid zone."); + } + + DataCenter zone = _dcDao.findById(zoneId); + if (zone.getNetworkType() == NetworkType.Basic) { + throw new InvalidParameterValueException("Network creation is not allowed in zone with network type " + NetworkType.Basic); } - //Check permissions - if (isAdmin(ctxAccount.getType())) { - if (domainId != null) { - if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) { - throw new PermissionDeniedException("Failed to create a newtwork, invalid domain id (" + domainId + ") given."); - } - if (accountName != null) { - owner = _accountDao.findActiveAccount(accountName, domainId); - if (owner == null) { - throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); - } - } - } else { - owner = ctxAccount; - } - } else { - //regular user can't create networks for anybody else but himself - owner = ctxAccount; - } - - ownerId = owner.getId(); + Account owner = _accountMgr.finalizeOwner(ctxAccount, accountName, domainId); //Don't allow to create network with vlan that already exists in the system - if (networkOffering.getGuestIpType() == GuestIpType.Direct && vlanId != null) { + if (vlanId != null) { String uri ="vlan://" + vlanId; List networks = _networksDao.listBy(zoneId, uri); if ((networks != null && !networks.isEmpty())) { throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId); } } - - //if VlanId is Direct untagged, verify if there is already network of this type in the zone - if (networkOffering.getGuestIpType() == GuestIpType.DirectPodBased && vlanId != null && vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { - SearchBuilder sb = _networksDao.createSearchBuilder(); - sb.and("broadcastDomainType", sb.entity().getBroadcastDomainType(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - - SearchBuilder networkSearch = _networkOfferingDao.createSearchBuilder(); - networkSearch.and("guestIpType", networkSearch.entity().getGuestIpType(), SearchCriteria.Op.EQ); - sb.join("networkSearch", networkSearch, sb.entity().getNetworkOfferingId(), networkSearch.entity().getId(), JoinBuilder.JoinType.INNER); - - SearchCriteria sc = sb.create(); - sc.setParameters("broadcastDomainType", BroadcastDomainType.Native); - sc.setParameters("dataCenterId", zoneId); - sc.setJoinParameters("networkSearch", "guestIpType", GuestIpType.DirectPodBased); - - List networks = _networksDao.search(sc, null); - if (networks!= null && !networks.isEmpty()) { - throw new InvalidParameterValueException("Network with untagged vlan already exists for the zone " + zoneId); - } - } - - //Regular user can create only network of Virtual type - if (ctxAccount.getType() == Account.ACCOUNT_TYPE_NORMAL && networkOffering.getGuestIpType() != GuestIpType.Virtual) { - throw new InvalidParameterValueException("Regular user can create only networ of type " + GuestIpType.Virtual); - } - + //VlanId can be specified only when network offering supports it if (ctxAccount.getType() == Account.ACCOUNT_TYPE_NORMAL && vlanId != null && !networkOffering.getSpecifyVlan()) { throw new InvalidParameterValueException("Can't specify vlan because network offering doesn't support it"); @@ -1417,17 +1375,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared); + List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared, isDefault); Long networkId = null; + Network network = null; if (networks == null || networks.isEmpty()) { txn.rollback(); throw new CloudRuntimeException("Fail to create a network"); } else { + network = networks.get(0); networkId = networks.get(0).getId(); - } - - for (Network network : networks) { if (network.getGuestType() == GuestIpType.Virtual) { s_logger.debug("Creating a source natp ip for " + network); PublicIp ip = assignSourceNatIpAddress(owner, network, userId); @@ -1437,12 +1394,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } + Long ownerId = owner.getId(); //Don't pass owner to create vlan when network offering is of type Direct - done to prevent accountVlanMap entry creation when vlan is mapped to network - if (networkOffering.getGuestIpType() == GuestIpType.Direct) { + if (network.getGuestType() == GuestIpType.Direct) { owner = null; } - if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN && networkOffering.getGuestIpType() == GuestIpType.Direct && startIP != null && endIP != null && gateway != null) { + if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN && network.getGuestType() == GuestIpType.Direct && startIP != null && endIP != null && gateway != null) { //Create vlan ip range Vlan vlan = _configMgr.createVlanAndPublicIpRange(userId, zoneId, null, startIP, endIP, gateway, netmask, false, vlanId, owner, networkId); if (vlan == null) { @@ -1486,21 +1444,29 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Long domainId = cmd.getDomainId(); String accountName = cmd.getAccountName(); String type = cmd.getType(); + String trafficType = cmd.getTrafficType(); Boolean isSystem = cmd.getIsSystem(); + Boolean isShared = cmd.getIsShared(); + Boolean isDefault = cmd.isDefault(); Long accountId = null; if (isSystem == null) { isSystem = false; } - if (isAdmin(account.getType())) { + //Account/domainId parameters and isSystem are mutually exclusive + if (isSystem && (accountName != null || domainId != null)) { + throw new InvalidParameterValueException("System network belongs to system, account and domainId parameters can't be specified"); + } + + if (_accountMgr.isAdmin(account.getType())) { if (domainId != null) { if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) { throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list networks"); } if (accountName != null) { - account = _accountDao.findActiveAccount(accountName, domainId); + account = _accountMgr.getActiveAccount(accountName, domainId); if (account == null) { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); } @@ -1510,6 +1476,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag accountId = account.getId(); } } else { + accountName = account.getAccountName(); + domainId = account.getDomainId(); accountId = account.getId(); } @@ -1534,7 +1502,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag sc.setJoinParameters("networkOfferingSearch", "systemOnly", false); } else { sc.setJoinParameters("networkOfferingSearch", "systemOnly", true); - sc.setJoinParameters("networkOfferingSearch", "trafficType", TrafficType.Public); sc.setJoinParameters("zoneSearch", "networkType", NetworkType.Advanced.toString()); } @@ -1555,8 +1522,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (type != null) { sc.addAnd("guestType", SearchCriteria.Op.EQ, type); } - if (account.getType() != Account.ACCOUNT_TYPE_ADMIN || (accountName != null && domainId != null)) { + + if (!isSystem && (isShared == null || !isShared) && accountName != null && domainId != null) { sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); + sc.addAnd("isShared", SearchCriteria.Op.EQ, false); + } + + if (isShared != null) { + sc.addAnd("isShared", SearchCriteria.Op.EQ, isShared); + } + + if (isDefault != null) { + sc.addAnd("isDefault", SearchCriteria.Op.EQ, isDefault); + } + + if (trafficType != null) { + sc.addAnd("trafficType", SearchCriteria.Op.EQ, trafficType); } List networks = _networksDao.search(sc, searchFilter); @@ -1567,7 +1548,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @DB public boolean deleteNetwork(long networkId) throws InvalidParameterValueException, PermissionDeniedException{ Long userId = UserContext.current().getCallerUserId(); - Account account = UserContext.current().getCaller(); + Account caller = UserContext.current().getCaller(); //Verify network id NetworkVO network = _networksDao.findById(networkId); @@ -1580,14 +1561,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag String name = network.getName(); //Perform permission check - if (account != null) { - if (!isAdmin(account.getType())) { - if (network.getAccountId() != account.getId()) { - throw new PermissionDeniedException("Account " + account.getAccountName() + " does not own network id=" + networkId + ", permission denied"); - } - } else if (!(account.getType() == Account.ACCOUNT_TYPE_ADMIN) && !_domainDao.isChildDomain(account.getDomainId(), _accountDao.findById(network.getAccountId()).getId())) { - throw new PermissionDeniedException("Unable to delete network " + networkId + ", permission denied."); + if (!_accountMgr.isAdmin(caller.getType())) { + if (network.getAccountId() != caller.getId()) { + throw new PermissionDeniedException("Account " + caller.getAccountName() + " does not own network id=" + networkId + ", permission denied"); } + } else { + Account owner = _accountMgr.getAccount(network.getAccountId()); + Domain domain = _domainDao.findById(owner.getDomainId()); + _accountMgr.checkAccess(caller, domain); } //Don't allow to remove network if there are non-destroyed vms using it @@ -1689,7 +1670,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public boolean applyRules(List rules, boolean continueOnError) throws ResourceUnavailableException { - if (rules.size() == 0) { + if (rules == null || rules.size() == 0) { s_logger.debug("There are no rules to forward to the network elements"); return true; } @@ -1757,17 +1738,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException { //This method reapplies Ip addresses, LoadBalancer and PortForwarding rules - String accountName = cmd.getAccountName(); - long domainId = cmd.getDomainId(); - Account caller = UserContext.current().getCaller(); - - Account owner = _accountDao.findActiveAccount(accountName, domainId); - if (owner == null) { - throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied"); - } - - _accountMgr.checkAccess(caller, owner); - + Account caller = UserContext.current().getCaller(); Long networkId = cmd.getNetworkId(); Network network = null; if (networkId != null) { @@ -1777,45 +1748,43 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } + Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); + if (!_accountMgr.isAdmin(caller.getType())) { + _accountMgr.checkAccess(caller, network); + } else { + Domain domain = _domainDao.findById(owner.getDomainId()); + _accountMgr.checkAccess(caller, domain); + } + s_logger.debug("Restarting network " + networkId + "..."); - boolean success = true; if (!applyIpAssociations(network, false)) { s_logger.warn("Failed to apply ips as a part of network " + networkId + " restart"); - success = false; + return false; } else { s_logger.debug("Ip addresses are reapplied successfully as a part of network " + networkId + " restart"); } - //Reapply lb rules - List lbs = _lbDao.listByNetworkId(networkId); - List lbRules = new ArrayList(); - for (LoadBalancerVO lb : lbs) { - List dstList = _lbMgr.getExistingDestinations(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); - lbRules.add(loadBalancing); - } - + List lbRules = _lbMgr.listByNetworkId(networkId); + if (!applyRules(lbRules, true)) { s_logger.warn("Failed to apply load balancing rules as a part of network " + network.getId() + " restart"); - success = false; + return false; } else { s_logger.debug("Load balancing rules are reapplied successfully as a part of network " + networkId + " restart"); } //Reapply pf rules - List pfRules = _pfRulesDao.listByNetworkId(networkId); + List pfRules = _rulesMgr.listByNetworkId(networkId); if (!applyRules(pfRules, true)) { s_logger.warn("Failed to apply port forwarding rules as a part of network " + network.getId() + " restart"); - success = false; + return false; } else { s_logger.debug("Port forwarding rules are reapplied successfully as a part of network " + networkId + " restart"); } - if (success){ - s_logger.debug("Network " + networkId + " is restarted successfully."); - } - return success; + s_logger.debug("Network " + networkId + " is restarted successfully."); + return true; } @Override @@ -1874,26 +1843,26 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public long getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(long zoneId, TrafficType trafficType, GuestIpType guestType) { + public Network getSystemNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) { //find system public network offering Long networkOfferingId = null; List offerings = _networkOfferingDao.listSystemNetworkOfferings(); for (NetworkOfferingVO offering: offerings) { - if (offering.getTrafficType() == trafficType && offering.getGuestIpType() == guestType) { + if (offering.getTrafficType() == trafficType) { networkOfferingId = offering.getId(); break; } } if (networkOfferingId == null) { - throw new InvalidParameterValueException("Unable to find system network offering with traffic type " + trafficType + " and guestIpType " + guestType); + throw new InvalidParameterValueException("Unable to find system network offering with traffic type " + trafficType); } List networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, networkOfferingId, zoneId); if (networks == null) { throw new InvalidParameterValueException("Unable to find network with traffic type " + trafficType + " in zone " + zoneId); } - return networks.get(0).getId(); + return networks.get(0); } @Override @@ -1907,21 +1876,27 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public Network getBasicZoneDefaultPublicNetwork(long zoneId) { - SearchBuilder sb = _networksDao.createSearchBuilder(); - sb.and("trafficType", sb.entity().getTrafficType(), SearchCriteria.Op.EQ); - sb.and("guestType", sb.entity().getGuestType(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - SearchCriteria sc = sb.create(); - sc.setParameters("trafficType", TrafficType.Public); - sc.setParameters("guestType", GuestIpType.DirectPodBased); - sc.setParameters("dataCenterId", zoneId); - - List networks = _networksDao.search(sc, null); - if (networks == null || networks.isEmpty()) { - return null; - } else { - return networks.get(0); - } + public List listPodVlans(long podId) { + List vlans = _vlanDao.listVlansForPodByType(podId, VlanType.DirectAttached); + return vlans; } + + @Override + public List listNetworksUsedByVm(long vmId, boolean isSystem) { + List networks = new ArrayList(); + + List nics = _nicDao.listBy(vmId); + if (nics != null) { + for (Nic nic : nics) { + NetworkVO network = _networksDao.findByIdIncludingRemoved(nic.getNetworkId()); + NetworkOffering no = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId()); + if (no.isSystemOnly() == isSystem) { + networks.add(network); + } + } + } + + return networks; + } + } diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index e62655ceca8..b0662251865 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -32,7 +32,6 @@ import javax.persistence.Transient; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -132,6 +131,9 @@ public class NetworkVO implements Network { @Column(name="reservation_id") String reservationId; + @Column(name="is_default") + boolean isDefault; + public NetworkVO() { } @@ -142,20 +144,25 @@ public class NetworkVO implements Network { * @param broadcastDomainType * @param networkOfferingId * @param dataCenterId + * @param state TODO */ - public NetworkVO(TrafficType trafficType, GuestIpType guestType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, long dataCenterId) { + public NetworkVO(TrafficType trafficType, GuestIpType guestType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, long dataCenterId, State state) { this.trafficType = trafficType; this.mode = mode; this.broadcastDomainType = broadcastDomainType; this.networkOfferingId = networkOfferingId; this.dataCenterId = dataCenterId; - this.state = State.Allocated; + if (state == null) { + state = State.Allocated; + } else { + this.state = state; + } this.id = -1; this.guestType = guestType; } - public NetworkVO(long id, Network that, long offeringId, long dataCenterId, String guruName, long domainId, long accountId, long related, String name, String displayText, Boolean isShared) { - this(id, that.getTrafficType(), that.getGuestType(), that.getMode(), that.getBroadcastDomainType(), offeringId, dataCenterId, domainId, accountId, related, name, displayText, isShared); + public NetworkVO(long id, Network that, long offeringId, long dataCenterId, String guruName, long domainId, long accountId, long related, String name, String displayText, Boolean isShared, boolean isDefault) { + this(id, that.getTrafficType(), that.getGuestType(), that.getMode(), that.getBroadcastDomainType(), offeringId, dataCenterId, domainId, accountId, related, name, displayText, isShared, isDefault); this.gateway = that.getGateway(); this.dns1 = that.getDns1(); this.dns2 = that.getDns2(); @@ -180,10 +187,11 @@ public class NetworkVO implements Network { * @param accountId * @param name * @param displayText - * @param isShared TODO + * @param isShared + * @param isDefault */ - public NetworkVO(long id, TrafficType trafficType, GuestIpType guestType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, long dataCenterId, long domainId, long accountId, long related, String name, String displayText, Boolean isShared) { - this(trafficType, guestType, mode, broadcastDomainType, networkOfferingId, dataCenterId); + public NetworkVO(long id, TrafficType trafficType, GuestIpType guestType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, long dataCenterId, long domainId, long accountId, long related, String name, String displayText, Boolean isShared, boolean isDefault) { + this(trafficType, guestType, mode, broadcastDomainType, networkOfferingId, dataCenterId, State.Allocated); this.domainId = domainId; this.accountId = accountId; this.related = related; @@ -191,6 +199,7 @@ public class NetworkVO implements Network { this.name = name; this.displayText = displayText; this.isShared = isShared; + this.isDefault = isDefault; } @Override @@ -369,6 +378,11 @@ public class NetworkVO implements Network { public boolean isShared() { return isShared; } + + @Override + public boolean isDefault() { + return isDefault; + } public void setShared(boolean isShared) { this.isShared = isShared; diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index d4596841c03..6deeccbef5c 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -19,9 +19,9 @@ package com.cloud.network.dao; import java.util.List; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.NetworkAccountVO; import com.cloud.network.NetworkVO; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.SearchBuilder; diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index aa455af6523..533cbab5916 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -23,13 +23,13 @@ import java.util.Random; import javax.ejb.Local; import javax.persistence.TableGenerator; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.NetworkAccountDaoImpl; import com.cloud.network.NetworkAccountVO; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; diff --git a/server/src/com/cloud/network/element/DhcpElement.java b/server/src/com/cloud/network/element/DhcpElement.java index 3f9767f32d9..433f4cb9063 100644 --- a/server/src/com/cloud/network/element/DhcpElement.java +++ b/server/src/com/cloud/network/element/DhcpElement.java @@ -26,21 +26,23 @@ import javax.ejb.Local; import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.Network.Capability; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; +import com.cloud.network.Networks.TrafficType; import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.NetworkDao; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.rules.FirewallRule; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.uservm.UserVm; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; @@ -67,16 +69,24 @@ public class DhcpElement extends AdapterBase implements NetworkElement{ @Inject UserVmDao _userVmDao; @Inject DomainRouterDao _routerDao; - private boolean canHandle(GuestIpType ipType, DeployDestination dest) { + private boolean canHandle(GuestIpType ipType, DeployDestination dest, TrafficType trafficType) { DataCenter dc = dest.getDataCenter(); String provider = dc.getGatewayProvider(); - return ((ipType == GuestIpType.Virtual && !provider.equals(Provider.VirtualRouter.getName())) || (provider.equals(Provider.VirtualRouter.getName()) && (ipType == GuestIpType.Direct || ipType == GuestIpType.DirectPodBased))); + if (provider.equals(Provider.VirtualRouter.getName())) { + if (dc.getNetworkType() == NetworkType.Basic) { + return (ipType == GuestIpType.Direct && trafficType == TrafficType.Guest); + } else { + return (ipType == GuestIpType.Direct); + } + } else { + return (ipType == GuestIpType.Virtual); + } } @Override public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException { - if (!canHandle(offering.getGuestIpType(), dest)) { + if (!canHandle(network.getGuestType(), dest, offering.getTrafficType())) { return false; } _routerMgr.deployDhcp(network, dest, context.getAccount()); @@ -85,7 +95,7 @@ public class DhcpElement extends AdapterBase implements NetworkElement{ @Override public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - if (canHandle(network.getGuestType(), dest)) { + if (canHandle(network.getGuestType(), dest, network.getTrafficType())) { if (vm.getType() != VirtualMachine.Type.User) { return false; diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 8908a82b7b0..0e59a7363cc 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -35,6 +35,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.LoadBalancerVO; import com.cloud.network.Network; import com.cloud.network.Network.Capability; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; @@ -52,7 +53,6 @@ import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.vpn.RemoteAccessVpnElement; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.uservm.UserVm; import com.cloud.utils.component.AdapterBase; @@ -93,7 +93,7 @@ public class VirtualRouterElement extends AdapterBase implements NetworkElement, @Override public boolean implement(Network guestConfig, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException { - if (!canHandle(offering.getGuestIpType(), dest.getDataCenter())) { + if (!canHandle(guestConfig.getGuestType(), dest.getDataCenter())) { return false; } _routerMgr.deployVirtualRouter(guestConfig, dest, context.getAccount()); diff --git a/server/src/com/cloud/network/guru/ControlNetworkGuru.java b/server/src/com/cloud/network/guru/ControlNetworkGuru.java index 43436adc626..5cc92d4802a 100644 --- a/server/src/com/cloud/network/guru/ControlNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ControlNetworkGuru.java @@ -1,4 +1,18 @@ /** + * Copyright (C) 2010 Cloud.com, 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 . * */ package com.cloud.network.guru; @@ -25,6 +39,7 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.NetworkOffering; +import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.ComponentLocator; @@ -40,16 +55,26 @@ import com.cloud.vm.VirtualMachineProfile; public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGuru { private static final Logger s_logger = Logger.getLogger(ControlNetworkGuru.class); @Inject DataCenterDao _dcDao; + @Inject NetworkOfferingDao _networkOfferingDao; String _cidr; String _gateway; + + protected boolean canHandle(NetworkOffering offering) { + if (offering.isSystemOnly() && offering.getTrafficType() == TrafficType.Control) { + return true; + } else { + s_logger.trace("We only care about System only Control network"); + return false; + } + } @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network specifiedConfig, Account owner) { - if (offering.getTrafficType() != TrafficType.Control) { + if (!canHandle(offering)) { return null; } - NetworkVO config = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), Mode.Static, BroadcastDomainType.LinkLocal, offering.getId(), plan.getDataCenterId()); + NetworkVO config = new NetworkVO(offering.getTrafficType(), null, Mode.Static, BroadcastDomainType.LinkLocal, offering.getId(), plan.getDataCenterId(), Network.State.Setup); config.setCidr(_cidr); config.setGateway(_gateway); @@ -64,8 +89,9 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { - if (config.getTrafficType() != TrafficType.Control) { - return null; + NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(config.getNetworkOfferingId()); + if (!canHandle(offering)) { + return null; } if(vm.getHypervisorType() == HypervisorType.VmWare && vm.getType() != VirtualMachine.Type.DomainRouter) { diff --git a/server/src/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/com/cloud/network/guru/DirectNetworkGuru.java index ec4bcc1ed59..54890e5320c 100644 --- a/server/src/com/cloud/network/guru/DirectNetworkGuru.java +++ b/server/src/com/cloud/network/guru/DirectNetworkGuru.java @@ -1,4 +1,18 @@ /** + * Copyright (C) 2010 Cloud.com, 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 . * */ package com.cloud.network.guru; @@ -8,7 +22,7 @@ import javax.ejb.Local; import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; @@ -19,6 +33,7 @@ import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.State; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; @@ -30,7 +45,7 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; @@ -48,16 +63,32 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { @Inject VlanDao _vlanDao; @Inject NetworkManager _networkMgr; @Inject IPAddressDao _ipAddressDao; - + @Inject NetworkOfferingDao _networkOfferingDao; + + protected boolean canHandle(NetworkOffering offering, DataCenter dc) { + //this guru handles only non-system Public network + if (dc.getNetworkType() == NetworkType.Advanced && offering.getTrafficType() == TrafficType.Public && !offering.isSystemOnly()) { + return true; + } else { + s_logger.trace("We only take care of Public Direct networks"); + return false; + } + } + @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { - if (!(offering.getTrafficType() == TrafficType.Public && (offering.getGuestIpType() == GuestIpType.Direct || offering.getGuestIpType() == GuestIpType.DirectPodBased))) { - s_logger.trace("We only take care of public direct network, so this is no ours"); + DataCenter dc = _dcDao.findById(plan.getDataCenterId()); + + if (!canHandle(offering, dc)) { return null; } - NetworkVO config = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId()); - DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); + State state = State.Allocated; + if (offering.isSystemOnly()) { + state = State.Setup; + } + + NetworkVO config = new NetworkVO(offering.getTrafficType(), GuestIpType.Direct, Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId(), state); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || @@ -92,10 +123,10 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { - PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId()); + PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.DirectAttached, network.getId()); nic.setIp4Address(ip.getAddress().toString()); nic.setGateway(ip.getGateway()); - nic.setNetmask(ip.getNetmask()); + nic.setNetmask(ip.getNetmask()); nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); nic.setBroadcastType(BroadcastDomainType.Vlan); nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag())); @@ -110,6 +141,12 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { @Override public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { + + DataCenter dc = _dcDao.findById(network.getDataCenterId()); + NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId()); + if (!canHandle(offering, dc)) { + return null; + } if (nic == null) { nic = new NicProfile(ReservationStrategy.Create, null, null, null, null); @@ -119,7 +156,6 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { nic.setStrategy(ReservationStrategy.Create); } - DataCenter dc = _dcDao.findById(network.getDataCenterId()); getIp(nic, dc, vm, network); return nic; diff --git a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java new file mode 100644 index 00000000000..a7f2bfd5801 --- /dev/null +++ b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java @@ -0,0 +1,123 @@ +/** + * Copyright (C) 2010 Cloud.com, 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 . + * + */ + + +package com.cloud.network.guru; + +import java.net.URI; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.dc.DataCenter; +import com.cloud.dc.Pod; +import com.cloud.dc.Vlan; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; +import com.cloud.network.Network; +import com.cloud.network.NetworkManager; +import com.cloud.network.Networks.AddressFormat; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.addr.PublicIp; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.offering.NetworkOffering; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.resource.Resource.ReservationStrategy; +import com.cloud.utils.component.Inject; +import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=NetworkGuru.class) +public class DirectPodBasedNetworkGuru extends DirectNetworkGuru{ +private static final Logger s_logger = Logger.getLogger(DirectPodBasedNetworkGuru.class); + + @Inject DataCenterDao _dcDao; + @Inject VlanDao _vlanDao; + @Inject NetworkManager _networkMgr; + @Inject IPAddressDao _ipAddressDao; + @Inject NetworkOfferingDao _networkOfferingDao; + + + protected boolean canHandle(NetworkOffering offering, DataCenter dc) { + //this guru handles system Direct pod based network + if (dc.getNetworkType() == NetworkType.Basic && offering.getTrafficType() == TrafficType.Guest && offering.isSystemOnly()) { + return true; + } else { + s_logger.trace("We only take care of Guest Direct Pod based networks"); + return false; + } + } + + @Override + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, + InsufficientAddressCapacityException, ConcurrentOperationException { + + DataCenter dc = _dcDao.findById(network.getDataCenterId()); + NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId()); + + if (!canHandle(offering, dc)) { + return null; + } + + if (nic == null) { + nic = new NicProfile(ReservationStrategy.Start, null, null, null, null); + } else { + nic.setStrategy(ReservationStrategy.Start); + } + + return nic; + } + + @Override + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { + if (nic.getIp4Address() == null) { + getIp(nic, dest.getPod(), vm, network); + } + } + + protected void getIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { + DataCenter dc = _dcDao.findById(pod.getDataCenterId()); + if (nic.getIp4Address() == null) { + PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId()); + nic.setIp4Address(ip.getAddress().toString()); + nic.setGateway(ip.getGateway()); + nic.setNetmask(ip.getNetmask()); + if(ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase(Vlan.UNTAGGED)) { + nic.setIsolationUri(URI.create("ec2://" + Vlan.UNTAGGED)); + nic.setBroadcastUri(URI.create("vlan://" + Vlan.UNTAGGED)); + nic.setBroadcastType(BroadcastDomainType.Native); + } + nic.setFormat(AddressFormat.Ip4); + nic.setReservationId(String.valueOf(ip.getVlanTag())); + nic.setMacAddress(ip.getMacAddress()); + } + nic.setDns1(dc.getDns1()); + nic.setDns2(dc.getDns2()); + } + +} diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index a44b97763a6..e2b3d9595e6 100644 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -24,7 +24,10 @@ import java.util.TreeSet; import javax.ejb.Local; -import com.cloud.dc.DataCenterVO; +import org.apache.log4j.Logger; + +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; @@ -33,6 +36,7 @@ import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.State; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; @@ -41,7 +45,6 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; @@ -56,6 +59,7 @@ import com.cloud.vm.dao.NicDao; @Local(value=NetworkGuru.class) public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { + private static final Logger s_logger = Logger.getLogger(GuestNetworkGuru.class); @Inject protected NetworkManager _networkMgr; @Inject protected DataCenterDao _dcDao; @Inject protected VlanDao _vlanDao; @@ -69,25 +73,24 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { super(); } + protected boolean canHandle(NetworkOffering offering, DataCenter dc) { + //This guru handles only non-system Guest network + if (dc.getNetworkType() == NetworkType.Advanced && offering.getTrafficType() == TrafficType.Guest && !offering.isSystemOnly()) { + return true; + } else { + s_logger.trace("We only take care of Guest networks in zone of type " + NetworkType.Advanced); + return false; + } + } + @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { - if (offering.getTrafficType() != TrafficType.Guest || offering.getGuestIpType() != GuestIpType.Virtual) { + DataCenter dc = _dcDao.findById(plan.getDataCenterId()); + if (!canHandle(offering, dc)) { return null; } - - BroadcastDomainType broadcastType = null; - Mode mode = null; - GuestIpType ipType = offering.getGuestIpType(); - if (ipType == GuestIpType.Virtual) { - mode = Mode.Dhcp; - broadcastType = BroadcastDomainType.Vlan; - } else { - broadcastType = BroadcastDomainType.Native; - mode = Mode.Dhcp; - } - DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); - - NetworkVO network = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), mode, broadcastType, offering.getId(), plan.getDataCenterId()); + + NetworkVO network = new NetworkVO(offering.getTrafficType(), GuestIpType.Virtual, Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId(), State.Allocated); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { @@ -135,7 +138,9 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { assert (network.getState() == State.Implementing) : "Why are we implementing " + network; long dcId = dest.getDataCenter().getId(); - NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getGuestType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), network.getDataCenterId()); + + + NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getGuestType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), network.getDataCenterId(), State.Allocated); if (network.getBroadcastUri() == null) { String vnet = _dcDao.allocateVnet(dcId, network.getAccountId(), context.getReservationId()); diff --git a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java index 126c5df3aab..2fb0229bd23 100644 --- a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java @@ -50,7 +50,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { return null; } - NetworkVO config = new NetworkVO(type, offering.getGuestIpType(), Mode.Static, BroadcastDomainType.Native, offering.getId(), plan.getDataCenterId()); + NetworkVO config = new NetworkVO(type, null, Mode.Static, BroadcastDomainType.Native, offering.getId(), plan.getDataCenterId(), Network.State.Setup); DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); config.setDns1(dc.getDns1()); config.setDns2(dc.getDns2()); diff --git a/server/src/com/cloud/network/guru/PublicNetworkGuru.java b/server/src/com/cloud/network/guru/PublicNetworkGuru.java index 59dbce2b260..7c45f8b066b 100644 --- a/server/src/com/cloud/network/guru/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PublicNetworkGuru.java @@ -3,15 +3,12 @@ */ package com.cloud.network.guru; -import java.net.URI; - import javax.ejb.Local; import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; @@ -23,6 +20,7 @@ import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; +import com.cloud.network.Network.State; import com.cloud.network.Networks.AddressFormat; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; @@ -31,7 +29,7 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; @@ -50,17 +48,28 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { @Inject VlanDao _vlanDao; @Inject NetworkManager _networkMgr; @Inject IPAddressDao _ipAddressDao; + @Inject NetworkOfferingDao _networkOfferingDao; + + + protected boolean canHandle(NetworkOffering offering, DataCenter dc) { + if (dc.getNetworkType() == NetworkType.Advanced && offering.getTrafficType() == TrafficType.Public && offering.isSystemOnly()) { + return true; + } else { + s_logger.trace("We only take care of System only Public Virtual Network"); + return false; + } + } @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network network, Account owner) { - if (offering.getTrafficType() != TrafficType.Public || (offering.getGuestIpType() != null && offering.getGuestIpType() != GuestIpType.Virtual)) { - s_logger.trace("We only take care of Public Virtual Network"); + DataCenter dc = _dcDao.findById(plan.getDataCenterId()); + + if (!canHandle(offering, dc)) { return null; } if (offering.getTrafficType() == TrafficType.Public) { - NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), Mode.Static, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId()); - DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); + NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), null, Mode.Static, BroadcastDomainType.Vlan, offering.getId(), plan.getDataCenterId(), State.Setup); ntwk.setDns1(dc.getDns1()); ntwk.setDns2(dc.getDns2()); return ntwk; @@ -75,20 +84,13 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { protected void getIp(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { if (nic.getIp4Address() == null) { - PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), vm.getOwner(), dc.getNetworkType().equals(NetworkType.Basic) ? VlanType.DirectAttached : VlanType.VirtualNetwork, null); + PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), null, vm.getOwner(), VlanType.VirtualNetwork, null); nic.setIp4Address(ip.getAddress().toString()); nic.setGateway(ip.getGateway()); - nic.setNetmask(ip.getNetmask()); - if(ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase("untagged")) { - nic.setIsolationUri(URI.create("vlan://untagged")); - nic.setBroadcastUri(URI.create("vlan://untagged")); - nic.setBroadcastType(BroadcastDomainType.Native); - } else if (ip.getVlanTag() != null){ - nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); - nic.setBroadcastUri(IsolationType.Vlan.toUri(ip.getVlanTag())); - nic.setBroadcastType(BroadcastDomainType.Vlan); - } - + nic.setNetmask(ip.getNetmask()); + nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastUri(IsolationType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastType(BroadcastDomainType.Vlan); nic.setFormat(AddressFormat.Ip4); nic.setReservationId(String.valueOf(ip.getVlanTag())); nic.setMacAddress(ip.getMacAddress()); @@ -100,7 +102,10 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { @Override public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException { - if (network.getTrafficType() != TrafficType.Public) { + + DataCenter dc = _dcDao.findById(network.getDataCenterId()); + NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId()); + if (!canHandle(offering, dc)) { return null; } @@ -108,7 +113,6 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { nic = new NicProfile(ReservationStrategy.Create, null, null, null, null); } - DataCenter dc = _dcDao.findById(network.getDataCenterId()); getIp(nic, dc, vm, network); if (nic.getIp4Address() == null) { diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 255d0fcd1eb..459f7710f07 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -1329,18 +1329,17 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, return _lbDao.search(sc, searchFilter); } - -// @Override -// public LoadBalancerVO findLoadBalancer(Long accountId, String name) { -// SearchCriteria sc = _loadBalancerDao.createSearchCriteria(); -// sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); -// sc.addAnd("name", SearchCriteria.Op.EQ, name); -// List loadBalancers = _loadBalancerDao.search(sc, null); -// if ((loadBalancers != null) && !loadBalancers.isEmpty()) { -// return loadBalancers.get(0); -// } -// return null; -// } - + + @Override + public List listByNetworkId(long networkId) { + List lbs = _lbDao.listByNetworkId(networkId); + List lbRules = new ArrayList(); + for (LoadBalancerVO lb : lbs) { + List dstList = getExistingDestinations(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); + lbRules.add(loadBalancing); + } + return lbRules; + } } diff --git a/server/src/com/cloud/network/ovs/GreTunnelException.java b/server/src/com/cloud/network/ovs/GreTunnelException.java new file mode 100644 index 00000000000..b88baee0259 --- /dev/null +++ b/server/src/com/cloud/network/ovs/GreTunnelException.java @@ -0,0 +1,7 @@ +package com.cloud.network.ovs; + +public class GreTunnelException extends Exception { + public GreTunnelException(String msg) { + super(msg); + } +} diff --git a/server/src/com/cloud/network/ovs/OvsListener.java b/server/src/com/cloud/network/ovs/OvsListener.java new file mode 100644 index 00000000000..213edaf7b5f --- /dev/null +++ b/server/src/com/cloud/network/ovs/OvsListener.java @@ -0,0 +1,191 @@ +package com.cloud.network.ovs; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.EntityExistsException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.PingRoutingWithOvsCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.exception.ConnectionException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.network.ovs.dao.GreTunnelDao; +import com.cloud.network.ovs.dao.GreTunnelVO; +import com.cloud.network.ovs.dao.OvsWorkDao; +import com.cloud.network.ovs.dao.OvsWorkVO.Step; +import com.cloud.network.ovs.dao.VlanMappingDao; +import com.cloud.network.ovs.dao.VlanMappingVO; +import com.cloud.utils.component.Inject; + +public class OvsListener implements Listener { + public static final Logger s_logger = Logger.getLogger(OvsListener.class.getName()); + OvsNetworkManager _ovsNetworkMgr; + OvsWorkDao _workDao; + GreTunnelDao _tunnelDao; + VlanMappingDao _mappingDao; + HostDao _hostDao; + + public OvsListener(OvsNetworkManager ovsMgr, OvsWorkDao workDao, GreTunnelDao tunnelDao, + VlanMappingDao mappingDao, HostDao hostDao) { + this._ovsNetworkMgr = ovsMgr; + this._workDao = workDao; + this._tunnelDao = tunnelDao; + this._mappingDao = mappingDao; + this._hostDao = hostDao; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + Set failedFlowVms = new HashSet(); + try { + for (Answer ans : answers) { + if (ans instanceof OvsCreateGreTunnelAnswer) { + OvsCreateGreTunnelAnswer r = (OvsCreateGreTunnelAnswer) ans; + String s = String + .format("(hostIP:%1$s, remoteIP:%2$s, bridge:%3$s, greKey:%4$s)", + r.getHostIp(), r.getRemoteIp(), + r.getBridge(), r.getKey()); + if (!r.getResult()) { + s_logger.warn("Create GRE tunnel failed due to " + + r.getDetails() + s); + } else { + GreTunnelVO tunnel = _tunnelDao.getByFromAndTo( + r.getFrom(), r.getTo()); + if (tunnel == null) { + throw new GreTunnelException( + "No record matches from = " + r.getFrom() + " to = " + r.getTo()); + } else { + tunnel.setInPort(r.getPort()); + _tunnelDao.update(tunnel.getId(), tunnel); + s_logger.info("Create GRE tunnel success" + s + + " from " + r.getFrom() + " to " + + r.getTo() + " inport=" + r.getPort()); + } + } + } else if (ans instanceof OvsSetTagAndFlowAnswer) { + OvsSetTagAndFlowAnswer r = (OvsSetTagAndFlowAnswer) ans; + if (!r.getResult()) { + s_logger.warn("Failed to set flow for VM " + + r.getVmId()); + _workDao.updateStep(r.getVmId(), r.getSeqNo(), + Step.Error); + failedFlowVms.add(r.getVmId()); + } else { + s_logger.info("Success to set flow for VM " + + r.getVmId()); + _workDao.updateStep(r.getVmId(), r.getSeqNo(), + Step.Done); + } + } + // TODO: handle delete failure + } + } catch (Exception e) { + e.printStackTrace(); + } + if (failedFlowVms.size() > 0) { + _ovsNetworkMgr.scheduleFlowUpdateToHosts(failedFlowVms, false, new Long(10*1000l)); + } + + return true; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + boolean processed = false; + for (Command cmd : commands) { + if (cmd instanceof PingRoutingWithOvsCommand) { + PingRoutingWithOvsCommand ping = (PingRoutingWithOvsCommand)cmd; + if (ping !=null && ping.getStates().size() > 0) { + _ovsNetworkMgr.fullSync(ping.getStates()); + } + processed = true; + } + } + return processed; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, + AgentControlCommand cmd) { + return null; + } + + @Override + public void processConnect(HostVO host, StartupCommand cmd) + throws ConnectionException { + if (host.getType() != Host.Type.Routing) { + return; + } + + List maps = _mappingDao.listByHostId(host.getId()); + if (maps.size() == 0) { + for (int i=0; i<512; i++) { + VlanMappingVO vo = new VlanMappingVO(0, host.getId(), i); + _mappingDao.persist(vo); + } + } + + try { + List hosts = _hostDao.listByType(Host.Type.Routing); + for (HostVO h : hosts) { + if (h.getId() == host.getId()) { + continue; + } + + GreTunnelVO t = _tunnelDao.getByFromAndTo(host.getId(), h.getId()); + if (t == null) { + t = new GreTunnelVO(host.getId(), h.getId()); + try { + _tunnelDao.persist(t); + } catch (EntityExistsException e) { + s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", host.getId(), h.getId())); + } + } + + t = _tunnelDao.getByFromAndTo(h.getId(), host.getId()); + if (t == null) { + t = new GreTunnelVO(h.getId(), host.getId()); + try { + _tunnelDao.persist(t); + } catch (EntityExistsException e) { + s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", h.getId(), host.getId())); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + return true; + } + + @Override + public boolean isRecurring() { + return false; + } + + @Override + public int getTimeout() { + return -1; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + return true; + } + +} diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManager.java b/server/src/com/cloud/network/ovs/OvsNetworkManager.java new file mode 100644 index 00000000000..6931886ca04 --- /dev/null +++ b/server/src/com/cloud/network/ovs/OvsNetworkManager.java @@ -0,0 +1,38 @@ +package com.cloud.network.ovs; + +import java.util.List; +import java.util.Set; + +import com.cloud.agent.manager.Commands; +import com.cloud.deploy.DeployDestination; +import com.cloud.utils.Pair; +import com.cloud.utils.component.Manager; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachineProfile; + +public interface OvsNetworkManager extends Manager { + public boolean isOvsNetworkEnabled(); + + public void UserVmCheckAndCreateTunnel(Commands cmds, + VirtualMachineProfile profile, DeployDestination dest) throws GreTunnelException; + + public void applyDefaultFlowToUserVm(Commands cmds, + VirtualMachineProfile profile, DeployDestination dest); + + public void applyDefaultFlowToRouter(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest); + + public void handleVmStateTransition(VMInstanceVO userVm, State vmState); + + public void RouterCheckAndCreateTunnel(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest) throws GreTunnelException; + + public void fullSync(List> states); + + public void scheduleFlowUpdateToHosts(Set affectedVms, boolean updateSeqno, Long delayMs); +} diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java new file mode 100644 index 00000000000..da5dd3a6641 --- /dev/null +++ b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java @@ -0,0 +1,689 @@ +package com.cloud.network.ovs; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import javax.persistence.EntityExistsException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.manager.Commands; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.ovs.dao.GreTunnelDao; +import com.cloud.network.ovs.dao.GreTunnelVO; +import com.cloud.network.ovs.dao.OvsWorkDao; +import com.cloud.network.ovs.dao.OvsWorkVO; +import com.cloud.network.ovs.dao.OvsWorkVO.Step; +import com.cloud.network.ovs.dao.VlanMappingDao; +import com.cloud.network.ovs.dao.VlanMappingDirtyDao; +import com.cloud.network.ovs.dao.VlanMappingVO; +import com.cloud.network.ovs.dao.VmFlowLogDao; +import com.cloud.network.ovs.dao.VmFlowLogVO; +import com.cloud.server.ManagementServer; +import com.cloud.user.AccountVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.Pair; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; + +@Local(value={OvsNetworkManager.class}) +public class OvsNetworkManagerImpl implements OvsNetworkManager { + private static final Logger s_logger = Logger.getLogger(OvsNetworkManagerImpl.class); + @Inject ConfigurationDao _configDao; + @Inject VlanMappingDao _vlanMappingDao; + @Inject UserVmDao _userVmDao; + @Inject HostDao _hostDao; + @Inject AgentManager _agentMgr; + @Inject NicDao _nicDao; + @Inject NetworkDao _networkDao; + @Inject VlanMappingDirtyDao _vlanMappingDirtyDao; + @Inject DomainRouterDao _routerDao; + @Inject OvsWorkDao _workDao; + @Inject VmFlowLogDao _flowLogDao; + @Inject UserVmDao _userVMDao; + @Inject VMInstanceDao _instanceDao; + @Inject AccountDao _accountDao; + @Inject GreTunnelDao _tunnelDao; + String _name; + boolean _isEnabled; + ScheduledExecutorService _executorPool; + ScheduledExecutorService _cleanupExecutor; + OvsListener _ovsListener; + + private long _serverId; + private final long _timeBetweenCleanups = 30; //seconds + + public class WorkerThread implements Runnable { + @Override + public void run() { + work(); + } + + WorkerThread() { + + } + } + + public class CleanupThread implements Runnable { + @Override + public void run() { + cleanupFinishedWork(); + cleanupUnfinishedWork(); + } + + CleanupThread() { + + } + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + _name = name; + _isEnabled = Boolean.parseBoolean(_configDao.getValue(Config.OvsNetwork.key())); + _serverId = ((ManagementServer)ComponentLocator.getComponent(ManagementServer.Name)).getId(); + _executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("OVS")); + _cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("OVS-Cleanup")); + _ovsListener = new OvsListener(this, _workDao, _tunnelDao, _vlanMappingDao, _hostDao); + _agentMgr.registerForHostEvents(_ovsListener, true, true, true); + + return true; + } + + @Override + public boolean start() { + if (_isEnabled) { + _cleanupExecutor.scheduleAtFixedRate(new CleanupThread(), _timeBetweenCleanups, _timeBetweenCleanups, TimeUnit.SECONDS); + } + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean isOvsNetworkEnabled() { + return _isEnabled; + } + + public void cleanupFinishedWork() { + Date before = new Date(System.currentTimeMillis() - 24*3600*1000l); + int numDeleted = _workDao.deleteFinishedWork(before); + if (numDeleted > 0) { + s_logger.info("Ovs cleanup deleted " + numDeleted + " finished work items older than " + before.toString()); + } + + } + + + private void cleanupUnfinishedWork() { + Date before = new Date(System.currentTimeMillis() - 30*1000l); + List unfinished = _workDao.findUnfinishedWork(before); + if (unfinished.size() > 0) { + s_logger.info("Ovscleanup found " + unfinished.size() + " unfinished work items older than " + before.toString()); + Set affectedVms = new HashSet(); + for (OvsWorkVO work: unfinished) { + affectedVms.add(work.getInstanceId()); + } + + s_logger.info("Ovs cleanup re-schedule unfinished work"); + scheduleFlowUpdateToHosts(affectedVms, false, null); + } else { + s_logger.debug("Ovs cleanup found no unfinished work items older than " + before.toString()); + } + } + + //TODO: think about lock, how new VM start when we change rows + @DB + public void work() { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Checking the database"); + } + final OvsWorkVO work = _workDao.take(_serverId); + if (work == null) { + return; + } + Long userVmId = work.getInstanceId(); + VirtualMachine vm = null; + Long seqnum = null; + Long vmId = work.getInstanceId(); + s_logger.info("Ovs working on " + work.toString()); + final Transaction txn = Transaction.currentTxn(); + txn.start(); + try { + vm = _userVMDao.acquireInLockTable(vmId); + if (vm == null) { + vm = _routerDao.acquireInLockTable(vmId); + if (vm == null) { + s_logger.warn("Ovs unable to acquire lock on vm id=" + userVmId); + return ; + } + } + + Long agentId = null; + VmFlowLogVO log = _flowLogDao.findByVmId(userVmId); + if (log == null) { + s_logger.warn("Ovs cannot find log record for vm id=" + userVmId); + return; + } + seqnum = log.getLogsequence(); + + if (vm != null && vm.getState() == State.Running) { + agentId = vm.getHostId(); + if (agentId != null ) { + String vlans = getVlanInPortMapping(vm.getAccountId(), vm.getHostId()); + String tag = Long.toString(_vlanMappingDao.findByAccountIdAndHostId( + vm.getAccountId(), vm.getHostId()).getVlan()); + + Commands cmds = new Commands(new OvsSetTagAndFlowCommand( + vm.getName(), tag, vlans, seqnum.toString(), + vm.getId())); + + try { + _agentMgr.send(agentId, cmds, _ovsListener); + } catch (AgentUnavailableException e) { + s_logger.debug("Unable to send updates for vm: " + + userVmId + "(agentid=" + agentId + ")"); + _workDao.updateStep(work.getInstanceId(), seqnum, + Step.Done); + } + } + } + } finally { + if (vm != null) { + if (vm.getType() == VirtualMachine.Type.User) { + _userVMDao.releaseFromLockTable(vmId); + } else if (vm.getType() == VirtualMachine.Type.DomainRouter) { + _routerDao.releaseFromLockTable(vmId); + } else { + assert 1 == 0 : "Should not be here"; + } + + _workDao.updateStep(work.getId(), Step.Done); + } + txn.commit(); + } + + + } + + @DB + protected long askVlanId(long accountId, long hostId) throws OvsVlanExhaustedException { + assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!"; + final Transaction txn = Transaction.currentTxn(); + txn.start(); + + VlanMappingVO currVlan = _vlanMappingDao.lockByAccountIdAndHostId(accountId, hostId); + long vlan = 0; + + if (currVlan != null) { + vlan = currVlan.getVlan(); + currVlan.ref(); + _vlanMappingDao.update(currVlan.getId(), currVlan); + s_logger.debug("Already has an Vlan " + vlan + " on host " + hostId + + " for account " + accountId + ", use it, reference count is " + currVlan.getRef()); + txn.commit(); + return vlan; + } + + Listmappings = _vlanMappingDao.listByHostId(hostId); + assert mappings.size() > 0: "where is my data!? it should be added when host connected!"; + + VlanMappingVO target = null; + for (VlanMappingVO vo : mappings) { + if (vo.getAccountId() == 0) { + target = _vlanMappingDao.lockRow(vo.getId(), true); + if (target == null || target.getAccountId() != 0) { + s_logger.debug("Someone took vlan mapping host = " + + vo.getHostId() + " vlan = " + vo.getVlan()); + continue; + } else { + break; + } + } + } + + if (target == null) { + throw new OvsVlanExhaustedException("vlan exhausted on host " + hostId); + } + + target.setAccountId(accountId); + target.ref(); + _vlanMappingDao.update(target.getId(), target); + _vlanMappingDirtyDao.markDirty(accountId); + String s = String.format("allocate a new vlan %1$s(account:%2$s, hostId:%3$s), mark dirty", + vlan, accountId, hostId); + s_logger.debug("OVSDIRTY:" + s); + txn.commit(); + return target.getVlan(); + } + + @DB + protected void CheckAndCreateTunnel(VMInstanceVO instance, + DeployDestination dest) throws GreTunnelException { + if (!_isEnabled) { + return; + } + + if (instance.getType() != VirtualMachine.Type.User + && instance.getType() != VirtualMachine.Type.DomainRouter) { + return; + } + + final Transaction txn = Transaction.currentTxn(); + long hostId = dest.getHost().getId(); + long accountId = instance.getAccountId(); + //TODO: considerate router? + Listvms = _userVmDao.listByAccountId(accountId); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + Listins = new ArrayList(); + ins.addAll(vms); + ins.add(router); + ListtoHostIds = new ArrayList(); + ListfromHostIds = new ArrayList(); + + for (VMInstanceVO v : ins) { + Long rh = v.getHostId(); + if (rh == null || rh.longValue() == hostId) { + continue; + } + + txn.start(); + GreTunnelVO tunnel = _tunnelDao.lockByFromAndTo(hostId, + rh.longValue()); + txn.commit(); + if (tunnel == null) { + throw new GreTunnelException(String.format( + "No entity(from=%1$s, to=%2$s) of failed to lock", + hostId, rh.longValue())); + } + + if (tunnel.getInPort() == 0 && !toHostIds.contains(rh)) { + toHostIds.add(rh); + } + + txn.start(); + tunnel = _tunnelDao.lockByFromAndTo(rh.longValue(), hostId); + txn.commit(); + if (tunnel == null) { + throw new GreTunnelException(String.format( + "No entity(from=%1$s, to=%2$s) of failed to lock", + rh.longValue(), hostId)); + } + + if (tunnel.getInPort() == 0 && !fromHostIds.contains(rh)) { + fromHostIds.add(rh); + } + } + + try { + String myIp = dest.getHost().getPrivateIpAddress(); + for (Long i : toHostIds) { + HostVO rHost = _hostDao.findById(i.longValue()); + Commands cmds = new Commands( + new OvsCreateGreTunnelCommand( + rHost.getPrivateIpAddress(), "1", hostId, + i.longValue())); + _agentMgr.send(hostId, cmds , _ovsListener); + s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i.longValue()); + } + + for (Long i : fromHostIds) { + Commands cmd2s = new Commands(new OvsCreateGreTunnelCommand(myIp, "1", i.longValue(), hostId)); + _agentMgr.send(i.longValue(), cmd2s , _ovsListener); + s_logger.debug("Ask host " + i.longValue() + " to create gre tunnel to " + hostId); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @DB + protected String getVlanInPortMapping(long accountId, long from) { + List tunnels = _tunnelDao.getByFrom(from); + if (tunnels.size() == 0) { + return "[]"; + } else { + List maps = new ArrayList(); + for (GreTunnelVO t : tunnels) { + VlanMappingVO m = _vlanMappingDao.findByAccountIdAndHostId(accountId, t.getTo()); + if (m == null) { + s_logger.debug("Host " + t.getTo() + " has no VM for account " + accountId + ", skip it"); + continue; + } + String s = String.format("%1$s:%2$s", m.getVlan(), t.getInPort()); + maps.add(s); + } + + return maps.toString(); + } + } + + protected void applyDefaultFlow(Commands cmds, + VMInstanceVO instance, DeployDestination dest) { + if (!_isEnabled) { + return; + } + + VirtualMachine.Type vmType = instance.getType(); + if (vmType != VirtualMachine.Type.User + && vmType != VirtualMachine.Type.DomainRouter) { + return; + } + + try { + long hostId = instance.getHostId(); + long accountId = instance.getAccountId(); + String tag = Long.toString(askVlanId(accountId, hostId)); + CheckAndUpdateDhcpFlow(instance); + String vlans = getVlanInPortMapping(accountId, hostId); + VmFlowLogVO log = _flowLogDao.findOrNewByVmId(instance.getId(), + instance.getName()); + cmds.addCommand(new OvsSetTagAndFlowCommand(instance.getName(), + tag, vlans, Long.toString(log.getLogsequence()), instance + .getId())); + } catch (OvsVlanExhaustedException e) { + e.printStackTrace(); + } + } + + //FIXME: if router has record in database but not start, this will hang 10 secs due to host + //plugin cannot found vif for router. + protected void CheckAndUpdateDhcpFlow(VMInstanceVO instance) { + if (!_isEnabled) { + return; + } + + if (instance.getType() == VirtualMachine.Type.DomainRouter) { + return; + } + + long accountId = instance.getAccountId(); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + if (router == null) { + return; + } + + if (!_vlanMappingDirtyDao.isDirty(accountId)) { + return; + } + + try { + long hostId = router.getHostId(); + String tag = Long.toString(_vlanMappingDao.findByAccountIdAndHostId(accountId, hostId).getVlan()); + VmFlowLogVO log = _flowLogDao.findOrNewByVmId(instance.getId(), instance.getName()); + String vlans = getVlanInPortMapping(accountId, hostId); + s_logger.debug("ask router " + router.getName() + " on host " + + hostId + " update vlan map to " + vlans); + Commands cmds = new Commands(new OvsSetTagAndFlowCommand( + router.getName(), tag, vlans, Long.toString(log.getLogsequence()), instance.getId())); + _agentMgr.send(router.getHostId(), cmds, _ovsListener); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @DB + @Override + public void scheduleFlowUpdateToHosts(Set affectedVms, boolean updateSeqno, Long delayMs) { + if (!_isEnabled) { + return; + } + + if (affectedVms == null) { + return; + } + + if (delayMs == null) { + delayMs = new Long(100l); + } + + for (Long vmId: affectedVms) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + VmFlowLogVO log = null; + OvsWorkVO work = null; + VirtualMachine vm = null; + try { + vm = _userVMDao.acquireInLockTable(vmId); + if (vm == null) { + vm = _routerDao.acquireInLockTable(vmId); + if (vm == null) { + s_logger.warn("Ovs failed to acquire lock on vm id " + vmId); + continue; + } + } + log = _flowLogDao.findOrNewByVmId(vmId, vm.getName()); + + if (log != null && updateSeqno){ + log.incrLogsequence(); + _flowLogDao.update(log.getId(), log); + } + + work = _workDao.findByVmIdStep(vmId, Step.Scheduled); + if (work == null) { + work = new OvsWorkVO(vmId, null, null, OvsWorkVO.Step.Scheduled, null); + work = _workDao.persist(work); + } + + work.setLogsequenceNumber(log.getLogsequence()); + _workDao.update(work.getId(), work); + } finally { + if (vm != null) { + if (vm.getType() == VirtualMachine.Type.User) { + _userVMDao.releaseFromLockTable(vmId); + } else if (vm.getType() == VirtualMachine.Type.DomainRouter) { + _routerDao.releaseFromLockTable(vmId); + } else { + assert 1 == 0 : "Should not be here"; + } + } + } + txn.commit(); + + _executorPool.schedule(new WorkerThread(), delayMs, TimeUnit.MILLISECONDS); + + } + } + + protected Set getAffectedVms(VMInstanceVO instance, boolean tellRouter) { + long accountId = instance.getAccountId(); + if (!_vlanMappingDirtyDao.isDirty(accountId)) { + s_logger.debug("OVSAFFECTED: no VM affected by " + instance.getName()); + return null; + } + + Set affectedVms = new HashSet(); + List vms = _userVmDao.listByAccountId(accountId); + for (UserVmVO vm : vms) { + affectedVms.add(new Long(vm.getId())); + } + + if (tellRouter && instance.getType() != VirtualMachine.Type.DomainRouter) { + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + if (router != null) { + affectedVms.add(new Long(router.getId())); + } + } + return affectedVms; + } + + protected void handleVmStateChange(VMInstanceVO instance, boolean tellRouter) { + Set affectedVms = getAffectedVms(instance, tellRouter); + scheduleFlowUpdateToHosts(affectedVms, true, null); + _vlanMappingDirtyDao.clean(instance.getAccountId()); + s_logger.debug("OVSDIRTY:Clean dirty for account " + instance.getAccountId()); + } + + @DB + protected void checkAndRemove(VMInstanceVO instance) { + long accountId = instance.getAccountId(); + long hostId = instance.getHostId(); + + final Transaction txn = Transaction.currentTxn(); + txn.start(); + VlanMappingVO vo = _vlanMappingDao.lockByAccountIdAndHostId(accountId, hostId); + assert vo!=null: "Why there is no record for account " + accountId + " host " + hostId; + if (vo.unref() == 0) { + vo.setAccountId(0); + _vlanMappingDirtyDao.markDirty(accountId); + String s = String.format("%1$s is the last VM(host:%2$s, accountId:%3$s), remove vlan", + instance.getName(), hostId, accountId); + s_logger.debug("OVSDIRTY:" + s); + } else { + s_logger.debug(instance.getName() + + " reduces reference count of (account,host) = (" + + accountId + "," + hostId + ") to " + vo.getRef()); + } + _vlanMappingDao.update(vo.getId(), vo); + _flowLogDao.deleteByVmId(instance.getId()); + txn.commit(); + + try { + Commands cmds = new Commands(new OvsDeleteFlowCommand(instance.getName())); + _agentMgr.send(hostId, cmds, _ovsListener); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void handleVmStateTransition(VMInstanceVO instance, State vmState) { + if (!_isEnabled) { + return; + } + + switch (vmState) { + case Creating: + case Destroyed: + case Error: + case Migrating: + case Expunging: + case Starting: + case Unknown: + return; + case Running: + handleVmStateChange(instance, false); + break; + case Stopping: + case Stopped: + checkAndRemove(instance); + handleVmStateChange(instance, true); + break; + } + + } + + @Override + public void UserVmCheckAndCreateTunnel(Commands cmds, + VirtualMachineProfile profile, DeployDestination dest) throws GreTunnelException { + CheckAndCreateTunnel(profile.getVirtualMachine(), dest); + } + + @Override + public void RouterCheckAndCreateTunnel(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest) throws GreTunnelException { + CheckAndCreateTunnel(profile.getVirtualMachine(), dest); + } + + @Override + public void applyDefaultFlowToUserVm(Commands cmds, + VirtualMachineProfile profile, DeployDestination dest) { + applyDefaultFlow(cmds, profile.getVirtualMachine(), dest); + + } + + @Override + public void applyDefaultFlowToRouter(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest) { + applyDefaultFlow(cmds, profile.getVirtualMachine(), dest); + } + + @Override + public void fullSync(List> states) { + if (!_isEnabled) { + return; + } + + //TODO:debug code, remove in future + List accounts = _accountDao.listAll(); + for (AccountVO acnt : accounts) { + if (_vlanMappingDirtyDao.isDirty(acnt.getId())) { + s_logger.warn("Vlan mapping for account " + + acnt.getAccountName() + " id " + acnt.getId() + + " is dirty"); + } + } + + if (states.size() ==0) { + s_logger.info("Nothing to do, Ovs fullsync is happy"); + return; + } + + SetvmIds = new HashSet(); + for (Pairstate : states) { + if (state.second() == -1) { + s_logger.warn("Ovs fullsync get wrong seqno for " + state.first()); + continue; + } + VmFlowLogVO log = _flowLogDao.findByName(state.first()); + if (log.getLogsequence() != state.second()) { + s_logger.debug("Ovs fullsync detected unmatch seq number for " + state.first() + ", run sync"); + VMInstanceVO vo = _instanceDao.findById(log.getInstanceId()); + if (vo == null) { + s_logger.warn("Ovs can't find " + state.first() + " in vm_instance!"); + continue; + } + + if (vo.getType() != VirtualMachine.Type.User && vo.getType() != VirtualMachine.Type.DomainRouter) { + s_logger.warn("Ovs fullsync: why we sync a " + vo.getType().toString() + " VM???"); + continue; + } + vmIds.add(new Long(vo.getId())); + } + } + + if (vmIds.size() > 0) { + scheduleFlowUpdateToHosts(vmIds, false, null); + } + } + +} diff --git a/server/src/com/cloud/network/ovs/OvsVlanExhaustedException.java b/server/src/com/cloud/network/ovs/OvsVlanExhaustedException.java new file mode 100644 index 00000000000..fcf9e6dad4d --- /dev/null +++ b/server/src/com/cloud/network/ovs/OvsVlanExhaustedException.java @@ -0,0 +1,7 @@ +package com.cloud.network.ovs; + +public class OvsVlanExhaustedException extends Exception { + public OvsVlanExhaustedException(String msg) { + super(msg); + } +} diff --git a/server/src/com/cloud/network/ovs/dao/GreTunnelDao.java b/server/src/com/cloud/network/ovs/dao/GreTunnelDao.java new file mode 100644 index 00000000000..2faa31e6af6 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/GreTunnelDao.java @@ -0,0 +1,11 @@ +package com.cloud.network.ovs.dao; + +import java.util.List; + +import com.cloud.utils.db.GenericDao; + +public interface GreTunnelDao extends GenericDao { + List getByFrom(long from); + GreTunnelVO getByFromAndTo(long from, long To); + GreTunnelVO lockByFromAndTo(long from, long to); +} diff --git a/server/src/com/cloud/network/ovs/dao/GreTunnelDaoImpl.java b/server/src/com/cloud/network/ovs/dao/GreTunnelDaoImpl.java new file mode 100644 index 00000000000..05a6c4b94d7 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/GreTunnelDaoImpl.java @@ -0,0 +1,52 @@ +package com.cloud.network.ovs.dao; + +import java.util.List; + +import javax.ejb.Local; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Local(value = { GreTunnelDao.class }) +public class GreTunnelDaoImpl extends GenericDaoBase + implements GreTunnelDao { + protected final SearchBuilder fromSearch; + protected final SearchBuilder fromToSearch; + + public GreTunnelDaoImpl() { + fromSearch = createSearchBuilder(); + fromSearch.and("from", fromSearch.entity().getFrom(), Op.EQ); + fromSearch.done(); + + fromToSearch = createSearchBuilder(); + fromToSearch.and("from", fromToSearch.entity().getFrom(), Op.EQ); + fromToSearch.and("to", fromToSearch.entity().getTo(), Op.EQ); + fromToSearch.done(); + } + + @Override + public List getByFrom(long from) { + SearchCriteria sc = fromSearch.create(); + sc.setParameters("from", from); + return listBy(sc, null); + } + + @Override + public GreTunnelVO getByFromAndTo(long from, long to) { + SearchCriteria sc = fromToSearch.create(); + sc.setParameters("from", from); + sc.setParameters("to", to); + return findOneBy(sc); + } + + @Override + public GreTunnelVO lockByFromAndTo(long from, long to) { + SearchCriteria sc = fromToSearch.create(); + sc.setParameters("from", from); + sc.setParameters("to", to); + return lockOneRandomRow(sc, true); + } + +} diff --git a/server/src/com/cloud/network/ovs/dao/GreTunnelVO.java b/server/src/com/cloud/network/ovs/dao/GreTunnelVO.java new file mode 100644 index 00000000000..94697e55a60 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/GreTunnelVO.java @@ -0,0 +1,64 @@ +package com.cloud.network.ovs.dao; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name=("ovs_tunnel_alloc")) +public class GreTunnelVO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "from") + private long from; + + @Column(name = "to") + private long to; + + @Column(name = "in_port") + private int inPort; + + public GreTunnelVO() { + + } + + public GreTunnelVO(long from, long to) { + this.from = from; + this.to = to; + this.inPort = 0; + } + + public GreTunnelVO(long id, long from, long to) { + this.from = from; + this.to = to; + this.inPort = 0; + this.id = id; + } + + public void setInPort(int port) { + inPort = port; + } + + public long getFrom() { + return from; + } + + public long getTo() { + return to; + } + + public int getInPort() { + return inPort; + } + + public long getId() { + return id; + } + +} diff --git a/server/src/com/cloud/network/ovs/dao/OvsWorkDao.java b/server/src/com/cloud/network/ovs/dao/OvsWorkDao.java new file mode 100644 index 00000000000..048de9d9c78 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsWorkDao.java @@ -0,0 +1,23 @@ +package com.cloud.network.ovs.dao; + +import java.util.Date; +import java.util.List; + +import com.cloud.network.ovs.dao.OvsWorkVO.Step; +import com.cloud.utils.db.GenericDao; + +public interface OvsWorkDao extends GenericDao { + OvsWorkVO findByVmId(long vmId, boolean taken); + + OvsWorkVO findByVmIdStep(long vmId, Step step); + + OvsWorkVO take(long serverId); + + void updateStep(Long vmId, Long logSequenceNumber, Step done); + + void updateStep(Long workId, Step done); + + int deleteFinishedWork(Date timeBefore); + + List findUnfinishedWork(Date timeBefore); +} diff --git a/server/src/com/cloud/network/ovs/dao/OvsWorkDaoImpl.java b/server/src/com/cloud/network/ovs/dao/OvsWorkDaoImpl.java new file mode 100644 index 00000000000..4c0f572cda8 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsWorkDaoImpl.java @@ -0,0 +1,189 @@ +package com.cloud.network.ovs.dao; + +import java.util.Date; +import java.util.List; +import javax.ejb.Local; +import com.cloud.ha.HaWorkVO; +import com.cloud.network.ovs.dao.OvsWorkVO.Step; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; + +@Local(value={OvsWorkDao.class}) +public class OvsWorkDaoImpl extends GenericDaoBase implements + OvsWorkDao { + private SearchBuilder VmIdTakenSearch; + private SearchBuilder VmIdSeqNumSearch; + private SearchBuilder VmIdUnTakenSearch; + private SearchBuilder UntakenWorkSearch; + private SearchBuilder VmIdStepSearch; + private SearchBuilder CleanupSearch; + + + protected OvsWorkDaoImpl() { + VmIdTakenSearch = createSearchBuilder(); + VmIdTakenSearch.and("vmId", VmIdTakenSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + VmIdTakenSearch.and("taken", VmIdTakenSearch.entity().getDateTaken(), SearchCriteria.Op.NNULL); + + VmIdTakenSearch.done(); + + VmIdUnTakenSearch = createSearchBuilder(); + VmIdUnTakenSearch.and("vmId", VmIdUnTakenSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + VmIdUnTakenSearch.and("taken", VmIdUnTakenSearch.entity().getDateTaken(), SearchCriteria.Op.NULL); + + VmIdUnTakenSearch.done(); + + UntakenWorkSearch = createSearchBuilder(); + UntakenWorkSearch.and("server", UntakenWorkSearch.entity().getServerId(), SearchCriteria.Op.NULL); + UntakenWorkSearch.and("taken", UntakenWorkSearch.entity().getDateTaken(), SearchCriteria.Op.NULL); + UntakenWorkSearch.and("step", UntakenWorkSearch.entity().getStep(), SearchCriteria.Op.EQ); + + UntakenWorkSearch.done(); + + VmIdSeqNumSearch = createSearchBuilder(); + VmIdSeqNumSearch.and("vmId", VmIdSeqNumSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + VmIdSeqNumSearch.and("seqno", VmIdSeqNumSearch.entity().getLogsequenceNumber(), SearchCriteria.Op.EQ); + + VmIdSeqNumSearch.done(); + + VmIdStepSearch = createSearchBuilder(); + VmIdStepSearch.and("vmId", VmIdStepSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + VmIdStepSearch.and("step", VmIdStepSearch.entity().getStep(), SearchCriteria.Op.EQ); + + VmIdStepSearch.done(); + + CleanupSearch = createSearchBuilder(); + CleanupSearch.and("taken", CleanupSearch.entity().getDateTaken(), Op.LTEQ); + CleanupSearch.and("step", CleanupSearch.entity().getStep(), SearchCriteria.Op.IN); + + CleanupSearch.done(); + + + } + + @Override + public OvsWorkVO findByVmId(long vmId, boolean taken) { + SearchCriteria sc = taken?VmIdTakenSearch.create():VmIdUnTakenSearch.create(); + sc.setParameters("vmId", vmId); + return findOneIncludingRemovedBy(sc); + } + + @Override + public OvsWorkVO take(long serverId) { + final Transaction txn = Transaction.currentTxn(); + try { + final SearchCriteria sc = UntakenWorkSearch.create(); + sc.setParameters("step", Step.Scheduled); + + final Filter filter = new Filter(OvsWorkVO.class, null, true, 0l, 1l);//FIXME: order desc by update time? + + txn.start(); + final List vos = lockRows(sc, filter, true); + if (vos.size() == 0) { + txn.commit(); + return null; + } + OvsWorkVO work = null; + for (OvsWorkVO w: vos) { + //ensure that there is no job in Processing state for the same VM + if ( findByVmIdStep(w.getInstanceId(), Step.Processing) == null) { + work = w; + break; + } + } + if (work == null) { + txn.commit(); + return null; + } + work.setServerId(serverId); + work.setDateTaken(new Date()); + work.setStep(OvsWorkVO.Step.Processing); + + update(work.getId(), work); + + txn.commit(); + + return work; + + } catch (final Throwable e) { + throw new CloudRuntimeException("Unable to execute take", e); + } + } + + @Override + @DB + public void updateStep(Long vmId, Long logSequenceNumber, Step step) { + final Transaction txn = Transaction.currentTxn(); + txn.start(); + SearchCriteria sc = VmIdSeqNumSearch.create(); + sc.setParameters("vmId", vmId); + sc.setParameters("seqno", logSequenceNumber); + + final Filter filter = new Filter(HaWorkVO.class, null, true, 0l, 1l); + + final List vos = lockRows(sc, filter, true); + if (vos.size() == 0) { + txn.commit(); + return; + } + OvsWorkVO work = vos.get(0); + work.setStep(step); + update(work.getId(), work); + + txn.commit(); + } + + @Override + public OvsWorkVO findByVmIdStep(long vmId, Step step) { + SearchCriteria sc = VmIdStepSearch.create(); + sc.setParameters("vmId", vmId); + sc.setParameters("step", step); + return findOneIncludingRemovedBy(sc); + } + + @Override + public void updateStep(Long workId, Step step) { + final Transaction txn = Transaction.currentTxn(); + txn.start(); + + OvsWorkVO work = lockRow(workId, true); + if (work == null) { + txn.commit(); + return; + } + work.setStep(step); + update(work.getId(), work); + + txn.commit(); + + } + + @Override + public int deleteFinishedWork(Date timeBefore) { + final SearchCriteria sc = CleanupSearch.create(); + sc.setParameters("taken", timeBefore); + sc.setParameters("step", Step.Done); + + return expunge(sc); + } + + @Override + public List findUnfinishedWork(Date timeBefore) { + final SearchCriteria sc = CleanupSearch.create(); + sc.setParameters("taken", timeBefore); + sc.setParameters("step", Step.Processing); + + List result = listIncludingRemovedBy(sc); + + OvsWorkVO work = createForUpdate(); + work.setStep(Step.Error); + update(work, sc); + + return result; + } +} diff --git a/server/src/com/cloud/network/ovs/dao/OvsWorkVO.java b/server/src/com/cloud/network/ovs/dao/OvsWorkVO.java new file mode 100644 index 00000000000..0a49f583c05 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/OvsWorkVO.java @@ -0,0 +1,123 @@ +package com.cloud.network.ovs.dao; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import com.cloud.utils.db.GenericDao; + + +@Entity +@Table(name="ovs_work") +public class OvsWorkVO { + public enum Step { + Scheduled, + Processing, + Done, + Error + } + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private Long id; + + @Column(name="instance_id", updatable=false, nullable=false) + private Long instanceId; // vm_instance id + + + @Column(name="mgmt_server_id", nullable=true) + private Long serverId; + + @Column(name=GenericDao.CREATED_COLUMN) + private Date created; + + + @Column(name="step", nullable = false) + @Enumerated(value=EnumType.STRING) + private Step step; + + @Column(name="taken", nullable=true) + @Temporal(value=TemporalType.TIMESTAMP) + private Date dateTaken; + + @Column(name="seq_no", nullable=true) + private Long logsequenceNumber = null; + + + protected OvsWorkVO() { + } + + public Long getId() { + return id; + } + + public Long getInstanceId() { + return instanceId; + } + + + public Long getServerId() { + return serverId; + } + + + public void setServerId(final Long serverId) { + this.serverId = serverId; + } + + public Date getCreated() { + return created; + } + + + + public OvsWorkVO(Long instanceId, Long serverId, Date created, + Step step, Date dateTaken) { + super(); + this.instanceId = instanceId; + this.serverId = serverId; + this.created = created; + this.step = step; + this.dateTaken = dateTaken; + } + + @Override + public String toString() { + return new StringBuilder("[Ovs-Work:id=").append(id).append(":vm=").append(instanceId).append("]").toString(); + } + + public Date getDateTaken() { + return dateTaken; + } + + public void setStep(Step step) { + this.step = step; + } + + public Step getStep() { + return step; + } + + public void setDateTaken(Date date) { + dateTaken = date; + } + + public Long getLogsequenceNumber() { + return logsequenceNumber; + } + + public void setLogsequenceNumber(Long logsequenceNumber) { + this.logsequenceNumber = logsequenceNumber; + } + +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDao.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDao.java new file mode 100644 index 00000000000..fe5a58d3707 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDao.java @@ -0,0 +1,19 @@ +package com.cloud.network.ovs.dao; + +import java.util.List; + +import com.cloud.utils.db.GenericDao; + +public interface VlanMappingDao extends GenericDao { + List listByAccountIdAndHostId(long accountId, long hostId); + + List listByHostId(long hostId); + + List listByAccountId(long accountId); + + List lockByAccountId(long accoutnId); + + VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId); + + VlanMappingVO lockByAccountIdAndHostId(long accountId, long hostId); +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java new file mode 100644 index 00000000000..59d969cf076 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java @@ -0,0 +1,88 @@ +package com.cloud.network.ovs.dao; + +import java.util.List; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +import javax.ejb.Local; + +@Local(value = { VlanMappingDao.class }) +public class VlanMappingDaoImpl extends GenericDaoBase + implements VlanMappingDao { + protected final SearchBuilder accountIdSearch; + protected final SearchBuilder hostSearch; + protected final SearchBuilder accountHostSearch; + + public VlanMappingDaoImpl() { + super(); + accountHostSearch = createSearchBuilder(); + accountHostSearch.and("host_id", accountHostSearch.entity().getHostId(), Op.EQ); + accountHostSearch.and("account_id", accountHostSearch.entity().getAccountId(), Op.EQ); + accountHostSearch.done(); + + accountIdSearch = createSearchBuilder(); + accountIdSearch.and("account_id", accountIdSearch.entity().getAccountId(), Op.EQ); + accountIdSearch.done(); + + hostSearch = createSearchBuilder(); + hostSearch.and("host_id", hostSearch.entity().getHostId(), Op.EQ); + hostSearch.done(); + } + + @Override + public List listByAccountIdAndHostId(long accountId, + long hostId) { + SearchCriteria sc = accountHostSearch.create(); + sc.setParameters("account_id", accountId); + sc.setParameters("host_id", hostId); + return listBy(sc, null); + } + + @Override + public List listByHostId(long hostId) { + SearchCriteria sc = hostSearch.create(); + sc.setParameters("host_id", hostId); + + return listBy(sc, null); + } + + @Override + public List listByAccountId(long accountId) { + SearchCriteria sc = accountIdSearch.create(); + sc.setParameters("account_id", accountId); + + return listBy(sc, null); + } + + @Override + public VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId) { + return getByAccountIdAndHostId(accountId, hostId, false); + } + + @Override + public List lockByAccountId(long accountId) { + SearchCriteria sc = accountIdSearch.create(); + sc.setParameters("account_id", accountId); + return lockRows(sc, null, true); + } + + @Override + public VlanMappingVO lockByAccountIdAndHostId(long accountId, long hostId) { + return getByAccountIdAndHostId(accountId, hostId, true); + } + + private VlanMappingVO getByAccountIdAndHostId(long accountId, long hostId, boolean lock) { + SearchCriteria sc = accountHostSearch.create(); + sc.setParameters("account_id", accountId); + sc.setParameters("host_id", hostId); + + if (!lock) { + return findOneBy(sc); + } else { + return lockOneRandomRow(sc, true); + } + } +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDao.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDao.java new file mode 100644 index 00000000000..1719ab26bf0 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDao.java @@ -0,0 +1,9 @@ +package com.cloud.network.ovs.dao; + +import com.cloud.utils.db.GenericDao; + +public interface VlanMappingDirtyDao extends GenericDao { + public boolean isDirty(long accountId); + public void markDirty(long accountId); + public void clean(long accountId); +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java new file mode 100644 index 00000000000..fb6739b7cda --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java @@ -0,0 +1,61 @@ +package com.cloud.network.ovs.dao; + +import javax.ejb.Local; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Local(value = { VlanMappingDirtyDao.class }) +public class VlanMappingDirtyDaoImpl extends + GenericDaoBase implements VlanMappingDirtyDao { + protected final SearchBuilder AccountIdSearch; + + public VlanMappingDirtyDaoImpl() { + super(); + AccountIdSearch = createSearchBuilder(); + AccountIdSearch.and("account_id", AccountIdSearch.entity().getAccountId(), Op.EQ); + AccountIdSearch.done(); + } + + @Override + public boolean isDirty(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("account_id", accountId); + VlanMappingDirtyVO vo = findOneBy(sc); + if (vo == null) { + return false; + } + return vo.isDirty(); + } + + @Override + public void markDirty(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("account_id", accountId); + VlanMappingDirtyVO vo = findOneBy(sc); + if (vo == null) { + vo = new VlanMappingDirtyVO(accountId, true); + persist(vo); + } else { + vo.markDirty(); + update(vo, sc); + } + } + + @Override + public void clean(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("account_id", accountId); + VlanMappingDirtyVO vo = findOneBy(sc); + if (vo == null) { + vo = new VlanMappingDirtyVO(accountId, false); + persist(vo); + } else { + vo.clean(); + update(vo, sc); + } + } + +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java new file mode 100644 index 00000000000..7a921609dfc --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java @@ -0,0 +1,55 @@ +package com.cloud.network.ovs.dao; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name=("ovs_vlan_mapping_dirty")) +public class VlanMappingDirtyVO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "dirty") + private boolean dirty; + + @Column(name = "account_id") + private long accountId; + + public VlanMappingDirtyVO() { + + } + + public VlanMappingDirtyVO(long accountId, boolean dirty) { + this.accountId = accountId; + this.dirty = dirty; + } + + public long getId() { + return id; + } + + public long getAccountId() { + return accountId; + } + + public boolean isDirty() { + return dirty; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + public void markDirty() { + setDirty(true); + } + public void clean() { + setDirty(false); + } +} diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java b/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java new file mode 100644 index 00000000000..487bfb1153d --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java @@ -0,0 +1,79 @@ +package com.cloud.network.ovs.dao; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Column; + +@Entity +@Table(name=("ovs_host_vlan_alloc")) +public class VlanMappingVO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "host_id") + private long hostId; + + @Column(name = "account_id") + private long accountId; + + @Column(name = "vlan") + private long vlan; + + @Column(name = "ref") + int ref; + + public VlanMappingVO(long accountId, long hostId, long vlan) { + this.hostId = hostId; + this.accountId = accountId; + this.vlan = vlan; + this.ref = 0; + } + + public VlanMappingVO() { + + } + + public long getHostId() { + return hostId; + } + + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + public long getVlan() { + return vlan; + } + + public long getId() { + return id; + } + + public int getRef() { + return ref; + } + + public void setRef(int ref) { + this.ref = ref; + } + + public void ref() { + ref++; + setRef(ref); + } + + public int unref() { + ref--; + setRef(ref); + return getRef(); + } +} diff --git a/server/src/com/cloud/network/ovs/dao/VmFlowLogDao.java b/server/src/com/cloud/network/ovs/dao/VmFlowLogDao.java new file mode 100644 index 00000000000..a8a97e48094 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VmFlowLogDao.java @@ -0,0 +1,10 @@ +package com.cloud.network.ovs.dao; + +import com.cloud.utils.db.GenericDao; + +public interface VmFlowLogDao extends GenericDao { + VmFlowLogVO findByVmId(long vmId); + VmFlowLogVO findOrNewByVmId(long vmId, String name); + VmFlowLogVO findByName(String name); + void deleteByVmId(long vmId); +} diff --git a/server/src/com/cloud/network/ovs/dao/VmFlowLogDaoImpl.java b/server/src/com/cloud/network/ovs/dao/VmFlowLogDaoImpl.java new file mode 100644 index 00000000000..b7d44fe01ba --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VmFlowLogDaoImpl.java @@ -0,0 +1,57 @@ +package com.cloud.network.ovs.dao; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import javax.ejb.Local; + +@Local(value={VmFlowLogDao.class}) +public class VmFlowLogDaoImpl extends GenericDaoBase + implements VmFlowLogDao { + private SearchBuilder VmIdSearch; + private SearchBuilder VmNameSearch; + + @Override + public VmFlowLogVO findByVmId(long vmId) { + SearchCriteria sc = VmIdSearch.create(); + sc.setParameters("vmId", vmId); + return findOneIncludingRemovedBy(sc); + } + + protected VmFlowLogDaoImpl() { + VmIdSearch = createSearchBuilder(); + VmIdSearch.and("vmId", VmIdSearch.entity().getInstanceId(), + SearchCriteria.Op.EQ); + VmIdSearch.done(); + + VmNameSearch = createSearchBuilder(); + VmNameSearch.and("name", VmNameSearch.entity().getName(), + SearchCriteria.Op.EQ); + VmNameSearch.done(); + + } + + @Override + public VmFlowLogVO findOrNewByVmId(long vmId, String name) { + VmFlowLogVO log = findByVmId(vmId); + if (log == null) { + log = new VmFlowLogVO(vmId, name); + log = persist(log); + } + return log; + } + + @Override + public void deleteByVmId(long vmId) { + SearchCriteria sc = VmIdSearch.create(); + sc.setParameters("vmId", vmId); + expunge(sc); + } + + @Override + public VmFlowLogVO findByName(String name) { + SearchCriteria sc = VmNameSearch.create(); + sc.setParameters("name", name); + return findOneIncludingRemovedBy(sc); + } +} diff --git a/server/src/com/cloud/network/ovs/dao/VmFlowLogVO.java b/server/src/com/cloud/network/ovs/dao/VmFlowLogVO.java new file mode 100644 index 00000000000..13733185d28 --- /dev/null +++ b/server/src/com/cloud/network/ovs/dao/VmFlowLogVO.java @@ -0,0 +1,67 @@ +package com.cloud.network.ovs.dao; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.utils.db.GenericDao; + +@Entity +@Table(name="ovs_vm_flow_log") +public class VmFlowLogVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private Long id; + + @Column(name="instance_id", updatable=false, nullable=false) + private Long instanceId; // vm_instance id + + @Column(name=GenericDao.CREATED_COLUMN) + private Date created; + + @Column(name="logsequence") + long logsequence; + + @Column(name="vm_name", updatable=false, nullable=false, length=255) + protected String name = null; + + protected VmFlowLogVO() { + + } + + public VmFlowLogVO(Long instanceId, String name) { + super(); + this.instanceId = instanceId; + this.name = name; + } + + public Long getId() { + return id; + } + + public Long getInstanceId() { + return instanceId; + } + + public Date getCreated() { + return created; + } + + public long getLogsequence() { + return logsequence; + } + + public void incrLogsequence() { + logsequence++; + } + + public String getName() { + return name; + } +} diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 7fedecfac4a..091d3ac1234 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -72,8 +72,10 @@ import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; +import com.cloud.dc.Vlan; import com.cloud.dc.dao.AccountVlanMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; @@ -103,6 +105,7 @@ import com.cloud.network.IPAddressVO; import com.cloud.network.IpAddress; import com.cloud.network.LoadBalancerVO; import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; @@ -126,14 +129,14 @@ import com.cloud.network.dao.VpnUserDao; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRulesManager; +import com.cloud.network.ovs.GreTunnelException; +import com.cloud.network.ovs.OvsNetworkManager; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.PortForwardingRuleVO; import com.cloud.network.rules.RulesManager; import com.cloud.network.rules.dao.PortForwardingRulesDao; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.service.ServiceOfferingVO; @@ -172,6 +175,7 @@ import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineGuru; @@ -181,6 +185,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; /** * VirtualNetworkApplianceManagerImpl manages the different types of @@ -289,6 +294,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian PortForwardingRulesDao _pfRulesDao; @Inject RemoteAccessVpnDao _vpnDao; + @Inject + VMInstanceDao _instanceDao; + @Inject + OvsNetworkManager _ovsNetworkMgr; long _routerTemplateId = -1; int _routerRamSize; @@ -304,7 +313,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian private int _networkRate; private int _multicastRate; String _networkDomain; - boolean _noDefaultRouteForDirectNetwork; private VMTemplateVO _template; @@ -340,51 +348,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (s_logger.isDebugEnabled()) { s_logger.debug("Attempting to destroy router " + routerId); } - - DomainRouterVO router = _routerDao.acquireInLockTable(routerId); - + + DomainRouterVO router = _routerDao.findById(routerId); if (router == null) { - s_logger.debug("Unable to acquire lock on router " + routerId); - return false; + return true; } - - try { - if (router.getState() == State.Destroyed || router.getState() == State.Expunging || router.getRemoved() != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find router or router is destroyed: " + routerId); - } - return true; - } - - if (stopRouterInternal(router.getId())) { - return false; - } - - router = _routerDao.findById(routerId); - if (!_itMgr.stateTransitTo(router, VirtualMachine.Event.DestroyRequested, router.getHostId())) { - s_logger.debug("VM " + router.toString() + " is not in a state to be destroyed."); - return false; - } - } finally { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Release lock on router " + routerId + " for stop"); - } - _routerDao.releaseFromLockTable(routerId); - } - - router.setPublicIpAddress(null); - router.setVlanDbId(null); - _routerDao.update(router.getId(), router); - _routerDao.remove(router.getId()); - - List vols = _volsDao.findByInstance(routerId); - _storageMgr.destroy(router, vols); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully destroyed router: " + routerId); - } - - return true; + return _itMgr.expunge(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); } @Override @@ -562,7 +531,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian userStats.setNetBytesSent(userStats.getNetBytesSent() + netBytes); userStats.setCurrentBytesSent(0); _userStatsDao.update(userStats.getId(), userStats); - s_logger.debug("Successfully updated user statistics as a part of domR id=" + router.getId() + " reboot/stop"); + s_logger.debug("Successfully updated user statistics as a part of domR " + router + " reboot/stop"); } else { s_logger.warn("User stats were not created for account " + router.getAccountId() + " and dc " + router.getDataCenterId()); } @@ -618,12 +587,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian throw new ResourceUnavailableException("Unable to reboot domR, it is not in right state " + router.getState(), DataCenter.class, router.getDataCenterId()); } - s_logger.debug("Stopping and starting router id=" + router.getId() + " as a part of router reboot"); + s_logger.debug("Stopping and starting router " + router + " as a part of router reboot"); if (stopRouter(routerId) != null) { return startRouter(routerId); } else { - throw new CloudRuntimeException("Failed to reboot router id=" + router.getId()); + throw new CloudRuntimeException("Failed to reboot router " + router); } } @@ -680,7 +649,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian _networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr)); _multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); _offering = new ServiceOfferingVO("System Offering For Software Router", 1, _routerRamSize, 0, 0, 0, true, null, - NetworkOffering.GuestIpType.Virtual, useLocalStorage, true, null, true); + Network.GuestIpType.Virtual, useLocalStorage, true, null, true); _offering.setUniqueName("Cloud.Com-SoftwareRouter"); _offering = _serviceOfferingDao.persistSystemServiceOffering(_offering); _template = _templateDao.findRoutingTemplate(); @@ -691,8 +660,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } _systemAcct = _accountService.getSystemAccount(); - - _noDefaultRouteForDirectNetwork = Boolean.parseBoolean(configs.get(Config.DirectNetworkNoDefaultRoute.key())); s_logger.info("DomainRouterManager is configured."); @@ -731,11 +698,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } } - @Override - public void completeStartCommand(final DomainRouterVO router) { - _itMgr.stateTransitTo(router, VirtualMachine.Event.AgentReportRunning, router.getHostId()); - } - @Override public void completeStopCommand(final DomainRouterVO router) { completeStopCommand(router, VirtualMachine.Event.AgentReportStopped); @@ -901,12 +863,22 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian @Override public void run() { try { - final List ids = _routerDao.findLonelyRouters(); - s_logger.info("Found " + ids.size() + " routers to stop. "); - - for (final Long id : ids) { - stopRouterInternal(id); + final List ids = findLonelyRouters(); + Long size; + if (ids == null || ids.isEmpty()) { + size = 0L; + } else { + size = Long.valueOf(ids.size()); } + + s_logger.info("Found " + size + " routers to stop. "); + + if (ids != null) { + for (final Long id : ids) { + stopRouterInternal(id); + } + } + s_logger.info("Done my job. Time to rest."); } catch (Exception e) { s_logger.warn("Unable to stop routers. Will retry. ", e); @@ -1023,13 +995,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian PublicIp sourceNatIp = _networkMgr.assignSourceNatIpAddress(owner, guestNetwork, _accountService.getSystemUser().getId()); - List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork); + List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork); NetworkOfferingVO controlOffering = offerings.get(0); - NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false).get(0); + NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false, false).get(0); List> networks = new ArrayList>(3); - NetworkOfferingVO publicOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmPublicNetwork).get(0); - List publicConfigs = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false); + NetworkOfferingVO publicOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork).get(0); + List publicConfigs = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false, false); NicProfile defaultNic = new NicProfile(); defaultNic.setDefaultNic(true); defaultNic.setIp4Address(sourceNatIp.getAddress().addr()); @@ -1037,13 +1009,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian defaultNic.setNetmask(sourceNatIp.getNetmask()); defaultNic.setTrafficType(TrafficType.Public); defaultNic.setMacAddress(sourceNatIp.getMacAddress()); - if (sourceNatIp.getVlanTag().equals("untagged")) { - defaultNic.setBroadcastType(BroadcastDomainType.Native); - } else { - defaultNic.setBroadcastType(BroadcastDomainType.Vlan); - defaultNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag())); - defaultNic.setIsolationUri(IsolationType.Vlan.toUri(sourceNatIp.getVlanTag())); - } + defaultNic.setBroadcastType(BroadcastDomainType.Vlan); + defaultNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag())); + defaultNic.setIsolationUri(IsolationType.Vlan.toUri(sourceNatIp.getVlanTag())); defaultNic.setDeviceId(2); networks.add(new Pair(publicConfigs.get(0), defaultNic)); NicProfile gatewayNic = new NicProfile(); @@ -1054,14 +1022,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian gatewayNic.setMode(guestNetwork.getMode()); String gatewayCidr = guestNetwork.getCidr(); - String[] cidrPair = gatewayCidr.split("\\/"); - long guestCidrSize = Long.parseLong(cidrPair[1]); - gatewayNic.setNetmask(NetUtils.getCidrNetmask(guestCidrSize)); + gatewayNic.setNetmask(NetUtils.getCidrNetmask(gatewayCidr)); networks.add(new Pair((NetworkVO) guestNetwork, gatewayNic)); networks.add(new Pair(controlConfig, null)); router = new DomainRouterVO(id, _offering.getId(), VirtualMachineName.getRouterName(id, _instance), _template.getId(), - _template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), _offering.getOfferHA()); + _template.getHypervisorType(), _template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), _offering.getOfferHA()); router = _itMgr.allocate(router, _template, _offering, networks, plan, null, owner); if(router != null){ EventUtils.saveEvent(User.UID_SYSTEM, owner.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ROUTER_CREATE, "successfully create router : " + router.getName(), startEventId); @@ -1069,10 +1035,23 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian EventUtils.saveEvent(User.UID_SYSTEM, owner.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ROUTER_CREATE, "router creation failed", startEventId); } - } - - + } State state = router.getState(); + + if ( state == State.Starting ) { + // wait 300 seconds + for ( int i = 0; i < 300; ) { + try { + Thread.sleep(2); + } catch (Exception e) { + } + i += 2; + state = router.getState(); + if ( state != State.Starting ) { + break; + } + } + } if (state != State.Starting && state != State.Running) { long startEventId = EventUtils.saveStartedEvent(User.UID_SYSTEM, owner.getId(), EventTypes.EVENT_ROUTER_START, "Starting router : " +router.getName()); router = this.start(router, _accountService.getSystemUser(), _accountService.getSystemAccount()); @@ -1082,7 +1061,11 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian EventUtils.saveEvent(User.UID_SYSTEM, owner.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ROUTER_START, "failed to start router", startEventId); } } - return router; + state = router.getState(); + if ( state == State.Running ) { + return router; + } + throw new CloudRuntimeException(router.getName() + " is not running , it is in " + state); } @Override @@ -1097,8 +1080,17 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian + guestNetwork; DataCenterDeployment plan = new DataCenterDeployment(dcId); - - DomainRouterVO router = _routerDao.findByNetworkConfiguration(guestNetwork.getId()); + DataCenter dc = _dcDao.findById(dcId); + DomainRouterVO router = null; + Long podId = dest.getPod().getId(); + + //In Basic zone and Guest network we have to start domR per pod, not per network + if (dc.getNetworkType() == NetworkType.Basic && guestNetwork.getTrafficType() == TrafficType.Guest) { + router = _routerDao.findByNetworkConfigurationAndPod(guestNetwork.getId(), podId); + } else { + router = _routerDao.findByNetworkConfiguration(guestNetwork.getId()); + } + if (router == null) { long startEventId = EventUtils.saveStartedEvent(User.UID_SYSTEM, owner.getId(), EventTypes.EVENT_ROUTER_CREATE, "Starting to create router for accountId : " +owner.getAccountId()); long id = _routerDao.getNextInSequence(Long.class, "id"); @@ -1106,9 +1098,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian s_logger.debug("Creating the router " + id); } - List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork); + List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork); NetworkOfferingVO controlOffering = offerings.get(0); - NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false).get(0); + NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false, false).get(0); List> networks = new ArrayList>(3); NicProfile gatewayNic = new NicProfile(); @@ -1117,7 +1109,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian networks.add(new Pair(controlConfig, null)); router = new DomainRouterVO(id, _offering.getId(), VirtualMachineName.getRouterName(id, _instance), _template.getId(), - _template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), _offering.getOfferHA()); + _template.getHypervisorType(), _template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), _offering.getOfferHA()); router.setRole(Role.DHCP_USERDATA); router = _itMgr.allocate(router, _template, _offering, networks, plan, null, owner); if(router != null){ @@ -1148,12 +1140,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian String type = null; String dhcpRange = null; - // get first ip address from network cidr - String cidr = network.getCidr(); - String[] splitResult = cidr.split("\\/"); - long size = Long.valueOf(splitResult[1]); - dhcpRange = NetUtils.getIpRangeStartIpFromCidr(splitResult[0], size); - + DataCenter dc = dest.getDataCenter(); + + if (dc.getNetworkType() == NetworkType.Advanced) { + String cidr = network.getCidr(); + dhcpRange = NetUtils.getDhcpRange(cidr); + } + String domain = network.getNetworkDomain(); if (router.getRole() == Role.DHCP_USERDATA) { type = "dhcpsrvr"; @@ -1177,6 +1170,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (nic.getDns2() != null) { buf.append(" dns2=").append(nic.getDns2()); } + if (dc.getNetworkType() == NetworkType.Basic) { + long cidrSize = NetUtils.getCidrSize(nic.getNetmask()); + String cidr = NetUtils.getCidrSubNet(nic.getGateway(), cidrSize); + if (cidr != null) { + dhcpRange = NetUtils.getIpRangeStartIpFromCidr(cidr, cidrSize); + } + } } if (nic.getTrafficType() == TrafficType.Management) { buf.append(" localgw=").append(dest.getPod().getGateway()); @@ -1199,7 +1199,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian buf.append(" domain=" + router.getDomain()); } - if (_noDefaultRouteForDirectNetwork && network.getGuestType() == GuestIpType.Direct) { + if (!network.isDefault() && network.getGuestType() == GuestIpType.Direct) { buf.append(" defaultroute=false"); } else { buf.append(" defaultroute=true"); @@ -1221,6 +1221,14 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian @Override public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException{ NicProfile controlNic = (NicProfile) profile.getParameter("control.nic"); + try { + _ovsNetworkMgr.RouterCheckAndCreateTunnel(cmds, profile, dest); + _ovsNetworkMgr.applyDefaultFlowToRouter(cmds, profile, dest); + } catch (GreTunnelException e) { + e.printStackTrace(); + } + + cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20)); DomainRouterVO router = profile.getVirtualMachine(); @@ -1280,12 +1288,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } } - s_logger.debug("Found " + rulesToReapply.size() + " port forwarding rule(s) to apply as a part of domR " + router.getId() + " start."); + s_logger.debug("Found " + rulesToReapply.size() + " port forwarding rule(s) to apply as a part of domR " + router + " start."); if (!rulesToReapply.isEmpty()) { createApplyPortForwardingRulesCommands(rulesToReapply, router, cmds); } - s_logger.debug("Found " + vpns.size() + " vpn(s) to apply as a part of domR " + router.getId() + " start."); + s_logger.debug("Found " + vpns.size() + " vpn(s) to apply as a part of domR " + router + " start."); if (!vpns.isEmpty()) { for (RemoteAccessVpn vpn : vpns) { createApplyVpnCommands(vpn, router, cmds); @@ -1301,19 +1309,21 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian lbRules.add(loadBalancing); } - s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of domR " + router.getId() + " start."); + s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of domR " + router + " start."); if (!lbRules.isEmpty()) { createApplyLoadBalancingRulesCommands(lbRules, router, cmds); } - - //Resend dhcp - createDhcpEntriesCommands(router, cmds); - - //Resend user data - createUserDataCommands(router, cmds); } } + //Resend dhcp + s_logger.debug("Reapplying dhcp entries as a part of domR " + router + " start..."); + createDhcpEntriesCommands(router, cmds); + + //Resend user data + s_logger.debug("Reapplying user data entries as a part of domR " + router + " start..."); + createUserDataCommands(router, cmds); + return true; } @@ -1325,6 +1335,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian return false; } + DomainRouterVO router = profile.getVirtualMachine(); + _ovsNetworkMgr.handleVmStateTransition(router, State.Running); return true; } @@ -1333,6 +1345,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (answer != null && answer.length > 0) { processStopOrRebootAnswer(profile.getVirtualMachine(), answer[0]); } + + DomainRouterVO router = profile.getVirtualMachine(); + _ovsNetworkMgr.handleVmStateTransition(router, State.Stopped); } @Override @@ -1399,8 +1414,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian private DomainRouterVO start(DomainRouterVO router, User user, Account caller) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - s_logger.debug("Starting router id=" + router.getId()); - if (_itMgr.start(router, null, user, caller, null) != null) { + s_logger.debug("Starting router " + router); + if (_itMgr.start(router, null, user, caller) != null) { return _routerDao.findById(router.getId()); } else { return null; @@ -1408,7 +1423,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } private DomainRouterVO stop(DomainRouterVO router, User user, Account caller) throws ConcurrentOperationException, ResourceUnavailableException { - s_logger.debug("Stopping router id=" + router.getId()); + s_logger.debug("Stopping router " + router); if (_itMgr.stop(router, user, caller)) { return _routerDao.findById(router.getId()); } else { @@ -1676,7 +1691,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (vm.getUserData() != null) { NicVO nic = _nicDao.findByInstanceIdAndNetworkId(networkId, vm.getId()); if (nic != null) { - s_logger.debug("Creating user data entry for vm id=" + vm.getId() + " on domR " + router.getId()); + s_logger.debug("Creating user data entry for vm " + vm + " on domR " + router); String serviceOffering = _serviceOfferingDao.findById(vm.getServiceOfferingId()).getDisplayText(); String zoneName = _dcDao.findById(router.getDataCenterId()).getName(); cmds.addCommand( @@ -1696,7 +1711,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian for (UserVmVO vm : vms) { NicVO nic = _nicDao.findByInstanceIdAndNetworkId(networkId, vm.getId()); if (nic != null) { - s_logger.debug("Creating dhcp entry for vm id=" + vm.getId() + " on domR " + router.getId()); + s_logger.debug("Creating dhcp entry for vm " + vm + " on domR " + router + "."); DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), vm.getName()); dhcpCommand.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress()); @@ -1798,4 +1813,46 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian // TODO Auto-generated method stub return false; } + + + private List findLonelyRouters() { + List routersToStop = new ArrayList(); + List runningRouters = _instanceDao.listByTypeAndState(State.Running, VirtualMachine.Type.DomainRouter); + + for (VMInstanceVO router : runningRouters) { + DataCenter dc = _configMgr.getZone(router.getDataCenterId()); + if (dc.getNetworkType() == NetworkType.Advanced) { + //Only non-system networks should be reviewed as system network can always have other system vms running + List routerNetworks = _networkMgr.listNetworksUsedByVm(router.getId(), false); + List networksToCheck = new ArrayList(); + for (Network routerNetwork : routerNetworks){ + if ((routerNetwork.getGuestType() == GuestIpType.Direct && routerNetwork.getTrafficType() == TrafficType.Public) || (routerNetwork.getGuestType() == GuestIpType.Virtual && routerNetwork.getTrafficType() == TrafficType.Guest)) { + networksToCheck.add(routerNetwork); + } + } + + boolean toStop = true; + for (Network network : networksToCheck) { + int count = _networkMgr.getActiveNicsInNetwork(network.getId()); + if (count > 1) { + s_logger.trace("Network id=" + network.getId() + " used by router " + router + " has more than 1 active nic (number of nics is " + count + ")"); + toStop = false; + break; + } + } + + if (toStop) { + s_logger.trace("Adding router " + router + " to stop list of Router Monitor"); + routersToStop.add(router.getId()); + } + } + } + + return routersToStop; + } + + @Override + public void completeStartCommand(DomainRouterVO router) { + _itMgr.stateTransitTo(router, VirtualMachine.Event.AgentReportRunning, router.getHostId()); + } } diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java index 136464e509f..8d101623642 100644 --- a/server/src/com/cloud/network/rules/RulesManager.java +++ b/server/src/com/cloud/network/rules/RulesManager.java @@ -75,4 +75,6 @@ public interface RulesManager extends RulesService { FirewallRule[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, int... ports) throws NetworkRuleConflictException; boolean releasePorts(Ip ip, String protocol, FirewallRule.Purpose purpose, int... ports); + + List listByNetworkId(long networkId); } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index edd43b431c0..29e4fe2364d 100644 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -36,13 +36,13 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IPAddressVO; import com.cloud.network.IpAddress; import com.cloud.network.Network; +import com.cloud.network.Network.GuestIpType; import com.cloud.network.NetworkManager; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.State; import com.cloud.network.rules.dao.PortForwardingRulesDao; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.UserContext; @@ -526,6 +526,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return allRules; } - + + @Override + public List listByNetworkId(long networkId) { + return _forwardingDao.listByNetworkId(networkId); + } } diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 3b53cc03896..4270d31d860 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -613,22 +613,24 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return null; } } - IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocol, startPort, endPort, ngVO.getId()); + IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocol, startPortOrType, endPortOrCode, ngVO.getId()); if (ingressRule != null) { continue; //rule already exists. } - ingressRule = new IngressRuleVO(securityGroup.getId(), startPort, endPort, protocol, ngVO.getId(), ngVO.getName(), ngVO.getAccountName()); + ingressRule = new IngressRuleVO(securityGroup.getId(), startPortOrType, endPortOrCode, protocol, ngVO.getId(), ngVO.getName(), ngVO.getAccountName()); ingressRule = _ingressRuleDao.persist(ingressRule); newRules.add(ingressRule); } - for (String cidr: cidrList) { - IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndCidr(securityGroup.getId(),protocol, startPort, endPort, cidr); - if (ingressRule != null) { - continue; + if(cidrList != null) { + for (String cidr: cidrList) { + IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndCidr(securityGroup.getId(),protocol, startPortOrType, endPortOrCode, cidr); + if (ingressRule != null) { + continue; + } + ingressRule = new IngressRuleVO(securityGroup.getId(), startPortOrType, endPortOrCode, protocol, cidr); + ingressRule = _ingressRuleDao.persist(ingressRule); + newRules.add(ingressRule); } - ingressRule = new IngressRuleVO(securityGroup.getId(), startPort, endPort, protocol, cidr); - ingressRule = _ingressRuleDao.persist(ingressRule); - newRules.add(ingressRule); } if (s_logger.isDebugEnabled()) { s_logger.debug("Added " + newRules.size() + " rules to security group " + groupName); @@ -1080,16 +1082,16 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG s_logger.warn("Failed to acquire lock on user vm id=" + userVmId); } try { - for (SecurityGroupVO networkGroup:uniqueGroups) { + for (SecurityGroupVO securityGroup:uniqueGroups) { //don't let the group be deleted from under us. - SecurityGroupVO ngrpLock = _securityGroupDao.lockRow(networkGroup.getId(), false); + SecurityGroupVO ngrpLock = _securityGroupDao.lockRow(securityGroup.getId(), false); if (ngrpLock == null) { - s_logger.warn("Failed to acquire lock on network group id=" + networkGroup.getId() + " name=" + networkGroup.getName()); + s_logger.warn("Failed to acquire lock on network group id=" + securityGroup.getId() + " name=" + securityGroup.getName()); txn.rollback(); return false; } - if (_securityGroupVMMapDao.findByVmIdGroupId(userVmId, networkGroup.getId()) == null) { - SecurityGroupVMMapVO groupVmMapVO = new SecurityGroupVMMapVO(networkGroup.getId(), userVmId); + if (_securityGroupVMMapDao.findByVmIdGroupId(userVmId, securityGroup.getId()) == null) { + SecurityGroupVMMapVO groupVmMapVO = new SecurityGroupVMMapVO(securityGroup.getId(), userVmId); _securityGroupVMMapDao.persist(groupVmMapVO); } } diff --git a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java index 20e6880f14b..f4df776966e 100644 --- a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java +++ b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java @@ -40,7 +40,7 @@ public class SecurityGroupDaoImpl extends GenericDaoBase AccountIdNameSearch = createSearchBuilder(); AccountIdNameSearch.and("accountId", AccountIdNameSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountIdNameSearch.and("groupName", AccountIdNameSearch.entity().getName(), SearchCriteria.Op.EQ); + AccountIdNameSearch.and("name", AccountIdNameSearch.entity().getName(), SearchCriteria.Op.EQ); AccountIdNamesSearch = createSearchBuilder(); AccountIdNamesSearch.and("accountId", AccountIdNamesSearch.entity().getAccountId(), SearchCriteria.Op.EQ); @@ -74,7 +74,7 @@ public class SecurityGroupDaoImpl extends GenericDaoBase public SecurityGroupVO findByAccountAndName(Long accountId, String name) { SearchCriteria sc = AccountIdNameSearch.create(); sc.setParameters("accountId", accountId); - sc.setParameters("groupName", name); + sc.setParameters("name", name); return findOneIncludingRemovedBy(sc); } diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java index b8e4872579d..a7cdeb9628b 100644 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -28,7 +28,6 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.NetworkOffering; import com.cloud.service.ServiceOfferingVO; @@ -37,11 +36,7 @@ import com.cloud.utils.db.GenericDao; @Entity @Table(name="network_offerings") public class NetworkOfferingVO implements NetworkOffering { - public final static String SystemVmPublicNetwork = "System-Public-Network"; - public final static String SystemVmControlNetwork = "System-Control-Network"; - public final static String SystemVmManagementNetwork = "System-Management-Network"; - public final static String SystemVmStorageNetwork = "System-Storage-Network"; - + @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") @@ -62,10 +57,6 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name="concurrent_connections") Integer concurrentConnections; - @Column(name="type") - @Enumerated(value=EnumType.STRING) - GuestIpType guestIpType; - @Column(name="traffic_type") @Enumerated(value=EnumType.STRING) TrafficType trafficType; @@ -121,11 +112,6 @@ public class NetworkOfferingVO implements NetworkOffering { return displayText; } - @Override - public GuestIpType getGuestIpType() { - return guestIpType; - } - @Override public long getId() { return id; @@ -200,10 +186,6 @@ public class NetworkOfferingVO implements NetworkOffering { this.concurrentConnections = concurrentConnections; } - public void setGuestIpType(GuestIpType guestIpType) { - this.guestIpType = guestIpType; - } - public void setTrafficType(TrafficType trafficType) { this.trafficType = trafficType; } @@ -311,10 +293,9 @@ public class NetworkOfferingVO implements NetworkOffering { this.dhcpService = dhcpService; } - public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, GuestIpType type, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, Integer concurrentConnections, boolean isDefault, Availability availability, boolean lbService, boolean gatewayService, boolean dhcpService, boolean firewallService, boolean dnsService, boolean userDataService, boolean vpnService) { + public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, Integer concurrentConnections, boolean isDefault, Availability availability, boolean lbService, boolean gatewayService, boolean dhcpService, boolean firewallService, boolean dnsService, boolean userDataService, boolean vpnService) { this.name = name; this.displayText = displayText; - this.guestIpType = type; this.rateMbps = rateMbps; this.multicastRateMbps = multicastRateMbps; this.concurrentConnections = concurrentConnections; @@ -333,7 +314,7 @@ public class NetworkOfferingVO implements NetworkOffering { } public NetworkOfferingVO(ServiceOfferingVO offering) { - this("Network Offering for " + offering.getName(), "Network Offering for " + offering.getDisplayText(), TrafficType.Guest, offering.getGuestIpType(), false, false, offering.getRateMbps(), offering.getMulticastRateMbps(), null, false, Availability.Required, false, false, false, false, false, false, false); + this("Network Offering for " + offering.getName(), "Network Offering for " + offering.getDisplayText(), TrafficType.Guest, false, false, offering.getRateMbps(), offering.getMulticastRateMbps(), null, false, Availability.Required, false, false, false, false, false, false, false); this.serviceOfferingId = offering.getId(); } @@ -342,15 +323,14 @@ public class NetworkOfferingVO implements NetworkOffering { * Network Offering for all system vms. * @param name * @param trafficType - * @param type */ - public NetworkOfferingVO(String name, TrafficType trafficType, GuestIpType type) { - this(name, "System Offering for " + name, trafficType, type, true, false, null, null, null, false, Availability.Required, false, false, false, false, false, false, false); + public NetworkOfferingVO(String name, TrafficType trafficType) { + this(name, "System Offering for " + name, trafficType, true, false, null, null, null, false, Availability.Required, false, false, false, false, false, false, false); } @Override public String toString() { StringBuilder buf = new StringBuilder("[Network Offering ["); - return buf.append(id).append("-").append(trafficType).append("-").append(name).append("-").append(guestIpType).append("]").toString(); + return buf.append(id).append("-").append(trafficType).append("-").append(name).append("]").toString(); } } diff --git a/server/src/com/cloud/offerings/dao/NetworkOfferingDao.java b/server/src/com/cloud/offerings/dao/NetworkOfferingDao.java index c7bc7188910..245f6e41bac 100644 --- a/server/src/com/cloud/offerings/dao/NetworkOfferingDao.java +++ b/server/src/com/cloud/offerings/dao/NetworkOfferingDao.java @@ -5,9 +5,7 @@ package com.cloud.offerings.dao; import java.util.List; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.service.ServiceOfferingVO; import com.cloud.utils.db.GenericDao; /** @@ -33,11 +31,8 @@ public interface NetworkOfferingDao extends GenericDao */ NetworkOfferingVO persistDefaultNetworkOffering(NetworkOfferingVO offering); - NetworkOfferingVO findByServiceOffering(ServiceOfferingVO offering); - List listNonSystemNetworkOfferings(); List listSystemNetworkOfferings(); - List findByType(GuestIpType type); } diff --git a/server/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java b/server/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java index 505e2742b19..63bbaaa630c 100644 --- a/server/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java +++ b/server/src/com/cloud/offerings/dao/NetworkOfferingDaoImpl.java @@ -11,14 +11,11 @@ import javax.persistence.EntityExistsException; import org.apache.log4j.Logger; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.service.ServiceOfferingVO; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.exception.CloudRuntimeException; @Local(value=NetworkOfferingDao.class) @DB(txn=false) public class NetworkOfferingDaoImpl extends GenericDaoBase implements NetworkOfferingDao { @@ -26,9 +23,7 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase NameSearch; - final SearchBuilder ServiceOfferingSearch; final SearchBuilder SystemOfferingSearch; - final SearchBuilder TypeSearch; protected NetworkOfferingDaoImpl() { super(); @@ -37,14 +32,6 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase sc = ServiceOfferingSearch.create(); - sc.setParameters("serviceoffering", offering.getGuestIpType()); - - NetworkOfferingVO vo = findOneBy(sc); - if (vo != null) { - return vo; - } - - vo = new NetworkOfferingVO(offering); - try { - return persist(vo); - } catch (Exception e) { - s_logger.debug("Got a persistence exception. Assuming it's because service offering id is duplicate"); - vo = findOneBy(sc); - if (vo != null) { - return vo; - } - - throw new CloudRuntimeException("Unable to persist network offering", e); - } - } - @Override public List listNonSystemNetworkOfferings() { SearchCriteria sc = SystemOfferingSearch.create(); @@ -107,13 +70,6 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase findByType(GuestIpType type) { - SearchCriteria sc = TypeSearch.create(); - sc.setParameters("guestIpType", type); - return listBy(sc); - } - @Override public List listSystemNetworkOfferings() { SearchCriteria sc = SystemOfferingSearch.create(); diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index c9bff361a5f..ea8c55a716d 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -47,7 +47,6 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; @@ -57,15 +56,19 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InternalErrorException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Network; import com.cloud.network.Network.State; import com.cloud.network.NetworkVO; -import com.cloud.network.Networks.Availability; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.guru.ControlNetworkGuru; +import com.cloud.network.guru.DirectPodBasedNetworkGuru; +import com.cloud.network.guru.PodBasedNetworkGuru; +import com.cloud.network.guru.PublicNetworkGuru; import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; +import com.cloud.offering.NetworkOffering.Availability; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.service.ServiceOfferingVO; @@ -665,7 +668,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); int networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr)); int multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr)); - NetworkOffering.GuestIpType guestIpType = useVirtualNetwork ? NetworkOffering.GuestIpType.Virtual : NetworkOffering.GuestIpType.Direct; + Network.GuestIpType guestIpType = useVirtualNetwork ? Network.GuestIpType.Virtual : Network.GuestIpType.Direct; tags = cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, multicastRate, offerHA, displayText, guestIpType, localStorageRequired, false, tags, false); @@ -694,20 +697,21 @@ public class ConfigurationServerImpl implements ConfigurationServer { Integer rateMbps = getIntegerConfigValue(Config.NetworkThrottlingRate.key(), null); Integer multicastRateMbps = getIntegerConfigValue(Config.MulticastThrottlingRate.key(), null); - NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmPublicNetwork, TrafficType.Public, null); + NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemPublicNetwork, TrafficType.Public); publicNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(publicNetworkOffering); - NetworkOfferingVO managementNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmManagementNetwork, TrafficType.Management, null); + NetworkOfferingVO managementNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemManagementNetwork, TrafficType.Management); managementNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(managementNetworkOffering); - NetworkOfferingVO controlNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmControlNetwork, TrafficType.Control, null); + NetworkOfferingVO controlNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemControlNetwork, TrafficType.Control); controlNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(controlNetworkOffering); - NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmStorageNetwork, TrafficType.Storage, null); + NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemStorageNetwork, TrafficType.Storage); storageNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(storageNetworkOffering); - NetworkOfferingVO defaultGuestNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultVirtualizedNetworkOffering, "Virtual Vlan", TrafficType.Guest, GuestIpType.Virtual, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); + NetworkOfferingVO guestNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SysteGuestNetwork, TrafficType.Guest); + guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering); + + NetworkOfferingVO defaultGuestNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultVirtualizedNetworkOffering, "Virtual Vlan", TrafficType.Guest, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering); - NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Public, GuestIpType.Direct, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); + NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Public, false, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering); - NetworkOfferingVO defaultGuestDirectPodBasedNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectPodBasedNetworkOffering, "DirectPodBased", TrafficType.Public, GuestIpType.DirectPodBased, true, false, rateMbps, multicastRateMbps, null, true, Availability.Required, false, false, false, false, false, false, false); - defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectPodBasedNetworkOffering); } private Integer getIntegerConfigValue(String configKey, Integer dflt) { @@ -723,10 +727,11 @@ public class ConfigurationServerImpl implements ConfigurationServer { long id = 1; HashMap guruNames = new HashMap(); - guruNames.put(TrafficType.Public, "PublicNetworkGuru-com.cloud.network.guru.PublicNetworkGuru"); - guruNames.put(TrafficType.Management, "PodBasedNetworkGuru-com.cloud.network.guru.PodBasedNetworkGuru"); - guruNames.put(TrafficType.Control, "ControlNetworkGuru-com.cloud.network.guru.ControlNetworkGuru"); - guruNames.put(TrafficType.Storage, "PodBasedNetworkGuru-com.cloud.network.guru.PodBasedNetworkGuru"); + guruNames.put(TrafficType.Public, PublicNetworkGuru.class.getSimpleName()); + guruNames.put(TrafficType.Management, PodBasedNetworkGuru.class.getSimpleName()); + guruNames.put(TrafficType.Control, ControlNetworkGuru.class.getSimpleName()); + guruNames.put(TrafficType.Storage, PodBasedNetworkGuru.class.getSimpleName()); + guruNames.put(TrafficType.Guest, DirectPodBasedNetworkGuru.class.getSimpleName()); for (DataCenterVO zone : zones) { long zoneId = zone.getId(); @@ -747,21 +752,29 @@ public class ConfigurationServerImpl implements ConfigurationServer { BroadcastDomainType broadcastDomainType = null; TrafficType trafficType= offering.getTrafficType(); - GuestIpType guestIpType = offering.getGuestIpType(); - if (offering.getGuestIpType() != GuestIpType.DirectPodBased) { - if (trafficType == TrafficType.Management || trafficType == TrafficType.Storage) { - broadcastDomainType = BroadcastDomainType.Native; - } else if (trafficType == TrafficType.Public) { + + boolean isNetworkDefault = false; + if (trafficType == TrafficType.Management || trafficType == TrafficType.Storage) { + broadcastDomainType = BroadcastDomainType.Native; + } else if (trafficType == TrafficType.Control) { + broadcastDomainType = BroadcastDomainType.LinkLocal; + } else if (offering.getTrafficType() == TrafficType.Public) { + if (zone.getNetworkType() == NetworkType.Advanced) { broadcastDomainType = BroadcastDomainType.Vlan; - } else if (trafficType == TrafficType.Control) { - broadcastDomainType = BroadcastDomainType.LinkLocal; - } - } else if (zone.getNetworkType() == NetworkType.Basic && offering.getGuestIpType() == GuestIpType.DirectPodBased){ - broadcastDomainType = BroadcastDomainType.Vlan; + } else { + continue; + } + } else if (offering.getTrafficType() == TrafficType.Guest) { + if (zone.getNetworkType() == NetworkType.Basic) { + isNetworkDefault = true; + broadcastDomainType = BroadcastDomainType.Native; + } else { + continue; + } } if (broadcastDomainType != null) { - NetworkVO network = new NetworkVO(id, trafficType, guestIpType, mode, broadcastDomainType, networkOfferingId, zoneId, domainId, accountId, related, null, null, true); + NetworkVO network = new NetworkVO(id, trafficType, null, mode, broadcastDomainType, networkOfferingId, zoneId, domainId, accountId, related, null, null, true, isNetworkDefault); network.setGuruName(guruNames.get(network.getTrafficType())); network.setDns1(zone.getDns1()); network.setDns2(zone.getDns2()); @@ -778,33 +791,35 @@ public class ConfigurationServerImpl implements ConfigurationServer { private void updateVlanWithNetworkId(VlanVO vlan) { long zoneId = vlan.getDataCenterId(); long networkId = 0L; - if (vlan.getVlanType() == VlanType.VirtualNetwork) { - networkId = getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(zoneId, TrafficType.Public, null); - } else if (vlan.getVlanType() == VlanType.DirectAttached) { - networkId = getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(zoneId, TrafficType.Public, GuestIpType.DirectPodBased); + DataCenterVO zone = _zoneDao.findById(zoneId); + + if (zone.getNetworkType() == NetworkType.Advanced) { + networkId = getSystemNetworkIdByZoneAndTrafficType(zoneId, TrafficType.Public); + } else { + networkId = getSystemNetworkIdByZoneAndTrafficType(zoneId, TrafficType.Guest); } - + vlan.setNetworkId(networkId); _vlanDao.update(vlan.getId(), vlan); } - private long getSystemNetworkIdByZoneAndTrafficTypeAndGuestType(long zoneId, TrafficType trafficType, GuestIpType guestType) { + private long getSystemNetworkIdByZoneAndTrafficType(long zoneId, TrafficType trafficType) { //find system public network offering Long networkOfferingId = null; List offerings = _networkOfferingDao.listSystemNetworkOfferings(); for (NetworkOfferingVO offering: offerings) { - if (offering.getTrafficType() == trafficType && offering.getGuestIpType() == guestType) { + if (offering.getTrafficType() == trafficType) { networkOfferingId = offering.getId(); break; } } if (networkOfferingId == null) { - throw new InvalidParameterValueException("Unable to find system network offering with traffic type " + trafficType + " and guestIpType " + guestType); + throw new InvalidParameterValueException("Unable to find system network offering with traffic type " + trafficType); } List networks = _networkDao.listBy(Account.ACCOUNT_ID_SYSTEM, networkOfferingId, zoneId); - if (networks == null) { + if (networks == null || networks.isEmpty()) { throw new InvalidParameterValueException("Unable to find network with traffic type " + trafficType + " in zone " + zoneId); } return networks.get(0).getId(); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 32d6e24e541..a968d184db3 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2745,7 +2745,7 @@ public class ManagementServerImpl implements ManagementServer { } GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName())); - if(answer != null) { + if(answer != null && answer.getResult()) { return new Pair(answer.getAddress(), answer.getPort()); } diff --git a/server/src/com/cloud/service/ServiceOfferingVO.java b/server/src/com/cloud/service/ServiceOfferingVO.java index 9591f6c8b57..d50c4513b8c 100644 --- a/server/src/com/cloud/service/ServiceOfferingVO.java +++ b/server/src/com/cloud/service/ServiceOfferingVO.java @@ -27,7 +27,7 @@ import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import javax.persistence.Transient; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; import com.cloud.offering.ServiceOffering; import com.cloud.storage.DiskOfferingVO; @@ -56,13 +56,13 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Column(name="guest_ip_type") @Enumerated(EnumType.STRING) - private NetworkOffering.GuestIpType guestIpType; + private Network.GuestIpType guestIpType; protected ServiceOfferingVO() { super(); } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, NetworkOffering.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse) { + public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, Network.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse) { super(name, displayText, false, tags, recreatable, useLocalStorage, systemUse,false); this.cpu = cpu; this.ramSize = ramSize; @@ -73,7 +73,7 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.guestIpType = guestIpType; } - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, NetworkOffering.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, Long domainId) { + public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, int rateMbps, int multicastRateMbps, boolean offerHA, String displayText, Network.GuestIpType guestIpType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, Long domainId) { super(name, displayText, false, tags, recreatable, useLocalStorage, systemUse,false,domainId); this.cpu = cpu; this.ramSize = ramSize; @@ -149,12 +149,12 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering return multicastRateMbps; } - public void setGuestIpType(NetworkOffering.GuestIpType guestIpType) { + public void setGuestIpType(Network.GuestIpType guestIpType) { this.guestIpType = guestIpType; } @Override - public NetworkOffering.GuestIpType getGuestIpType() { + public Network.GuestIpType getGuestIpType() { return guestIpType; } diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index 3914ee5e036..6b599037f69 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -365,26 +365,25 @@ public class ConsoleProxyServlet extends HttpServlet { return true; VMInstanceVO vm = _ms.findVMInstanceById(vmId); - UserVmVO userVm; switch(vm.getType()) { case User : - userVm = _ms.findUserVMInstanceById(vmId); - if(userVm.getAccountId() != accountObj.getId()) { + case DomainRouter: + if(vm.getAccountId() != accountObj.getId()) { // access from another normal user if(accountObj.getType() == Account.ACCOUNT_TYPE_NORMAL) { if(s_logger.isDebugEnabled()) { - s_logger.debug("VM access is denied. VM owner account " + userVm.getAccountId() + s_logger.debug("VM access is denied. VM owner account " + vm.getAccountId() + " does not match the account id in session " + accountObj.getId() + " and caller is a normal user"); } return false; } if(accountObj.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || accountObj.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN) { - if(!_ms.isChildDomain(accountObj.getDomainId(), userVm.getDomainId())) { + if(!_ms.isChildDomain(accountObj.getDomainId(), vm.getDomainId())) { if(s_logger.isDebugEnabled()) { - s_logger.debug("VM access is denied. VM owner account " + userVm.getAccountId() + s_logger.debug("VM access is denied. VM owner account " + vm.getAccountId() + " does not match the account id in session " + accountObj.getId() + " and the domain-admin caller does not manage the target domain"); } return false; @@ -394,7 +393,6 @@ public class ConsoleProxyServlet extends HttpServlet { break; case ConsoleProxy : - case DomainRouter : case SecondaryStorageVm: return false; diff --git a/server/src/com/cloud/storage/StorageManager.java b/server/src/com/cloud/storage/StorageManager.java index 336750c1556..a269546790d 100755 --- a/server/src/com/cloud/storage/StorageManager.java +++ b/server/src/com/cloud/storage/StorageManager.java @@ -81,14 +81,6 @@ public interface StorageManager extends Manager { */ List unshare(VMInstanceVO vm, HostVO host); - /** - * destroy the storage volumes of a certain vm. - * - * @param vm vm to destroy. - * @param vols volumes to remove from storage pool - */ - void destroy(VMInstanceVO vm, List vols); - /** * Creates volumes for a particular VM. * @param account account to create volumes for. @@ -205,7 +197,7 @@ public interface StorageManager extends Manager { * Marks the specified volume as destroyed in the management server database. The expunge thread will delete the volume from its storage pool. * @param volume */ - void destroyVolume(VolumeVO volume); + void destroyVolume(VolumeVO volume) throws ConcurrentOperationException; /** Create capacity entries in the op capacity table * @param storagePool @@ -282,5 +274,5 @@ public interface StorageManager extends Manager { void release(VirtualMachineProfile profile); - void cleanupVolumes(Long vmId); + void cleanupVolumes(long vmId) throws ConcurrentOperationException; } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 0ba0d3f998b..254844457bb 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -114,7 +114,6 @@ import com.cloud.host.dao.DetailsDao; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.NetworkManager; -import com.cloud.network.VirtualNetworkApplianceService; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; @@ -141,7 +140,6 @@ import com.cloud.storage.snapshot.SnapshotScheduler; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.User; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; @@ -874,7 +872,11 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag s_logger.debug(e.getMessage()); } if (rootCreated != null) { - destroyVolume(rootCreated); + try { + destroyVolume(rootCreated); + } catch (Exception e1) { + s_logger.warn("Unable to mark a volume as destroyed: " + rootCreated, e1); + } } throw new CloudRuntimeException("Unable to create volumes for " + vm, e); } @@ -953,55 +955,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag return true; } - @Override - public void destroy(VMInstanceVO vm, List vols) { - if (s_logger.isDebugEnabled() && vm != null) { - s_logger.debug("Destroying volumes of " + vm.toString()); - } - - for (VolumeVO vol : vols) { - _volsDao.detachVolume(vol.getId()); - _volsDao.destroyVolume(vol.getId()); - - // First delete the entries in the snapshot_policy and - // snapshot_schedule table for the volume. - // They should not get executed after the volume is destroyed. - _snapshotMgr.deletePoliciesForVolume(vol.getId()); - - String volumePath = vol.getPath(); - Long poolId = vol.getPoolId(); - if (poolId != null && volumePath != null && !volumePath.trim().isEmpty()) { - Answer answer = null; - StoragePoolVO pool = _storagePoolDao.findById(poolId); - String vmName = null; - if (vm != null) { - vmName = vm.getInstanceName(); - } - final DestroyCommand cmd = new DestroyCommand(pool, vol, vmName); - boolean removed = false; - List poolhosts = _storagePoolHostDao.listByPoolId(poolId); - for (StoragePoolHostVO poolhost : poolhosts) { - answer = _agentMgr.easySend(poolhost.getHostId(), cmd); - if (answer != null && answer.getResult()) { - removed = true; - break; - } - } - - if (removed) { - _volsDao.remove(vol.getId()); - } else { - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_STORAGE_MISC, vol.getDataCenterId(), vol.getPodId(), - "Storage cleanup required for storage pool: " + pool.getName(), "Volume folder: " + vol.getFolder() + ", Volume Path: " + vol.getPath() + ", Volume id: " +vol.getId()+ ", Volume Name: " +vol.getName()+ ", Storage PoolId: " +vol.getPoolId()); - s_logger.warn("destroy volume " + vol.getFolder() + " : " + vol.getPath() + " failed for Volume id : " +vol.getId()+ " Volume Name: " +vol.getName()+ " Storage PoolId : " +vol.getPoolId()); - } - } else { - _volsDao.remove(vol.getId()); - } - } - - } - @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; @@ -1477,11 +1430,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag DeleteStoragePoolCommand cmd = new DeleteStoragePoolCommand(sPool); final Answer answer = _agentMgr.easySend(host.getHostId(), cmd); - if (answer != null) { - if (answer.getResult() == true) { - deleteFlag = true; - break; - } + if (answer != null && answer.getResult()) { + deleteFlag = true; + break; } } @@ -1599,13 +1550,13 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag String destPrimaryStorageVolumePath = cvAnswer.getVolumePath(); String destPrimaryStorageVolumeFolder = cvAnswer.getVolumeFolder(); - // Delete the volume on the source storage pool - final DestroyCommand cmd = new DestroyCommand(srcPool, volume, null); - Answer destroyAnswer = _agentMgr.easySend(sourceHostId, cmd); - - if (destroyAnswer == null || !destroyAnswer.getResult()) { - throw new CloudRuntimeException("Failed to delete the volume from the source primary storage pool."); + try { + destroyVolume(volume); + } catch (ConcurrentOperationException e) { + s_logger.warn("Concurrent Operation", e); } + + expungeVolume(volume); volume.setPath(destPrimaryStorageVolumePath); volume.setFolder(destPrimaryStorageVolumeFolder); @@ -1851,16 +1802,14 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override @DB - public void destroyVolume(VolumeVO volume) { + public void destroyVolume(VolumeVO volume) throws ConcurrentOperationException { Transaction txn = Transaction.currentTxn(); txn.start(); - - Long volumeId = volume.getId(); - _volsDao.destroyVolume(volumeId); + + _volsDao.update(volume, Volume.Event.Destroy); + long volumeId = volume.getId(); - EventUtils.saveEvent(User.UID_SYSTEM, volume.getAccountId(), EventTypes.EVENT_VOLUME_DELETE, "Volume " +volume.getName()+ " deleted"); - - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), null, null , null); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volumeId, volume.getName(), null, null , null); _usageEventDao.persist(usageEvent); // Delete the recurring snapshot policies for this volume. @@ -1996,120 +1945,92 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag return answer; } - protected class StorageGarbageCollector implements Runnable { - - public StorageGarbageCollector() { - } - - @Override - public void run() { - try { - s_logger.info("Storage Garbage Collection Thread is running."); - - GlobalLock scanLock = GlobalLock.getInternLock(this.getClass().getName()); - try { - if (scanLock.lock(3)) { - try { - cleanupStorage(true); - } finally { - scanLock.unlock(); - } - } - } finally { - scanLock.releaseRef(); - } - - } catch (Exception e) { - s_logger.error("Caught the following Exception", e); - } - } - } - @Override public void cleanupStorage(boolean recurring) { + GlobalLock scanLock = GlobalLock.getInternLock(this.getClass().getName()); + + try { + if (scanLock.lock(3)) { + try { + // Cleanup primary storage pools + List storagePools = _storagePoolDao.listAll(); + for (StoragePoolVO pool : storagePools) { + try { + if (recurring && pool.isLocal()) { + continue; + } - // Cleanup primary storage pools - List storagePools = _storagePoolDao.listAll(); - for (StoragePoolVO pool : storagePools) { - try { - if (recurring && pool.isLocal()) { - continue; - } - - List unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool); - s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName()); - for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { - if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - s_logger.debug("Storage pool garbage collector is skipping templatePoolVO with ID: " + templatePoolVO.getId() + " because it is not completely downloaded."); - continue; - } - - if (!templatePoolVO.getMarkedForGC()) { - templatePoolVO.setMarkedForGC(true); - _vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO); - s_logger.debug("Storage pool garbage collector has marked templatePoolVO with ID: " + templatePoolVO.getId() + " for garbage collection."); - continue; - } - - _tmpltMgr.evictTemplateFromStoragePool(templatePoolVO); - } - } catch (Exception e) { - s_logger.warn("Problem cleaning up primary storage pool " + pool, e); - } - } + List unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool); + s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName()); + for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { + if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + s_logger.debug("Storage pool garbage collector is skipping templatePoolVO with ID: " + templatePoolVO.getId() + " because it is not completely downloaded."); + continue; + } - // Cleanup secondary storage hosts - List secondaryStorageHosts = _hostDao.listSecondaryStorageHosts(); - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - try { - long hostId = secondaryStorageHost.getId(); - List destroyedTemplateHostVOs = _vmTemplateHostDao.listDestroyed(hostId); - s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateHostVOs.size() + " templates to cleanup on secondary storage host: " - + secondaryStorageHost.getName()); - for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) { - if (!_tmpltMgr.templateIsDeleteable(destroyedTemplateHostVO)) { - s_logger.debug("Not deleting template at: " + destroyedTemplateHostVO.getInstallPath()); - continue; - } - - String installPath = destroyedTemplateHostVO.getInstallPath(); - - if (installPath != null) { - Answer answer = _agentMgr.easySend(hostId, new DeleteTemplateCommand(destroyedTemplateHostVO.getInstallPath())); - - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete template at: " + destroyedTemplateHostVO.getInstallPath()); - } else { - _vmTemplateHostDao.remove(destroyedTemplateHostVO.getId()); - s_logger.debug("Deleted template at: " + destroyedTemplateHostVO.getInstallPath()); - } - } else { - _vmTemplateHostDao.remove(destroyedTemplateHostVO.getId()); - } - } - } catch (Exception e) { - s_logger.warn("problem cleaning up secondary storage " + secondaryStorageHost, e); - } - } - - List vols = _volsDao.listRemovedButNotDestroyed(); - for (VolumeVO vol : vols) { - try { - Long poolId = vol.getPoolId(); - Answer answer = null; - StoragePoolVO pool = _storagePoolDao.findById(poolId); - final DestroyCommand cmd = new DestroyCommand(pool, vol, null); - answer = sendToPool(pool, cmd); - if (answer != null && answer.getResult()) { - s_logger.debug("Destroyed " + vol); - vol.setDestroyed(true); - _volsDao.update(vol.getId(), vol); - } - } catch (Exception e) { - s_logger.warn("Unable to destroy " + vol.getId(), e); - } - } + if (!templatePoolVO.getMarkedForGC()) { + templatePoolVO.setMarkedForGC(true); + _vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO); + s_logger.debug("Storage pool garbage collector has marked templatePoolVO with ID: " + templatePoolVO.getId() + " for garbage collection."); + continue; + } + _tmpltMgr.evictTemplateFromStoragePool(templatePoolVO); + } + } catch (Exception e) { + s_logger.warn("Problem cleaning up primary storage pool " + pool, e); + } + } + + // Cleanup secondary storage hosts + List secondaryStorageHosts = _hostDao.listSecondaryStorageHosts(); + for (HostVO secondaryStorageHost : secondaryStorageHosts) { + try { + long hostId = secondaryStorageHost.getId(); + List destroyedTemplateHostVOs = _vmTemplateHostDao.listDestroyed(hostId); + s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateHostVOs.size() + " templates to cleanup on secondary storage host: " + + secondaryStorageHost.getName()); + for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) { + if (!_tmpltMgr.templateIsDeleteable(destroyedTemplateHostVO)) { + s_logger.debug("Not deleting template at: " + destroyedTemplateHostVO.getInstallPath()); + continue; + } + + String installPath = destroyedTemplateHostVO.getInstallPath(); + + if (installPath != null) { + Answer answer = _agentMgr.easySend(hostId, new DeleteTemplateCommand(destroyedTemplateHostVO.getInstallPath())); + + if (answer == null || !answer.getResult()) { + s_logger.debug("Failed to delete template at: " + destroyedTemplateHostVO.getInstallPath()); + } else { + _vmTemplateHostDao.remove(destroyedTemplateHostVO.getId()); + s_logger.debug("Deleted template at: " + destroyedTemplateHostVO.getInstallPath()); + } + } else { + _vmTemplateHostDao.remove(destroyedTemplateHostVO.getId()); + } + } + } catch (Exception e) { + s_logger.warn("problem cleaning up secondary storage " + secondaryStorageHost, e); + } + } + + List vols = _volsDao.listVolumesToBeDestroyed(); + for (VolumeVO vol : vols) { + try { + expungeVolume(vol); + } catch (Exception e) { + s_logger.warn("Unable to destroy " + vol.getId(), e); + } + } + } finally { + scanLock.unlock(); + } + } + } finally { + scanLock.releaseRef(); + } } @Override @@ -2191,7 +2112,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } //shut down the running vms - if(vmInstance.getState().equals(State.Running) || vmInstance.getState().equals(State.Starting)) + if(vmInstance.getState().equals(State.Running) || vmInstance.getState().equals(State.Starting) || vmInstance.getState().equals(State.Stopping)) { //if the instance is of type consoleproxy, call the console proxy @@ -2473,7 +2394,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } @Override - public boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException { + public boolean deleteVolume(DeleteVolumeCmd cmd) throws ConcurrentOperationException { Account account = UserContext.current().getCaller(); Long volumeId = cmd.getId(); @@ -2516,20 +2437,13 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } // Check that the volume is not already destroyed - if (volume.getDestroyed()) { - throw new InvalidParameterValueException("Please specify a volume that is not already destroyed."); + if (volume.getState() != Volume.State.Destroy) { + destroyVolume(volume); } - try { - // Destroy the volume - destroyVolume(volume); - } catch (Exception e) { - s_logger.warn("Error destroying volume:"+e); - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error destroying volume:"+e); - } + expungeVolume(volume); return true; - } private boolean validateVolumeSizeRange(long size) throws InvalidParameterValueException { @@ -2655,6 +2569,12 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag for (VolumeVO vol : vols) { Volume.State state = vol.getState(); if (state == Volume.State.Ready) { + + if(vol.getPoolId() == null) { + s_logger.warn("Found volume:"+vol.getId()+" with no storage pool associated with it"); + throw new StorageUnavailableException("Volume " + vol + " has no storage pool associated with it, and the pool id associated with it is:", vol.getPoolId()); + } + StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId()); if (pool.getRemoved() != null || pool.isInMaintenance()) { if (vol.isRecreatable()) { @@ -2797,17 +2717,92 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag //add code here } - @Override - public void cleanupVolumes(Long vmId){ - List volumesForVm = _volsDao.findByInstance(vmId); - for(VolumeVO vol : volumesForVm){ - if(vol.getVolumeType().equals(VolumeType.ROOT)){ - destroyVolume(vol); + public void expungeVolume(VolumeVO vol) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Expunging " + vol); + } + String vmName = null; + if (vol.getVolumeType() == VolumeType.ROOT && vol.getInstanceId() != null) { + VirtualMachine vm = _vmInstanceDao.findByIdIncludingRemoved(vol.getInstanceId()); + if (vm != null) { + vmName = vm.getInstanceName(); + } + } + + String volumePath = vol.getPath(); + Long poolId = vol.getPoolId(); + if (poolId == null || volumePath == null || volumePath.trim().isEmpty()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Marking volume that was never created as destroyed: " + vol); + } + _volsDao.remove(vol.getId()); + return; + } + + StoragePoolVO pool = _storagePoolDao.findById(poolId); + if (pool == null) { + s_logger.debug("Removing volume as storage pool is gone: " + poolId); + _volsDao.remove(vol.getId()); + return; + } + + DestroyCommand cmd = new DestroyCommand(pool, vol, vmName); + Answer answer = this.sendToPool(pool, cmd); + + if (answer != null && answer.getResult()) { + _volsDao.remove(vol.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Volume successfully expunged from " + poolId); + } + } else { + s_logger.info("Will retry delete of " + vol + " from " + poolId); + } + } + + @Override @DB + public void cleanupVolumes(long vmId) throws ConcurrentOperationException { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Cleaning storage for vm: " + vmId); + } + List volumesForVm = _volsDao.findByInstance(vmId); + List toBeExpunged = new ArrayList(); + Transaction txn = Transaction.currentTxn(); + txn.start(); + for (VolumeVO vol : volumesForVm) { + if (vol.getVolumeType().equals(VolumeType.ROOT)) { + destroyVolume(vol); + toBeExpunged.add(vol); } else { - //data volume - _volsDao.detachVolume(vol.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Detaching " + vol); + } + _volsDao.detachVolume(vol.getId()); } } + txn.commit(); + + for (VolumeVO expunge : toBeExpunged) { + expungeVolume(expunge); + } } + + protected class StorageGarbageCollector implements Runnable { + + public StorageGarbageCollector() { + } + + @Override + public void run() { + try { + s_logger.trace("Storage Garbage Collection Thread is running."); + + cleanupStorage(true); + + } catch (Exception e) { + s_logger.error("Caught the following Exception", e); + } + } + } + } diff --git a/server/src/com/cloud/storage/allocator/LocalStoragePoolAllocator.java b/server/src/com/cloud/storage/allocator/LocalStoragePoolAllocator.java index 255461e3b8f..2e8d3f3fa1c 100644 --- a/server/src/com/cloud/storage/allocator/LocalStoragePoolAllocator.java +++ b/server/src/com/cloud/storage/allocator/LocalStoragePoolAllocator.java @@ -32,7 +32,7 @@ import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -150,14 +150,14 @@ public class LocalStoragePoolAllocator extends FirstFitStoragePoolAllocator { } } else if(vm.getType() == VirtualMachine.Type.ConsoleProxy) { so = new ServiceOfferingVO("Fake Offering For DomP", 1, - _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + _proxyRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.SecondaryStorageVm) { - so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.DomainRouter) { - so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else { assert(false) : "Unsupported system vm type"; - so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, false); + so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, false); } long usedMemory = calcHostAllocatedCpuMemoryCapacity(vmOnHost, CapacityVO.CAPACITY_TYPE_MEMORY); @@ -256,14 +256,14 @@ public class LocalStoragePoolAllocator extends FirstFitStoragePoolAllocator { so = _offeringDao.findById(userVm.getServiceOfferingId()); } else if(vm.getType() == VirtualMachine.Type.ConsoleProxy) { so = new ServiceOfferingVO("Fake Offering For DomP", 1, - _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + _proxyRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.SecondaryStorageVm) { - so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else if(vm.getType() == VirtualMachine.Type.DomainRouter) { - so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, true); + so = new ServiceOfferingVO("Fake Offering For DomR", 1, _routerRamSize, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, true); } else { assert(false) : "Unsupported system vm type"; - so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtual, false, true, null, false); + so = new ServiceOfferingVO("Fake Offering For unknow system VM", 1, 128, 0, 0, 0, false, null, Network.GuestIpType.Virtual, false, true, null, false); } if(capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) { diff --git a/server/src/com/cloud/storage/dao/VolumeDao.java b/server/src/com/cloud/storage/dao/VolumeDao.java index cfd3c9ada0c..e35b5e041ff 100755 --- a/server/src/com/cloud/storage/dao/VolumeDao.java +++ b/server/src/com/cloud/storage/dao/VolumeDao.java @@ -36,14 +36,10 @@ public interface VolumeDao extends GenericDao { List findByDetachedDestroyed(); List findByAccountAndPod(long accountId, long podId); List findByTemplateAndZone(long templateId, long zoneId); - List findVMInstancesByStorageHost(long hostId, Volume.MirrorState mState); - List findStrandedMirrorVolumes(); List findVmsStoredOnHost(long hostId); void deleteVolumesByInstance(long instanceId); void attachVolume(long volumeId, long vmId, long deviceId); void detachVolume(long volumeId); - void destroyVolume(long volumeId); - void recoverVolume(long volumeId); boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId); List listRemovedButNotDestroyed(); List findCreatedByInstance(long id); @@ -59,4 +55,6 @@ public interface VolumeDao extends GenericDao { */ boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException; HypervisorType getHypervisorType(long volumeId); + + List listVolumesToBeDestroyed(); } diff --git a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java index 5cd20f8315e..ecdb37b9bb0 100755 --- a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java @@ -32,7 +32,6 @@ import com.cloud.async.AsyncInstanceCreateStatus; import com.cloud.exception.ConcurrentOperationException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Volume; -import com.cloud.storage.Volume.MirrorState; import com.cloud.storage.Volume.VolumeType; import com.cloud.storage.VolumeVO; import com.cloud.utils.Pair; @@ -52,22 +51,14 @@ import com.cloud.utils.exception.CloudRuntimeException; public class VolumeDaoImpl extends GenericDaoBase implements VolumeDao { private static final Logger s_logger = Logger.getLogger(VolumeDaoImpl.class); protected final SearchBuilder DetachedAccountIdSearch; - protected final SearchBuilder AccountIdSearch; - protected final SearchBuilder AccountPodSearch; protected final SearchBuilder TemplateZoneSearch; protected final GenericSearchBuilder TotalSizeByPoolSearch; - protected final SearchBuilder InstanceIdSearch; - protected final SearchBuilder InstanceAndTypeSearch; - protected final SearchBuilder InstanceIdDestroyedSearch; - protected final SearchBuilder InstanceIdCreatedSearch; protected final SearchBuilder DetachedDestroyedSearch; - protected final SearchBuilder MirrorSearch; protected final GenericSearchBuilder ActiveTemplateSearch; protected final SearchBuilder RemovedButNotDestroyedSearch; - protected final SearchBuilder PoolIdSearch; - protected final SearchBuilder InstanceAndDeviceIdSearch; protected final SearchBuilder InstanceStatesSearch; - protected final SearchBuilder IdStateSearch; + + protected final SearchBuilder AllFieldsSearch; protected final Attribute _stateAttr; @@ -115,7 +106,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByAccount(long accountId) { - SearchCriteria sc = AccountIdSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("accountId", accountId); sc.setParameters("destroyed", false); return listBy(sc); @@ -123,14 +114,14 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByInstance(long id) { - SearchCriteria sc = InstanceIdSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); return listBy(sc); } @Override public List findByInstanceAndDeviceId(long instanceId, long deviceId){ - SearchCriteria sc = InstanceAndDeviceIdSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", instanceId); sc.setParameters("deviceId", deviceId); return listBy(sc); @@ -138,14 +129,14 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByPoolId(long poolId) { - SearchCriteria sc = PoolIdSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("poolId", poolId); return listBy(sc); } @Override public List findCreatedByInstance(long id) { - SearchCriteria sc = InstanceIdCreatedSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); sc.setParameters("status", AsyncInstanceCreateStatus.Created); sc.setParameters("destroyed", false); @@ -163,7 +154,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByInstanceAndType(long id, VolumeType vType) { - SearchCriteria sc = InstanceAndTypeSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", id); sc.setParameters("vType", vType.toString()); return listBy(sc); @@ -171,7 +162,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByInstanceIdDestroyed(long vmId) { - SearchCriteria sc = InstanceIdDestroyedSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", vmId); sc.setParameters("destroyed", true); return listIncludingRemovedBy(sc); @@ -186,8 +177,8 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public List findByAccountAndPod(long accountId, long podId) { - SearchCriteria sc = AccountPodSearch.create(); - sc.setParameters("account", accountId); + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); sc.setParameters("pod", podId); sc.setParameters("destroyed", false); sc.setParameters("status", AsyncInstanceCreateStatus.Created); @@ -204,38 +195,6 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol return listIncludingRemovedBy(sc); } - @Override @DB - public List findVMInstancesByStorageHost(long hostId, Volume.MirrorState mirrState) { - - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - - try { - String sql = SELECT_VM_SQL; - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, hostId); - pstmt.setString(2, mirrState.toString()); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - result.add(rs.getLong(1)); - } - return result; - } catch (SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + SELECT_VM_SQL, e); - } catch (Throwable e) { - throw new CloudRuntimeException("Caught: " + SELECT_VM_SQL, e); - } - } - - @Override - public List findStrandedMirrorVolumes() { - SearchCriteria sc = MirrorSearch.create(); - sc.setParameters("mirrorState", MirrorState.ACTIVE.toString()); - - return listIncludingRemovedBy(sc); - } - @Override public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) { SearchCriteria sc = ActiveTemplateSearch.create(); @@ -250,7 +209,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Override public void deleteVolumesByInstance(long instanceId) { - SearchCriteria sc = InstanceIdSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instanceId", instanceId); expunge(sc); } @@ -275,20 +234,6 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol update(volumeId, volume); } - @Override - public void destroyVolume(long volumeId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setDestroyed(true); - update(volumeId, volume); - } - - @Override - public void recoverVolume(long volumeId) { - VolumeVO volume = createForUpdate(volumeId); - volume.setDestroyed(false); - update(volumeId, volume); - } - @Override public boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException { Volume.State oldState = vol.getState(); @@ -299,7 +244,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol UpdateBuilder builder = getUpdateBuilder(vol); builder.set(vol, _stateAttr, newState); - SearchCriteria sc = IdStateSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("id", vol.getId()); sc.setParameters("state", oldState); @@ -310,6 +255,8 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol } return rows == 1; } + + @Override @DB public HypervisorType getHypervisorType(long volumeId) { /*lookup from cluster of pool*/ @@ -321,8 +268,9 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol pstmt = txn.prepareAutoCloseStatement(sql); pstmt.setLong(1, volumeId); ResultSet rs = pstmt.executeQuery(); - if (rs.next()) - return HypervisorType.getType(rs.getString(1)); + if (rs.next()) { + return HypervisorType.getType(rs.getString(1)); + } return HypervisorType.None; } catch (SQLException e) { throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e); @@ -332,98 +280,59 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol } protected VolumeDaoImpl() { - AccountIdSearch = createSearchBuilder(); - AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountIdSearch.and("destroyed", AccountIdSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - AccountIdSearch.done(); + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getDestroyed(), Op.EQ); + AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ); + AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ); + AllFieldsSearch.and("status", AllFieldsSearch.entity().getStatus(), Op.EQ); + AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getInstanceId(), Op.EQ); + AllFieldsSearch.and("deviceId", AllFieldsSearch.entity().getDeviceId(), Op.EQ); + AllFieldsSearch.and("poolId", AllFieldsSearch.entity().getPoolId(), Op.EQ); + AllFieldsSearch.and("vType", AllFieldsSearch.entity().getVolumeType(), Op.EQ); + AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); + AllFieldsSearch.done(); DetachedAccountIdSearch = createSearchBuilder(); - DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), SearchCriteria.Op.NULL); + DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), Op.EQ); + DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getDestroyed(), Op.EQ); + DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), Op.NULL); DetachedAccountIdSearch.done(); - AccountPodSearch = createSearchBuilder(); - AccountPodSearch.and("account", AccountPodSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountPodSearch.and("pod", AccountPodSearch.entity().getPodId(), SearchCriteria.Op.EQ); - AccountPodSearch.and("destroyed", AccountPodSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - AccountPodSearch.and("status", AccountPodSearch.entity().getStatus(), SearchCriteria.Op.EQ); - AccountPodSearch.done(); - TemplateZoneSearch = createSearchBuilder(); - TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), Op.EQ); + TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), Op.EQ); TemplateZoneSearch.done(); TotalSizeByPoolSearch = createSearchBuilder(SumCount.class); TotalSizeByPoolSearch.select("sum", Func.SUM, TotalSizeByPoolSearch.entity().getSize()); TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[])null); - TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), Op.EQ); + TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), Op.NULL); TotalSizeByPoolSearch.done(); - - InstanceIdCreatedSearch = createSearchBuilder(); - InstanceIdCreatedSearch.and("instanceId", InstanceIdCreatedSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceIdCreatedSearch.and("status", InstanceIdCreatedSearch.entity().getStatus(), SearchCriteria.Op.EQ); - InstanceIdCreatedSearch.and("destroyed", InstanceIdCreatedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - InstanceIdCreatedSearch.done(); - - InstanceIdSearch = createSearchBuilder(); - InstanceIdSearch.and("instanceId", InstanceIdSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceIdSearch.done(); - - InstanceAndDeviceIdSearch = createSearchBuilder(); - InstanceAndDeviceIdSearch.and("instanceId", InstanceAndDeviceIdSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceAndDeviceIdSearch.and("deviceId", InstanceAndDeviceIdSearch.entity().getDeviceId(), SearchCriteria.Op.EQ); - InstanceAndDeviceIdSearch.done(); - - PoolIdSearch = createSearchBuilder(); - PoolIdSearch.and("poolId", PoolIdSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - PoolIdSearch.done(); - - InstanceAndTypeSearch= createSearchBuilder(); - InstanceAndTypeSearch.and("instanceId", InstanceAndTypeSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceAndTypeSearch.and("vType", InstanceAndTypeSearch.entity().getVolumeType(), SearchCriteria.Op.EQ); - InstanceAndTypeSearch.done(); - - InstanceIdDestroyedSearch = createSearchBuilder(); - InstanceIdDestroyedSearch.and("instanceId", InstanceIdDestroyedSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceIdDestroyedSearch.and("destroyed", InstanceIdDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - InstanceIdDestroyedSearch.done(); - DetachedDestroyedSearch = createSearchBuilder(); - DetachedDestroyedSearch.and("instanceId", DetachedDestroyedSearch.entity().getInstanceId(), SearchCriteria.Op.NULL); - DetachedDestroyedSearch.and("destroyed", DetachedDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + DetachedDestroyedSearch.and("instanceId", DetachedDestroyedSearch.entity().getInstanceId(), Op.NULL); + DetachedDestroyedSearch.and("destroyed", DetachedDestroyedSearch.entity().getDestroyed(), Op.EQ); DetachedDestroyedSearch.done(); - MirrorSearch = createSearchBuilder(); - MirrorSearch.and("mirrorVolume", MirrorSearch.entity().getMirrorVolume(), Op.NULL); - MirrorSearch.and("mirrorState", MirrorSearch.entity().getMirrorState(), Op.EQ); - MirrorSearch.done(); - ActiveTemplateSearch = createSearchBuilder(Long.class); - ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ); - ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); - ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), SearchCriteria.Op.NULL); + ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), Op.EQ); + ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), Op.EQ); + ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), Op.NULL); ActiveTemplateSearch.select(null, Func.COUNT, null); ActiveTemplateSearch.done(); RemovedButNotDestroyedSearch = createSearchBuilder(); - RemovedButNotDestroyedSearch.and("destroyed", RemovedButNotDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - RemovedButNotDestroyedSearch.and("removed", RemovedButNotDestroyedSearch.entity().getRemoved(), SearchCriteria.Op.NNULL); + RemovedButNotDestroyedSearch.and("destroyed", RemovedButNotDestroyedSearch.entity().getDestroyed(), Op.EQ); + RemovedButNotDestroyedSearch.and("removed", RemovedButNotDestroyedSearch.entity().getRemoved(), Op.NNULL); RemovedButNotDestroyedSearch.done(); InstanceStatesSearch = createSearchBuilder(); - InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), SearchCriteria.Op.IN); + InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), Op.EQ); + InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN); InstanceStatesSearch.done(); - IdStateSearch = createSearchBuilder(); - IdStateSearch.and("id", IdStateSearch.entity().getId(), SearchCriteria.Op.EQ); - IdStateSearch.and("state", IdStateSearch.entity().getState(), SearchCriteria.Op.EQ); - IdStateSearch.done(); - _stateAttr = _allAttributes.get("state"); assert _stateAttr != null : "Couldn't get the state attribute"; } @@ -443,4 +352,12 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol public SumCount() { } } + + @Override + public List listVolumesToBeDestroyed() { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("state", Volume.State.Destroy); + + return listBy(sc); + } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 6af5602f90d..258890bc2a3 100644 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -56,6 +56,8 @@ import com.cloud.async.BaseAsyncJobExecutor; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.DataCenterDao; @@ -80,12 +82,12 @@ import com.cloud.info.RunningHostCountInfo; import com.cloud.info.RunningHostInfoAgregator; import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.network.IpAddrAllocator; +import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; -import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -259,7 +261,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(secStorageVmId); Account systemAcct = _accountMgr.getSystemAccount(); User systemUser = _accountMgr.getSystemUser(); - return _itMgr.start(secStorageVm, null, systemUser, systemAcct, null); + return _itMgr.start(secStorageVm, null, systemUser, systemAcct); } @@ -313,7 +315,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V setupCmd.setCopyPassword(copyPasswd); setupCmd.setCopyUserName(TemplateConstants.DEFAULT_HTTP_AUTH_USER); Answer answer = _agentMgr.easySend(storageHost.getId(), setupCmd); - if (answer != null) { + if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully programmed http auth into " + secStorageVm.getName()); } @@ -357,7 +359,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V } } Answer answer = _agentMgr.easySend(storageHost.getId(), cpc); - if (answer != null) { + if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully programmed firewall rules into " + secStorageVm.getName()); } @@ -440,23 +442,28 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V Account systemAcct = _accountMgr.getSystemAccount(); DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); + DataCenter dc = _dcDao.findById(plan.getDataCenterId()); - List defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmPublicNetwork); - List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork); + List defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork); + if (dc.getNetworkType() == NetworkType.Basic) { + defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SysteGuestNetwork); + } + + List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork); List> networks = new ArrayList>(offerings.size() + 1); NicProfile defaultNic = new NicProfile(); defaultNic.setDefaultNic(true); defaultNic.setDeviceId(2); try { - networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false).get(0), defaultNic)); + networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false, false).get(0), defaultNic)); for (NetworkOfferingVO offering : offerings) { - networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false).get(0), null)); + networks.add(new Pair(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false, false).get(0), null)); } } catch (ConcurrentOperationException e) { s_logger.info("Unable to setup due to concurrent operation. " + e); return new HashMap(); } - SecondaryStorageVmVO secStorageVm = new SecondaryStorageVmVO(id, _serviceOffering.getId(), name, _template.getId(), + SecondaryStorageVmVO secStorageVm = new SecondaryStorageVmVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getHypervisorType(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId()); try { secStorageVm = _itMgr.allocate(secStorageVm, _template, _serviceOffering, networks, plan, null, systemAcct); @@ -936,7 +943,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key())); - _serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, true, null, NetworkOffering.GuestIpType.Virtual, useLocalStorage, true, null, true); + _serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, true, null, Network.GuestIpType.Virtual, useLocalStorage, true, null, true); _serviceOffering.setUniqueName("Cloud.com-SecondaryStorage"); _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); _template = _templateDao.findConsoleProxyTemplate(); @@ -1076,7 +1083,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V final RebootCommand cmd = new RebootCommand(secStorageVm.getInstanceName()); final Answer answer = _agentMgr.easySend(secStorageVm.getHostId(), cmd); - if (answer != null) { + if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully reboot secondary storage vm " + secStorageVm.getName()); } @@ -1102,68 +1109,15 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V } @Override - @DB public boolean destroySecStorageVm(long vmId) { - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy secondary storage vm " + vmId + ", update async job-" + job.getId()); - } - _asyncMgr.updateAsyncJobAttachment(job.getId(), "secstorage_vm", vmId); + SecondaryStorageVmVO ssvm = _secStorageVmDao.findById(vmId); + + try { + return _itMgr.expunge(ssvm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + } catch (ResourceUnavailableException e) { + s_logger.warn("Unable to expunge " + ssvm, e); + return false; } - - SecondaryStorageVmVO vm = _secStorageVmDao.findById(vmId); - if (vm == null || vm.getState() == State.Destroyed) { - String msg = "Unable to find vm or vm is destroyed: " + vmId; - if (s_logger.isDebugEnabled()) { - s_logger.debug(msg); - } - return true; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Destroying secondary storage vm vm " + vmId); - } - - if (! _itMgr.stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, null)) { - String msg = "Unable to destroy the vm because it is not in the correct state: " + vmId; - s_logger.debug(msg); - return false; - } - - Transaction txn = Transaction.currentTxn(); - List vols = null; - try { - vols = _volsDao.findByInstance(vmId); - if (vols.size() != 0) { - _storageMgr.destroy(vm, vols); - } - - return true; - } finally { - try { - txn.start(); - // release critical system resources used by the VM before we - // delete them - if (vm.getPublicIpAddress() != null) { - freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId()); - } - vm.setPublicIpAddress(null); - - _secStorageVmDao.remove(vm.getId()); - - txn.commit(); - } catch (Exception e) { - s_logger.error("Caught this error: ", e); - txn.rollback(); - return false; - } finally { - s_logger.debug("secondary storage vm vm is destroyed : " - + vm.getName()); - } - } } @DB @@ -1267,7 +1221,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V MigrateCommand cmd = new MigrateCommand(secStorageVm.getInstanceName(), host.getPrivateIpAddress(), false); Answer answer = _agentMgr.easySend(fromHost.getId(), cmd); - if (answer == null) { + if (answer == null || !answer.getResult()) { return false; } @@ -1504,10 +1458,11 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V cmds.addCommand("checkSsh", check); SecondaryStorageVmVO secVm = profile.getVirtualMachine(); - List nics = _nicDao.listBy(secVm.getId()); + DataCenter dc = dest.getDataCenter(); + List nics = _nicDao.listBy(secVm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); - if (network.getTrafficType() == TrafficType.Public) { + if ((network.getTrafficType() == TrafficType.Public && dc.getNetworkType() == NetworkType.Advanced) || (network.getTrafficType() == TrafficType.Guest && dc.getNetworkType() == NetworkType.Basic)) { secVm.setPublicIpAddress(nic.getIp4Address()); secVm.setPublicNetmask(nic.getNetmask()); secVm.setPublicMacAddress(nic.getMacAddress()); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index ded81534115..044bd672065 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -349,21 +349,18 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volumeId + " is being used, try it later "); } } + if (_volsDao.getHypervisorType(volume.getId()).equals(HypervisorType.KVM)) { - /*for kvm, only Fedora supports snapshot, currently*/ StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId()); List hosts = _hostDao.listByCluster(cluster.getId()); if (hosts != null && !hosts.isEmpty()) { HostVO host = hosts.get(0); - _hostDao.loadDetails(host); - String hostOS = host.getDetail("Host.OS"); - String hostOSVersion = host.getDetail("Host.OS.Version"); - if (! (hostOS != null && hostOS.equalsIgnoreCase("Fedora") && hostOSVersion != null && Integer.parseInt(hostOSVersion) >= 13)) { - throw new CloudRuntimeException("KVM Snapshot is not supported on:" + hostOS + ": " + hostOSVersion + ". Please install Fedora 13 and above to enable snapshot"); - } + if (!hostSupportSnapsthot(host)) + throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId()); } } + SnapshotVO snapshot = null; boolean backedUp = false; try { @@ -1248,6 +1245,24 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma return success; } + + private boolean hostSupportSnapsthot(HostVO host) { + if (host.getHypervisorType() != HypervisorType.KVM) { + return true; + } + // Determine host capabilities + String caps = host.getCapabilities(); + + if (caps != null) { + String[] tokens = caps.split(","); + for (String token : tokens) { + if (token.contains("snapshot")) { + return true; + } + } + } + return false; + } } diff --git a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java index 676b4a03e65..0eab7c396e5 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java +++ b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java @@ -6,6 +6,7 @@ import java.util.Date; import java.util.List; import java.util.Map; import java.util.Timer; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -62,7 +63,6 @@ public class UploadMonitorImpl implements UploadMonitor { static final Logger s_logger = Logger.getLogger(UploadMonitorImpl.class); - private String _hyperVisorType; @Inject VMTemplateHostDao _vmTemplateHostDao; @Inject @@ -84,10 +84,10 @@ public class UploadMonitorImpl implements UploadMonitor { private String _name; private Boolean _sslCopy = new Boolean(false); - private String _copyAuthPasswd; private ScheduledExecutorService _executor = null; Timer _timer; + int _cleanupInterval; final Map _listenerMap = new ConcurrentHashMap(); @@ -200,7 +200,8 @@ public class UploadMonitorImpl implements UploadMonitor { _uploadDao.persist(uploadTemplateObj); try{ // Create Symlink at ssvm - CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(vmTemplateHost.getInstallPath()); + String uuid = UUID.randomUUID().toString() + ".vhd"; + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(vmTemplateHost.getInstallPath(), uuid); long result = send(sserver.getId(), cmd, null); if (result == -1){ errorString = "Unable to create a link for " +type+ " id:"+template.getId(); @@ -217,7 +218,7 @@ public class UploadMonitorImpl implements UploadMonitor { s_logger.error(errorString); throw new CloudRuntimeException(errorString); } - String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), vmTemplateHost.getInstallPath()); + String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), uuid); UploadVO vo = _uploadDao.createForUpdate(); vo.setLastUpdated(new Date()); vo.setUploadUrl(extractURL); @@ -259,7 +260,8 @@ public class UploadMonitorImpl implements UploadMonitor { _uploadDao.update(uploadJob.getId(), uploadJob); // Create Symlink at ssvm - CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(path); + String uuid = UUID.randomUUID().toString() + ".vhd"; + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(path, uuid); long result = send(ApiDBUtils.findUploadById(uploadId).getHostId(), cmd, null); if (result == -1){ errorString = "Unable to create a link for " +type+ " id:"+entityId; @@ -276,7 +278,7 @@ public class UploadMonitorImpl implements UploadMonitor { s_logger.warn(errorString); throw new CloudRuntimeException(errorString); } - String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), path); + String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), uuid); UploadVO vo = _uploadDao.createForUpdate(); vo.setLastUpdated(new Date()); vo.setUploadUrl(extractURL); @@ -298,7 +300,7 @@ public class UploadMonitorImpl implements UploadMonitor { } } - private String generateCopyUrl(String ipAddress, String path){ + private String generateCopyUrl(String ipAddress, String uuid){ String hostname = ipAddress; String scheme = "http"; if (_sslCopy) { @@ -306,7 +308,7 @@ public class UploadMonitorImpl implements UploadMonitor { hostname = hostname + ".realhostip.com"; scheme = "https"; } - return scheme + "://" + hostname + "/copy" + path.substring(path.lastIndexOf("/")); + return scheme + "://" + hostname + "/userdata/" + uuid; } @@ -320,18 +322,17 @@ public class UploadMonitorImpl implements UploadMonitor { throws ConfigurationException { _name = name; final Map configs = _configDao.getConfiguration("ManagementServer", params); - //_sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy")); + _sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy")); String cert = configs.get("secstorage.secure.copy.cert"); if ("realhostip.com".equalsIgnoreCase(cert)) { s_logger.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs"); - } - - _hyperVisorType = _configDao.getValue("hypervisor.type"); - - _copyAuthPasswd = configs.get("secstorage.copy.password"); + } _agentMgr.registerForHostEvents(new UploadListener(this), true, false, false); + String cleanupInterval = configs.get("extract.url.cleanup.interval"); + _cleanupInterval = NumbersUtil.parseInt(cleanupInterval, 14400); + String workers = (String)params.get("expunge.workers"); int wrks = NumbersUtil.parseInt(workers, 1); @@ -345,9 +346,8 @@ public class UploadMonitorImpl implements UploadMonitor { } @Override - public boolean start() { - //FIX ME - Make the timings configurable. // Keep them to 86400 for now. - _executor.scheduleWithFixedDelay(new StorageGarbageCollector(), 86400, 86400, TimeUnit.SECONDS); + public boolean start() { + _executor.scheduleWithFixedDelay(new StorageGarbageCollector(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS); _timer = new Timer(); return true; } @@ -469,7 +469,7 @@ public class UploadMonitorImpl implements UploadMonitor { public void cleanupStorage() { - final int EXTRACT_URL_LIFE_LIMIT_IN_SECONDS = 86400;//FIX ME make it configurable. + final int EXTRACT_URL_LIFE_LIMIT_IN_SECONDS = 14400;//FIX ME make it configurable. List extractJobs= _uploadDao.listByModeAndStatus(Mode.HTTP_DOWNLOAD, Status.DOWNLOAD_URL_CREATED); for (UploadVO extractJob : extractJobs){ @@ -477,7 +477,7 @@ public class UploadMonitorImpl implements UploadMonitor { String path = extractJob.getInstallPath(); s_logger.debug("Sending deletion of extract URL "+extractJob.getUploadUrl()); // Would delete the symlink for the Type and if Type == VOLUME then also the volume - DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path, extractJob.getType()); + DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path, extractJob.getType(),extractJob.getUploadUrl()); long result = send(extractJob.getHostId(), cmd, null); if (result == -1){ s_logger.warn("Unable to delete the link for " +extractJob.getType()+ " id=" +extractJob.getTypeId()+ " url="+extractJob.getUploadUrl()); diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 0be711d149e..58860348d28 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -501,6 +501,9 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe if (template.getTemplateType() == Storage.TemplateType.SYSTEM){ throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it is a default System template"); } + if (template.getTemplateType() == Storage.TemplateType.PERHOST){ + throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it resides on host and not on SSVM"); + } if (isISO) { if (template.getFormat() != ImageFormat.ISO ){ throw new InvalidParameterValueException("Unsupported format, could not extract the ISO"); diff --git a/server/src/com/cloud/test/DatabaseConfig.java b/server/src/com/cloud/test/DatabaseConfig.java old mode 100644 new mode 100755 index fe2d292d826..773e8f13907 --- a/server/src/com/cloud/test/DatabaseConfig.java +++ b/server/src/com/cloud/test/DatabaseConfig.java @@ -51,7 +51,8 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.cloud.host.Status; -import com.cloud.offering.NetworkOffering; +import com.cloud.network.Network; +import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDaoImpl; import com.cloud.storage.DiskOfferingVO; @@ -269,6 +270,7 @@ public class DatabaseConfig { s_configurationComponents.put("consoleproxy.session.max", "AgentManager"); s_configurationComponents.put("consoleproxy.session.timeout", "AgentManager"); s_configurationComponents.put("expunge.workers", "UserVmManager"); + s_configurationComponents.put("extract.url.cleanup.interval", "management-server"); s_configurationComponents.put("stop.retry.interval", "HighAvailabilityManager"); s_configurationComponents.put("restart.retry.interval", "HighAvailabilityManager"); s_configurationComponents.put("investigate.retry.interval", "HighAvailabilityManager"); @@ -325,6 +327,7 @@ public class DatabaseConfig { s_defaultConfigurationValues.put("max.account.user.vms", "20"); s_defaultConfigurationValues.put("max.account.public.ips", "20"); s_defaultConfigurationValues.put("expunge.interval", "86400"); + s_defaultConfigurationValues.put("extract.url.cleanup.interval", "120"); s_defaultConfigurationValues.put("instance.name", "VM"); s_defaultConfigurationValues.put("expunge.workers", "1"); s_defaultConfigurationValues.put("stop.retry.interval", "600"); @@ -751,11 +754,11 @@ public class DatabaseConfig { boolean ha = Boolean.parseBoolean(_currentObjectParams.get("enableHA")); boolean mirroring = Boolean.parseBoolean(_currentObjectParams.get("mirrored")); String guestIpType = _currentObjectParams.get("guestIpType"); - NetworkOffering.GuestIpType type = null; + Network.GuestIpType type = null; if (guestIpType == null) { - type = NetworkOffering.GuestIpType.Virtual; + type = Network.GuestIpType.Virtual; } else { - type = NetworkOffering.GuestIpType.valueOf(guestIpType); + type = Network.GuestIpType.valueOf(guestIpType); } boolean useLocalStorage; diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index b24428a1f29..5b2b8da31c7 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -98,8 +98,6 @@ public interface AccountManager extends AccountService { List searchForLimits(Criteria c); - - /** * Disables an account by accountId * @param accountId diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index d952e9a1a49..f8dfe283141 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -74,7 +74,6 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IPAddressVO; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; -import com.cloud.network.VirtualNetworkApplianceService; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.router.VirtualNetworkApplianceManager; @@ -674,7 +673,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag return _systemAccount; } - public static boolean isAdmin(short accountType) { + @Override + public boolean isAdmin(short accountType) { return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); @@ -1576,4 +1576,49 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } } + + public Account finalizeOwner(Account caller, String accountName, Long domainId) { + if (isAdmin(caller.getType())) { + if (domainId != null) { + DomainVO domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId); + } + + if (accountName != null) { + Account owner = _accountDao.findActiveAccount(accountName, domainId); + if (owner == null) { + throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); + } + checkAccess(caller, domain); + return owner; + } else { + throw new InvalidParameterValueException("Account have to be specified along with domainId"); + } + } else { + return caller; + } + } else { + //regular user can't create resources for other people + return caller; + } + } + + @Override + public Account getActiveAccount(String accountName, Long domainId) { + if (accountName == null || domainId == null) { + throw new InvalidParameterValueException("Both accountName and domainId are required for finding active account in the system"); + } else { + return _accountDao.findActiveAccount(accountName, domainId); + } + } + + @Override + public Account getAccount(Long accountId) { + if (accountId == null) { + throw new InvalidParameterValueException("AccountId is required by account search"); + } else { + return _accountDao.findById(accountId); + } + } } diff --git a/server/src/com/cloud/vm/ItWorkDao.java b/server/src/com/cloud/vm/ItWorkDao.java index 51c60943a9c..93b30c1654c 100644 --- a/server/src/com/cloud/vm/ItWorkDao.java +++ b/server/src/com/cloud/vm/ItWorkDao.java @@ -18,7 +18,21 @@ package com.cloud.vm; import com.cloud.utils.db.GenericDao; +import com.cloud.vm.VirtualMachine.State; public interface ItWorkDao extends GenericDao { - + /** + * find a work item based on the instanceId and the state. + * + * @param instanceId vm instance id + * @param state state + * @return ItWorkVO if found; null if not. + */ + ItWorkVO findByInstance(long instanceId, State state); + + /** + * cleanup rows that are either Done or Cancelled and been that way + * for at least wait time. + */ + void cleanup(long wait); } diff --git a/server/src/com/cloud/vm/ItWorkDaoImpl.java b/server/src/com/cloud/vm/ItWorkDaoImpl.java index 87ee53ae2fd..b7159fa417f 100644 --- a/server/src/com/cloud/vm/ItWorkDaoImpl.java +++ b/server/src/com/cloud/vm/ItWorkDaoImpl.java @@ -20,10 +20,55 @@ package com.cloud.vm; import javax.ejb.Local; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.time.InaccurateClock; +import com.cloud.vm.ItWorkVO.Step; +import com.cloud.vm.VirtualMachine.State; @Local(value=ItWorkDao.class) public class ItWorkDaoImpl extends GenericDaoBase implements ItWorkDao { + protected final SearchBuilder AllFieldsSearch; + protected final SearchBuilder CleanupSearch; + protected ItWorkDaoImpl() { super(); + + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("instance", AllFieldsSearch.entity().getInstanceId(), Op.EQ); + AllFieldsSearch.and("op", AllFieldsSearch.entity().getType(), Op.EQ); + AllFieldsSearch.and("step", AllFieldsSearch.entity().getStep(), Op.EQ); + AllFieldsSearch.done(); + + CleanupSearch = createSearchBuilder(); + CleanupSearch.and("step", CleanupSearch.entity().getType(), Op.IN); + CleanupSearch.and("time", CleanupSearch.entity().getUpdatedAt(), Op.LT); + CleanupSearch.done(); + } + + @Override + public ItWorkVO findByInstance(long instanceId, State state) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instance", instanceId); + sc.setParameters("op", state); + + return findOneBy(sc); + } + + @Override + public void cleanup(long wait) { + SearchCriteria sc = CleanupSearch.create(); + sc.setParameters("step", Step.Done, Step.Cancelled); + sc.setParameters("time", InaccurateClock.getTimeInSeconds() - wait); + + remove(sc); + } + + @Override + public boolean update(String id, ItWorkVO work) { + work.setUpdatedAt(InaccurateClock.getTimeInSeconds()); + + return super.update(id, work); } } diff --git a/server/src/com/cloud/vm/ItWorkVO.java b/server/src/com/cloud/vm/ItWorkVO.java index a823c7be11b..ca94b3825f1 100644 --- a/server/src/com/cloud/vm/ItWorkVO.java +++ b/server/src/com/cloud/vm/ItWorkVO.java @@ -17,81 +17,115 @@ */ package com.cloud.vm; -import java.util.Date; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import com.cloud.utils.db.GenericDao; +import com.cloud.utils.time.InaccurateClock; +import com.cloud.vm.VirtualMachine.State; @Entity @Table(name="op_it_work") public class ItWorkVO { - enum Type { - Start, - Cleanup; + enum ResourceType { + Volume, + Nic } - enum State { - Working, - Cancelling, + enum Step { + Reserve, + Prepare, + Start, + Started, + Cancelled, + Done } @Id @Column(name="id") String id; - @Column(name=GenericDao.CREATED_COLUMN) - Date created; + @Column(name="created_at") + long createdAt; @Column(name="mgmt_server_id") long managementServerId; @Column(name="type") - Type type; + State type; @Column(name="thread") String threadName; - @Column(name="state") - State state; + @Column(name="step") + Step step; - @Column(name="cancel_taken") - @Temporal(value=TemporalType.TIMESTAMP) - Date taken; + @Column(name="updated_at") + long updatedAt; + @Column(name="instance_id") + long instanceId; + + public long getInstanceId() { + return instanceId; + } + + @Column(name="resource_id") + long resourceId; + + @Column(name="resource_type") + ResourceType resourceType; + + + public long getResourceId() { + return resourceId; + } + + public void setResourceId(long resourceId) { + this.resourceId = resourceId; + } + + public ResourceType getResourceType() { + return resourceType; + } + + public void setResourceType(ResourceType resourceType) { + this.resourceType = resourceType; + } + protected ItWorkVO() { } - protected ItWorkVO(String id, long managementServerId, Type type) { + protected ItWorkVO(String id, long managementServerId, State type, long instanceId) { this.id = id; this.managementServerId = managementServerId; this.type = type; this.threadName = Thread.currentThread().getName(); - this.state = State.Working; + this.step = Step.Prepare; + this.instanceId = instanceId; + this.resourceType = null; + this.createdAt = InaccurateClock.getTimeInSeconds(); + this.updatedAt = createdAt; } public String getId() { return id; } - public Date getCreated() { - return created; + public Long getCreatedAt() { + return createdAt; } - + public long getManagementServerId() { return managementServerId; } - public Type getType() { + public State getType() { return type; } - public void setType(Type type) { + public void setType(State type) { this.type = type; } @@ -99,15 +133,27 @@ public class ItWorkVO { return threadName; } - public State getState() { - return state; + public Step getStep() { + return step; } - public void setState(State state) { - this.state = state; + public void setStep(Step step) { + this.step = step; } - public Date getTaken() { - return taken; + public long getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + } + + public long getSecondsTaskIsInactive() { + return InaccurateClock.getTimeInSeconds() - this.updatedAt; + } + + public long getSecondsTaskHasBeenCreated() { + return InaccurateClock.getTimeInSeconds() - this.createdAt; } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index b58a2e1e0c7..f3d01f78d0b 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -122,7 +122,6 @@ import com.cloud.network.IpAddrAllocator; import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; -import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; @@ -130,11 +129,11 @@ import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.lb.LoadBalancingRulesManager; +import com.cloud.network.ovs.GreTunnelException; +import com.cloud.network.ovs.OvsNetworkManager; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.rules.RulesManager; import com.cloud.network.security.SecurityGroupManager; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.offering.ServiceOffering; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.server.Criteria; @@ -266,6 +265,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Inject UsageEventDao _usageEventDao; @Inject SSHKeyPairDao _sshKeyPairDao; @Inject UserVmDetailsDao _vmDetailsDao; + @Inject OvsNetworkManager _ovsNetworkMgr; private IpAddrAllocator _IpAllocator; ScheduledExecutorService _executor = null; @@ -939,7 +939,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager public void releaseGuestIpAddress(UserVmVO userVm) { ServiceOffering offering = _offeringDao.findById(userVm.getServiceOfferingId()); - if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtual) { + if (offering.getGuestIpType() != Network.GuestIpType.Virtual) { IPAddressVO guestIP = (userVm.getGuestIpAddress() == null) ? null : _ipAddressDao.findById(new Ip(userVm.getGuestIpAddress())); if (guestIP != null && guestIP.getAllocatedTime() != null) { _ipAddressDao.unassignIpAddress(new Ip(userVm.getGuestIpAddress())); @@ -1033,13 +1033,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager // Recover the VM's disks List volumes = _volsDao.findByInstanceIdDestroyed(vmId); for (VolumeVO volume : volumes) { - _volsDao.recoverVolume(volume.getId()); // Create an event Long templateId = volume.getTemplateId(); Long diskOfferingId = volume.getDiskOfferingId(); long sizeMB = volume.getSize()/(1024*1024); StoragePoolVO pool = _storagePoolDao.findById(volume.getPoolId()); - EventUtils.saveEvent(User.UID_SYSTEM, volume.getAccountId(), EventTypes.EVENT_VOLUME_CREATE, "Created volume: "+ volume.getName() +" with size: " + sizeMB + " MB in pool: " + pool.getName()); UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, templateId , sizeMB); _usageEventDao.persist(usageEvent); @@ -1134,14 +1132,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new CloudRuntimeException("Shouldn't even be here!"); } } - - @Override - public void completeStartCommand(UserVmVO vm) { - _itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId()); - _networkGroupMgr.handleVmStateTransition(vm, State.Running); - - } - + @Override public void completeStopCommand(UserVmVO instance) { completeStopCommand(1L, instance, VirtualMachine.Event.AgentReportStopped); @@ -1172,7 +1163,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } txn.commit(); - _networkGroupMgr.handleVmStateTransition(vm, State.Stopped); } catch (Throwable th) { s_logger.error("Error during stop: ", th); throw new CloudRuntimeException("Error during stop: ", th); @@ -2256,9 +2246,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager s_logger.debug("Allocating in the DB for vm"); if (dc.getNetworkType() == NetworkType.Basic && networkList == null) { - Network defaultNetwork = _networkMgr.getBasicZoneDefaultPublicNetwork(dc.getId()); + Network defaultNetwork = _networkMgr.getSystemNetworkByZoneAndTrafficType(dc.getId(), TrafficType.Guest); if (defaultNetwork == null) { - throw new InvalidParameterValueException("Unable to find a default directPodBased network to start a vm"); + throw new InvalidParameterValueException("Unable to find a default network to start a vm"); } else { networkList = new ArrayList(); networkList.add(defaultNetwork.getId()); @@ -2270,6 +2260,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } List> networks = new ArrayList>(); + short defaultNetworkNumber = 0; for (Long networkId : networkList) { NetworkVO network = _networkDao.findById(networkId); if (network == null) { @@ -2282,10 +2273,21 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new PermissionDeniedException("Unable to create a vm using network with id " + networkId + ", permission denied"); } } + + if (network.isDefault()) { + defaultNetworkNumber++; + } networks.add(new Pair(network, null)); } } + //at least one network default network has to be set + if (defaultNetworkNumber == 0) { + throw new InvalidParameterValueException("At least 1 default network has to be specified for the vm"); + } else if (defaultNetworkNumber >1) { + throw new InvalidParameterValueException("Only 1 default network per vm is supported"); + } + long id = _vmDao.getNextInSequence(Long.class, "id"); String hostName = cmd.getName(); @@ -2304,9 +2306,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } - UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), - template.getId(), template.getGuestOSId(), offering.getOfferHA(), domainId, owner.getId(), offering.getId(), - userData, hostName, sshPublicKey); + HypervisorType hypervisorType = null; + if (template == null || template.getHypervisorType() == null || template.getHypervisorType() == HypervisorType.None) { + hypervisorType = cmd.getHypervisor(); + } else { + hypervisorType = template.getHypervisorType(); + } + + UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), template.getId(), hypervisorType, + template.getGuestOSId(), offering.getOfferHA(), domainId, owner.getId(), offering.getId(), userData, hostName, sshPublicKey); if (_itMgr.allocate(vm, template, offering, rootDiskOffering, dataDiskOfferings, networks, null, plan, cmd.getHypervisor(), owner) == null) { @@ -2371,8 +2379,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager AccountVO owner = _accountDao.findById(vm.getAccountId()); try { - vm = _itMgr.start(vm, null, caller, owner, cmd.getHypervisor()); - } finally { + vm = _itMgr.start(vm, null, caller, owner); + } catch (Exception e) { + e.printStackTrace(); + } + finally { updateVmStateForFailedVmCreation(vm.getId()); } vm.setPassword(password); @@ -2426,12 +2437,26 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } _vmDao.update(userVm.getId(), userVm); + + try { + _ovsNetworkMgr.UserVmCheckAndCreateTunnel(cmds, profile, dest); + _ovsNetworkMgr.applyDefaultFlowToUserVm(cmds, profile, dest); + } catch (GreTunnelException e) { + e.printStackTrace(); + } + return true; } @Override public boolean finalizeStart(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - return true; + UserVmVO vm = profile.getVirtualMachine(); + _networkGroupMgr.handleVmStateTransition(vm, State.Running); + _ovsNetworkMgr.handleVmStateTransition(vm, State.Running); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(), vm.getTemplateId(), null); + _usageEventDao.persist(usageEvent); + + return true; } @Override @@ -2483,6 +2508,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public void finalizeStop(VirtualMachineProfile profile, long hostId, String reservationId, Answer...answer) { + UserVmVO vm = profile.getVirtualMachine(); + _networkGroupMgr.handleVmStateTransition(vm, State.Stopped); + _ovsNetworkMgr.handleVmStateTransition(vm, State.Stopped); } public String generateRandomPassword() { @@ -2508,9 +2536,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager userId = accountAndUserValidation(vmId, account, userId, vm); UserVO user = _userDao.findById(userId); - VolumeVO disk = _volsDao.findByInstance(vmId).get(0); - HypervisorType hyperType = _volsDao.getHypervisorType(disk.getId()); - return _itMgr.start(vm, null, user, account, hyperType); + return _itMgr.start(vm, null, user, account); } @Override @@ -2543,6 +2569,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new CloudRuntimeException("Failed to destroy vm with id " + vmId); } } + + @Override + public void completeStartCommand(UserVmVO vm) { + _itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId()); + } @Override @@ -2701,7 +2732,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } if (useVirtualNetwork != null) { - sc.setJoinParameters("serviceSearch", "guestIpType", NetworkOffering.GuestIpType.Virtual.toString()); + sc.setJoinParameters("serviceSearch", "guestIpType", Network.GuestIpType.Virtual.toString()); } if (keyword != null) { diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index a866e168450..c3020e1311b 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -35,7 +35,6 @@ import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; -import com.cloud.vm.VirtualMachine.Event; /** * Manages allocating resources to vms. @@ -71,7 +70,7 @@ public interface VirtualMachineManager extends Manager { HypervisorType hyperType, Account owner) throws InsufficientCapacityException; - T start(T vm, Map params, User caller, Account account, HypervisorType hyperType) throws InsufficientCapacityException, ResourceUnavailableException; + T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException; boolean stop(T vm, User caller, Account account) throws ResourceUnavailableException; @@ -79,9 +78,9 @@ public interface VirtualMachineManager extends Manager { void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru); - boolean stateTransitTo(VMInstanceVO vm, Event e, Long id); + boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId); - T advanceStart(T vm, Map params, User caller, Account account, HypervisorType hyperType) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; + T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; boolean advanceStop(T vm, boolean forced, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException; diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 7f58a0c3bf6..54cfe63342f 100644 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -22,6 +22,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -31,14 +34,13 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager.OnError; import com.cloud.agent.api.Answer; +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.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; import com.cloud.cluster.ClusterManager; -import com.cloud.cluster.ClusterManagerListener; -import com.cloud.cluster.ManagementServerHostVO; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; @@ -67,66 +69,78 @@ import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; import com.cloud.storage.Volume.VolumeType; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; -import com.cloud.uservm.UserVm; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; +import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.StateListener; import com.cloud.utils.fsm.StateMachine2; -import com.cloud.vm.ItWorkVO.Type; +import com.cloud.vm.ItWorkVO.Step; import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.SecondaryStorageVmDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Local(value=VirtualMachineManager.class) -public class VirtualMachineManagerImpl implements VirtualMachineManager, ClusterManagerListener { +public class VirtualMachineManagerImpl implements VirtualMachineManager { private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class); String _name; - @Inject private StorageManager _storageMgr; - @Inject private NetworkManager _networkMgr; - @Inject private AgentManager _agentMgr; - @Inject private VMInstanceDao _vmDao; - @Inject private ServiceOfferingDao _offeringDao; - @Inject private VMTemplateDao _templateDao; - @Inject private UserDao _userDao; - @Inject private AccountDao _accountDao; - @Inject private DomainDao _domainDao; - @Inject private ClusterManager _clusterMgr; - @Inject private ItWorkDao _workDao; - @Inject private UserVmDao _userVmDao; - @Inject private DomainRouterDao _routerDao; - @Inject private ConsoleProxyDao _consoleDao; - @Inject private SecondaryStorageVmDao _secondaryDao; - @Inject private UsageEventDao _usageEventDao; + @Inject protected StorageManager _storageMgr; + @Inject protected NetworkManager _networkMgr; + @Inject protected AgentManager _agentMgr; + @Inject protected VMInstanceDao _vmDao; + @Inject protected ServiceOfferingDao _offeringDao; + @Inject protected VMTemplateDao _templateDao; + @Inject protected UserDao _userDao; + @Inject protected AccountDao _accountDao; + @Inject protected DomainDao _domainDao; + @Inject protected ClusterManager _clusterMgr; + @Inject protected ItWorkDao _workDao; + @Inject protected UserVmDao _userVmDao; + @Inject protected DomainRouterDao _routerDao; + @Inject protected ConsoleProxyDao _consoleDao; + @Inject protected SecondaryStorageVmDao _secondaryDao; + @Inject protected UsageEventDao _usageEventDao; + @Inject protected NicDao _nicsDao; @Inject(adapter=DeploymentPlanner.class) - private Adapters _planners; + protected Adapters _planners; @Inject(adapter=StateListener.class) - private Adapters> _stateListner; + protected Adapters> _stateListner; + Map> _vmGurus = new HashMap>(); Map _hvGurus = new HashMap(); - private StateMachine2 _stateMachine; + protected StateMachine2 _stateMachine; - private int _retry; - private long _nodeId; + ScheduledExecutorService _executor = null; + + protected int _retry; + protected long _nodeId; + protected long _cleanupWait; + protected long _cleanupInterval; + protected long _cancelWait; + protected long _opWaitInterval; + protected int _lockStateRetry; @Override public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) { @@ -150,7 +164,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster s_logger.debug("Allocating entries for VM: " + vm); } - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, params, hyperType); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, params); vm.setDataCenterId(plan.getDataCenterId()); if (plan.getPodId() != null) { @@ -200,6 +214,58 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster return vm; } + protected void reserveNics(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { +// List nics = _nicsDao.listBy(vmProfile.getId()); +// for (NicVO nic : nics) { +// Pair implemented = _networkMgr.implementNetwork(nic.getNetworkId(), dest, context); +// NetworkGuru concierge = implemented.first(); +// NetworkVO network = implemented.second(); +// NicProfile profile = null; +// if (nic.getReservationStrategy() == ReservationStrategy.Start) { +// nic.setState(Resource.State.Reserving); +// nic.setReservationId(context.getReservationId()); +// _nicsDao.update(nic.getId(), nic); +// URI broadcastUri = nic.getBroadcastUri(); +// if (broadcastUri == null) { +// network.getBroadcastUri(); +// } +// +// URI isolationUri = nic.getIsolationUri(); +// +// profile = new NicProfile(nic, network, broadcastUri, isolationUri); +// concierge.reserve(profile, network, vmProfile, dest, context); +// nic.setIp4Address(profile.getIp4Address()); +// nic.setIp6Address(profile.getIp6Address()); +// nic.setMacAddress(profile.getMacAddress()); +// nic.setIsolationUri(profile.getIsolationUri()); +// nic.setBroadcastUri(profile.getBroadCastUri()); +// nic.setReserver(concierge.getName()); +// nic.setState(Resource.State.Reserved); +// nic.setNetmask(profile.getNetmask()); +// nic.setGateway(profile.getGateway()); +// nic.setAddressFormat(profile.getFormat()); +// _nicsDao.update(nic.getId(), nic); +// } else { +// profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri()); +// } +// +// for (NetworkElement element : _networkElements) { +// if (s_logger.isDebugEnabled()) { +// s_logger.debug("Asking " + element.getName() + " to prepare for " + nic); +// } +// element.prepare(network, profile, vmProfile, dest, context); +// } +// +// vmProfile.addNic(profile); +// _networksDao.changeActiveNicsBy(network.getId(), 1); +// } + } + + protected void prepareNics(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) { + + } + + @Override public T allocate(T vm, VMTemplateVO template, @@ -283,6 +349,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster @Override public boolean start() { + _executor.scheduleAtFixedRate(new CleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS); return true; } @@ -309,8 +376,14 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster _hvGurus.put(guru.getHypervisorType(), guru); } + _cancelWait = NumbersUtil.parseLong(params.get(Config.VmOpCancelInterval.key()), 3600); + _cleanupWait = NumbersUtil.parseLong(params.get(Config.VmOpCleanupWait.key()), 3600); + _cleanupInterval = NumbersUtil.parseLong(params.get(Config.VmOpCleanupInterval.key()), 86400) * 1000; + _opWaitInterval = NumbersUtil.parseLong(params.get(Config.VmOpWaitInterval.key()), 120) * 1000; + _lockStateRetry = NumbersUtil.parseInt(params.get(Config.VmOpLockStateRetry.key()), 5); + + _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup")); _nodeId = _clusterMgr.getId(); - _clusterMgr.registerListener(this); setStateMachine(); @@ -326,144 +399,232 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster } @Override - public T start(T vm, Map params, User caller, Account account, HypervisorType hyperType) throws InsufficientCapacityException, ResourceUnavailableException { + public T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException { try { - return advanceStart(vm, params, caller, account, hyperType); + return advanceStart(vm, params, caller, account); } catch (ConcurrentOperationException e) { throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e); } } + private Answer getStartAnswer(Answer[] answers) { + for (Answer ans : answers) { + if (ans instanceof StartAnswer) { + return ans; + } + } + + assert false : "Why there is no Start Answer???"; + return null; + } + + protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException { + while (true) { + ItWorkVO vo = _workDao.findByInstance(vm.getId(), state); + if (vo == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find work for " + vm); + } + return true; + } + + if (vo.getStep() == Step.Done || vo.getStep() == Step.Cancelled) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Work for " + vm + " is " + vo.getStep()); + } + return true; + } + + if (vo.getSecondsTaskIsInactive() > _cancelWait) { + s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive()); + return false; + } + + try { + Thread.sleep(_opWaitInterval); + } catch (InterruptedException e) { + s_logger.info("Waiting for " + vm + " but is interrupted"); + throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted"); + } + s_logger.debug("Waiting some more to make sure there's no activity on " + vm); + } + + + } + + @DB + protected Ternary changeToStartState(VirtualMachineGuru vmGuru, T vm, User caller, Account account) throws ConcurrentOperationException { + long vmId = vm.getId(); + + ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getId()); + int retry = _lockStateRetry; + while (retry-- != 0) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) { + + Journal journal = new Journal.LogJournal("Creating " + vm, s_logger); + work = _workDao.persist(work); + ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId()); + } + txn.commit(); + return new Ternary(vmGuru.findById(vmId), context, work); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Determining why we're unable to update the state to Starting for " + vm); + } + + VMInstanceVO instance = _vmDao.lockRow(vmId, true); + if (instance == null) { + throw new ConcurrentOperationException("Unable to acquire lock on " + vm); + } + + State state = instance.getState(); + if (state == State.Running) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("VM is already started: " + vm); + } + txn.commit(); + return null; + } + + if (state.isTransitional()) { + if (!checkWorkItems(vm, state)) { + throw new ConcurrentOperationException("There are concurrent operations on the VM " + vm); + } else { + continue; + } + } + + if (state != State.Stopped) { + s_logger.debug("VM " + vm + " is not in a state to be started: " + state); + txn.commit(); + return null; + } + } + + throw new ConcurrentOperationException("Unable to change the state of " + vm); + } + @Override - public T advanceStart(T vm, Map params, User caller, Account account, HypervisorType hyperType) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - State state = vm.getState(); - if (state == State.Starting || state == State.Running) { - s_logger.debug("VM is already started: " + vm); - return vm; + public T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { + long vmId = vm.getId(); + + VirtualMachineGuru vmGuru = getVmGuru(vm); + + Ternary start = changeToStartState(vmGuru, vm, caller, account); + if (start == null) { + return vmGuru.findById(vmId); } - if (state != State.Stopped) { - s_logger.debug("VM " + vm + " is not in a state to be started: " + state); - return null; - } + vm = start.first(); + ReservationContext ctx = start.second(); + ItWorkVO work = start.third(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating actual resources for VM " + vm); - } + T startedVm = null; - Journal journal = new Journal.LogJournal("Creating " + vm, s_logger); - - ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, ItWorkVO.Type.Start); - work = _workDao.persist(work); - - ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account); - - ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); - VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); - - DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodId(), null, null); - - HypervisorGuru hvGuru; - if (hyperType != null && !hyperType.equals(HypervisorType.None)) { - hvGuru = _hvGurus.get(hyperType); - } else { - hvGuru = _hvGurus.get(template.getHypervisorType()); - } - @SuppressWarnings("unchecked") - VirtualMachineGuru vmGuru = (VirtualMachineGuru)_vmGurus.get(vm.getType()); - - vm.setReservationId(work.getId()); - - ExcludeList avoids = new ExcludeList(); - int retry = _retry; - DeployDestination dest = null; - while (retry-- != 0) { // It's != so that it can match -1. - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, null, params, hyperType); - - for (DeploymentPlanner planner : _planners) { - dest = planner.plan(vmProfile, plan, avoids); - if (dest != null) { - avoids.addHost(dest.getHost().getId()); - journal.record("Deployment found ", vmProfile, dest); - break; + try { + ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); + VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); + + DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodId(), null, null); + + HypervisorGuru hvGuru = _hvGurus.get(vm.getHypervisorType()); + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, null, params); + + Journal journal = start.second().getJournal(); + + ExcludeList avoids = new ExcludeList(); + int retry = _retry; + while (retry-- != 0) { // It's != so that it can match -1. + + DeployDestination dest = null; + for (DeploymentPlanner planner : _planners) { + dest = planner.plan(vmProfile, plan, avoids); + if (dest != null) { + avoids.addHost(dest.getHost().getId()); + journal.record("Deployment found ", vmProfile, dest); + break; + } } - } - - if (dest == null) { - if (retry != (_retry -1)) { - stateTransitTo(vm, Event.OperationFailed, null); - } - throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); - } - - if (retry == (_retry -1)) { - if (!stateTransitTo(vm, Event.StartRequested, dest.getHost().getId())) { - throw new ConcurrentOperationException("Unable to start vm " + vm + " due to concurrent operations"); - } - } else { + + if (dest == null) { + throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); + } + stateTransitTo(vm, Event.OperationRetry, dest.getHost().getId()); - } - - vm.setDataCenterId(dest.getDataCenter().getId()); - vm.setPodId(dest.getPod().getId()); - - try { - _storageMgr.prepare(vmProfile, dest); - _networkMgr.prepare(vmProfile, dest, context); - } catch (ConcurrentOperationException e) { - stateTransitTo(vm, Event.OperationFailed, null); - throw e; - } catch (ResourceUnavailableException e) { - s_logger.warn("Unable to contact storage.", e); - avoids.addCluster(dest.getCluster().getId()); - continue; - } catch (InsufficientCapacityException e) { - s_logger.warn("Insufficient capacity ", e); - avoids.add(e); - continue; - } catch (RuntimeException e) { - s_logger.warn("Failed to start instance " + vm, e); - stateTransitTo(vm, Event.OperationFailed, null); - return null; - } - - vmGuru.finalizeVirtualMachineProfile(vmProfile, dest, context); - - VirtualMachineTO vmTO = hvGuru.implement(vmProfile); - - Commands cmds = new Commands(OnError.Revert); - cmds.addCommand(new StartCommand(vmTO)); - - vmGuru.finalizeDeployment(cmds, vmProfile, dest, context); - try { - Answer[] answers = _agentMgr.send(dest.getHost().getId(), cmds); - if (answers[0].getResult() && vmGuru.finalizeStart(cmds, vmProfile, dest, context)) { - if (!stateTransitTo(vm, Event.OperationSucceeded, dest.getHost().getId())) { - throw new CloudRuntimeException("Unable to transition to a new state."); + + try { + _storageMgr.prepare(vmProfile, dest); + _networkMgr.prepare(vmProfile, dest, ctx); + } catch (ResourceUnavailableException e) { + if (!avoids.add(e)) { + if (e.getScope() == Volume.class || e.getScope() == Nic.class) { + throw e; + } else { + throw new CloudRuntimeException("Resource is not available to start the VM.", e); + } } - if(vm instanceof UserVm){ - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(), vm.getTemplateId(), null); - _usageEventDao.persist(usageEvent); + s_logger.info("Unable to contact resource.", e); + continue; + } catch (InsufficientCapacityException e) { + if (!avoids.add(e)) { + if (e.getScope() == Volume.class || e.getScope() == Nic.class) { + throw e; + } else { + throw new CloudRuntimeException("Insufficient capacity to start the VM.", e); + } } - return vm; + s_logger.info("Insufficient capacity ", e); + continue; + } catch (RuntimeException e) { + s_logger.warn("Failed to start instance " + vm, e); + throw new CloudRuntimeException("Failed to start " + vm, e); + } + + vmGuru.finalizeVirtualMachineProfile(vmProfile, dest, ctx); + + VirtualMachineTO vmTO = hvGuru.implement(vmProfile); + + Commands cmds = new Commands(OnError.Revert); + cmds.addCommand(new StartCommand(vmTO)); + + vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); + try { + Answer[] answers = _agentMgr.send(dest.getHost().getId(), cmds); + if (getStartAnswer(answers).getResult() && vmGuru.finalizeStart(cmds, vmProfile, dest, ctx)) { + if (!stateTransitTo(vm, Event.OperationSucceeded, dest.getHost().getId())) { + throw new CloudRuntimeException("Unable to transition to a new state."); + } + startedVm = vm; + break; + } + s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + answers[0].getDetails()); + } catch (AgentUnavailableException e) { + s_logger.debug("Unable to send the start command to host " + dest.getHost()); + continue; + } catch (OperationTimedoutException e) { + s_logger.debug("Unable to send the start command to host " + dest.getHost()); + continue; } - s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + answers[0].getDetails()); - } catch (AgentUnavailableException e) { - s_logger.debug("Unable to send the start command to host " + dest.getHost()); - continue; - } catch (OperationTimedoutException e) { - s_logger.debug("Unable to send the start command to host " + dest.getHost()); - continue; } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creation complete for VM " + vm); + } + } finally { + if (startedVm == null) { + stateTransitTo(vm, Event.OperationFailed, null); + } + work.setStep(Step.Done); + _workDao.update(work.getId(), work); } - stateTransitTo(vm, Event.OperationFailed, null); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creation complete for VM " + vm); - } - - return null; + return startedVm; } @Override @@ -563,22 +724,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster stateTransitTo(vm, Event.OperationSucceeded, null); if (cleanup) { - ItWorkVO work = new ItWorkVO(reservationId, _nodeId, Type.Cleanup); + ItWorkVO work = new ItWorkVO(reservationId, _nodeId, State.Stopping, vm.getId()); _workDao.persist(work); } return stopped; } - @Override - public void onManagementNodeJoined(List nodeList, long selfNodeId) { - - } - - @Override - public void onManagementNodeLeft(List nodeList, long selfNodeId) { - } - private void setStateMachine() { _stateMachine = new StateMachine2(); @@ -628,21 +780,36 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster _stateMachine.registerListeners(_stateListner); } - @Override - public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long id) { + protected boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId, String reservationId) { + vm.setReservationId(reservationId); if (vm instanceof UserVmVO) { - return _stateMachine.transitTO(vm, e, id, _userVmDao); + return _stateMachine.transitTO(vm, e, hostId, _userVmDao); } else if (vm instanceof ConsoleProxyVO) { - return _stateMachine.transitTO(vm, e, id, _consoleDao); + return _stateMachine.transitTO(vm, e, hostId, _consoleDao); } else if (vm instanceof SecondaryStorageVmVO) { - return _stateMachine.transitTO(vm, e, id, _secondaryDao); + return _stateMachine.transitTO(vm, e, hostId, _secondaryDao); } else if (vm instanceof DomainRouterVO) { - return _stateMachine.transitTO(vm, e, id, _routerDao); + return _stateMachine.transitTO(vm, e, hostId, _routerDao); } else { - return _stateMachine.transitTO(vm, e, id, _vmDao); + return _stateMachine.transitTO(vm, e, hostId, _vmDao); } } + @Override + public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) { + if (vm instanceof UserVmVO) { + return _stateMachine.transitTO(vm, e, hostId, _userVmDao); + } else if (vm instanceof ConsoleProxyVO) { + return _stateMachine.transitTO(vm, e, hostId, _consoleDao); + } else if (vm instanceof SecondaryStorageVmVO) { + return _stateMachine.transitTO(vm, e, hostId, _secondaryDao); + } else if (vm instanceof DomainRouterVO) { + return _stateMachine.transitTO(vm, e, hostId, _routerDao); + } else { + return _stateMachine.transitTO(vm, e, hostId, _vmDao); + } + } + @Override public boolean remove(T vm, User user, Account caller) { return _vmDao.remove(vm.getId()); @@ -672,4 +839,17 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Cluster return true; } + + protected class CleanupTask implements Runnable { + + @Override + public void run() { + s_logger.trace("VM Operation Thread Running"); + try { + _workDao.cleanup(_cleanupWait); + } catch (Exception e) { + s_logger.error("VM Operations failed due to ", e); + } + } + } } diff --git a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java index 60b7135e000..28551ac3989 100644 --- a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java @@ -51,9 +51,8 @@ public class VirtualMachineProfileImpl implements Virtua BootloaderType _bootloader; VirtualMachine.Type _type; - HypervisorType _hyperType; - public VirtualMachineProfileImpl(T vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params, HypervisorType hyperType) { + public VirtualMachineProfileImpl(T vm, VMTemplateVO template, ServiceOfferingVO offering, Account owner, Map params) { _vm = vm; _template = template; _offering = offering; @@ -63,11 +62,10 @@ public class VirtualMachineProfileImpl implements Virtua _params = new HashMap(); } _type = vm.getType(); - _hyperType = hyperType; } public VirtualMachineProfileImpl(T vm) { - this(vm, null, null, null, null, null); + this(vm, null, null, null, null); } public VirtualMachineProfileImpl(VirtualMachine.Type type) { @@ -112,11 +110,7 @@ public class VirtualMachineProfileImpl implements Virtua @Override public HypervisorType getHypervisorType() { - if (_hyperType != null && !_hyperType.equals(HypervisorType.None)) { - return _hyperType; - } - getTemplate(); - return _template.getHypervisorType(); + return _vm.getHypervisorType(); } @Override diff --git a/server/src/com/cloud/vm/dao/DomainRouterDao.java b/server/src/com/cloud/vm/dao/DomainRouterDao.java index 3b0e1ff16c9..0c4e68c1416 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDao.java @@ -92,9 +92,6 @@ public interface DomainRouterDao extends GenericDao, State * @return DomainRouterVO or null if not found. */ public DomainRouterVO findByPublicIpAddress(String ipAddress); - - - public List findLonelyRouters(); /** * Gets the next dhcp ip address to be used for vms from this domain router. @@ -122,4 +119,6 @@ public interface DomainRouterDao extends GenericDao, State DomainRouterVO findByNetworkConfiguration(long networkConfigurationId); DomainRouterVO findByNetworkConfigurationIncludingRemoved(long networkConfigurationId); + + DomainRouterVO findByNetworkConfigurationAndPod(long networkConfigurationId, long podId); } diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index deac41ce05d..5811186c8f3 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -20,7 +20,6 @@ package com.cloud.vm.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -46,7 +45,6 @@ import com.cloud.vm.VirtualMachine.State; public class DomainRouterDaoImpl extends GenericDaoBase implements DomainRouterDao { private static final Logger s_logger = Logger.getLogger(DomainRouterDaoImpl.class); - private static final String FindLonelyRoutersSql = "SELECT dr.id FROM domain_router dr, vm_instance vm WHERE dr.id=vm.id AND vm.state = 'Running' AND dr.id NOT IN (SELECT DISTINCT domain_router_id FROM user_vm uvm, vm_instance vmi WHERE (vmi.state = 'Running' OR vmi.state = 'Starting' OR vmi.state='Stopping' OR vmi.state = 'Migrating') AND vmi.id = uvm.id)"; private static final String GetNextDhcpAddressSql = "UPDATE domain_router set dhcp_ip_address = (@LAST_DHCP:=dhcp_ip_address) + 1 WHERE id = ?"; private static final String GetLastDhcpSql = "SELECT @LAST_DHCP"; @@ -126,6 +124,8 @@ public class DomainRouterDaoImpl extends GenericDaoBase im NetworkConfigSearch = createSearchBuilder(); NetworkConfigSearch.and("network", NetworkConfigSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); + NetworkConfigSearch.and("podId", NetworkConfigSearch.entity().getPodId(), SearchCriteria.Op.EQ); + NetworkConfigSearch.done(); _updateTimeAttr = _allAttributes.get("updateTime"); assert _updateTimeAttr != null : "Couldn't get this updateTime attribute"; @@ -253,24 +253,6 @@ public class DomainRouterDaoImpl extends GenericDaoBase im return listBy(sc); } - @Override - public List findLonelyRouters() { - ArrayList ids = new ArrayList(); - PreparedStatement pstmt = null; - Transaction txn = Transaction.currentTxn(); - try { - pstmt = txn.prepareAutoCloseStatement(FindLonelyRoutersSql); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - ids.add(rs.getLong(1)); - } - - } catch (SQLException e) { - throw new CloudRuntimeException("Problem finding routers: " + pstmt.toString(), e); - } - return ids; - } - @Override public long getNextDhcpIpAddress(long id) { Transaction txn = Transaction.currentTxn(); @@ -366,4 +348,11 @@ public class DomainRouterDaoImpl extends GenericDaoBase im sc.setParameters("state", State.Stopped); return listBy(sc); } + @Override + public DomainRouterVO findByNetworkConfigurationAndPod(long networkConfigurationId, long podId) { + SearchCriteria sc = NetworkConfigSearch.create(); + sc.setParameters("network", networkConfigurationId); + sc.setParameters("podId", podId); + return findOneBy(sc); + } } diff --git a/server/src/com/cloud/vm/dao/UserVmDao.java b/server/src/com/cloud/vm/dao/UserVmDao.java index bc7dcf758cf..d372d9bd811 100755 --- a/server/src/com/cloud/vm/dao/UserVmDao.java +++ b/server/src/com/cloud/vm/dao/UserVmDao.java @@ -100,4 +100,5 @@ public interface UserVmDao extends GenericDao, StateDao listByAccountIdAndHostId(long accountId, long hostId); } diff --git a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java index f61904d461d..73e439ded71 100755 --- a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java +++ b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java @@ -57,6 +57,7 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use protected final SearchBuilder GuestIpSearch; protected final SearchBuilder ZoneAccountGuestIpSearch; protected final SearchBuilder ZoneNameSearch; + protected final SearchBuilder AccountHostSearch; protected final SearchBuilder DestroySearch; protected SearchBuilder AccountDataCenterVirtualSearch; @@ -136,6 +137,11 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use ZoneNameSearch.and("dataCenterId", ZoneNameSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); ZoneNameSearch.and("name", ZoneNameSearch.entity().getName(), SearchCriteria.Op.EQ); ZoneNameSearch.done(); + + AccountHostSearch = createSearchBuilder(); + AccountHostSearch.and("accountId", AccountHostSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountHostSearch.and("hostId", AccountHostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + AccountHostSearch.done(); _updateTimeAttr = _allAttributes.get("updateTime"); assert _updateTimeAttr != null : "Couldn't get this updateTime attribute"; @@ -401,4 +407,12 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use sc.setParameters("name", name); return findOneBy(sc); } + + @Override + public List listByAccountIdAndHostId(long accountId, long hostId) { + SearchCriteria sc = AccountHostSearch.create(); + sc.setParameters("hostId", hostId); + sc.setParameters("accountId", accountId); + return listBy(sc); + } } diff --git a/server/src/com/cloud/vm/dao/VMInstanceDao.java b/server/src/com/cloud/vm/dao/VMInstanceDao.java index 9babfaabdf6..8ad0edcd9f5 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDao.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDao.java @@ -53,7 +53,7 @@ public interface VMInstanceDao extends GenericDao, StateDao< */ public List listNonExpungedByZoneAndTemplate(long zoneId, long templateId); - boolean updateIf(VMInstanceVO vm, VirtualMachine.Event event, Long hostId); + boolean updateIf(VMInstanceVO vm, VirtualMachine.Event event, Long hostId, String reservationId); /** * Find vm instance with names like. @@ -84,4 +84,6 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByZoneIdAndType(long zoneId, VirtualMachine.Type type); List listUpByHostId(Long hostId); List listByLastHostId(Long hostId); + + List listByTypeAndState(State state, VirtualMachine.Type type); } diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 3c7adce640d..5875a4420e1 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -62,6 +62,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected final SearchBuilder HostIdTypesSearch; protected final SearchBuilder HostIdUpTypesSearch; protected final SearchBuilder HostUpSearch; + protected final SearchBuilder TypeStateSearch; protected final Attribute _updateTimeAttr; @@ -136,6 +137,11 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem HostUpSearch.and("states", HostUpSearch.entity().getState(), SearchCriteria.Op.IN); HostUpSearch.done(); + TypeStateSearch = createSearchBuilder(); + TypeStateSearch.and("type", TypeStateSearch.entity().getType(), SearchCriteria.Op.EQ); + TypeStateSearch.and("state", TypeStateSearch.entity().getState(), SearchCriteria.Op.EQ); + TypeStateSearch.done(); + _updateTimeAttr = _allAttributes.get("updateTime"); assert _updateTimeAttr != null : "Couldn't get this updateTime attribute"; } @@ -148,7 +154,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem } @Override - public boolean updateIf(VMInstanceVO vm, VirtualMachine.Event event, Long hostId) { + public boolean updateIf(VMInstanceVO vm, VirtualMachine.Event event, Long hostId, String reservationId) { State oldState = vm.getState(); State newState = oldState.getNextState(event); @@ -167,10 +173,12 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem sc.setParameters("update", vm.getUpdated()); vm.incrUpdated(); + vm.setReservationId(reservationId); UpdateBuilder ub = getUpdateBuilder(vm); ub.set(vm, "state", newState); ub.set(vm, "hostId", hostId); ub.set(vm, _updateTimeAttr, new Date()); + int result = update(vm, sc); if (result == 0 && s_logger.isDebugEnabled()) { @@ -282,6 +290,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem sc.setParameters("types", (Object[]) types); return listBy(sc); } + + @Override + public List listByTypeAndState(State state, VirtualMachine.Type type) { + SearchCriteria sc = TypeStateSearch.create(); + sc.setParameters("type", type); + sc.setParameters("state", state); + return listBy(sc); + } @Override public VMInstanceVO findByIdTypes(long id, Type... types) { diff --git a/setup/db/create-index-fk.sql b/setup/db/create-index-fk.sql index 998ea1ecd0b..ef3868c213b 100755 --- a/setup/db/create-index-fk.sql +++ b/setup/db/create-index-fk.sql @@ -95,24 +95,6 @@ ALTER TABLE `cloud`.`cluster_details` ADD CONSTRAINT `fk_cluster_details__cluste ALTER TABLE `cloud`.`vm_template` ADD INDEX `i_vm_template__removed`(`removed`); ALTER TABLE `cloud`.`vm_template` ADD INDEX `i_vm_template__public`(`public`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__removed`(`removed`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__type`(`type`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__pod_id`(`pod_id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__update_time`(`update_time`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__update_count`(`update_count`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__state`(`state`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__data_center_id`(`data_center_id`); -ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__host_id` FOREIGN KEY `fk_vm_instance__host_id` (`host_id`) REFERENCES `host` (`id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__host_id`(`host_id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__last_host_id`(`last_host_id`); - -ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__template_id` FOREIGN KEY `fk_vm_instance__template_id` (`vm_template_id`) REFERENCES `vm_template` (`id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__template_id`(`vm_template_id`); -ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__account_id` FOREIGN KEY `fk_vm_instance__account_id` (`account_id`) REFERENCES `account` (`id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__account_id`(`account_id`); -ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__service_offering_id` FOREIGN KEY `fk_vm_instance__service_offering_id` (`service_offering_id`) REFERENCES `service_offering` (`id`); -ALTER TABLE `cloud`.`vm_instance` ADD INDEX `i_vm_instance__service_offering_id`(`service_offering_id`); - ALTER TABLE `cloud`.`service_offering` ADD CONSTRAINT `fk_service_offering__id` FOREIGN KEY `fk_service_offering__id`(`id`) REFERENCES `disk_offering`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__domain_router_id` FOREIGN KEY `fk_user_vm__domain_router_id` (`domain_router_id`) REFERENCES `domain_router` (`id`); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 9fc06341d9a..b1bf554c1ed 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -98,11 +98,14 @@ DROP TABLE IF EXISTS `cloud`.`host_tags`; CREATE TABLE `cloud`.`op_it_work` ( `id` char(40) COMMENT 'id', `mgmt_server_id` bigint unsigned COMMENT 'management server id', - `created` timestamp NOT NULL COMMENT 'when was this work detail created', + `created_at` bigint unsigned NOT NULL COMMENT 'when was this work detail created', `thread` varchar(255) NOT NULL COMMENT 'thread name', `type` char(32) NOT NULL COMMENT 'type of work', - `state` char(32) NOT NULL COMMENT 'state', - `cancel_taken` timestamp COMMENT 'time it was taken over', + `step` char(32) NOT NULL COMMENT 'state', + `updated_at` bigint unsigned NOT NULL COMMENT 'time it was taken over', + `instance_id` bigint unsigned NOT NULL COMMENT 'vm instance', + `resource_type` char(32) COMMENT 'type of resource being worked on', + `resource_id` bigint unsigned COMMENT 'resource id being worked on', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -148,6 +151,7 @@ CREATE TABLE `cloud`.`networks` ( `shared` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '0 if network is shared, 1 if network dedicated', `network_domain` varchar(255) COMMENT 'domain', `reservation_id` char(40) COMMENT 'reservation id', + `is_default` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if network is default', `created` datetime NOT NULL COMMENT 'date created', `removed` datetime COMMENT 'date removed if not null', PRIMARY KEY (`id`) @@ -200,7 +204,6 @@ CREATE TABLE `cloud`.`nics` ( CREATE TABLE `cloud`.`network_offerings` ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id', `name` varchar(64) NOT NULL unique COMMENT 'network offering', - `type` varchar(32) COMMENT 'type of network', `display_text` varchar(255) NOT NULL COMMENT 'text to display to users', `nw_rate` smallint unsigned COMMENT 'network rate throttle mbits/s', `mc_rate` smallint unsigned COMMENT 'mcast rate throttle mbits/s', @@ -212,7 +215,7 @@ CREATE TABLE `cloud`.`network_offerings` ( `service_offering_id` bigint unsigned UNIQUE COMMENT 'service offering id that this network offering is tied to', `created` datetime NOT NULL COMMENT 'time the entry was created', `removed` datetime DEFAULT NULL COMMENT 'time the entry was removed', - `default` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if network is default', + `default` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if network offering is default', `availability` varchar(255) NOT NULL COMMENT 'availability of the network', `dns_service` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if network offering provides dns service', `gateway_service` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if network offering provides gateway service', @@ -674,7 +677,7 @@ CREATE TABLE `cloud`.`user_ip_address` ( INDEX `i_user_ip_address__source_nat`(`source_nat`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE VIEW `cloud`.`user_ip_address_view` AS SELECT INET_NTOA(user_ip_address.public_ip_address) as public_ip_address, user_ip_address.data_center_id, user_ip_address.account_id, user_ip_address.domain_id, user_ip_address.source_nat, user_ip_address.allocated, user_ip_address.vlan_db_id, user_ip_address.one_to_one_nat, user_ip_address.state, user_ip_address.mac_address, user_ip_address.network_id as associated_network_id from user_ip_address; +CREATE VIEW `cloud`.`user_ip_address_view` AS SELECT INET_NTOA(user_ip_address.public_ip_address) as ip_address, user_ip_address.data_center_id, user_ip_address.account_id, user_ip_address.domain_id, user_ip_address.source_nat, user_ip_address.allocated, user_ip_address.vlan_db_id, user_ip_address.one_to_one_nat, user_ip_address.state, user_ip_address.mac_address, user_ip_address.network_id as associated_network_id from user_ip_address; CREATE TABLE `cloud`.`user_statistics` ( `id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT, @@ -743,7 +746,23 @@ CREATE TABLE `cloud`.`vm_instance` ( `domain_id` bigint unsigned NOT NULL, `service_offering_id` bigint unsigned NOT NULL COMMENT 'service offering id', `reservation_id` char(40) COMMENT 'reservation id', - PRIMARY KEY (`id`) + `hypervisor_type` char(32) COMMENT 'hypervisor type', + PRIMARY KEY (`id`), + INDEX `i_vm_instance__removed`(`removed`), + INDEX `i_vm_instance__type`(`type`), + INDEX `i_vm_instance__pod_id`(`pod_id`), + INDEX `i_vm_instance__update_time`(`update_time`), + INDEX `i_vm_instance__update_count`(`update_count`), + INDEX `i_vm_instance__state`(`state`), + INDEX `i_vm_instance__data_center_id`(`data_center_id`), + CONSTRAINT `fk_vm_instance__host_id` FOREIGN KEY `fk_vm_instance__host_id` (`host_id`) REFERENCES `host` (`id`), + CONSTRAINT `fk_vm_instance__last_host_id` FOREIGN KEY `fk_vm_instance__last_host_id` (`last_host_id`) REFERENCES `host`(`id`), + CONSTRAINT `fk_vm_instance__template_id` FOREIGN KEY `fk_vm_instance__template_id` (`vm_template_id`) REFERENCES `vm_template` (`id`), + INDEX `i_vm_instance__template_id`(`vm_template_id`), + CONSTRAINT `fk_vm_instance__account_id` FOREIGN KEY `fk_vm_instance__account_id` (`account_id`) REFERENCES `account` (`id`), + INDEX `i_vm_instance__account_id`(`account_id`), + CONSTRAINT `fk_vm_instance__service_offering_id` FOREIGN KEY `fk_vm_instance__service_offering_id` (`service_offering_id`) REFERENCES `service_offering` (`id`), + INDEX `i_vm_instance__service_offering_id`(`service_offering_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`user_vm` ( @@ -1326,7 +1345,52 @@ CREATE TABLE `cloud`.`usage_event` ( `offering_id` bigint unsigned, `template_id` bigint unsigned, `size` bigint unsigned, + `processed` tinyint NOT NULL default '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`ovs_host_vlan_alloc`( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `host_id` bigint unsigned COMMENT 'host id', + `account_id` bigint unsigned COMMENT 'account id', + `vlan` bigint unsigned COMMENT 'vlan id under account #account_id on host #host_id', + `ref` int unsigned NOT NULL DEFAULT 0 COMMENT 'reference count', + PRIMARY KEY(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`ovs_tunnel_alloc`( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `from` bigint unsigned COMMENT 'from host id', + `to` bigint unsigned COMMENT 'to host id', + `in_port` int unsigned COMMENT 'in port on open vswitch', + PRIMARY KEY(`from`, `to`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`ovs_vlan_mapping_dirty`( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `account_id` bigint unsigned COMMENT 'account id', + `dirty` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 means vlan mapping of this account was changed', + PRIMARY KEY(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`ovs_vm_flow_log` ( + `id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id', + `instance_id` bigint unsigned NOT NULL COMMENT 'vm instance that needs flows to be synced.', + `created` datetime NOT NULL COMMENT 'time the entry was requested', + `logsequence` bigint unsigned COMMENT 'seq number to be sent to agent, uniquely identifies flow update', + `vm_name` varchar(255) NOT NULL COMMENT 'vm name', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`ovs_work` ( + `id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id', + `instance_id` bigint unsigned NOT NULL COMMENT 'vm instance that needs rules to be synced.', + `mgmt_server_id` bigint unsigned COMMENT 'management server that has taken up the work of doing rule sync', + `created` datetime NOT NULL COMMENT 'time the entry was requested', + `taken` datetime COMMENT 'time it was taken by the management server', + `step` varchar(32) NOT NULL COMMENT 'Step in the work', + `seq_no` bigint unsigned COMMENT 'seq number to be sent to agent, uniquely identifies ruleset update', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + SET foreign_key_checks = 1; diff --git a/ui/2.1/jsp/tab_networking.jsp b/ui/2.1/jsp/tab_networking.jsp index 5f1774690e7..714e60c30c9 100755 --- a/ui/2.1/jsp/tab_networking.jsp +++ b/ui/2.1/jsp/tab_networking.jsp @@ -8,7 +8,7 @@ long milliseconds = new Date().getTime(); - -
+ -
+
+
+
+ Is Default:
+
+
+
+
+
+
+
<%=t.t("vlan")%>:
@@ -336,7 +346,7 @@
-
+
<%=t.t("gateway")%>:
@@ -346,7 +356,7 @@
-
+
Netmask:
@@ -356,7 +366,7 @@
-
+
Domain:
@@ -366,7 +376,7 @@
-
+
Account:
@@ -996,6 +1006,14 @@ + +
  • + +
  • -
    +
    @@ -215,7 +215,7 @@ Step 4
    -
    +
    @@ -315,7 +315,7 @@ Step 4
    -
    +
    @@ -361,7 +361,53 @@
    - + + + +
    +
    +
    +
    + Back +
    +
    + Go to Step 4
    +
    +
    + +
    +
    + + + + + - - - - +
    +
    +
    + Add Ingress Rule
    + +
    +
    @@ -215,60 +224,6 @@ - - - -
    +
    <%=t.t("Domain")%>:
    @@ -213,7 +223,7 @@
    -
    +
    <%=t.t("Created")%>:
    diff --git a/ui/jsp/volume.jsp b/ui/jsp/volume.jsp index c94a9943e37..b50325a90ce 100644 --- a/ui/jsp/volume.jsp +++ b/ui/jsp/volume.jsp @@ -754,6 +754,13 @@ +
    diff --git a/ui/jsp/zone.jsp b/ui/jsp/zone.jsp index b4004953eb9..9d54c1ae090 100644 --- a/ui/jsp/zone.jsp +++ b/ui/jsp/zone.jsp @@ -22,8 +22,10 @@
    <%=t.t("details")%>
    +