diff --git a/agent/conf/log4j-cloud.xml.in b/agent/conf/log4j-cloud.xml.in index 9cc49282f55..7cb5c6dbaf9 100644 --- a/agent/conf/log4j-cloud.xml.in +++ b/agent/conf/log4j-cloud.xml.in @@ -10,7 +10,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in b/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in index fcaaca8c33e..404ed74af0f 100755 --- a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in +++ b/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in @@ -1,7 +1,14 @@ #!/bin/bash +### BEGIN INIT INFO +# Provides: cloud agent +# Required-Start: $network +# Required-Stop: $network +# Default-Start: 3 4 5 +# Default-Stop: 0 1 2 6 +# X-Interactive: true +# Short-Description: Start/stop apache2 web server +### END INIT INFO -# 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 @@ -23,6 +30,20 @@ unset OPTIONS DAEMONIZE=@BINDIR@/@PACKAGE@-daemonize PROG=@LIBEXECDIR@/agent-runner +wait_for_network() { + i=1 + while [ $i -lt 10 ] + do + if ip addr show cloudbr0 |grep -w inet > /dev/null 2>&1; then + break + else + continue + fi + sleep 1 + let i=$i+1 + done +} + start() { log_daemon_msg $"Starting $PROGNAME" "$SHORTNAME" if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then @@ -38,6 +59,9 @@ start() { exit 1 fi + #FIXME: wait for network + wait_for_network + if start-stop-daemon --start --quiet \ --pidfile "$PIDFILE" \ --exec "$DAEMONIZE" -- -n "$SHORTNAME" -p "$PIDFILE" -l "$LOGFILE" "$PROG" $OPTIONS diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index a8b0c1bfcb3..0cecb77f794 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -1545,7 +1545,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); return new SecurityIngressRuleAnswer(cmd, false, "programming network rules failed"); } else { - s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); + s_logger.debug("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); return new SecurityIngressRuleAnswer(cmd); } } @@ -1857,7 +1857,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser(); String result = cpuScript.execute(parser); if (result != null) { - s_logger.info("Unable to get the host CPU state: " + result); + s_logger.debug("Unable to get the host CPU state: " + result); return new Answer(cmd, false, result); } double cpuUtil = (100.0D - Double.parseDouble(parser.getLine())); @@ -1869,7 +1869,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv final OutputInterpreter.OneLineParser Memparser = new OutputInterpreter.OneLineParser(); result = memScript.execute(Memparser); if (result != null) { - s_logger.info("Unable to get the host Mem state: " + result); + s_logger.debug("Unable to get the host Mem state: " + result); return new Answer(cmd, false, result); } freeMem = Long.parseLong(Memparser.getLine()); @@ -1880,7 +1880,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv final OutputInterpreter.OneLineParser totMemparser = new OutputInterpreter.OneLineParser(); result = totalMem.execute(totMemparser); if (result != null) { - s_logger.info("Unable to get the host Mem state: " + result); + s_logger.debug("Unable to get the host Mem state: " + result); return new Answer(cmd, false, result); } long totMem = Long.parseLong(totMemparser.getLine()); @@ -2824,7 +2824,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv 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); - s_logger.info("cpus=" + cpus + ", speed=" + speed + ", ram=" + ram + ", dom0ram=" + dom0ram); + s_logger.debug("cpus=" + cpus + ", speed=" + speed + ", ram=" + ram + ", dom0ram=" + dom0ram); return info; } diff --git a/agent/src/com/cloud/agent/vmdata/JettyVmDataServer.java b/agent/src/com/cloud/agent/vmdata/JettyVmDataServer.java index 38ebe1ac33d..8b8cbb3fcf7 100644 --- a/agent/src/com/cloud/agent/vmdata/JettyVmDataServer.java +++ b/agent/src/com/cloud/agent/vmdata/JettyVmDataServer.java @@ -21,6 +21,7 @@ package com.cloud.agent.vmdata; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -38,6 +39,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Handler; @@ -294,10 +296,18 @@ public class JettyVmDataServer implements VmDataServer { try { _fs.create(vmDataDir, item[1]); String vmDataFile = vmDataDir + File.separator + item[1]; + byte[] data; if (item[2] != null) { - BufferedWriter writer = new BufferedWriter(new FileWriter(vmDataFile)); - writer.write(item[2]); - writer.close(); + if (item[1].equals("user-data")) { + data = Base64.decodeBase64(item[2]); + } else { + data = item[2].getBytes(); + } + if (data != null && data.length > 0) { + FileOutputStream writer = new FileOutputStream(vmDataFile); + writer.write(data); + writer.close(); + } } } catch (IOException e) { s_logger.warn("Failed to write vm data item " + item[1], e); diff --git a/api/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java b/api/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java index 376a94f302b..e7a2540df25 100755 --- a/api/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java +++ b/api/src/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java @@ -22,8 +22,16 @@ import com.cloud.agent.api.Command; public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { + public CreateEntityDownloadURLCommand(String parent, String installPath, String uuid) { // this constructor is for creating template download url + super(); + this.parent = parent; // parent is required as not the template can be child of one of many parents + this.installPath = installPath; + this.extractLinkUUID = uuid; + } + public CreateEntityDownloadURLCommand(String installPath, String uuid) { super(); + this.parent = parent; this.installPath = installPath; this.extractLinkUUID = uuid; } @@ -32,6 +40,7 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { } private String installPath; + private String parent; private String extractLinkUUID; @Override @@ -46,6 +55,14 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { public void setInstallPath(String installPath) { this.installPath = installPath; } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } public String getExtractLinkUUID() { return extractLinkUUID; diff --git a/api/src/com/cloud/agent/api/to/NicTO.java b/api/src/com/cloud/agent/api/to/NicTO.java index f3d2715b896..8f4ee247dec 100644 --- a/api/src/com/cloud/agent/api/to/NicTO.java +++ b/api/src/com/cloud/agent/api/to/NicTO.java @@ -27,7 +27,6 @@ public class NicTO extends NetworkTO { Integer networkRateMulticastMbps; boolean defaultNic; - public NicTO() { super(); } diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index af72c02ee14..80f0dd1aa0c 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -549,5 +549,8 @@ public abstract class BaseCmd { (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); - } + } + public static boolean isRootAdmin(short accountType) { + return ((accountType == Account.ACCOUNT_TYPE_ADMIN)); + } } diff --git a/api/src/com/cloud/api/ResponseGenerator.java b/api/src/com/cloud/api/ResponseGenerator.java index 730b85415d8..28b631c633b 100644 --- a/api/src/com/cloud/api/ResponseGenerator.java +++ b/api/src/com/cloud/api/ResponseGenerator.java @@ -161,7 +161,7 @@ public interface ResponseGenerator { RemoteAccessVpnResponse createRemoteAccessVpnResponse(RemoteAccessVpn vpn); void createTemplateResponse(List responses, Pair templateZonePair, boolean isAdmin, - Account account); + Account account, boolean readyOnly); ListResponse createTemplateResponse2(VirtualMachineTemplate template, Long zoneId); @@ -187,7 +187,7 @@ public interface ResponseGenerator { EventResponse createEventResponse(Event event); - ListResponse createIsoResponse(Set> isoZonePairSet, boolean onlyReady, Account account, Boolean isBootable); + ListResponse createIsoResponse(Set> isoZonePairSet, boolean onlyReady, Account account, Boolean isBootable, boolean readyOnly); TemplateResponse createIsoResponse(VirtualMachineTemplate result); diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index 5a50a2f15b3..eccfcae258a 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -18,6 +18,8 @@ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -42,10 +44,10 @@ public class CreateNetworkCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the network") + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the network") private String name; - @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the network") + @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the network") private String displayText; @Parameter(name=ApiConstants.NETWORK_OFFERING_ID, type=CommandType.LONG, required=true, description="the network offering id") @@ -76,13 +78,16 @@ public class CreateNetworkCmd extends BaseCmd { private Long domainId; @Parameter(name=ApiConstants.IS_SHARED, type=CommandType.BOOLEAN, description="true is network is shared across accounts in the Zone") - private Boolean isShared; + 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.NETWORK_DOMAIN, type=CommandType.STRING, description="network domain") private String networkDomain; + + @Parameter(name=ApiConstants.TAGS, type=CommandType.LIST, collectionType=CommandType.STRING, description="Tag the network") + private List tags; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -90,6 +95,10 @@ public class CreateNetworkCmd extends BaseCmd { public Long getNetworkOfferingId() { return networkOfferingId; } + + public List getTags() { + return tags; + } public Long getZoneId() { return zoneId; diff --git a/api/src/com/cloud/api/commands/ListIsosCmd.java b/api/src/com/cloud/api/commands/ListIsosCmd.java index 7d76b6989a9..c2765008620 100755 --- a/api/src/com/cloud/api/commands/ListIsosCmd.java +++ b/api/src/com/cloud/api/commands/ListIsosCmd.java @@ -124,6 +124,17 @@ public class ListIsosCmd extends BaseListCmd { public Long getZoneId() { return zoneId; } + + public boolean listInReadyState() { + Account account = UserContext.current().getCaller(); + // It is account specific if account is admin type and domainId and accountName are not null + boolean isAccountSpecific = (account == null || isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + // Show only those that are downloaded. + TemplateFilter templateFilter = TemplateFilter.valueOf(getIsoFilter()); + boolean onlyReady = (templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.selfexecutable) || (templateFilter == TemplateFilter.sharedexecutable) + || (templateFilter == TemplateFilter.executable && isAccountSpecific) || (templateFilter == TemplateFilter.community); + return onlyReady; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// @@ -160,7 +171,7 @@ public class ListIsosCmd extends BaseListCmd { isAdmin = true; } - ListResponse response = _responseGenerator.createIsoResponse(isoZonePairSet, isAdmin, account, bootable); + ListResponse response = _responseGenerator.createIsoResponse(isoZonePairSet, isAdmin, account, bootable, listInReadyState()); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java b/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java index 320f21434e4..69d5c9a5931 100644 --- a/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java +++ b/api/src/com/cloud/api/commands/ListServiceOfferingsCmd.java @@ -26,7 +26,6 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ListResponse; import com.cloud.api.response.ServiceOfferingResponse; import com.cloud.offering.ServiceOffering; diff --git a/api/src/com/cloud/api/commands/ListTemplatesCmd.java b/api/src/com/cloud/api/commands/ListTemplatesCmd.java index ae88c63fce5..6f58acd829f 100755 --- a/api/src/com/cloud/api/commands/ListTemplatesCmd.java +++ b/api/src/com/cloud/api/commands/ListTemplatesCmd.java @@ -105,6 +105,17 @@ public class ListTemplatesCmd extends BaseListCmd { public Long getZoneId() { return zoneId; } + + public boolean listInReadyState() { + Account account = UserContext.current().getCaller(); + // It is account specific if account is admin type and domainId and accountName are not null + boolean isAccountSpecific = (account == null || isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + // Show only those that are downloaded. + TemplateFilter templateFilter = TemplateFilter.valueOf(getTemplateFilter()); + boolean onlyReady = (templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.selfexecutable) || (templateFilter == TemplateFilter.sharedexecutable) + || (templateFilter == TemplateFilter.executable && isAccountSpecific) || (templateFilter == TemplateFilter.community); + return onlyReady; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// @@ -133,7 +144,7 @@ public class ListTemplatesCmd extends BaseListCmd { List templateResponses = new ArrayList(); for (Pair template : templateZonePairSet) { - _responseGenerator.createTemplateResponse(templateResponses, template, isAdmin, account); + _responseGenerator.createTemplateResponse(templateResponses, template, isAdmin, account, listInReadyState()); } response.setResponses(templateResponses); diff --git a/api/src/com/cloud/api/commands/UpdateNetworkCmd.java b/api/src/com/cloud/api/commands/UpdateNetworkCmd.java index 8169714d231..da7542ae214 100644 --- a/api/src/com/cloud/api/commands/UpdateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/UpdateNetworkCmd.java @@ -18,6 +18,8 @@ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -44,12 +46,15 @@ public class UpdateNetworkCmd extends BaseCmd { @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the network") private Long id; - @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the new name for the network") + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the new name for the network") private String name; - @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="the new display text for the network") + @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="the new display text for the network") private String displayText; + @Parameter(name=ApiConstants.TAGS, type=CommandType.LIST, collectionType=CommandType.STRING, description="tags for the network") + private List tags; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -65,7 +70,11 @@ public class UpdateNetworkCmd extends BaseCmd { public String getDisplayText() { return displayText; - } + } + + public List getTags() { + return tags; + } ///////////////////////////////////////////////////// @@ -90,7 +99,7 @@ public class UpdateNetworkCmd extends BaseCmd { @Override public void execute() throws InsufficientCapacityException, ConcurrentOperationException{ - Network result = _networkService.updateNetwork(getId(), getNetworkName(), getDisplayText(), UserContext.current().getCaller()); + Network result = _networkService.updateNetwork(getId(), getNetworkName(), getDisplayText(), tags, UserContext.current().getCaller()); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/api/response/DomainRouterResponse.java b/api/src/com/cloud/api/response/DomainRouterResponse.java index 87ff69a89ae..33ce06a53ac 100644 --- a/api/src/com/cloud/api/response/DomainRouterResponse.java +++ b/api/src/com/cloud/api/response/DomainRouterResponse.java @@ -113,6 +113,12 @@ public class DomainRouterResponse extends BaseResponse { @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain associated with the router") private String domainName; + @SerializedName("serviceofferingid") @Param(description="the ID of the service offering of the virtual machine") + private Long serviceOfferingId; + + @SerializedName("serviceofferingname") @Param(description="the name of the service offering of the virtual machine") + private String serviceOfferingName; + @@ -353,4 +359,19 @@ public class DomainRouterResponse extends BaseResponse { this.linkLocalNetworkId = linkLocalNetworkId; } + public Long getServiceOfferingId() { + return serviceOfferingId; + } + + public void setServiceOfferingId(Long serviceOfferingId) { + this.serviceOfferingId = serviceOfferingId; + } + + public String getServiceOfferingName() { + return serviceOfferingName; + } + + public void setServiceOfferingName(String serviceOfferingName) { + this.serviceOfferingName = serviceOfferingName; + } } diff --git a/api/src/com/cloud/api/response/TemplateResponse.java b/api/src/com/cloud/api/response/TemplateResponse.java index 696848a4efa..2c97f64cabd 100755 --- a/api/src/com/cloud/api/response/TemplateResponse.java +++ b/api/src/com/cloud/api/response/TemplateResponse.java @@ -19,6 +19,7 @@ package com.cloud.api.response; import java.util.Date; +import com.cloud.api.ApiConstants; import com.cloud.serializer.Param; import com.cloud.storage.Storage.ImageFormat; import com.google.gson.annotations.SerializedName; @@ -113,6 +114,12 @@ public class TemplateResponse extends BaseResponse { @SerializedName("sourcetemplateid") @Param(description="the template ID of the parent template if present") private Long sourcetemplateId; + @SerializedName(ApiConstants.HOST_ID) @Param(description="the ID of the secondary storage host for the template") + private Long hostId; + + @SerializedName("hostname") @Param(description="the name of the secondary storage host for the template") + private String hostName; + public Long getObjectId() { return getId(); } @@ -348,4 +355,20 @@ public class TemplateResponse extends BaseResponse { public void setSourceTemplateId(Long sourcetemplateId) { this.sourcetemplateId = sourcetemplateId; } + + public Long getHostId() { + return hostId; + } + + public void setHostId(Long hostId) { + this.hostId = hostId; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } } diff --git a/api/src/com/cloud/host/Status.java b/api/src/com/cloud/host/Status.java index 87da0ef2bb7..cbcdb40776d 100644 --- a/api/src/com/cloud/host/Status.java +++ b/api/src/com/cloud/host/Status.java @@ -33,7 +33,7 @@ public enum Status { Maintenance(false, false, false), Alert(true, true, true), Removed(true, false, true), - Rebalance(false, false, false); + Rebalancing(false, false, false); private final boolean updateManagementServer; private final boolean checkManagementServer; @@ -137,7 +137,7 @@ public enum Status { s_fsm.addTransition(Status.Up, Event.Ping, Status.Up); s_fsm.addTransition(Status.Up, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Up, Event.ManagementServerDown, Status.Disconnected); - s_fsm.addTransition(Status.Up, Event.StartAgentRebalance, Status.Rebalance); + s_fsm.addTransition(Status.Up, Event.StartAgentRebalance, Status.Rebalancing); s_fsm.addTransition(Status.Updating, Event.PingTimeout, Status.Alert); s_fsm.addTransition(Status.Updating, Event.Ping, Status.Updating); s_fsm.addTransition(Status.Updating, Event.AgentConnected, Status.Connecting); @@ -183,8 +183,8 @@ public enum Status { s_fsm.addTransition(Status.Alert, Event.Ping, Status.Up); s_fsm.addTransition(Status.Alert, Event.Remove, Status.Removed); s_fsm.addTransition(Status.Alert, Event.ManagementServerDown, Status.Alert); - s_fsm.addTransition(Status.Rebalance, Event.RebalanceFailed, Status.Alert); - s_fsm.addTransition(Status.Rebalance, Event.RebalanceCompleted, Status.Connecting); + s_fsm.addTransition(Status.Rebalancing, Event.RebalanceFailed, Status.Alert); + s_fsm.addTransition(Status.Rebalancing, Event.RebalanceCompleted, Status.Connecting); } public static void main(String[] args) { diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 5e62ae89119..e866eec9b83 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -81,7 +81,7 @@ public interface NetworkService { Long getDedicatedNetworkDomain(long networkId); - Network updateNetwork(long networkId, String name, String displayText, Account caller); + Network updateNetwork(long networkId, String name, String displayText, List tags, Account caller); Integer getNetworkRate(long networkId, Long vmId); diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index 58627f136d8..8ea04c9ca0b 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -26,7 +26,7 @@ import com.cloud.utils.fsm.StateObject; /** - * VirtualMachine describes the properties held by a virtual machine + * VirtualMachine describes the properties held by a virtual machine * */ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject { @@ -40,7 +40,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject Migrating(true, "VM is being migrated. host id holds to from host"), Error(false, "VM is in error"), Unknown(false, "VM state is unknown."), - Shutdowned(false, "VM is shutdowned from inside"); + Shutdowned(false, "VM is shutdowned from inside"); private final boolean _transitional; @@ -71,20 +71,20 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportStopped, State.Stopped); s_fsm.addTransition(State.Stopped, VirtualMachine.Event.OperationFailed, State.Error); s_fsm.addTransition(State.Stopped, VirtualMachine.Event.ExpungeOperation, State.Expunging); - s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationRetry, State.Starting); s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationFailed, State.Stopped); s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportRunning, State.Running); s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.RecoveryRequested, State.Stopped); s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.ExpungeOperation, State.Expunging); s_fsm.addTransition(State.Running, VirtualMachine.Event.MigrationRequested, State.Migrating); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportRunning, State.Running); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportStopped, State.Stopped); s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); - s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); @@ -96,7 +96,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportRunning, State.Running); s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportStopped, State.Stopped); s_fsm.addTransition(State.Stopping, VirtualMachine.Event.StopRequested, State.Stopping); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Expunging, VirtualMachine.Event.OperationFailed, State.Expunging); s_fsm.addTransition(State.Expunging, VirtualMachine.Event.ExpungeOperation, State.Expunging); s_fsm.addTransition(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging); @@ -166,7 +166,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject /** * @return The name of the vm instance used by the cloud stack to uniquely * reference this VM. You can build names that starts with this name and it - * guarantees uniqueness for things related to the VM. + * guarantees uniqueness for things related to the VM. */ public String getInstanceName(); @@ -176,7 +176,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject public long getId(); /** - * @return the host name of the virtual machine. If the user did not + * @return the host name of the virtual machine. If the user did not * specify the host name when creating the virtual machine then it is * defaults to the instance name. */ @@ -216,12 +216,12 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject /** * @return pod id. */ - public Long getPodId(); + public Long getPodIdToDeployIn(); /** * @return data center id. */ - public long getDataCenterId(); + public long getDataCenterIdToDeployIn(); /** * @return id of the host it was assigned last time. @@ -230,8 +230,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject @Override public Long getHostId(); - public void setLastHostId(Long lastHostId); - /** * @return should HA be enabled for this machine? */ @@ -239,8 +237,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject /** * @return should limit CPU usage to the service offering? - */ - public boolean limitCpuUse(); + */ + public boolean limitCpuUse(); /** * @return date when machine was created */ diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 2201e48afe9..23997e77524 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -210,6 +210,7 @@ label.add.primary.storage=Add Primary Storage label.add.secondary.storage=Add Secondary Storage label.add.security.group=Add Security Group label.add.service.offering=Add Service Offering +label.add.system.service.offering=Add System Service Offering label.add.template=Add Template label.add.user=Add User label.add.vlan=Add VLAN @@ -429,6 +430,7 @@ label.menu.physical.resources=Physical Resources label.menu.running.instances=Running Instances label.menu.security.groups=Security Groups label.menu.service.offerings=Service Offerings +label.menu.system.service.offerings=System Service Offerings label.menu.snapshots=Snapshots label.menu.stopped.instances=Stopped Instances label.menu.storage=Storage @@ -541,6 +543,7 @@ label.security.groups=Security Groups label.sent=Sent label.server=Server label.service.offering=Service Offering +label.system.service.offering=System Service Offering label.session.expired=Session Expired label.shared=Shared label.size=Size @@ -774,7 +777,8 @@ message.zone.step.2.desc=Please enter the following info to add a new zone message.zone.step.3.desc=Please enter the following info to add a new pod message.apply.snapshot.policy=You have successfully updated your current snapshot policy. message.disable.snapshot.policy=You have successfully disabled your current snapshot policy. -message.action.change.service.warning=Your instance must be stopped before attempting to change its current service offering. +message.action.change.service.warning.for.instance=Your instance must be stopped before attempting to change its current service offering. +message.action.change.service.warning.for.router=Your router must be stopped before attempting to change its current service offering. message.action.reset.password.warning=Your instance must be stopped before attempting to change its current password. message.action.reset.password.off=Your instance currently does not support this feature. diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index a991e84fcde..c63aa0c047a 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -93,7 +93,7 @@ - + diff --git a/cloud.spec b/cloud.spec index 96a3c4d6374..80d5855a66b 100644 --- a/cloud.spec +++ b/cloud.spec @@ -221,7 +221,6 @@ Requires: jpackage-utils Requires: %{name}-daemonize Requires: /sbin/service Requires: /sbin/chkconfig -Requires: jnetpcap Group: System Environment/Libraries %package baremetal-agent @@ -304,6 +303,7 @@ The Cloud.com command line tools contain a few Python modules that can call clou %package premium-agent Summary: Cloud.com premium agent Requires: cloud-agent +Requires: jnetpcap Group: System Environment/Libraries %description premium-agent The Cloud.com premium agent diff --git a/core/src/com/cloud/agent/transport/Request.java b/core/src/com/cloud/agent/transport/Request.java index 79028e9e477..455f32db19d 100755 --- a/core/src/com/cloud/agent/transport/Request.java +++ b/core/src/com/cloud/agent/transport/Request.java @@ -198,8 +198,8 @@ public class Request { _agentId = agentId; } - public void setVia(long agentId) { - _via = agentId; + public void setVia(long viaId) { + _via = viaId; } public boolean executeInSequence() { @@ -238,8 +238,8 @@ public class Request { buffer.putLong(_seq); buffer.putInt(contentSize); buffer.putLong(_mgmtId); - buffer.putLong(_via); buffer.putLong(_agentId); + buffer.putLong(_via); buffer.flip(); return buffer; @@ -301,6 +301,11 @@ public class Request { } } } + + @Override + public String toString() { + return log("", true, Level.DEBUG); + } protected String log(String msg, boolean logContent, Level level) { StringBuilder content = new StringBuilder(); @@ -373,8 +378,8 @@ public class Request { final long seq = buff.getLong(); final int size = buff.getInt(); final long mgmtId = buff.getLong(); - final long via = buff.getLong(); final long agentId = buff.getLong(); + final long via = buff.getLong(); byte[] command = null; int offset = 0; @@ -421,9 +426,13 @@ public class Request { } public static long getAgentId(final byte[] bytes) { - return NumbersUtil.bytesToLong(bytes, 24); + return NumbersUtil.bytesToLong(bytes, 28); } + public static long getViaAgentId(final byte[] bytes) { + return NumbersUtil.bytesToLong(bytes, 24); + } + public static boolean fromServer(final byte[] bytes) { return (bytes[3] & FLAG_FROM_SERVER) > 0; } diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 79d164a3890..cdfcb5fd696 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -32,12 +32,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Queue; +import java.util.Random; import java.util.Set; import java.util.UUID; @@ -120,8 +122,8 @@ import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; -import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.UpdateHostPasswordCommand; +import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; @@ -182,7 +184,6 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; -import com.cloud.storage.resource.StoragePoolResource; import com.cloud.storage.template.TemplateInfo; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.NumbersUtil; @@ -222,14 +223,21 @@ import com.xensource.xenapi.VMGuestMetrics; import com.xensource.xenapi.XenAPIObject; /** - * Encapsulates the interface to the XenServer API. + * CitrixResourceBase encapsulates the calls to the XenServer Xapi process + * to perform the required functionalities for CloudStack. + * + * ==============> READ THIS <============== + * Because the XenServer objects can expire when the session expires, we cannot + * keep any of the actual XenServer objects in this class. The only + * thing that is constant is the UUID of the XenServer objects but not the + * objects themselves! This is very important before you do any changes in + * this code here. * */ @Local(value = ServerResource.class) public abstract class CitrixResourceBase implements ServerResource, HypervisorResource { private static final Logger s_logger = Logger.getLogger(CitrixResourceBase.class); protected static final XenServerConnectionPool _connPool = XenServerConnectionPool.getInstance(); - protected static final int MB = 1024 * 1024; protected String _name; protected String _username; protected Queue _password=new LinkedList(); @@ -247,38 +255,43 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected String _guestNetworkName; protected int _wait; protected String _instance; //instance name (default is usually "VM") + static final Random _rand = new Random(System.currentTimeMillis()); protected IAgentControl _agentControl; final int _maxWeight = 256; - protected final XenServerHost _host = new XenServerHost(); + protected final XsHost _host = new XsHost(); // Guest and Host Performance Statistics - protected boolean _collectHostStats = false; protected String _consolidationFunction = "AVERAGE"; protected int _pollingIntervalInSeconds = 60; protected boolean _canBridgeFirewall = false; protected boolean _isOvs = false; protected List _tmpDom0Vif = new ArrayList(); - protected HashMap _pools = new HashMap(5); + protected String _localGateway; public enum SRType { NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA; + + String _str; + + private SRType() { + _str = super.toString().toLowerCase(); + } @Override public String toString() { - return super.toString().toLowerCase(); + return _str; } public boolean equals(String type) { - return super.toString().equalsIgnoreCase(type); + return _str.equalsIgnoreCase(type); } } protected static HashMap s_statesTable; - protected String _localGateway; static { s_statesTable = new HashMap(); s_statesTable.put(Types.VmPowerState.HALTED, State.Stopped); @@ -302,7 +315,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (VmPowerState.HALTED.equals(vmRec.powerState) && vmRec.affinity.equals(host)) { try { - vm.destroy(conn); + vm.destroy(conn); } catch (Exception e) { s_logger.warn("Catch Exception " + e.getClass().getName() + ": unable to destroy VM " + vmRec.nameLabel + " due to " + e.toString()); success = false; @@ -318,25 +331,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe @Override public void disconnected() { - } - - protected Pair getVmByNameLabel(Connection conn, Host host, String nameLabel, boolean getRecord) throws XmlRpcException, XenAPIException { - Set vms = host.getResidentVMs(conn); - for (VM vm : vms) { - VM.Record rec = null; - String name = null; - if (getRecord) { - rec = vm.getRecord(conn); - name = rec.nameLabel; - } else { - name = vm.getNameLabel(conn); - } - if (name.equals(nameLabel)) { - return new Pair(vm, rec); - } - } - - return null; } protected boolean pingdomr(Connection conn, String host, String port) { @@ -351,7 +345,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected boolean pingxenserver() { + protected boolean pingXenServer() { Session slaveSession = null; Connection slaveConn = null; try { @@ -499,20 +493,25 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - Pair getNativeNetworkForTraffic(Connection conn, TrafficType type) throws XenAPIException, XmlRpcException { + protected XsLocalNetwork getNativeNetworkForTraffic(Connection conn, TrafficType type, String tag) throws XenAPIException, XmlRpcException { + if (tag != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Looking for network named " + tag); + } + return getNetworkByName(conn, tag); + } + if (type == TrafficType.Guest) { - return new Pair(Network.getByUuid(conn, _host.guestNetwork), _host.guestPif); + return new XsLocalNetwork(Network.getByUuid(conn, _host.guestNetwork), null, PIF.getByUuid(conn, _host.guestPif), null); } else if (type == TrafficType.Control) { - setupLinkLocalNetwork(conn); - return new Pair(Network.getByUuid(conn, _host.linkLocalNetwork), null); + setupLinkLocalNetwork(conn); + return new XsLocalNetwork(Network.getByUuid(conn, _host.linkLocalNetwork)); } else if (type == TrafficType.Management) { - return new Pair(Network.getByUuid(conn, _host.privateNetwork), _host.privatePif); + return new XsLocalNetwork(Network.getByUuid(conn, _host.privateNetwork), null, PIF.getByUuid(conn, _host.privatePif), null); } else if (type == TrafficType.Public) { - return new Pair(Network.getByUuid(conn, _host.publicNetwork), _host.publicPif); + return new XsLocalNetwork(Network.getByUuid(conn, _host.publicNetwork), null, PIF.getByUuid(conn, _host.publicPif), null); } else if (type == TrafficType.Storage) { - return new Pair(Network.getByUuid(conn, _host.storageNetwork1), _host.storagePif1); - } else if (type == TrafficType.Vpn) { - return new Pair(Network.getByUuid(conn, _host.publicNetwork), _host.publicPif); + return new XsLocalNetwork(Network.getByUuid(conn, _host.storageNetwork1), null, PIF.getByUuid(conn, _host.storagePif1), null); } throw new CloudRuntimeException("Unsupported network type: " + type); @@ -524,8 +523,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe * 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 + * @throws XmlRpcException + * @throws XenAPIException */ private void enableXenServerNetwork(Connection conn, Network nw, String vifNameLabel, String networkDesc) throws XenAPIException, XmlRpcException { @@ -572,10 +571,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vswitchNw = networks.iterator().next(); } - enableXenServerNetwork(conn, vswitchNw, "vswitch", - "vswicth network"); + enableXenServerNetwork(conn, vswitchNw, "vswitch", "vswicth network"); _host.vswitchNetwork = vswitchNw; - } + } return _host.vswitchNetwork; } catch (Exception e) { e.printStackTrace(); @@ -609,16 +607,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException { - Pair network = getNativeNetworkForTraffic(conn, nic.getType()); + String[] tags = nic.getTags(); + XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), tags != null && tags.length > 0 ? tags[0] : null); if (nic.getBroadcastUri() != null && nic.getBroadcastUri().toString().contains("untagged")) { - return network.first(); + return network.getNetwork(); } else if (nic.getBroadcastType() == BroadcastDomainType.Vlan) { URI broadcastUri = nic.getBroadcastUri(); assert broadcastUri.getScheme().equals(BroadcastDomainType.Vlan.scheme()); long vlan = Long.parseLong(broadcastUri.getHost()); - return enableVlanNetwork(conn, vlan, network.first(), network.second()); + return enableVlanNetwork(conn, vlan, network); } else if (nic.getBroadcastType() == BroadcastDomainType.Native || nic.getBroadcastType() == BroadcastDomainType.LinkLocal) { - return network.first(); + return network.getNetwork(); } else if (nic.getBroadcastType() == BroadcastDomainType.Vswitch) { String broadcastUri = nic.getBroadcastUri().toString(); String header = broadcastUri.substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()); @@ -753,12 +752,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else if (volume.getType() == Volume.Type.ROOT) { vbdr.mode = Types.VbdMode.RW; vbdr.type = Types.VbdType.DISK; - vbdr.unpluggable = false; + vbdr.unpluggable = false; } else { vbdr.mode = Types.VbdMode.RW; vbdr.type = Types.VbdType.DISK; vbdr.unpluggable = true; - } + } VBD vbd = VBD.create(conn, vbdr); if (s_logger.isDebugEnabled()) { @@ -774,7 +773,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); VM template = templates.iterator().next(); - VM vm = template.createClone(conn, vmSpec.getName()); + VM vm = template.createClone(conn, vmSpec.getName()); VM.Record vmr = vm.getRecord(conn); if (s_logger.isDebugEnabled()) { s_logger.debug("Created VM " + vmr.uuid + " for " + vmSpec.getName()); @@ -931,7 +930,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if( _host.systemvmisouuid == null ) { throw new CloudRuntimeException("can not find systemvmiso"); - } + } } VBD.Record cdromVBDR = new VBD.Record(); @@ -961,7 +960,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String result = connect(conn, cmd.getName(), privateIp, cmdPort); if (result != null) { return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result); - } + } } catch (Exception e) { return new CheckSshAnswer(cmd, e); } @@ -995,7 +994,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private void cleanUpTmpDomVif(Connection conn) { List vifs; - synchronized(_tmpDom0Vif) { + synchronized(_tmpDom0Vif) { vifs = _tmpDom0Vif; _tmpDom0Vif = new ArrayList(); } @@ -1018,8 +1017,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public StartAnswer execute(StartCommand cmd) { Connection conn = getConnection(); VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - String vmName = vmSpec.getName(); - State state = State.Stopped; + String vmName = vmSpec.getName(); + State state = State.Stopped; VM vm = null; try { @@ -1040,7 +1039,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe synchronized (_vms) { _vms.put(vmName, State.Starting); } - Host host = Host.getByUuid(conn, _host.uuid); + Host host = Host.getByUuid(conn, _host.uuid); vm = createVmFromTemplate(conn, vmSpec, host); for (VolumeTO disk : vmSpec.getDisks()) { @@ -1087,7 +1086,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } else { //For user vm, program the rules for each nic if the isolation uri scheme is ec2 NicTO[] nics = vmSpec.getNics(); - for (NicTO nic : nics) { + for (NicTO nic : nics) { if (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { result = callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), "vmID", Long.toString(vmSpec.getId())); @@ -1095,10 +1094,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn("Failed to program default network rules for " + vmName+" on nic with ip:"+nic.getIp()+" mac:"+nic.getMac()); } else { s_logger.info("Programmed default network rules for " + vmName+" on nic with ip:"+nic.getIp()+" mac:"+nic.getMac()); - } + } } } - } + } } state = State.Running; @@ -1243,7 +1242,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe int i = 0; for (StaticNatRuleTO rule : cmd.getRules()) { //1:1 NAT needs instanceip;publicip;domrip;op - args += rule.revoked() ? " -D " : " -A "; + args += rule.revoked() ? " -D " : " -A "; args += " -l " + rule.getSrcIp(); args += " -r " + rule.getDstIp(); args += " -P " + rule.getProtocol().toLowerCase(); @@ -1543,7 +1542,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); try { - IpAddressTO[] ips = cmd.getIpAddresses(); + IpAddressTO[] ips = cmd.getIpAddresses(); for (IpAddressTO ip : ips) { assignPublicIpAddress(conn, routerName, routerIp, ip.getPublicIp(), ip.isAdd(), ip.isFirstIP(), ip.isSourceNat(), ip.getVlanId(), @@ -1580,7 +1579,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected CheckHealthAnswer execute(CheckHealthCommand cmd) { - boolean result = pingxenserver(); + boolean result = pingXenServer(); return new CheckHealthAnswer(cmd, result); } @@ -1676,16 +1675,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe hostStats.setCpuUtilization(hostStats.getCpuUtilization() + getDataAverage(dataNode, col, numRows)); } -/* +/* if (param.contains("loadavg")) { hostStats.setAverageLoad((hostStats.getAverageLoad() + getDataAverage(dataNode, col, numRows))); } -*/ +*/ } } // add the host cpu utilization -/* +/* if (hostStats.getNumCpus() != 0) { hostStats.setCpuUtilization(hostStats.getCpuUtilization() / hostStats.getNumCpus()); s_logger.debug("Host cpu utilization " + hostStats.getCpuUtilization()); @@ -1701,7 +1700,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe HashMap vmStatsNameMap = new HashMap(); if( vmNames.size() == 0 ) { return new GetVmStatsAnswer(cmd, vmStatsNameMap); - } + } try { // Determine the UUIDs of the requested VMs @@ -1799,8 +1798,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } vmStatsAnswer.setCPUUtilization(vmStatsAnswer.getCPUUtilization()*100); - if(s_logger.isDebugEnabled()) - s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization()); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Vm cpu utilization " + vmStatsAnswer.getCPUUtilization()); + } } return vmResponseMap; @@ -1912,7 +1912,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn("Found an invalid value (infinity/NaN) in getDataAverage(), numRows>0"); return dummy; } - } + } } @@ -2173,9 +2173,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe snapshotvdi.setNameLabel(conn, "Template " + cmd.getName()); tmpl.destroy(conn); poolsr.scan(conn); - try{ + try{ Thread.sleep(5000); - } catch (Exception e) { + } catch (Exception e) { } String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI); VDI parent = getVDIbyUuid(conn, parentuuid); @@ -2355,7 +2355,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe break; } } - vm.poolMigrate(conn, dsthost, new HashMap()); + vm.poolMigrate(conn, dsthost, new HashMap()); vm.setAffinity(conn, dsthost); state = State.Stopping; } @@ -2704,7 +2704,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if( System.currentTimeMillis() - beginTime > timeout){ String msg = "Async " + timeout/1000 + " seconds timeout for task " + task.toString(); s_logger.warn(msg); - task.cancel(c); + task.cancel(c); throw new Types.BadAsyncResult(msg); } } @@ -2750,7 +2750,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); } } } @@ -2816,7 +2816,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); } } } @@ -2846,7 +2846,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { task.destroy(conn); } catch (Exception e1) { - s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); + s_logger.debug("unable to destroy task(" + task.toString() + ") on host(" + _host.uuid +") due to " + e1.toString()); } } } @@ -2880,8 +2880,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe "op", "download", "hostname", swift.getHostName(), "account", swift.getAccount(), "username", swift.getUserName(), "token", swift.getToken(), "rfilename", rfilename, "lfilename", lfilename); - if( result != null && result.equals("true")) + if( result != null && result.equals("true")) { return true; + } } catch (Exception e) { s_logger.warn("swift download failed due to " + e.toString()); } @@ -2895,8 +2896,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe "op", "upload", "hostname", swift.getHostName(), "account", swift.getAccount(), "username", swift.getUserName(), "token", swift.getToken(), "rfilename", rfilename, "lfilename", lfilename); - if( result != null && result.equals("true")) + if( result != null && result.equals("true")) { return true; + } } catch (Exception e) { s_logger.warn("swift download failed due to " + e.toString()); } @@ -2909,8 +2911,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe result = callHostPlugin(conn, "swift", "swift", "op", "delete", "hostname", swift.getHostName(), "account", swift.getAccount(), "username", swift.getUserName(), "token", swift.getToken(), "rfilename", rfilename); - if( result != null && result.equals("true")) + if( result != null && result.equals("true")) { return true; + } } catch (Exception e) { s_logger.warn("swift download failed due to " + e.toString()); } @@ -3109,7 +3112,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, bytesSent, bytesRcvd); - } + } } catch (XenAPIException e) { String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString(); s_logger.warn(msg, e); @@ -3145,11 +3148,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } catch (XenAPIException e) { String msg = "getVdis can not get VPD due to " + e.toString(); - s_logger.warn(msg, e); + s_logger.warn(msg, e); } catch (XmlRpcException e) { String msg = "getVdis can not get VPD due to " + e.getMessage(); s_logger.warn(msg, e); - } + } return vdis; } @@ -3267,7 +3270,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return true; } - protected Nic getManageMentNetwork(Connection conn) throws XmlRpcException, XenAPIException { + protected XsLocalNetwork getManagementNetwork(Connection conn) throws XmlRpcException, XenAPIException { PIF mgmtPif = null; PIF.Record mgmtPifRec = null; Host host = Host.getByUuid(conn, _host.uuid); @@ -3303,30 +3306,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } Network nk = mgmtPifRec.network; Network.Record nkRec = nk.getRecord(conn); - return new Nic(nk, nkRec, mgmtPif, mgmtPifRec); + return new XsLocalNetwork(nk, nkRec, mgmtPif, mgmtPifRec); } - protected Nic getLocalNetwork(Connection conn, String name) throws XmlRpcException, XenAPIException { - Set networks = Network.getByNameLabel(conn, name); - for (Network network : networks) { - Network.Record nr = network.getRecord(conn); - for (PIF pif : nr.PIFs) { - PIF.Record pr = pif.getRecord(conn); - if (_host.uuid.equals(pr.host.getUuid(conn))) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a network called " + name + " on host=" + _host.ip + "; Network=" - + nr.uuid + "; pif=" + pr.uuid); - } - return new Nic(network, nr, pif, pr); - } - } - } - - return null; - } - - protected VIF getCorrectVif(Connection conn, VM router, String vlanId) { try { Set routerVIFs = router.getVIFs(conn); @@ -3385,144 +3368,185 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return getVDIbyUuid(conn, volumePath); } - protected Network getNetworkByName(Connection conn, String name) throws BadServerResponse, XenAPIException, XmlRpcException { - Set networks = Network.getByNameLabel(conn, name); - if (networks.size() > 0) { - assert networks.size() == 1 : "How did we find more than one network with this name label" + name + "? Strange...."; - return networks.iterator().next(); // Found it. - } - - return null; - } - - protected synchronized Network getNetworkByName(Connection conn, String name, boolean lookForPif) throws XenAPIException, XmlRpcException { - Network found = null; + /** + * getNetworkByName() retrieves what the server thinks is the actual + * network used by the XenServer host. This method should always be + * used to talk to retrieve a network by the name. The reason is + * because of the problems in using the name label as the way to find + * the Network. + * + * To see how we are working around these problems, take a look at + * enableVlanNetwork(). The following description assumes you have looked + * at the description on that method. + * + * In order to understand this, we have to see what type of networks are + * within a XenServer that's under CloudStack control. + * + * - Native Networks: these are networks that are untagged on the + * XenServer and are used to crate VLAN networks on. These are + * created by the user and is assumed to be one per cluster. + * - VLAN Networks: these are dynamically created by CloudStack and can + * have problems with duplicated names. + * - LinkLocal Networks: these are dynamically created by CloudStack and + * can also have problems with duplicated names but these don't have + * actual PIFs. + * + * In order to speed to retrieval of a network, we do the following: + * - We retrieve by the name. If only one network is retrieved, we + * assume we retrieved the right network. + * - If more than one network is retrieved, we check to see which one + * has the pif for the local host and use that. + * - If a pif is not found, then we look at the tags and find the + * one with the lowest timestamp. (See enableVlanNetwork()) + * + * @param conn Xapi connection + * @param name name of the network + * @return XsNic an object that contains network, network record, pif, and pif record. + * @throws XenAPIException + * @throws XmlRpcException + * + * @see enableVlanNetwork + */ + protected XsLocalNetwork getNetworkByName(Connection conn, String name) throws XenAPIException, XmlRpcException { Set networks = Network.getByNameLabel(conn, name); if (networks.size() == 1) { - found = networks.iterator().next(); - } else if (networks.size() > 1) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found more than one network with the name " + name); + return new XsLocalNetwork(networks.iterator().next(), null, null, null); + } + + if (networks.size() == 0) { + return null; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found more than one network with the name " + name); + } + Network earliestNetwork = null; + Network.Record earliestNetworkRecord = null; + long earliestTimestamp = Long.MAX_VALUE; + int earliestRandom = Integer.MAX_VALUE; + for (Network network : networks) { + XsLocalNetwork nic = new XsLocalNetwork(network); + + if (nic.getPif(conn) != null) { + return nic; } - for (Network network : networks) { - if (!lookForPif) { - found = network; - break; - } - - Network.Record netr = network.getRecord(conn); - s_logger.debug("Checking network " + netr.uuid); - if (netr.PIFs.size() == 0) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Network " + netr.uuid + " has no pifs so skipping that."); + + Network.Record record = network.getRecord(conn); + if (record.tags != null) { + for (String tag : record.tags) { + Pair stamp = parseTimestamp(tag); + if (stamp == null) { + continue; } - } else { - for (PIF pif : netr.PIFs) { - PIF.Record pifr = pif.getRecord(conn); - if (_host.uuid.equals(pifr.host.getUuid(conn))) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Network " + netr.uuid + " has a pif " + pifr.uuid + " for our host "); - } - found = network; - break; - } + + if (stamp.first() < earliestTimestamp || (stamp.first() == earliestTimestamp && stamp.second() < earliestRandom)) { + earliestTimestamp = stamp.first(); + earliestRandom = stamp.second(); + earliestNetwork = network; + earliestNetworkRecord = record; } } } - } - - return found; - } - - protected Network enableVlanNetwork(Connection conn, long tag, String pifUuid) throws XenAPIException, XmlRpcException { - // In XenServer, vlan is added by - // 1. creating a network. - // 2. creating a vlan associating network with the pif. - // We always create - // 1. a network with VLAN[vlan id in decimal] - // 2. a vlan associating the network created with the pif to private - // network. - Network vlanNetwork = null; - String name = "VLAN" + Long.toString(tag); - - synchronized (name.intern()) { - vlanNetwork = getNetworkByName(conn, name); - if (vlanNetwork == null) { // Can't find it, then create it. - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip); - } - Network.Record nwr = new Network.Record(); - nwr.nameLabel = name; - nwr.bridge = name; - vlanNetwork = Network.create(conn, nwr); - } - - PIF nPif = PIF.getByUuid(conn, pifUuid); - PIF.Record nPifr = nPif.getRecord(conn); - - Network.Record vlanNetworkr = vlanNetwork.getRecord(conn); - if (vlanNetworkr.PIFs != null) { - for (PIF pif : vlanNetworkr.PIFs) { - PIF.Record pifr = pif.getRecord(conn); - if(pifr.host.equals(nPifr.host)) { - if (pifr.device.equals(nPifr.device) ) { - pif.plug(conn); - return vlanNetwork; - } else { - throw new CloudRuntimeException("Creating VLAN " + tag + " on " + nPifr.device + " failed due to this VLAN is already created on " + pifr.device); - } - - } - } - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Creating VLAN " + tag + " on host " + _host.ip + " on device " + nPifr.device); - } - VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); - PIF untaggedPif = vlan.getUntaggedPIF(conn); - if (!untaggedPif.getCurrentlyAttached(conn)) { - untaggedPif.plug(conn); - } } - return vlanNetwork; + return earliestNetwork != null ? new XsLocalNetwork(earliestNetwork, earliestNetworkRecord, null, null) : null; } - - protected Network enableVlanNetwork(Connection conn, long tag, Network network, String pifUuid) throws XenAPIException, XmlRpcException { - // In XenServer, vlan is added by - // 1. creating a network. - // 2. creating a vlan associating network with the pif. - // We always create - // 1. a network with VLAN[vlan id in decimal] - // 2. a vlan associating the network created with the pif to private - // network. - + + protected String generateTimeStamp() { + return new StringBuilder("CsCreateTime-").append(System.currentTimeMillis()).append("-").append(_rand.nextInt()).toString(); + } + + protected Pair parseTimestamp(String timeStampStr) { + String[] tokens = timeStampStr.split("-"); + assert(tokens.length == 3) : "It's our timestamp but it doesn't fit our format: " + timeStampStr; + if (!tokens[0].equals("CsCreateTime-")) { + return null; + } + return new Pair(Long.parseLong(tokens[1]), Integer.parseInt(tokens[2])); + } + + /** + * enableVlanNetwork creates a Network object, Vlan object, and thereby + * a tagged PIF object in Xapi. + * + * In XenServer, VLAN is added by + * - Create a network, which is unique cluster wide. + * - Find the PIF that you want to create the VLAN on. + * - Create a VLAN using the network and the PIF. As a result of this + * operation, a tagged PIF object is also created. + * + * Here is a list of problems with clustered Xapi implementation that + * we are trying to circumvent. + * - There can be multiple Networks with the same name-label so searching + * using name-label is not unique. + * - There are no other ways to search for Networks other than listing + * all of them which is not efficient in our implementation because + * we can have over 4000 VLAN networks. + * - In a clustered situation, it's possible for both hosts to detect + * that the Network is missing and both creates it. This causes a + * lot of problems as one host may be using one Network and another + * may be using a different network for their VMs. This causes + * problems in migration because the VMs are logically attached + * to different networks in Xapi's database but in reality, they + * are attached to the same network. + * + * To work around these problems, we do the following. + * + * - When creating the VLAN network, we name it as VLAN-UUID of the + * Network it is created on-VLAN Tag. Because VLAN tags is unique with + * one particular network, this is a unique name-label to quickly + * retrieve the the VLAN network with when we need it again. + * - When we create the VLAN network, we add a timestamp and a random + * number as a tag into the network. Then instead of creating + * VLAN on that network, we actually retrieve the Network again + * and this time uses the VLAN network with lowest timestamp or + * lowest random number as the VLAN network. This allows VLAN creation + * to happen on multiple hosts concurrently but even if two VLAN + * networks were created with the same name, only one of them is used. + * + * One cavaet about this approach is that it relies on the timestamp to + * be relatively accurate among different hosts. + * + * @param conn Xapi Connection + * @param tag VLAN tag + * @param network network on this host to create the VLAN on. + * @return VLAN Network created. + * @throws XenAPIException + * @throws XmlRpcException + */ + protected Network enableVlanNetwork(Connection conn, long tag, XsLocalNetwork network) throws XenAPIException, XmlRpcException { Network vlanNetwork = null; - String name = "VLAN" + Long.toString(tag); - - vlanNetwork = getNetworkByName(conn, name, true); - if (vlanNetwork == null) { // Can't find it, then create it. + String oldName = "VLAN" + Long.toString(tag); + String newName = "VLAN-" + network.getNetworkRecord(conn).uuid + "-" + tag; + XsLocalNetwork vlanNic = getNetworkByName(conn, newName); + if (vlanNic == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Couldn't find vlan network with the new name so trying old name: " + oldName); + } + vlanNic = getNetworkByName(conn, oldName); + if (vlanNic != null) { + s_logger.info("Renaming VLAN with old name " + oldName + " to " + newName); + vlanNic.getNetwork().setNameLabel(conn, newName); + } + } + if (vlanNic == null) { // Can't find it, then create it. if (s_logger.isDebugEnabled()) { s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip); } Network.Record nwr = new Network.Record(); - nwr.nameLabel = name; - nwr.bridge = name; + nwr.nameLabel = newName; + nwr.tags = new HashSet(); + nwr.tags.add(generateTimeStamp()); vlanNetwork = Network.create(conn, nwr); + vlanNic = getNetworkByName(conn, newName); } - PIF nPif = PIF.getByUuid(conn, pifUuid); - PIF.Record nPifr = nPif.getRecord(conn); - - Network.Record vlanNetworkr = vlanNetwork.getRecord(conn); - if (vlanNetworkr.PIFs != null) { - for (PIF pif : vlanNetworkr.PIFs) { - PIF.Record pifr = pif.getRecord(conn); - if (pifr.device.equals(nPifr.device) && pifr.host.equals(nPifr.host)) { - return vlanNetwork; - } - } + PIF nPif = network.getPif(conn); + PIF.Record nPifr = network.getPifRecord(conn); + + vlanNetwork = vlanNic.getNetwork(); + if (vlanNic.getPif(conn) != null) { + return vlanNetwork; } if (s_logger.isDebugEnabled()) { @@ -3541,7 +3565,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } protected SR getLocalLVMSR(Connection conn) { - try { + try { Map map = SR.getAllRecords(conn); for (Map.Entry entry : map.entrySet()) { SR.Record srRec = entry.getValue(); @@ -3614,13 +3638,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe public PingCommand getCurrentStatus(long id) { try { Connection conn = getConnection(); - if (!pingxenserver()) { + if (!pingXenServer()) { Thread.sleep(1000); - if (!pingxenserver()) { + if (!pingXenServer()) { s_logger.warn(" can not ping xenserver " + _host.uuid); return null; } - } + } HashMap newStates = sync(conn); if (newStates == null) { s_logger.warn("Unable to get current status from sync"); @@ -3677,18 +3701,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _host.speed = hc.getSpeed(conn).intValue(); break; } - Nic privateNic = getManageMentNetwork(conn); - _privateNetworkName = privateNic.nr.nameLabel; - _host.privatePif = privateNic.pr.uuid; - _host.privateNetwork = privateNic.nr.uuid; + XsLocalNetwork privateNic = getManagementNetwork(conn); + _privateNetworkName = privateNic.getNetworkRecord(conn).nameLabel; + _host.privatePif = privateNic.getPifRecord(conn).uuid; + _host.privateNetwork = privateNic.getNetworkRecord(conn).uuid; _canBridgeFirewall = can_bridge_firewall(conn); _host.systemvmisouuid = null; - Nic guestNic = null; + XsLocalNetwork guestNic = null; if (_guestNetworkName != null && !_guestNetworkName.equals(_privateNetworkName)) { - guestNic = getLocalNetwork(conn, _guestNetworkName); + guestNic = getNetworkByName(conn, _guestNetworkName); if (guestNic == null) { s_logger.warn("Unable to find guest network " + _guestNetworkName); throw new IllegalArgumentException("Unable to find guest network " + _guestNetworkName + " for host " + _host.ip); @@ -3697,12 +3721,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe guestNic = privateNic; _guestNetworkName = _privateNetworkName; } - _host.guestNetwork = guestNic.nr.uuid; - _host.guestPif = guestNic.pr.uuid; + _host.guestNetwork = guestNic.getNetworkRecord(conn).uuid; + _host.guestPif = guestNic.getPifRecord(conn).uuid; - Nic publicNic = null; + XsLocalNetwork publicNic = null; if (_publicNetworkName != null && !_publicNetworkName.equals(_guestNetworkName)) { - publicNic = getLocalNetwork(conn, _publicNetworkName); + publicNic = getNetworkByName(conn, _publicNetworkName); if (publicNic == null) { s_logger.warn("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); throw new IllegalArgumentException("Unable to find public network " + _publicNetworkName + " for host " + _host.ip); @@ -3711,30 +3735,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe publicNic = guestNic; _publicNetworkName = _guestNetworkName; } - _host.publicPif = publicNic.pr.uuid; - _host.publicNetwork = publicNic.nr.uuid; + _host.publicPif = publicNic.getPifRecord(conn).uuid; + _host.publicNetwork = publicNic.getNetworkRecord(conn).uuid; - Nic storageNic1 = null; + XsLocalNetwork storageNic1 = null; if (_storageNetworkName1 != null && !_storageNetworkName1.equals(_guestNetworkName)) { - storageNic1 = getLocalNetwork(conn, _storageNetworkName1); + storageNic1 = getNetworkByName(conn, _storageNetworkName1); } if (storageNic1 == null) { storageNic1 = guestNic; _storageNetworkName1 = _guestNetworkName; } - _host.storageNetwork1 = storageNic1.nr.uuid; - _host.storagePif1 = storageNic1.pr.uuid; + _host.storageNetwork1 = storageNic1.getNetworkRecord(conn).uuid; + _host.storagePif1 = storageNic1.getPifRecord(conn).uuid; - Nic storageNic2 = null; + XsLocalNetwork storageNic2 = null; if (_storageNetworkName2 != null && !_storageNetworkName2.equals(_guestNetworkName)) { - storageNic2 = getLocalNetwork(conn, _storageNetworkName2); + storageNic2 = getNetworkByName(conn, _storageNetworkName2); } if (storageNic2 == null) { storageNic2 = guestNic; _storageNetworkName2 = _guestNetworkName; } - _host.storageNetwork2 = storageNic2.nr.uuid; - _host.storagePif2 = storageNic2.pr.uuid; + _host.storageNetwork2 = storageNic2.getNetworkRecord(conn).uuid; + _host.storagePif2 = storageNic2.getPifRecord(conn).uuid; s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.ip); s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.ip); @@ -3900,7 +3924,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String tag = it.next(); if (tag.startsWith("vmops-version-")) { if (tag.contains(version)) { - s_logger.info(logX(host, "Host " + hr.address + " is already setup.")); + s_logger.info(logX(host, "Host " + hr.address + " is already setup.")); return; } else { it.remove(); @@ -3911,7 +3935,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22); try { sshConnection.connect(null, 60000, 60000); - if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { throw new CloudRuntimeException("Unable to authenticate"); } @@ -4070,7 +4094,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe PBD.Record pbdr = pbd.getRecord(conn); if (host.equals(pbdr.host)) { if (!pbdr.currentlyAttached) { - pbdPlug(conn, pbd, pbdr.uuid); + pbdPlug(conn, pbd, pbdr.uuid); } found = true; break; @@ -4081,7 +4105,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe pbdr.host = host; pbdr.uuid = ""; PBD pbd = PBD.create(conn, pbdr); - pbdPlug(conn, pbd, pbd.getUuid(conn)); + pbdPlug(conn, pbd, pbd.getUuid(conn)); } } else { for (PBD pbd : pbds) { @@ -4117,7 +4141,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); - } + } } @@ -4229,7 +4253,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } - protected boolean can_bridge_firewall(Connection conn) { + protected boolean can_bridge_firewall(Connection conn) { return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance)); } @@ -4369,7 +4393,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _isOvs = true; Connection conn = getConnection(); - String bridge = "unkonwn"; + String bridge = "unkonwn"; try { Network nw = setupvSwitchNetwork(conn); bridge = nw.getBridge(conn); @@ -4383,7 +4407,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _host.ip, bridge); } else { return new OvsCreateGreTunnelAnswer(cmd, true, result, _host.ip, bridge, Integer.parseInt(res[1])); - } + } } catch (Exception e) { e.printStackTrace(); } @@ -4456,7 +4480,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (_publicNetworkName != null) { details.put("public.network.device", _publicNetworkName); - } + } if (_guestNetworkName != null) { details.put("guest.network.device", _guestNetworkName); } @@ -4610,7 +4634,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private void CheckXenHostInfo() throws ConfigurationException { Connection conn = _connPool.slaveConnect(_host.ip, _username, _password); - if( conn == null ) { + if( conn == null ) { throw new ConfigurationException("Can not create slave connection to " + _host.ip); } try { @@ -4630,7 +4654,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe throw new ConfigurationException(msg); } } finally { - try { + try { Session.localLogout(conn); } catch (Exception e) { } @@ -4674,7 +4698,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vdir = vdi.getRecord(conn); s_logger.debug("Succesfully created VDI for " + cmd + ". Uuid = " + vdir.uuid); - VolumeTO vol = new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel, + VolumeTO vol = new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), vdir.nameLabel, pool.getPath(), vdir.uuid, vdir.virtualSize, null); return new CreateAnswer(cmd, vol); } catch (Exception e) { @@ -4731,7 +4755,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe SR sr = SR.create(conn, host, deviceConfig, new Long(0), name, uri.getHost() + uri.getPath(), SRType.NFS.toString(), "user", shared, new HashMap()); if( !checkSR(conn, sr) ) { throw new Exception("no attached PBD"); - } + } if (s_logger.isDebugEnabled()) { s_logger.debug(logX(sr, "Created a SR; UUID is " + sr.getUuid(conn) + " device config is " + deviceConfig)); } @@ -4850,7 +4874,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe continue; } if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) { - throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:" + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + _host.uuid); } } @@ -4894,7 +4918,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn(msg, e); throw new CloudRuntimeException(msg, e); } - } + } deviceConfig.put("SCSIid", scsiid); String result = SR.probe(conn, host, deviceConfig, type , smConfig); @@ -4906,9 +4930,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true, smConfig); } else { - sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId, + sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId, type, "user", true, smConfig); - Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn); + Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn); PBD.Record rec = new PBD.Record(); rec.deviceConfig = deviceConfig; rec.host = pRec.master; @@ -4964,7 +4988,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) { - throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:" + dc.get("serverpath") + " for pool " + pool.getUuid() + "on host:" + _host.uuid); } @@ -5013,6 +5037,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } try { + Set snapshots = vdi.getSnapshots(conn); + for( VDI snapshot: snapshots ) { + snapshot.destroy(conn); + } vdi.destroy(conn); } catch (Exception e) { String msg = "VDI destroy for " + volumeUUID + " failed due to " + e.toString(); @@ -5035,7 +5063,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/"; String mountpoint = remoteVolumesMountPath + volumeFolder; SR primaryStoragePool = getStorageRepository(conn, poolTO); - String srUuid = primaryStoragePool.getUuid(conn); + String srUuid = primaryStoragePool.getUuid(conn); if (toSecondaryStorage) { // Create the volume folder if (!createSecondaryStorageFolder(conn, remoteVolumesMountPath, volumeFolder)) { @@ -5058,7 +5086,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe removeSR(conn, secondaryStorage); } } else { - String uuid = copy_vhd_to_secondarystorage(conn, mountpoint, volumeUUID, srUuid); + String uuid = copy_vhd_to_secondarystorage(conn, mountpoint, volumeUUID, srUuid); return new CopyVolumeAnswer(cmd, true, null, null, uuid); } } else { @@ -5118,12 +5146,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if( deviceId != null ) { if( deviceId.longValue() == 3 ) { String msg = "Device 3 is reserved for CD-ROM, choose other device"; - return new AttachVolumeAnswer(cmd,msg); + return new AttachVolumeAnswer(cmd,msg); } if(isDeviceUsed(conn, vm, deviceId)) { String msg = "Device " + deviceId + " is used in VM " + vmName; return new AttachVolumeAnswer(cmd,msg); - } + } diskNumber = deviceId.toString(); } else { diskNumber = getUnusedDeviceNum(conn, vm); @@ -5474,7 +5502,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe result = postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUuid, userSpecifiedName, null, physicalSize, virtualSize, newTemplateId); if (!result) { throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templatePath); - } + } installPath = installPath + "/" + tmpltFilename; return new CreatePrivateTemplateAnswer(cmd, true, null, installPath, virtualSize, physicalSize, tmpltUuid, ImageFormat.VHD); } catch (Exception e) { @@ -5512,7 +5540,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return false; - } + } protected BackupSnapshotAnswer execute(final BackupSnapshotCommand cmd) { Connection conn = getConnection(); @@ -5540,7 +5568,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid); if ( prevBackupUuid != null ) { - try { + try { String snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI); if( snapshotPaUuid != null ) { String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI); @@ -5549,7 +5577,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe fullbackup = false; } } - } catch (Exception e) { + } catch (Exception e) { } } String filename = volumeId + "_" + cmd.getSnapshotId() + "_" + cmd.getSnapshotUuid(); @@ -5636,7 +5664,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // Get the absolute path of the snapshot on the secondary storage. URI snapshotURI = new URI(secondaryStoragePoolURL + "/snapshots/" + accountId + "/" + volumeId ); String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath() + "/" + backedUpSnapshotUuid + ".vhd"; - String srUuid = primaryStorageSR.getUuid(conn); + String srUuid = primaryStorageSR.getUuid(conn); volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid); result = true; } catch (XenAPIException e) { @@ -5679,16 +5707,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (uri != null) { String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); - - if (secondaryStorageMountPath == null) { - details = "Couldn't delete snapshot because the URL passed: " + secondaryStoragePoolURL - + " is invalid."; - } else { - details = deleteSnapshotBackup(conn, dcId, accountId, volumeId, secondaryStorageMountPath, backupUUID); - success = (details != null && details.equals("1")); - if (success) { - s_logger.debug("Successfully deleted snapshot backup " + backupUUID); - } + + details = deleteSnapshotBackup(conn, dcId, accountId, volumeId, secondaryStorageMountPath, backupUUID); + success = (details != null && details.equals("1")); + if (success) { + s_logger.debug("Successfully deleted snapshot backup " + backupUUID); } } return new DeleteSnapshotBackupAnswer(cmd, true, details); @@ -5738,14 +5761,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (uri != null) { String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); - if (secondaryStorageMountPath == null) { - details = "Couldn't delete snapshotsDir because the URL passed: " + secondaryStoragePoolURL + " is invalid."; - } else { - details = deleteSnapshotsDir(conn, dcId, accountId, volumeId, secondaryStorageMountPath); - success = (details != null && details.equals("1")); - if (success) { - s_logger.debug("Successfully deleted snapshotsDir for volume: " + volumeId); - } + details = deleteSnapshotsDir(conn, dcId, accountId, volumeId, secondaryStorageMountPath); + success = (details != null && details.equals("1")); + if (success) { + s_logger.debug("Successfully deleted snapshotsDir for volume: " + volumeId); } } @@ -5935,10 +5954,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return success; - } + } protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) { - String parentUuid = callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, + String parentUuid = callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid, "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString()); if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) { @@ -6058,7 +6077,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } catch (XenAPIException e) { String msg = "Unable to eject host " + _host.uuid + " due to " + e.toString(); - s_logger.warn(msg); + s_logger.warn(msg); host.destroy(conn); } return new Answer(cmd); @@ -6070,7 +6089,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String msg = "Exception Unable to destroy host " + _host.uuid + " in xenserver database due to " + e.getMessage(); s_logger.warn(msg, e); return new Answer(cmd, false, msg); - } + } } private Answer execute(CleanupNetworkRulesCmd cmd) { @@ -6092,24 +6111,71 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe - protected class Nic { - public Network n; - public Network.Record nr; - public PIF p; - public PIF.Record pr; + /** + * XsNic represents a network and the host's specific PIF. + */ + protected class XsLocalNetwork { + private Network _n; + private Network.Record _nr; + private PIF _p; + private PIF.Record _pr; - public Nic(Network n, Network.Record nr, PIF p, PIF.Record pr) { - this.n = n; - this.nr = nr; - this.p = p; - this.pr = pr; + public XsLocalNetwork(Network n) { + this(n, null, null, null); + } + + public XsLocalNetwork(Network n, Network.Record nr, PIF p, PIF.Record pr) { + _n = n; + _nr = nr; + _p = p; + _pr = pr; + } + + public Network getNetwork() { + return _n; + } + + public Network.Record getNetworkRecord(Connection conn) throws XenAPIException, XmlRpcException { + if (_nr == null) { + _nr = _n.getRecord(conn); + } + + return _nr; + } + + public PIF getPif(Connection conn) throws XenAPIException, XmlRpcException { + if (_p == null) { + Network.Record nr = getNetworkRecord(conn); + for (PIF pif : nr.PIFs) { + PIF.Record pr = pif.getRecord(conn); + if (_host.uuid.equals(pr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a network called " + nr.nameLabel + " on host=" + _host.ip + "; Network=" + nr.uuid + "; pif=" + pr.uuid); + } + _p = pif; + _pr = pr; + break; + } + } + } + return _p; + } + + public PIF.Record getPifRecord(Connection conn) throws XenAPIException, XmlRpcException { + if (_pr == null) { + PIF p = getPif(conn); + if (_pr == null) { + _pr = p.getRecord(conn); + } + } + return _pr; } } // A list of UUIDs that are gathered from the XenServer when // the resource first connects to XenServer. These UUIDs do // not change over time. - protected class XenServerHost { + protected class XsHost { public String systemvmisouuid; public String uuid; public String ip; diff --git a/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java b/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java index cd2ca921bba..de923bde251 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java +++ b/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java @@ -416,7 +416,7 @@ public class XenServer56Resource extends CitrixResourceBase { @Override public StartupCommand[] initialize() { - pingxenserver(); + pingXenServer(); StartupCommand[] cmds = super.initialize(); Connection conn = getConnection(); if (!setIptables(conn)) { diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index 6f554d94553..04ba5353c63 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -539,8 +539,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S _params.put(StorageLayer.InstanceConfigKey, _storage); _dlMgr = new DownloadManagerImpl(); _dlMgr.configure("DownloadManager", _params); - //_upldMgr = new UploadManagerImpl(); - //_upldMgr.configure("UploadManager", params); + _upldMgr = new UploadManagerImpl(); + _upldMgr.configure("UploadManager", params); } catch (ConfigurationException e) { s_logger.warn("Caught problem while configuring DownloadManager", e); return false; diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java index 17a2fbfd67b..e7a6d2e7ef1 100755 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java @@ -608,6 +608,7 @@ public class DownloadManagerImpl implements DownloadManager { private List listTemplates(String rootdir) { List result = new ArrayList(); + Script script = new Script(listTmpltScr, s_logger); script.add("-r", rootdir); ZfsPathParser zpp = new ZfsPathParser(rootdir); @@ -621,6 +622,11 @@ public class DownloadManagerImpl implements DownloadManager { public Map gatherTemplateInfo(String rootDir) { Map result = new HashMap(); String templateDir = rootDir + File.separator + _templateDir; + + if (! _storage.exists(templateDir)) { + _storage.mkdirs(templateDir); + } + List publicTmplts = listTemplates(templateDir); for (String tmplt : publicTmplts) { String path = tmplt.substring(0, tmplt.lastIndexOf(File.separator)); diff --git a/core/src/com/cloud/storage/template/UploadManagerImpl.java b/core/src/com/cloud/storage/template/UploadManagerImpl.java index d559ae0b3a3..da88da86868 100755 --- a/core/src/com/cloud/storage/template/UploadManagerImpl.java +++ b/core/src/com/cloud/storage/template/UploadManagerImpl.java @@ -373,11 +373,10 @@ public class UploadManagerImpl implements UploadManager { } - // 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(); + // 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() + " " + extractDir + uuid); + command.add("ln -sf /mnt/SecStorage/" + cmd.getParent() + File.separator + cmd.getInstallPath() + " " + extractDir + uuid); result = command.execute(); if (result != null) { String errorString = "Error in linking err=" + result; diff --git a/core/src/com/cloud/vm/DomainRouterVO.java b/core/src/com/cloud/vm/DomainRouterVO.java index a1b1e72dfce..02ab3a5c18f 100755 --- a/core/src/com/cloud/vm/DomainRouterVO.java +++ b/core/src/com/cloud/vm/DomainRouterVO.java @@ -90,8 +90,8 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter { } @Override - public long getDataCenterId() { - return dataCenterId; + public long getDataCenterIdToDeployIn() { + return dataCenterIdToDeployIn; } public String getPublicNetmask() { @@ -123,6 +123,10 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter { this.role = role; } + @Override + public long getServiceOfferingId() { + return serviceOfferingId; + } public void setServiceOfferingId(long serviceOfferingId) { this.serviceOfferingId = serviceOfferingId; } diff --git a/core/src/com/cloud/vm/VMInstanceVO.java b/core/src/com/cloud/vm/VMInstanceVO.java index 8fae48a868b..752849daba5 100644 --- a/core/src/com/cloud/vm/VMInstanceVO.java +++ b/core/src/com/cloud/vm/VMInstanceVO.java @@ -93,15 +93,15 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject - + diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py index a0dd1edb344..e51803b5271 100644 --- a/python/lib/cloudutils/globalEnv.py +++ b/python/lib/cloudutils/globalEnv.py @@ -9,7 +9,7 @@ class globalEnv: #debug self.debug = False #management server IP - self.mgtSvr = None + self.mgtSvr = "myagent.cloud.com" #zone id or zone name self.zone = None #pod id or pod name @@ -21,4 +21,4 @@ class globalEnv: #uuid self.uuid = None #default private network - self.privateNet = "cloudbr0" \ No newline at end of file + self.privateNet = "cloudbr0" diff --git a/python/lib/cloudutils/syscfg.py b/python/lib/cloudutils/syscfg.py index 74607f0f106..f8e07ea28f6 100644 --- a/python/lib/cloudutils/syscfg.py +++ b/python/lib/cloudutils/syscfg.py @@ -72,8 +72,12 @@ class sysConfigAgent(sysConfig): return True if os.geteuid() != 0: - raise CloudInternalException("Need to execute with root permission") + raise CloudInternalException("Need to execute with root permission\n") + hostname = bash("hostname -f") + if not hostname.isSuccess(): + raise CloudInternalException("Checking hostname ... [Failed]\nPlease edit /etc/hosts, add a Fully Qualified Domain Name as your hostname\n") + kvmEnabled = self.svo.isKVMEnabled() if not kvmEnabled: raise CloudInternalException("Checking KVM...[Failed]\nPlease enable KVM on this machine\n") @@ -125,7 +129,7 @@ class sysConfigServer(sysConfig): raise CloudInternalException("Need to execute with root permission") hostname = bash("hostname -f") if not hostname.isSuccess(): - raise CloudInternalException("Checking hostname ... [Failed]\nNeed to have a Fully Qualified Domain Name as your hostname") + raise CloudInternalException("Checking hostname ... [Failed]\nPlease edit /etc/hosts, add a Fully Qualified Domain Name as your hostname\n") return True class sysConfigServerRedhat(sysConfigServer): diff --git a/scripts/vm/hypervisor/xenserver/copy_vhd_from_secondarystorage.sh b/scripts/vm/hypervisor/xenserver/copy_vhd_from_secondarystorage.sh index c10882d5d50..f5d420e7d20 100755 --- a/scripts/vm/hypervisor/xenserver/copy_vhd_from_secondarystorage.sh +++ b/scripts/vm/hypervisor/xenserver/copy_vhd_from_secondarystorage.sh @@ -111,6 +111,12 @@ if [ $type == "nfs" ]; then uuid=$(uuidgen -r) desvhd=/var/run/sr-mount/$sruuid/$uuid copyvhd $desvhd $vhdfile 0 $type + $VHDUTIL set -n $desvhd -f "hidden" -v "0" > /dev/null + if [ $? -ne 0 ]; then + echo "21#failed to set hidden to 0 $desvhd" + cleanup + exit 0 + fi mv /var/run/sr-mount/$sruuid/$uuid /var/run/sr-mount/$sruuid/${uuid}.vhd xe sr-scan uuid=$sruuid if [ $? -ne 0 ]; then @@ -140,6 +146,12 @@ elif [ $type == "lvmoiscsi" -o $type == "lvm" -o $type == "lvmohba" ]; then exit 0 fi copyvhd $desvhd $vhdfile $lvsize $type + $VHDUTIL set -n $desvhd -f "hidden" -v "0" > /dev/null + if [ $? -ne 0 ]; then + echo "22#failed to set hidden to 0 $desvhd" + cleanup + exit 0 + fi xe sr-scan uuid=$sruuid if [ $? -ne 0 ]; then echo "14#failed to scan sr $sruuid" diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index df90b84dcd9..4b9146c78cb 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -4,8 +4,7 @@ # [Name of file]=[source path],[file permission],[destination path] # [destination path] is required. # If [file permission] is missing, 755 is assumed. -# If [source path] is missing, it looks in the same -# directory as the patch file. +# If [source path] is missing, it looks in the same directory as the patch file. # If [source path] starts with '/', then it is absolute path. # If [source path] starts with '~', then it is path relative to management server home directory. # If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file. diff --git a/server/src/com/cloud/acl/DomainChecker.java b/server/src/com/cloud/acl/DomainChecker.java index f6b39c4659b..058321aae47 100755 --- a/server/src/com/cloud/acl/DomainChecker.java +++ b/server/src/com/cloud/acl/DomainChecker.java @@ -82,7 +82,7 @@ public class DomainChecker extends AdapterBase implements SecurityChecker { // validate that the template is usable by the account if (!template.isPublicTemplate()) { Account owner = _accountDao.findById(template.getAccountId()); - if (BaseCmd.isAdmin(owner.getType()) || (owner.getId() == caller.getId())) { + if (BaseCmd.isRootAdmin(caller.getType()) || (owner.getId() == caller.getId())) { return true; } diff --git a/server/src/com/cloud/agent/manager/AgentAttache.java b/server/src/com/cloud/agent/manager/AgentAttache.java index 12934b18ece..470acb2c319 100644 --- a/server/src/com/cloud/agent/manager/AgentAttache.java +++ b/server/src/com/cloud/agent/manager/AgentAttache.java @@ -17,11 +17,13 @@ */ package com.cloud.agent.manager; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; @@ -238,8 +240,25 @@ public abstract class AgentAttache { return _requests.size(); } - public int getListenersSize() { - return _waitForList.size(); + public int getNonRecurringListenersSize() { + List nonRecurringListenersList = new ArrayList(); + if (_waitForList.isEmpty()) { + return 0; + } else { + final Set> entries = _waitForList.entrySet(); + final Iterator> it = entries.iterator(); + while (it.hasNext()) { + final Map.Entry entry = it.next(); + final Listener monitor = entry.getValue(); + if (!monitor.isRecurring()) { + //TODO - remove this debug statement later + s_logger.debug("Listener is " + entry.getValue() + " waiting on " + entry.getKey()); + nonRecurringListenersList.add(monitor); + } + } + } + + return nonRecurringListenersList.size(); } public boolean processAnswers(final long seq, final Response resp) { diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 81f0a620c40..e7e68a86b5b 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -82,6 +82,7 @@ import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.cluster.ManagementServerNode; import com.cloud.cluster.StackMaid; +import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; @@ -274,6 +275,9 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { _pingTimeout = (long) (multiplier * _pingInterval); s_logger.info("Ping Timeout is " + _pingTimeout); + + value = configs.get(Config.DirectAgentLoadSize.key()); + int threads = NumbersUtil.parseInt(value, 16); _instance = configs.get("instance.name"); if (_instance == null) { @@ -287,7 +291,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { _monitor = new AgentMonitor(_nodeId, _hostDao, _vmDao, _dcDao, _podDao, this, _alertMgr, _pingTimeout); registerForHostEvents(_monitor, true, true, false); - _executor = new ThreadPoolExecutor(16, 100, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("AgentTaskPool")); + _executor = new ThreadPoolExecutor(threads, threads, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("AgentTaskPool")); _connection = new NioServer("AgentManager", _port, workers + 10, this); @@ -489,9 +493,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { @Override public HostVO getSSAgent(HostVO ssHost) { if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) { - if( ssHost.getStatus() == Status.Up ) { - return ssHost; - } + return ssHost; } else if ( ssHost.getType() == Host.Type.SecondaryStorage) { Long dcId = ssHost.getDataCenterId(); List ssAHosts = _hostDao.listBy(Host.Type.SecondaryStorageVM, dcId); @@ -2155,7 +2157,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { Response response = null; if (attache == null) { - s_logger.debug("Processing sequence " + request.getSequence() + ": Processing " + request.toString()); + request.logD("Processing the first command "); if (!(cmd instanceof StartupCommand)) { s_logger.warn("Throwing away a request because it came through as the first command on a connect: " + request.toString()); return; diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 070a697be55..d916200e387 100644 --- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -129,7 +129,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust // schedule transfer scan executor - if agent LB is enabled if (_clusterMgr.isAgentRebalanceEnabled()) { - s_transferExecutor.scheduleAtFixedRate(getTransferScanTask(), ClusteredAgentRebalanceService.DEFAULT_TRANSFER_CHECK_INTERVAL, ClusteredAgentRebalanceService.DEFAULT_TRANSFER_CHECK_INTERVAL, + s_transferExecutor.scheduleAtFixedRate(getTransferScanTask(), 60000, ClusteredAgentRebalanceService.DEFAULT_TRANSFER_CHECK_INTERVAL, TimeUnit.MILLISECONDS); } @@ -524,7 +524,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } } if (agent == null) { - throw new AgentUnavailableException("Host is not in the right state", hostId); + throw new AgentUnavailableException("Host is not in the right state: " + host.getStatus() , hostId); } return agent; @@ -698,23 +698,26 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust @Override public void startRebalanceAgents() { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Management server " + _nodeId + " was asked to do agent rebalancing; checking how many hosts can be taken from this server"); - } - List allMS = _mshostDao.listBy(ManagementServerHost.State.Up, ManagementServerHost.State.Starting); - List allManagedAgents = _hostDao.listManagedAgents(); + List allManagedAgents = _hostDao.listManagedRoutingAgents(); - long avLoad = 0L; + int avLoad = 0; if (!allManagedAgents.isEmpty() && !allMS.isEmpty()) { avLoad = allManagedAgents.size() / allMS.size(); } else { if (s_logger.isDebugEnabled()) { - s_logger.debug("Management server " + _nodeId + " found no hosts to rebalance. Current number of active management server nodes in the system is " + allMS.size() + "; number of managed agents is " + allMS.size()); + s_logger.debug("There are no hosts to rebalance in the system. Current number of active management server nodes in the system is " + allMS.size() + "; number of managed agents is " + allManagedAgents.size()); } return; } + + if (avLoad == 0L) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("As calculated average load is less than 1, rounding it to 1"); + } + avLoad = 1; + } for (ManagementServerHostVO node : allMS) { if (node.getMsid() != _nodeId) { @@ -722,21 +725,21 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust List hostsToRebalance = new ArrayList(); for (AgentLoadBalancerPlanner lbPlanner : _lbPlanners) { hostsToRebalance = lbPlanner.getHostsToRebalance(node.getMsid(), avLoad); - if (!hostsToRebalance.isEmpty()) { + if (hostsToRebalance != null && !hostsToRebalance.isEmpty()) { break; } else { - s_logger.debug("Agent load balancer planner " + lbPlanner.getName() + " found no hosts to be rebalanced from management server " + _nodeId); + s_logger.debug("Agent load balancer planner " + lbPlanner.getName() + " found no hosts to be rebalanced from management server " + node.getMsid()); } } - if (!hostsToRebalance.isEmpty()) { + if (hostsToRebalance != null && !hostsToRebalance.isEmpty()) { for (HostVO host : hostsToRebalance) { long hostId = host.getId(); s_logger.debug("Asking management server " + node.getMsid() + " to give away host id=" + hostId); boolean result = true; - HostTransferMapVO transfer = _hostTransferDao.startAgentTransfering(hostId, _nodeId, node.getMsid()); + HostTransferMapVO transfer = _hostTransferDao.startAgentTransfering(hostId, node.getMsid(), _nodeId); try { - Answer[] answer = sendRebalanceCommand(hostId, _nodeId, Event.RequestAgentRebalance); + Answer[] answer = sendRebalanceCommand(hostId, node.getMsid(), Event.RequestAgentRebalance); if (answer == null) { s_logger.warn("Failed to get host id=" + hostId + " from management server " + node.getMsid()); result = false; @@ -756,7 +759,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } } } else { - s_logger.debug("Management server " + _nodeId + " found no hosts to rebalance."); + s_logger.debug("Found no hosts to rebalance from the management server " + node.getMsid()); } } } @@ -797,10 +800,11 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust s_logger.debug("Found " + _agentToTransferIds.size() + " agents to transfer"); for (Long hostId : _agentToTransferIds) { AgentAttache attache = findAttache(hostId); - if (attache.getQueueSize() == 0 && attache.getListenersSize() == 0) { - boolean result = true; + if (attache.getQueueSize() == 0 && attache.getNonRecurringListenersSize() == 0) { + boolean result = false; _agentToTransferIds.remove(hostId); try { + _hostTransferDao.startAgentTransfer(hostId); result = rebalanceHost(hostId); } finally { if (result) { @@ -810,16 +814,16 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } } } else { - // if we timed out waiting for the host to reconnect, remove host from rebalance list and mark it as failed to rebalance + // if we timed out waiting for the host to reconnect, remove host from rebalance list and delete from op_host_transfer DB // no need to do anything with the real attache Date cutTime = DateUtil.currentGMTTime(); - if (!(_hostTransferDao.isActive(hostId, new Date(cutTime.getTime() - rebalanceTimeOut)))) { + if (_hostTransferDao.isNotActive(hostId, new Date(cutTime.getTime() - rebalanceTimeOut))) { s_logger.debug("Timed out waiting for the host id=" + hostId + " to be ready to transfer, failing rebalance for this host"); _agentToTransferIds.remove(hostId); - HostTransferMapVO transferMap = _hostTransferDao.findById(hostId); - transferMap.setState(HostTransferState.TransferFailed); - _hostTransferDao.update(hostId, transferMap); - } + _hostTransferDao.completeAgentTransfer(hostId); + } else { + s_logger.debug("Agent " + hostId + " can't be transfered yet as its request queue size is " + attache.getQueueSize() + " and listener queue size is " + attache.getNonRecurringListenersSize()); + } } } } else { @@ -859,7 +863,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust _agents.put(hostId, attache); if (host != null && host.getRemoved() == null) { host.setManagementServerId(null); - s_logger.debug("Updating host id=" + hostId + " with the status " + Status.Rebalance); + s_logger.debug("Updating host id=" + hostId + " with the status " + Status.Rebalancing); _hostDao.updateStatus(host, Event.StartAgentRebalance, _nodeId); } @@ -877,7 +881,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust s_logger.debug("Got host id=" + hostId + " from management server " + map.getFutureOwner()); } - } + } else { + s_logger.warn("Unable to find agent " + hostId + " on management server " + _nodeId); + result = false; + } } else if (map.getFutureOwner() == _nodeId) { try { if (s_logger.isDebugEnabled()) { @@ -887,61 +894,57 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust loadDirectlyConnectedHost(host); } catch (Exception ex) { s_logger.warn("Unable to load directly connected host " + host.getId() + " as a part of rebalance due to exception: ", ex); + result = false; } } return result; - } private boolean finishRebalance(final long hostId, Event event) { HostTransferMapVO map = _hostTransferDao.findById(hostId); - AgentAttache attache = findAttache(hostId); - - if (attache == null) { - s_logger.debug("Unable to find attache for the host id=" + hostId + ", assuming that the agent disconnected already"); - HostTransferState state = (event == Event.RebalanceCompleted) ? HostTransferState.TransferCompleted : HostTransferState.TransferFailed; - map.setState(state); - _hostTransferDao.update(hostId, map); - return true; - } if (map.getInitialOwner() != _nodeId) { s_logger.warn("Why finish rebalance called not by initial host owner???"); return false; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Finishing rebalancing for the host id=" + hostId); + } + + boolean success = (event == Event.RebalanceCompleted) ? true : false; + if (s_logger.isDebugEnabled()) { + s_logger.debug("Finishing rebalancing for the agent " + hostId + " with result " + success); } - if (event == Event.RebalanceFailed) { - ((ClusteredDirectAgentAttache) attache).setTransferMode(false); - s_logger.debug("Rebalance failed for the host id=" + hostId); - map.setState(HostTransferState.TransferFailed); - _hostTransferDao.update(hostId, map); - } else if (event == Event.RebalanceCompleted) { - - //1) Get all the requests remove transfer attache + AgentAttache attache = findAttache(hostId); + if (attache == null) { + s_logger.debug("Unable to find attache for the host id=" + hostId + ", assuming that the agent disconnected already"); + return true; + } else if (success) { + s_logger.debug("Management server " + _nodeId + " is completing agent " + hostId + " rebalance"); + //1) Get all the requests before removing transfer attache LinkedList requests = ((ClusteredDirectAgentAttache) attache).getRequests(); - removeAgent(attache, Status.Rebalance); + removeAgent(attache, Status.Rebalancing); //2) Create forward attache - createAttache(hostId); - - //3) forward all the requests to the management server which owns the host now - if (!requests.isEmpty()) { - for (Request request : requests) { - routeToPeer(Long.toString(map.getFutureOwner()), request.getBytes()); + try { + getAttache(hostId); + //3) forward all the requests to the management server which owns the host now + if (!requests.isEmpty()) { + s_logger.debug("Forwarding requests held in transfer attache " + hostId + " from the management server " + _nodeId + " to " + map.getFutureOwner()); + for (Request request : requests) { + routeToPeer(Long.toString(map.getFutureOwner()), request.getBytes()); + } } + } catch (AgentUnavailableException ex) { + s_logger.warn("Not creating forward attache as agent is not available", ex); + //TODO - - have to handle the case when requests can't be forwarded due to lack of forward attache } - map.setState(HostTransferState.TransferCompleted); - _hostTransferDao.update(hostId, map); - - return true; - + } else { + ((ClusteredDirectAgentAttache) attache).setTransferMode(false); + //TODO - have to handle the case when agent fails to rebalance 1) Either connect it back 2) Or disconnect it } + + _hostTransferDao.completeAgentTransfer(hostId); return true; } } diff --git a/server/src/com/cloud/alert/ConsoleProxyAlertAdapter.java b/server/src/com/cloud/alert/ConsoleProxyAlertAdapter.java index c4e2556e15b..3e6a51438b1 100644 --- a/server/src/com/cloud/alert/ConsoleProxyAlertAdapter.java +++ b/server/src/com/cloud/alert/ConsoleProxyAlertAdapter.java @@ -73,7 +73,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy up in zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()), "Console proxy up (zone " + dc.getName() + ")" @@ -89,7 +89,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy down in zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()), "Console proxy down (zone " + dc.getName() + ")" @@ -105,7 +105,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy rebooted in zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()), "Console proxy rebooted (zone " + dc.getName() + ")" @@ -121,7 +121,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy creation failure. zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()) + ", error details: " + args.getMessage(), @@ -138,7 +138,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy startup failure. zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()) + ", error details: " + args.getMessage(), @@ -155,7 +155,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_CONSOLE_PROXY, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Failed to open console proxy firewall port. zone: " + dc.getName() + ", proxy: " + proxy.getHostName() + ", public IP: " + proxy.getPublicIpAddress() + ", private IP: " + (proxy.getPrivateIpAddress() == null ? "N/A" : proxy.getPrivateIpAddress()), @@ -172,7 +172,7 @@ public class ConsoleProxyAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_STORAGE_MISC, args.getZoneId(), - proxy.getPodId(), + proxy.getPodIdToDeployIn(), "Console proxy storage issue. zone: " + dc.getName() + ", message: " + args.getMessage(), "Console proxy alert (zone " + dc.getName() + ")" ); diff --git a/server/src/com/cloud/alert/SecondaryStorageVmAlertAdapter.java b/server/src/com/cloud/alert/SecondaryStorageVmAlertAdapter.java index 38850bad6f7..1907a68022e 100644 --- a/server/src/com/cloud/alert/SecondaryStorageVmAlertAdapter.java +++ b/server/src/com/cloud/alert/SecondaryStorageVmAlertAdapter.java @@ -73,7 +73,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm up in zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()), "Secondary Storage Vm up (zone " + dc.getName() + ")" @@ -89,7 +89,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm down in zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()), "Secondary Storage Vm down (zone " + dc.getName() + ")" @@ -105,7 +105,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm rebooted in zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()), "Secondary Storage Vm rebooted (zone " + dc.getName() + ")" @@ -121,7 +121,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm creation failure. zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()) + ", error details: " + args.getMessage(), @@ -138,7 +138,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm startup failure. zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()) + ", error details: " + args.getMessage(), @@ -155,7 +155,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_SSVM, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Failed to open secondary storage vm firewall port. zone: " + dc.getName() + ", secStorageVm: " + secStorageVm.getHostName() + ", public IP: " + secStorageVm.getPublicIpAddress() + ", private IP: " + (secStorageVm.getPrivateIpAddress() == null ? "N/A" : secStorageVm.getPrivateIpAddress()), @@ -172,7 +172,7 @@ public class SecondaryStorageVmAlertAdapter implements AlertAdapter { _alertMgr.sendAlert( AlertManager.ALERT_TYPE_STORAGE_MISC, args.getZoneId(), - secStorageVm.getPodId(), + secStorageVm.getPodIdToDeployIn(), "Secondary Storage Vm storage issue. zone: " + dc.getName() + ", message: " + args.getMessage(), "Secondary Storage Vm alert (zone " + dc.getName() + ")" ); diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 73bd4e2cc82..bded506edee 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -478,18 +478,13 @@ public class ApiDBUtils { return _volumeDao.getHypervisorType(volumeId); } - public static List listTemplateHostBy(long templateId, Long zoneId) { + public static List listTemplateHostBy(long templateId, Long zoneId, boolean readyOnly) { if (zoneId != null) { VMTemplateVO vmTemplate = findTemplateById(templateId); if (vmTemplate.getHypervisorType() == HypervisorType.BareMetal) { return _templateHostDao.listByTemplateId(templateId); } else { - HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId); - if (secondaryStorageHost == null) { - return new ArrayList(); - } else { - return _templateHostDao.listByHostTemplate(secondaryStorageHost.getId(), templateId); - } + return _templateHostDao.listByZoneTemplate(zoneId, templateId, readyOnly); } } else { return _templateHostDao.listByOnlyTemplateId(templateId); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index cc4dd5b0dba..e6514c0de67 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -17,6 +17,7 @@ */ package com.cloud.api; +import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; @@ -219,7 +220,7 @@ public class ApiResponseHelper implements ResponseGenerator { boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN); AccountResponse accountResponse = new AccountResponse(); accountResponse.setId(account.getId()); - accountResponse.setName(account.getAccountName()); + accountResponse.setName(encodeParam(account.getAccountName())); accountResponse.setAccountType(account.getType()); accountResponse.setDomainId(account.getDomainId()); accountResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName()); @@ -316,20 +317,20 @@ public class ApiResponseHelper implements ResponseGenerator { List userResponseList = new ArrayList(); for (UserVO user : usersForAccount) { UserResponse userResponse = new UserResponse(); - userResponse.setAccountName(account.getAccountName()); + userResponse.setAccountName(encodeParam(account.getAccountName())); userResponse.setAccountType(account.getType()); userResponse.setApiKey(user.getApiKey()); userResponse.setCreated(user.getCreated()); userResponse.setDomainId(account.getDomainId()); userResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName()); - userResponse.setEmail(user.getEmail()); + userResponse.setEmail(encodeParam(user.getEmail())); userResponse.setFirstname(user.getFirstname()); userResponse.setId(user.getId()); userResponse.setSecretKey(user.getSecretKey()); userResponse.setLastname(user.getLastname()); userResponse.setState(user.getState().toString()); userResponse.setTimezone(user.getTimezone()); - userResponse.setUsername(user.getUsername()); + userResponse.setUsername(encodeParam(user.getUsername())); userResponseList.add(userResponse); } @@ -1058,9 +1059,9 @@ public class ApiResponseHelper implements ResponseGenerator { } // Data Center Info - DataCenter zone = dataCenters.get(userVm.getDataCenterId()); + DataCenter zone = dataCenters.get(userVm.getDataCenterIdToDeployIn()); if (zone == null) { - zone = ApiDBUtils.findZoneById(userVm.getDataCenterId()); + zone = ApiDBUtils.findZoneById(userVm.getDataCenterIdToDeployIn()); dataCenters.put(zone.getId(), zone); } @@ -1223,11 +1224,13 @@ public class ApiResponseHelper implements ResponseGenerator { @Override public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) { + Map serviceOfferings = new HashMap(); + DomainRouterResponse routerResponse = new DomainRouterResponse(); routerResponse.setId(router.getId()); - routerResponse.setZoneId(router.getDataCenterId()); + routerResponse.setZoneId(router.getDataCenterIdToDeployIn()); routerResponse.setName(router.getHostName()); - routerResponse.setPodId(router.getPodId()); + routerResponse.setPodId(router.getPodIdToDeployIn()); routerResponse.setTemplateId(router.getTemplateId()); routerResponse.setCreated(router.getCreated()); routerResponse.setState(router.getState()); @@ -1236,7 +1239,17 @@ public class ApiResponseHelper implements ResponseGenerator { routerResponse.setHostId(router.getHostId()); routerResponse.setHostName(ApiDBUtils.findHostById(router.getHostId()).getName()); } + + // Service Offering Info + ServiceOffering offering = serviceOfferings.get(router.getServiceOfferingId()); + if (offering == null) { + offering = ApiDBUtils.findServiceOfferingById(router.getServiceOfferingId()); + serviceOfferings.put(offering.getId(), offering); + } + routerResponse.setServiceOfferingId(offering.getId()); + routerResponse.setServiceOfferingName(offering.getName()); + Account accountTemp = ApiDBUtils.findAccountById(router.getAccountId()); if (accountTemp != null) { routerResponse.setAccountName(accountTemp.getAccountName()); @@ -1268,7 +1281,7 @@ public class ApiResponseHelper implements ResponseGenerator { } } } - DataCenter zone = ApiDBUtils.findZoneById(router.getDataCenterId()); + DataCenter zone = ApiDBUtils.findZoneById(router.getDataCenterIdToDeployIn()); if (zone != null) { routerResponse.setZoneName(zone.getName()); routerResponse.setDns1(zone.getDns1()); @@ -1287,10 +1300,10 @@ public class ApiResponseHelper implements ResponseGenerator { vmResponse.setId(vm.getId()); vmResponse.setSystemVmType(vm.getType().toString().toLowerCase()); - vmResponse.setZoneId(vm.getDataCenterId()); + vmResponse.setZoneId(vm.getDataCenterIdToDeployIn()); vmResponse.setName(vm.getHostName()); - vmResponse.setPodId(vm.getPodId()); + vmResponse.setPodId(vm.getPodIdToDeployIn()); vmResponse.setTemplateId(vm.getTemplateId()); vmResponse.setCreated(vm.getCreated()); @@ -1309,7 +1322,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmResponse.setActiveViewerSessions(proxy.getActiveSession()); } - DataCenter zone = ApiDBUtils.findZoneById(vm.getDataCenterId()); + DataCenter zone = ApiDBUtils.findZoneById(vm.getDataCenterIdToDeployIn()); if (zone != null) { vmResponse.setZoneName(zone.getName()); vmResponse.setDns1(zone.getDns1()); @@ -1328,6 +1341,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmResponse.setPublicIp(singleNicProfile.getIp4Address()); vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress()); vmResponse.setPublicNetmask(singleNicProfile.getNetmask()); + vmResponse.setGateway(singleNicProfile.getGateway()); } else if (network.getTrafficType() == TrafficType.Management) { vmResponse.setPrivateIp(singleNicProfile.getIp4Address()); vmResponse.setPrivateMacAddress(singleNicProfile.getMacAddress()); @@ -1437,12 +1451,21 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public void createTemplateResponse(List responses, Pair templateZonePair, boolean isAdmin, Account account) { - List templateHostRefsForTemplate = ApiDBUtils.listTemplateHostBy(templateZonePair.first(), templateZonePair.second()); + public void createTemplateResponse(List responses, Pair templateZonePair, boolean isAdmin, Account account, boolean readyOnly) { + List templateHostRefsForTemplate = ApiDBUtils.listTemplateHostBy(templateZonePair.first(), templateZonePair.second(), readyOnly); VMTemplateVO template = ApiDBUtils.findTemplateById(templateZonePair.first()); for (VMTemplateHostVO templateHostRef : templateHostRefsForTemplate) { - + if (readyOnly) { + if (templateHostRef.getDownloadState() != Status.DOWNLOADED) { + continue; + } + for (TemplateResponse res : responses) { + if (res.getId() == templateHostRef.getTemplateId()) { + continue; + } + } + } TemplateResponse templateResponse = new TemplateResponse(); templateResponse.setId(template.getId()); templateResponse.setName(template.getName()); @@ -1479,8 +1502,11 @@ public class ApiResponseHelper implements ResponseGenerator { } HostVO host = ApiDBUtils.findHostById(templateHostRef.getHostId()); + templateResponse.setHostId(host.getId()); + templateResponse.setHostName(host.getName()); + DataCenterVO datacenter = ApiDBUtils.findZoneById(host.getDataCenterId()); - + // Add the zone ID templateResponse.setZoneId(host.getDataCenterId()); templateResponse.setZoneName(datacenter.getName()); @@ -1974,7 +2000,7 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public ListResponse createIsoResponse(Set> isoZonePairSet, boolean isAdmin, Account account, Boolean isBootable) { + public ListResponse createIsoResponse(Set> isoZonePairSet, boolean isAdmin, Account account, Boolean isBootable, boolean readyOnly) { ListResponse response = new ListResponse(); List isoResponses = new ArrayList(); @@ -2010,7 +2036,7 @@ public class ApiResponseHelper implements ResponseGenerator { } } - List isoHosts = ApiDBUtils.listTemplateHostBy(iso.getId(), isoZonePair.second()); + List isoHosts = ApiDBUtils.listTemplateHostBy(iso.getId(), isoZonePair.second(), readyOnly); for (VMTemplateHostVO isoHost : isoHosts) { TemplateResponse isoResponse = new TemplateResponse(); isoResponse.setId(iso.getId()); @@ -2501,4 +2527,13 @@ public class ApiResponseHelper implements ResponseGenerator { return sg.getId(); } } + + private String encodeParam(String value) { + try { + return URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20"); + } catch (Exception e) { + s_logger.warn("Unable to encode: " + value); + } + return value; + } } diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java index e040e4dba79..ba0018ea704 100644 --- a/server/src/com/cloud/async/AsyncJobManagerImpl.java +++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java @@ -136,7 +136,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe s_logger.debug("submit async job-" + job.getId() + ", details: " + job.toString()); } return job.getId(); - } catch(Exception e) { + } catch(Exception e) { txt.rollback(); String errMsg = "Unable to schedule async job for command " + job.getCmd() + ", unexpected exception."; s_logger.warn(errMsg, e); @@ -146,18 +146,20 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe @Override @DB public void completeAsyncJob(long jobId, int jobStatus, int resultCode, Object resultObject) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Complete async job-" + jobId + ", jobStatus: " + jobStatus + - ", resultCode: " + resultCode + ", result: " + resultObject); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Complete async job-" + jobId + ", jobStatus: " + jobStatus + + ", resultCode: " + resultCode + ", result: " + resultObject); + } Transaction txt = Transaction.currentTxn(); try { txt.start(); AsyncJobVO job = _jobDao.findById(jobId); if(job == null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("job-" + jobId + " no longer exists, we just log completion info here. " + jobStatus + - ", resultCode: " + resultCode + ", result: " + resultObject); + if(s_logger.isDebugEnabled()) { + s_logger.debug("job-" + jobId + " no longer exists, we just log completion info here. " + jobStatus + + ", resultCode: " + resultCode + ", result: " + resultObject); + } txt.rollback(); return; @@ -186,25 +188,28 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe @Override @DB public void updateAsyncJobStatus(long jobId, int processStatus, Object resultObject) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Update async-job progress, job-" + jobId + ", processStatus: " + processStatus + - ", result: " + resultObject); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Update async-job progress, job-" + jobId + ", processStatus: " + processStatus + + ", result: " + resultObject); + } Transaction txt = Transaction.currentTxn(); try { txt.start(); AsyncJobVO job = _jobDao.findById(jobId); if(job == null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("job-" + jobId + " no longer exists, we just log progress info here. progress status: " + processStatus); + if(s_logger.isDebugEnabled()) { + s_logger.debug("job-" + jobId + " no longer exists, we just log progress info here. progress status: " + processStatus); + } txt.rollback(); return; } job.setProcessStatus(processStatus); - if(resultObject != null) - job.setResult(ApiSerializerHelper.toSerializedStringOld(resultObject)); + if(resultObject != null) { + job.setResult(ApiSerializerHelper.toSerializedStringOld(resultObject)); + } job.setLastUpdated(DateUtil.currentGMTTime()); _jobDao.update(jobId, job); txt.commit(); @@ -216,9 +221,10 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe @Override @DB public void updateAsyncJobAttachment(long jobId, String instanceType, Long instanceId) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Update async-job attachment, job-" + jobId + ", instanceType: " + instanceType + - ", instanceId: " + instanceId); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Update async-job attachment, job-" + jobId + ", instanceType: " + instanceType + + ", instanceId: " + instanceId); + } Transaction txt = Transaction.currentTxn(); try { @@ -248,19 +254,21 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe return; } - if(s_logger.isDebugEnabled()) + if(s_logger.isDebugEnabled()) { s_logger.debug("Sync job-" + job.getId() + " execution on object " + syncObjType + "." + syncObjId); + } SyncQueueVO queue = null; // to deal with temporary DB exceptions like DB deadlock/Lock-wait time out cased rollbacks // we retry five times until we throw an exception - Random random = new Random(); + Random random = new Random(); for(int i = 0; i < 5; i++) { queue = _queueMgr.queue(syncObjType, syncObjId, "AsyncJob", job.getId()); - if(queue != null) - break; + if(queue != null) { + break; + } try { Thread.sleep(1000 + random.nextInt(5000)); @@ -302,8 +310,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe @Override @DB public AsyncJobResult queryAsyncJobResult(long jobId) { - if(s_logger.isTraceEnabled()) - s_logger.trace("Query async-job status, job-" + jobId); + if(s_logger.isTraceEnabled()) { + s_logger.trace("Query async-job status, job-" + jobId); + } Transaction txt = Transaction.currentTxn(); AsyncJobResult jobResult = new AsyncJobResult(jobId); @@ -321,15 +330,17 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe if(job.getStatus() == AsyncJobResult.STATUS_SUCCEEDED || job.getStatus() == AsyncJobResult.STATUS_FAILED) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Async job-" + jobId + " completed"); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Async job-" + jobId + " completed"); + } } else { job.setLastPolled(DateUtil.currentGMTTime()); _jobDao.update(jobId, job); } } else { - if(s_logger.isDebugEnabled()) - s_logger.debug("Async job-" + jobId + " does not exist, invalid job id?"); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Async job-" + jobId + " does not exist, invalid job id?"); + } jobResult.setJobStatus(AsyncJobResult.STATUS_FAILED); jobResult.setResult("job-" + jobId + " does not exist"); @@ -343,8 +354,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe txt.rollback(); } - if(s_logger.isTraceEnabled()) - s_logger.trace("Job status: " + jobResult.toString()); + if(s_logger.isTraceEnabled()) { + s_logger.trace("Job status: " + jobResult.toString()); + } return jobResult; } @@ -366,114 +378,122 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe return new Runnable() { @Override public void run() { - long jobId = 0; - try { - JmxUtil.registerMBean("AsyncJobManager", "Active Job " + job.getId(), new AsyncJobMBeanImpl(job)); - } catch(Exception e) { - s_logger.warn("Unable to register active job " + job.getId() + " to JMX minotoring due to exception " + ExceptionUtil.toString(e)); - } - - BaseAsyncCmd cmdObj = null; - Transaction txn = Transaction.open(Transaction.CLOUD_DB); - try { - jobId = job.getId(); - NDC.push("job-" + jobId); - - if(s_logger.isDebugEnabled()) { - s_logger.debug("Executing " + job.getCmd() + " for job-" + jobId); - } - - Class cmdClass = Class.forName(job.getCmd()); - cmdObj = (BaseAsyncCmd)cmdClass.newInstance(); - cmdObj.setJob(job); - - Type mapType = new TypeToken>() {}.getType(); - Gson gson = ApiGsonHelper.getBuilder().create(); - Map params = gson.fromJson(job.getCmdInfo(), mapType); - - // whenever we deserialize, the UserContext needs to be updated - String userIdStr = params.get("ctxUserId"); - String acctIdStr = params.get("ctxAccountId"); - Long userId = null; - Account accountObject = null; - - if (userIdStr != null) { - userId = Long.parseLong(userIdStr); - } - - if (acctIdStr != null) { - accountObject = _accountDao.findById(Long.parseLong(acctIdStr)); - } - - UserContext.registerContext(userId, accountObject, null, false); - try { - // dispatch could ultimately queue the job - _dispatcher.dispatch(cmdObj, params); - - // serialize this to the async job table - completeAsyncJob(jobId, AsyncJobResult.STATUS_SUCCEEDED, 0, cmdObj.getResponseObject()); - } finally { - UserContext.unregisterContext(); - } - - // commands might need to be queued as part of synchronization here, so they just have to be re-dispatched from the queue mechanism... - if (job.getSyncSource() != null) { - _queueMgr.purgeItem(job.getSyncSource().getId()); - checkQueue(job.getSyncSource().getQueueId()); - } - - if (s_logger.isDebugEnabled()) - s_logger.debug("Done executing " + job.getCmd() + " for job-" + jobId); + long jobId = 0; - } catch(Throwable e) { - if (e instanceof AsyncCommandQueued) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("job " + job.getCmd() + " for job-" + jobId + " was queued, processing the queue."); - } - checkQueue(((AsyncCommandQueued)e).getQueue().getId()); - } else { - String errorMsg = null; - int errorCode = BaseCmd.INTERNAL_ERROR; - if (!(e instanceof ServerApiException)) { - s_logger.error("Unexpected exception while executing " + job.getCmd(), e); - errorMsg = e.getMessage(); - } else { - ServerApiException sApiEx = (ServerApiException)e; - errorMsg = sApiEx.getDescription(); - errorCode = sApiEx.getErrorCode(); - } - - ExceptionResponse response = new ExceptionResponse(); - response.setErrorCode(errorCode); - response.setErrorText(errorMsg); - response.setResponseName((cmdObj == null) ? "unknowncommandresponse" : cmdObj.getCommandName()); - - // FIXME: setting resultCode to BaseCmd.INTERNAL_ERROR is not right, usually executors have their exception handling - // and we need to preserve that as much as possible here - completeAsyncJob(jobId, AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, response); - - // need to clean up any queue that happened as part of the dispatching and move on to the next item in the queue - try { - if (job.getSyncSource() != null) { - _queueMgr.purgeItem(job.getSyncSource().getId()); - checkQueue(job.getSyncSource().getQueueId()); - } - } catch(Throwable ex) { - s_logger.fatal("Exception on exception, log it for record", ex); - } - } - } finally { - try { - JmxUtil.unregisterMBean("AsyncJobManager", "Active Job " + job.getId()); + JmxUtil.registerMBean("AsyncJobManager", "Active Job " + job.getId(), new AsyncJobMBeanImpl(job)); } catch(Exception e) { - s_logger.warn("Unable to unregister active job " + job.getId() + " from JMX minotoring"); + s_logger.warn("Unable to register active job " + job.getId() + " to JMX minotoring due to exception " + ExceptionUtil.toString(e)); + } + + BaseAsyncCmd cmdObj = null; + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + jobId = job.getId(); + NDC.push("job-" + jobId); + + if(s_logger.isDebugEnabled()) { + s_logger.debug("Executing " + job.getCmd() + " for job-" + jobId); + } + + Class cmdClass = Class.forName(job.getCmd()); + cmdObj = (BaseAsyncCmd)cmdClass.newInstance(); + cmdObj.setJob(job); + + Type mapType = new TypeToken>() {}.getType(); + Gson gson = ApiGsonHelper.getBuilder().create(); + Map params = gson.fromJson(job.getCmdInfo(), mapType); + + // whenever we deserialize, the UserContext needs to be updated + String userIdStr = params.get("ctxUserId"); + String acctIdStr = params.get("ctxAccountId"); + Long userId = null; + Account accountObject = null; + + if (userIdStr != null) { + userId = Long.parseLong(userIdStr); + } + + if (acctIdStr != null) { + accountObject = _accountDao.findById(Long.parseLong(acctIdStr)); + } + + UserContext.registerContext(userId, accountObject, null, false); + try { + // dispatch could ultimately queue the job + _dispatcher.dispatch(cmdObj, params); + + // serialize this to the async job table + completeAsyncJob(jobId, AsyncJobResult.STATUS_SUCCEEDED, 0, cmdObj.getResponseObject()); + } finally { + UserContext.unregisterContext(); + } + + // commands might need to be queued as part of synchronization here, so they just have to be re-dispatched from the queue mechanism... + if (job.getSyncSource() != null) { + _queueMgr.purgeItem(job.getSyncSource().getId()); + checkQueue(job.getSyncSource().getQueueId()); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Done executing " + job.getCmd() + " for job-" + jobId); + } + + } catch(Throwable e) { + if (e instanceof AsyncCommandQueued) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("job " + job.getCmd() + " for job-" + jobId + " was queued, processing the queue."); + } + checkQueue(((AsyncCommandQueued)e).getQueue().getId()); + } else { + String errorMsg = null; + int errorCode = BaseCmd.INTERNAL_ERROR; + if (!(e instanceof ServerApiException)) { + s_logger.error("Unexpected exception while executing " + job.getCmd(), e); + errorMsg = e.getMessage(); + } else { + ServerApiException sApiEx = (ServerApiException)e; + errorMsg = sApiEx.getDescription(); + errorCode = sApiEx.getErrorCode(); + } + + ExceptionResponse response = new ExceptionResponse(); + response.setErrorCode(errorCode); + response.setErrorText(errorMsg); + response.setResponseName((cmdObj == null) ? "unknowncommandresponse" : cmdObj.getCommandName()); + + // FIXME: setting resultCode to BaseCmd.INTERNAL_ERROR is not right, usually executors have their exception handling + // and we need to preserve that as much as possible here + completeAsyncJob(jobId, AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, response); + + // need to clean up any queue that happened as part of the dispatching and move on to the next item in the queue + try { + if (job.getSyncSource() != null) { + _queueMgr.purgeItem(job.getSyncSource().getId()); + checkQueue(job.getSyncSource().getQueueId()); + } + } catch(Throwable ex) { + s_logger.fatal("Exception on exception, log it for record", ex); + } + } + } finally { + + try { + JmxUtil.unregisterMBean("AsyncJobManager", "Active Job " + job.getId()); + } catch(Exception e) { + s_logger.warn("Unable to unregister active job " + job.getId() + " from JMX minotoring"); + } + + StackMaid.current().exitCleanup(); + txn.close(); + NDC.pop(); + } + } catch (Throwable th) { + try { + s_logger.error("Caught: " + th); + } catch (Throwable th2) { } - - StackMaid.current().exitCleanup(); - txn.close(); - NDC.pop(); } } }; @@ -493,8 +513,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe _jobDao.update(job.getId(), job); scheduleExecution(job); } else { - if(s_logger.isDebugEnabled()) + if(s_logger.isDebugEnabled()) { s_logger.debug("Unable to find related job for queue item: " + item.toString()); + } _queueMgr.purgeItem(item.getId()); } @@ -503,10 +524,11 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe @Override public void releaseSyncSource(AsyncJobExecutor executor) { if(executor.getSyncSource() != null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Release sync source for job-" + executor.getJob().getId() + " sync source: " + if(s_logger.isDebugEnabled()) { + s_logger.debug("Release sync source for job-" + executor.getJob().getId() + " sync source: " + executor.getSyncSource().getContentType() + "-" - + executor.getSyncSource().getContentId()); + + executor.getSyncSource().getContentId()); + } _queueMgr.purgeItem(executor.getSyncSource().getId()); checkQueue(executor.getSyncSource().getQueueId()); @@ -518,8 +540,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe try { SyncQueueItemVO item = _queueMgr.dequeueFromOne(queueId, getMsid()); if(item != null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Executing sync queue item: " + item.toString()); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Executing sync queue item: " + item.toString()); + } executeQueueItem(item, false); } else { @@ -540,8 +563,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe List l = _queueMgr.dequeueFromAny(getMsid(), MAX_ONETIME_SCHEDULE_SIZE); if(l != null && l.size() > 0) { for(SyncQueueItemVO item: l) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Execute sync-queue item: " + item.toString()); + if(s_logger.isDebugEnabled()) { + s_logger.debug("Execute sync-queue item: " + item.toString()); + } executeQueueItem(item, false); } } @@ -592,8 +616,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe List blockItems = _queueMgr.getBlockedQueueItems(_jobCancelThresholdSeconds*1000, false); if(blockItems != null && blockItems.size() > 0) { for(SyncQueueItemVO item : blockItems) { - if(item.getContentType().equalsIgnoreCase("AsyncJob")) - completeAsyncJob(item.getContentId(), 2, 0, getResetResultMessage("Job is cancelled as it has been blocking others for too long")); + if(item.getContentType().equalsIgnoreCase("AsyncJob")) { + completeAsyncJob(item.getContentId(), 2, 0, getResetResultMessage("Job is cancelled as it has been blocking others for too long")); + } // purge the item and resume queue processing _queueMgr.purgeItem(item.getId()); @@ -611,8 +636,9 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe } private long getMsid() { - if(_clusterMgr != null) - return _clusterMgr.getManagementNodeId(); + if(_clusterMgr != null) { + return _clusterMgr.getManagementNodeId(); + } return MacAddress.getMacAddress().toLong(); } @@ -620,14 +646,15 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe private void cleanupPendingJobs(List l) { if(l != null && l.size() > 0) { for(SyncQueueItemVO item: l) { - if(s_logger.isInfoEnabled()) - s_logger.info("Discard left-over queue item: " + item.toString()); + if(s_logger.isInfoEnabled()) { + s_logger.info("Discard left-over queue item: " + item.toString()); + } String contentType = item.getContentType(); if(contentType != null && contentType.equals("AsyncJob")) { Long jobId = item.getContentId(); if(jobId != null) { - s_logger.warn("Mark job as failed as its correspoding queue-item has been discarded. job id: " + jobId); + s_logger.warn("Mark job as failed as its correspoding queue-item has been discarded. job id: " + jobId); completeAsyncJob(jobId, AsyncJobResult.STATUS_FAILED, 0, getResetResultMessage("Execution was cancelled because of server shutdown")); } } diff --git a/server/src/com/cloud/cluster/ClusterManagerImpl.java b/server/src/com/cloud/cluster/ClusterManagerImpl.java index 747898755a9..0ee0f796230 100644 --- a/server/src/com/cloud/cluster/ClusterManagerImpl.java +++ b/server/src/com/cloud/cluster/ClusterManagerImpl.java @@ -574,14 +574,11 @@ public class ClusterManagerImpl implements ClusterManager { Connection conn = getHeartbeatConnection(); _mshostDao.update(conn, _mshostId, getCurrentRunId(), DateUtil.currentGMTTime()); - // for cluster in Starting state check if there are any agents being transfered if (_state == State.Starting) { synchronized (stateLock) { - if (isClusterReadyToStart()) { - _mshostDao.update(conn, _mshostId, getCurrentRunId(), State.Up, DateUtil.currentGMTTime()); - _state = State.Up; - stateLock.notifyAll(); - } + _mshostDao.update(conn, _mshostId, getCurrentRunId(), State.Up, DateUtil.currentGMTTime()); + _state = State.Up; + stateLock.notifyAll(); } } @@ -618,45 +615,6 @@ public class ClusterManagerImpl implements ClusterManager { s_logger.error("Problem with the cluster heartbeat!", e); } } - - private boolean isClusterReadyToStart() { - if (!_agentLBEnabled) { - return true; - } - boolean isReady = false; - int transferCount = _hostTransferDao.listHostsJoiningCluster(_msId).size(); - if (transferCount == 0) { - //Check how many servers got transfered successfully - List rebalancedHosts = _hostTransferDao.listBy(_msId, HostTransferState.TransferCompleted); - - if (!rebalancedHosts.isEmpty() && s_logger.isDebugEnabled()) { - s_logger.debug(rebalancedHosts.size() + " hosts joined the cluster " + _msId + " as a result of rebalance process"); - - } - - for (HostTransferMapVO host : rebalancedHosts) { - _hostTransferDao.remove(host.getId()); - } - - //Check how many servers failed to transfer - List failedToRebalanceHosts = _hostTransferDao.listBy(_msId, HostTransferState.TransferFailed); - if (!failedToRebalanceHosts.isEmpty() && s_logger.isDebugEnabled()) { - s_logger.debug(failedToRebalanceHosts.size() + " hosts failed to join the cluster " + _msId + " as a result of rebalance process"); - } - - for (HostTransferMapVO host : failedToRebalanceHosts) { - _hostTransferDao.remove(host.getId()); - } - - s_logger.debug("There are no hosts currently joining cluser msid=" + _msId + ", so management server is ready to start"); - isReady = true; - } else if (s_logger.isDebugEnabled()) { - //TODO : change to trace mode later - s_logger.debug("There are " + transferCount + " agents currently joinging the cluster " + _msId); - } - - return isReady; - } }; } @@ -952,15 +910,15 @@ public class ClusterManagerImpl implements ClusterManager { s_logger.info("Management server (host id : " + _mshostId + ") is being started at " + _clusterNodeIP + ":" + _currentServiceAdapter.getServicePort()); } - // use seperate thread for heartbeat updates - _heartbeatScheduler.scheduleAtFixedRate(getHeartbeatTask(), heartbeatInterval, heartbeatInterval, TimeUnit.MILLISECONDS); - _notificationExecutor.submit(getNotificationTask()); - - // Do agent rebalancing + // Initiate agent rebalancing if (_agentLBEnabled) { s_logger.debug("Management server " + _msId + " is asking other peers to rebalance their agents"); _rebalanceService.startRebalanceAgents(); } + + // use seperate thread for heartbeat updates + _heartbeatScheduler.scheduleAtFixedRate(getHeartbeatTask(), heartbeatInterval, heartbeatInterval, TimeUnit.MILLISECONDS); + _notificationExecutor.submit(getNotificationTask()); //wait here for heartbeat task to update the host state try { diff --git a/server/src/com/cloud/cluster/agentlb/AgentLoadBalancerPlanner.java b/server/src/com/cloud/cluster/agentlb/AgentLoadBalancerPlanner.java index 2a87724d253..b9d5b0fa936 100644 --- a/server/src/com/cloud/cluster/agentlb/AgentLoadBalancerPlanner.java +++ b/server/src/com/cloud/cluster/agentlb/AgentLoadBalancerPlanner.java @@ -26,6 +26,6 @@ import com.cloud.utils.component.Adapter; public interface AgentLoadBalancerPlanner extends Adapter{ - List getHostsToRebalance(long msId, long avLoad); + List getHostsToRebalance(long msId, int avLoad); } diff --git a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java index 0f896d7f43c..1862ced8cbd 100644 --- a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java +++ b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java @@ -65,11 +65,11 @@ public class ClusterBasedAgentLoadBalancerPlanner implements AgentLoadBalancerPl } @Override - public List getHostsToRebalance(long msId, long avLoad) { + public List getHostsToRebalance(long msId, int avLoad) { List allHosts = _hostDao.listByManagementServer(msId); if (allHosts.size() <= avLoad) { - s_logger.debug("Agent load for management server " + msId + " doesn't exceed av load " + avLoad + "; so it doesn't participate in agent rebalancing process"); + s_logger.debug("Agent load = " + allHosts.size() + " for management server " + msId + " doesn't exceed average system agent load = " + avLoad + "; so it doesn't participate in agent rebalancing process"); return null; } @@ -96,9 +96,9 @@ public class ClusterBasedAgentLoadBalancerPlanner implements AgentLoadBalancerPl hostToClusterMap = sortByClusterSize(hostToClusterMap); - long hostsToGive = allHosts.size() - avLoad; - long hostsLeftToGive = hostsToGive; - long hostsLeft = directHosts.size(); + int hostsToGive = allHosts.size() - avLoad; + int hostsLeftToGive = hostsToGive; + int hostsLeft = directHosts.size(); List hostsToReturn = new ArrayList(); int count = 0; diff --git a/server/src/com/cloud/cluster/agentlb/HostTransferMapVO.java b/server/src/com/cloud/cluster/agentlb/HostTransferMapVO.java index a2bb428b084..d98d41b5345 100644 --- a/server/src/com/cloud/cluster/agentlb/HostTransferMapVO.java +++ b/server/src/com/cloud/cluster/agentlb/HostTransferMapVO.java @@ -35,7 +35,7 @@ import com.cloud.utils.db.GenericDao; public class HostTransferMapVO { public enum HostTransferState { - TransferRequested, TransferStarted, TransferCompleted, TransferFailed; + TransferRequested, TransferStarted; } @Id diff --git a/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDao.java b/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDao.java index 4bb0b172250..55e7802431f 100644 --- a/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDao.java +++ b/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDao.java @@ -29,13 +29,15 @@ public interface HostTransferMapDao extends GenericDao List listHostsLeavingCluster(long clusterId); - List listHostsJoiningCluster(long clusterId); + List listHostsJoiningCluster(long futureOwnerId); HostTransferMapVO startAgentTransfering(long hostId, long currentOwner, long futureOwner); - boolean completeAgentTransfering(long hostId, boolean success); + boolean completeAgentTransfer(long hostId); List listBy(long futureOwnerId, HostTransferState state); - boolean isActive(long hostId, Date cutTime); + boolean isNotActive(long hostId, Date cutTime); + + boolean startAgentTransfer(long hostId); } diff --git a/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDaoImpl.java b/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDaoImpl.java index 8491215e8cc..e600011e865 100644 --- a/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDaoImpl.java +++ b/server/src/com/cloud/cluster/agentlb/dao/HostTransferMapDaoImpl.java @@ -51,7 +51,7 @@ public class HostTransferMapDaoImpl extends GenericDaoBase listHostsJoiningCluster(long clusterId) { + public List listHostsJoiningCluster(long futureOwnerId) { SearchCriteria sc = IntermediateStateSearch.create(); - sc.setParameters("futureOwner", clusterId); - sc.setParameters("state", HostTransferState.TransferRequested, HostTransferState.TransferStarted); + sc.setParameters("futureOwner", futureOwnerId); + sc.setParameters("state", HostTransferState.TransferRequested); return listBy(sc); } @@ -88,14 +88,8 @@ public class HostTransferMapDaoImpl extends GenericDaoBase sc = InactiveSearch.create(); sc.setParameters("id", hostId); sc.setParameters("state", HostTransferState.TransferRequested); sc.setParameters("created", cutTime); - if (listBy(sc).isEmpty()) { - return true; - } else { return false; + } else { + return true; } } + @Override + public boolean startAgentTransfer(long hostId) { + HostTransferMapVO transfer = findById(hostId); + transfer.setState(HostTransferState.TransferStarted); + return update(hostId, transfer); + } + } diff --git a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java index 1d904777362..5db287b202c 100644 --- a/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java +++ b/server/src/com/cloud/cluster/dao/ManagementServerHostDaoImpl.java @@ -328,7 +328,7 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase listBy(ManagementServerHost.State...states) { SearchCriteria sc = StateSearch.create(); - sc.setParameters("status", (Object[]) states); + sc.setParameters("state", (Object[]) states); return listBy(sc); } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index f2c0176860b..da346ef3732 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -130,6 +130,7 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.SecondaryStorageVmDao; @@ -937,9 +938,13 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura selectSql += " AND taken IS NOT NULL"; } - if (tableName.equals("host_pod_ref")) { + if (tableName.equals("host_pod_ref") || tableName.equals("host") || tableName.equals("volumes")) { selectSql += " AND removed is NULL"; } + + if (tableName.equals("vm_instance")) { + selectSql += " AND state != '" + VirtualMachine.State.Expunging.toString() + "'"; + } Transaction txn = Transaction.currentTxn(); try { @@ -1060,11 +1065,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura List networks = _networkDao.listByZoneIncludingRemoved(zoneId); if (networks != null && !networks.isEmpty()) { for (NetworkVO network : networks) { - _networkDao.expunge(network.getId()); + _networkDao.remove(network.getId()); } } - - success = _zoneDao.expunge(zoneId); + success = _zoneDao.remove(zoneId); txn.commit(); @@ -1367,7 +1371,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } userNetwork.setBroadcastDomainType(broadcastDomainType); - _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, true, isNetworkDefault, false, null); + _networkMgr.setupNetwork(systemAccount, offering, userNetwork, plan, null, null, true, isNetworkDefault, false, null, null); } } } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index f08dfd8e006..da36c16645f 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -571,7 +571,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx Map context = new HashMap(); context.put("dc", dc); - HostPodVO pod = _podDao.findById(proxy.getPodId()); + HostPodVO pod = _podDao.findById(proxy.getPodIdToDeployIn()); context.put("pod", pod); context.put("proxyVmId", proxy.getId()); @@ -1116,7 +1116,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx } SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this, - new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterId(), proxy.getId(), proxy, null)); + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterIdToDeployIn(), proxy.getId(), proxy, null)); return true; } else { @@ -1325,7 +1325,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx if (externalDhcp) { buf.append(" bootproto=dhcp"); } - DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterId()); + DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterIdToDeployIn()); buf.append(" internaldns1=").append(dc.getInternalDns1()); if (dc.getInternalDns2() != null) { buf.append(" internaldns2=").append(dc.getInternalDns2()); diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java index 89d0f43f04f..420570fde58 100644 --- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java @@ -40,7 +40,7 @@ public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager imp @Override protected HostVO findHost(VMInstanceVO vm) { - List hosts = _hostDao.listBy(Type.ConsoleProxy, vm.getDataCenterId()); + List hosts = _hostDao.listBy(Type.ConsoleProxy, vm.getDataCenterIdToDeployIn()); return hosts.isEmpty() ? null : hosts.get(0); } diff --git a/server/src/com/cloud/dc/DataCenterVO.java b/server/src/com/cloud/dc/DataCenterVO.java index 63f58951172..950abfd619b 100644 --- a/server/src/com/cloud/dc/DataCenterVO.java +++ b/server/src/com/cloud/dc/DataCenterVO.java @@ -18,6 +18,7 @@ package com.cloud.dc; +import java.util.Date; import java.util.Map; import javax.persistence.Column; @@ -34,6 +35,7 @@ import javax.persistence.Transient; import com.cloud.network.Network.Provider; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.GenericDao; @Entity @Table(name="data_center") @@ -111,6 +113,9 @@ public class DataCenterVO implements DataCenter { @Column(name="zone_token") private String zoneToken; + + @Column(name=GenericDao.REMOVED_COLUMN) + private Date removed; // This is a delayed load value. If the value is null, // then this field has not been loaded yet. @@ -397,5 +402,9 @@ public class DataCenterVO implements DataCenter { public void setZoneToken(String zoneToken) { this.zoneToken = zoneToken; - } + } + + public Date getRemoved() { + return removed; + } } diff --git a/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java b/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java index 1957098e6e7..1cca111a85c 100644 --- a/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java +++ b/server/src/com/cloud/dc/dao/DataCenterDaoImpl.java @@ -32,6 +32,7 @@ import com.cloud.dc.DataCenterIpAddressVO; import com.cloud.dc.DataCenterLinkLocalIpAddressVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVnetVO; +import com.cloud.dc.HostPodVO; import com.cloud.dc.PodVlanVO; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; @@ -355,4 +356,18 @@ public class DataCenterDaoImpl extends GenericDaoBase implem } return result; } + + @Override + public boolean remove(Long id) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + DataCenterVO zone = createForUpdate(); + zone.setName(null); + + update(id, zone); + + boolean result = super.remove(id); + txn.commit(); + return result; + } } diff --git a/server/src/com/cloud/deploy/BareMetalPlanner.java b/server/src/com/cloud/deploy/BareMetalPlanner.java index b0ba4d0ba15..1df8ce10e1a 100644 --- a/server/src/com/cloud/deploy/BareMetalPlanner.java +++ b/server/src/com/cloud/deploy/BareMetalPlanner.java @@ -87,7 +87,7 @@ public class BareMetalPlanner implements DeploymentPlanner { } } - List clusters = _clusterDao.listByDcHyType(vm.getDataCenterId(), HypervisorType.BareMetal.toString()); + List clusters = _clusterDao.listByDcHyType(vm.getDataCenterIdToDeployIn(), HypervisorType.BareMetal.toString()); if (clusters.size() != 1) { throw new CloudRuntimeException("Invaild baremetal cluster number " + clusters.size()); } diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 47af2f55589..7ccb88ff396 100644 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -110,7 +110,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { String _allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key()); VirtualMachine vm = vmProfile.getVirtualMachine(); ServiceOffering offering = vmProfile.getServiceOffering(); - DataCenter dc = _dcDao.findById(vm.getDataCenterId()); + DataCenter dc = _dcDao.findById(vm.getDataCenterIdToDeployIn()); int cpu_requested = offering.getCpu() * offering.getSpeed(); long ram_requested = offering.getRamSize() * 1024L * 1024L; diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index fa5b5f992d0..8c3ee25908c 100644 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -273,8 +273,8 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager, Clu } if (!(_forceHA || vm.isHaEnabled())) { - String hostDesc = "id:" + vm.getHostId() + ", availability zone id:" + vm.getDataCenterId() + ", pod id:" + vm.getPodId(); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "VM (name: " + vm.getHostName() + ", id: " + vm.getId() + ") stopped unexpectedly on host " + hostDesc, + String hostDesc = "id:" + vm.getHostId() + ", availability zone id:" + vm.getDataCenterIdToDeployIn() + ", pod id:" + vm.getPodIdToDeployIn(); + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getHostName() + ", id: " + vm.getId() + ") stopped unexpectedly on host " + hostDesc, "Virtual Machine " + vm.getHostName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped unexpectedly."); if (s_logger.isDebugEnabled()) { @@ -404,7 +404,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager, Clu if (!fenced) { s_logger.debug("We were unable to fence off the VM " + vm); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "Insufficient capacity to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); return (System.currentTimeMillis() >> 10) + _restartRetryInterval; } @@ -462,19 +462,19 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager, Clu } } catch (final InsufficientCapacityException e) { s_logger.warn("Unable to restart " + vm.toString() + " due to " + e.getMessage()); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "Insufficient capacity to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); } catch (final ResourceUnavailableException e) { s_logger.warn("Unable to restart " + vm.toString() + " due to " + e.getMessage()); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "The Storage is unavailable for trying to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); } catch (ConcurrentOperationException e) { s_logger.warn("Unable to restart " + vm.toString() + " due to " + e.getMessage()); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "The Storage is unavailable for trying to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); } catch (OperationTimedoutException e) { s_logger.warn("Unable to restart " + vm.toString() + " due to " + e.getMessage()); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "Unable to restart " + vm.getHostName() + " which was running on host " + hostDesc, "The Storage is unavailable for trying to restart VM, name: " + vm.getHostName() + ", id: " + vmId + " which was running on host " + hostDesc); } vm = _itMgr.findById(vm.getType(), vm.getId()); diff --git a/server/src/com/cloud/ha/UserVmDomRInvestigator.java b/server/src/com/cloud/ha/UserVmDomRInvestigator.java index 5ddec06424c..4c982c9b3a6 100644 --- a/server/src/com/cloud/ha/UserVmDomRInvestigator.java +++ b/server/src/com/cloud/ha/UserVmDomRInvestigator.java @@ -172,7 +172,7 @@ public class UserVmDomRInvestigator extends AbstractInvestigatorImpl { || vm.getHypervisorType() == HypervisorType.KVM){ otherHosts.add(router.getHostId()); }else{ - otherHosts = findHostByPod(router.getPodId(), null); + otherHosts = findHostByPod(router.getPodIdToDeployIn(), null); } for (Long hostId : otherHosts) { try { diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java index de035f20743..95607033b3d 100644 --- a/server/src/com/cloud/host/dao/HostDao.java +++ b/server/src/com/cloud/host/dao/HostDao.java @@ -171,7 +171,7 @@ public interface HostDao extends GenericDao { List listManagedDirectAgents(); - List listManagedAgents(); + List listManagedRoutingAgents(); HostVO findTrafficMonitorHost(); diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index ed74c108703..06717dbfd27 100644 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -91,7 +91,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final SearchBuilder DirectConnectSearch; protected final SearchBuilder ManagedDirectConnectSearch; - protected final SearchBuilder ManagedConnectSearch; + protected final SearchBuilder ManagedRoutingServersSearch; protected final GenericSearchBuilder HostsInStatusSearch; protected final GenericSearchBuilder CountRoutingByDc; @@ -264,9 +264,10 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao ManagedDirectConnectSearch.and("server", ManagedDirectConnectSearch.entity().getManagementServerId(), SearchCriteria.Op.NULL); ManagedDirectConnectSearch.done(); - ManagedConnectSearch = createSearchBuilder(); - ManagedConnectSearch.and("server", ManagedConnectSearch.entity().getManagementServerId(), SearchCriteria.Op.NNULL); - ManagedConnectSearch.done(); + ManagedRoutingServersSearch = createSearchBuilder(); + ManagedRoutingServersSearch.and("server", ManagedRoutingServersSearch.entity().getManagementServerId(), SearchCriteria.Op.NNULL); + ManagedRoutingServersSearch.and("type", ManagedRoutingServersSearch.entity().getType(), SearchCriteria.Op.EQ); + ManagedRoutingServersSearch.done(); _statusAttr = _allAttributes.get("status"); _msIdAttr = _allAttributes.get("managementServerId"); @@ -868,8 +869,9 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } @Override - public List listManagedAgents() { - SearchCriteria sc = ManagedConnectSearch.create(); + public List listManagedRoutingAgents() { + SearchCriteria sc = ManagedRoutingServersSearch.create(); + sc.setParameters("type", Type.Routing); return listBy(sc); } diff --git a/server/src/com/cloud/migration/Db20to21MigrationUtil.java b/server/src/com/cloud/migration/Db20to21MigrationUtil.java index 6579a8da722..e3b752dee2a 100644 --- a/server/src/com/cloud/migration/Db20to21MigrationUtil.java +++ b/server/src/com/cloud/migration/Db20to21MigrationUtil.java @@ -570,7 +570,7 @@ public class Db20to21MigrationUtil { private void migrateSystemVmGuestMacAndState(long zoneId) { // for console proxy VMs SearchBuilder sb = _consoleProxyDao.createSearchBuilder(); - sb.and("zoneId", sb.entity().getDataCenterId(), Op.EQ); + sb.and("zoneId", sb.entity().getDataCenterIdToDeployIn(), Op.EQ); sb.done(); SearchCriteria sc = sb.create(); @@ -586,7 +586,7 @@ public class Db20to21MigrationUtil { proxy.setState(State.Stopping); } - String guestIpAddress = _dcDao.allocateLinkLocalIpAddress(proxy.getDataCenterId(), proxy.getPodId(), proxy.getId(), null); + String guestIpAddress = _dcDao.allocateLinkLocalIpAddress(proxy.getDataCenterIdToDeployIn(), proxy.getPodIdToDeployIn(), proxy.getId(), null); System.out.println("Assign link loal address to proxy " + proxy.getHostName() + ", link local address: " + guestIpAddress); _consoleProxyDao.update(proxy.getId(), proxy); @@ -594,7 +594,7 @@ public class Db20to21MigrationUtil { // for secondary storage VMs SearchBuilder sb2 = _secStorageVmDao.createSearchBuilder(); - sb2.and("zoneId", sb2.entity().getDataCenterId(), Op.EQ); + sb2.and("zoneId", sb2.entity().getDataCenterIdToDeployIn(), Op.EQ); sb2.done(); SearchCriteria sc2 = sb2.create(); @@ -610,7 +610,7 @@ public class Db20to21MigrationUtil { secStorageVm.setState(State.Stopping); } - String guestIpAddress = _dcDao.allocateLinkLocalIpAddress(secStorageVm.getDataCenterId(), secStorageVm.getPodId(), secStorageVm.getId(), null); + String guestIpAddress = _dcDao.allocateLinkLocalIpAddress(secStorageVm.getDataCenterIdToDeployIn(), secStorageVm.getPodIdToDeployIn(), secStorageVm.getId(), null); System.out.println("Assign link loal address to secondary storage VM " + secStorageVm.getHostName() + ", link local address: " + guestIpAddress); _secStorageVmDao.update(secStorageVm.getId(), secStorageVm); @@ -619,7 +619,7 @@ public class Db20to21MigrationUtil { // for Domain Router VMs // Although we can list those we are interested, but just too lazy, list all of them and check their states. SearchBuilder sb3 = _routerDao.createSearchBuilder(); - sb3.and("zoneId", sb3.entity().getDataCenterId(), Op.EQ); + sb3.and("zoneId", sb3.entity().getDataCenterIdToDeployIn(), Op.EQ); sb3.done(); SearchCriteria sc3 = sb3.create(); @@ -637,8 +637,8 @@ public class Db20to21MigrationUtil { private void migrateVmInstanceLastHostId(long zoneId, long podId) { SearchBuilder sb = _vmInstanceDao.createSearchBuilder(); - sb.and("zoneId", sb.entity().getDataCenterId(), Op.EQ); - sb.and("podId", sb.entity().getPodId(), Op.EQ); + sb.and("zoneId", sb.entity().getDataCenterIdToDeployIn(), Op.EQ); + sb.and("podId", sb.entity().getPodIdToDeployIn(), Op.EQ); sb.done(); Random rand = new Random(); diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 38fd847dbaf..6d9065b7241 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -109,7 +109,7 @@ public interface NetworkManager extends NetworkService { throws ConcurrentOperationException; List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault, - boolean errorIfAlreadySetup, Long domainId) throws ConcurrentOperationException; + boolean errorIfAlreadySetup, Long domainId, List tags) throws ConcurrentOperationException; List getSystemAccountNetworkOfferings(String... offeringNames); @@ -158,7 +158,7 @@ public interface NetworkManager extends NetworkService { boolean destroyNetwork(long networkId, ReservationContext context); Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, - Account owner, boolean isSecurityGroupEnabled, Long domainId) throws ConcurrentOperationException, InsufficientCapacityException; + Account owner, boolean isSecurityGroupEnabled, Long domainId, List tags) throws ConcurrentOperationException, InsufficientCapacityException; /** * @throws InsufficientCapacityException diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 3e7be21359b..1a12b438075 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.net.URI; +import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -264,7 +265,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (addrs.size() == 0) { if (podId != null) { throw new InsufficientAddressCapacityException("Insufficient address capacity", HostPodDao.class, podId); - } + } throw new InsufficientAddressCapacityException("Insufficient address capacity", DataCenter.class, dcId); } @@ -315,7 +316,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkVO network = _networksDao.findByIdIncludingRemoved(networkId); String guestType = ""; if( (network != null) && (network.getGuestType() != null) ){ - guestType = network.getGuestType().toString(); + guestType = network.getGuestType().toString(); } UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), isSourceNat, guestType); _usageEventDao.persist(usageEvent); @@ -829,13 +830,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override 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, false, null); + return setupNetwork(owner, offering, null, plan, name, displayText, isShared, isDefault, false, null, null); } @Override @DB public List setupNetwork(Account owner, NetworkOfferingVO offering, Network predefined, DeploymentPlan plan, String name, String displayText, boolean isShared, boolean isDefault, - boolean errorIfAlreadySetup, Long domainId) throws ConcurrentOperationException { + boolean errorIfAlreadySetup, Long domainId, List tags) throws ConcurrentOperationException { Account locked = _accountDao.acquireInLockTable(owner.getId()); if (locked == null) { throw new ConcurrentOperationException("Unable to acquire lock on " + owner); @@ -870,21 +871,21 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - List configs = new ArrayList(); + List networks = new ArrayList(); long related = -1; for (NetworkGuru guru : _networkGurus) { - Network config = guru.design(offering, plan, predefined, owner); - if (config == null) { + Network network = guru.design(offering, plan, predefined, owner); + if (network == null) { continue; } - if (config.getId() != -1) { - if (config instanceof NetworkVO) { - configs.add((NetworkVO) config); + if (network.getId() != -1) { + if (network instanceof NetworkVO) { + networks.add((NetworkVO) network); } else { - configs.add(_networksDao.findById(config.getId())); + networks.add(_networksDao.findById(network.getId())); } continue; } @@ -894,20 +895,21 @@ 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, isDefault, + NetworkVO vo = new NetworkVO(id, network, offering.getId(), plan.getDataCenterId(), guru.getName(), owner.getDomainId(), owner.getId(), related, name, displayText, isShared, isDefault, predefined.isSecurityGroupEnabled()); - configs.add(_networksDao.persist(vo, vo.getGuestType() != null)); + vo.setTags(tags); + networks.add(_networksDao.persist(vo, vo.getGuestType() != null)); if (domainId != null) { _networksDao.addDomainToNetwork(id, domainId); } } - if (configs.size() < 1) { + if (networks.size() < 1) { throw new CloudRuntimeException("Unable to convert network offering to network profile: " + offering.getId()); } - return configs; + return networks; } finally { s_logger.debug("Releasing lock for " + locked); _accountDao.releaseFromLockTable(locked.getId()); @@ -1133,7 +1135,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag network.setMode(result.getMode()); _networksDao.update(networkId, network); - // If this is a guest virtual network and the network offering does not support a shared source NAT rule, + // If this is a guest virtual network and the network offering does not support a shared source NAT rule, // associate a source NAT IP (if one isn't already associated with the network) if (network.getGuestType() == GuestIpType.Virtual && !offering.isSharedSourceNatService()) { List ips = _ipAddressDao.listByAssociatedNetwork(networkId, true); @@ -1247,6 +1249,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag updateNic(nic, network.getId(), 1); } else { profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate); + guru.updateNicProfile(profile, network); nic.setState(Nic.State.Reserved); updateNic(nic, network.getId(), 1); } @@ -1470,7 +1473,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Boolean isDefault = cmd.isDefault(); Long userId = UserContext.current().getCallerUserId(); Account caller = UserContext.current().getCaller(); + List tags = cmd.getTags(); boolean isDomainSpecific = false; + + if (tags != null && tags.size() > 1) { + throw new InvalidParameterException("Only one tag can be specified for a network at this time"); + } Transaction txn = Transaction.currentTxn(); @@ -1584,7 +1592,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag domainId = cmd.getDomainId(); } - Network network = createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, cidr, vlanId, networkDomain, owner, false, domainId); + Network network = createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, cidr, vlanId, networkDomain, owner, false, domainId, null); // 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 @@ -1605,7 +1613,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @DB public Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, - String networkDomain, Account owner, boolean isSecurityGroupEnabled, Long domainId) throws ConcurrentOperationException, InsufficientCapacityException { + String networkDomain, Account owner, boolean isSecurityGroupEnabled, Long domainId, List tags) throws ConcurrentOperationException, InsufficientCapacityException { NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); DataCenterVO zone = _dcDao.findById(zoneId); @@ -1706,7 +1714,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared, isDefault, true, domainId); + List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared, isDefault, true, domainId, tags); Network network = null; if (networks == null || networks.isEmpty()) { @@ -2520,7 +2528,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag // create new Virtual network for the user if it doesn't exist if (createNetwork) { List offerings = _configMgr.listNetworkOfferings(TrafficType.Guest, false); - network = createNetwork(offerings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, null, zoneId, null, null, null, null, owner, false, null); + network = createNetwork(offerings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, null, zoneId, null, null, null, null, owner, false, null, null); if (network == null) { s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId); @@ -2636,7 +2644,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return (zone.getGatewayProvider() != null && zone.getGatewayProvider().equals(Network.Provider.JuniperSRX.getName()) && zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())); } else { - return (zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())); + return (zone.getFirewallProvider() != null && zone.getFirewallProvider().equals(Network.Provider.JuniperSRX.getName())); } } @@ -2764,7 +2772,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkVO network = _networksDao.findByIdIncludingRemoved(ip.getSourceNetworkId()); String guestType = ""; if( (network != null) && (network.getGuestType() != null)){ - guestType = network.getGuestType().toString(); + guestType = network.getGuestType().toString(); } UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_RELEASE, ip.getAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(), isSourceNat, guestType); @@ -2826,14 +2834,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = false) - public Network updateNetwork(long networkId, String name, String displayText, Account caller) { + public Network updateNetwork(long networkId, String name, String displayText, List tags, Account caller) { // verify input parameters NetworkVO network = _networksDao.findById(networkId); if (network == null) { throw new InvalidParameterValueException("Network id=" + networkId + "doesn't exist in the system"); } - + + if (tags != null && tags.size() > 1) { + throw new InvalidParameterException("Unable to support more than one tag on network yet"); + } + // Don't allow to update system network NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId()); if (offering.isSystemOnly()) { @@ -2849,6 +2861,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (displayText != null) { network.setDisplayText(displayText); } + + if (tags != null) { + network.setTags(tags); + } _networksDao.update(networkId, network); diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index ab760faacfe..af60f5e27b1 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -22,11 +22,15 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import javax.persistence.CollectionTable; import javax.persistence.Column; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; +import javax.persistence.FetchType; import javax.persistence.Id; +import javax.persistence.JoinColumn; import javax.persistence.Table; import javax.persistence.TableGenerator; import javax.persistence.Transient; @@ -34,7 +38,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.network.dao.NetworkDao; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -73,7 +76,7 @@ public class NetworkVO implements Network { String displayText;; @Column(name="broadcast_uri") - URI broadcastUri; + URI broadcastUri; @Column(name="gateway") String gateway; @@ -132,7 +135,7 @@ public class NetworkVO implements Network { Date created; @Column(name="reservation_id") - String reservationId; + String reservationId; @Column(name="is_default") boolean isDefault; @@ -140,7 +143,9 @@ public class NetworkVO implements Network { @Column(name="is_security_group_enabled") boolean securityGroupEnabled; - @Transient + @ElementCollection(targetClass = String.class, fetch=FetchType.EAGER) + @Column(name="tag") + @CollectionTable(name="network_tags", joinColumns=@JoinColumn(name="network_id")) List tags; public NetworkVO() { @@ -408,7 +413,7 @@ public class NetworkVO implements Network { return isDefault; } - @Override + @Override public boolean isSecurityGroupEnabled() { return securityGroupEnabled; } @@ -464,10 +469,4 @@ public class NetworkVO implements Network { buf.append(id).append("|").append(trafficType.toString()).append("|").append(networkOfferingId).append("]"); return buf.toString(); } - - private static NetworkDao _networkDao = null; - static void init(NetworkDao networkDao) { - _networkDao = networkDao; - } - } diff --git a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java index 03e0b1e334f..155b31803e8 100644 --- a/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/guru/DirectPodBasedNetworkGuru.java @@ -117,6 +117,10 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru { getIp(nic, dest.getPod(), vm, network); nic.setStrategy(ReservationStrategy.Create); } + + DataCenter dc = _dcDao.findById(network.getDataCenterId()); + nic.setDns1(dc.getDns1()); + nic.setDns2(dc.getDns2()); } protected void getIp(NicProfile nic, Pod pod, VirtualMachineProfile vm, Network network) throws InsufficientVirtualNetworkCapcityException, diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java index 2210088bcd1..c8aa7e3b0b1 100644 --- a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java @@ -395,7 +395,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { long hostId = dest.getHost().getId(); long accountId = instance.getAccountId(); Listvms = _userVmDao.listByAccountId(accountId); - DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn()); Listins = new ArrayList(); ins.addAll(vms); ins.add(router); @@ -538,7 +538,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { } long accountId = instance.getAccountId(); - DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn()); if (router == null) { return; } @@ -639,7 +639,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { } if (tellRouter && instance.getType() != VirtualMachine.Type.DomainRouter) { - DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn()); if (router != null) { affectedVms.add(new Long(router.getId())); } diff --git a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index beae87e27e8..209c23032d2 100644 --- a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -153,7 +153,7 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { long hostId = dest.getHost().getId(); long accountId = instance.getAccountId(); Listvms = _userVmDao.listByAccountId(accountId); - DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn()); Listins = new ArrayList(); if (vms != null) { ins.addAll(vms); @@ -284,7 +284,7 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { return; } - DomainRouterVO router = _routerDao.findBy(vm.getAccountId(), vm.getDataCenterId()); + DomainRouterVO router = _routerDao.findBy(vm.getAccountId(), vm.getDataCenterIdToDeployIn()); if (router.getHostId() == vm.getHostId()) { return; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index fad8955e819..0558b2552a6 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -430,7 +430,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian final Transaction txn = Transaction.currentTxn(); try { txn.start(); - final UserStatisticsVO userStats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterId(), router.getNetworkId(), null, router.getId(), router.getType().toString()); + final UserStatisticsVO userStats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterIdToDeployIn(), router.getNetworkId(), null, router.getId(), router.getType().toString()); if (userStats != null) { final RebootAnswer sa = (RebootAnswer) answer; final Long received = sa.getBytesReceived(); @@ -463,7 +463,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian _userStatsDao.update(userStats.getId(), userStats); 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()); + s_logger.warn("User stats were not created for account " + router.getAccountId() + " and dc " + router.getDataCenterIdToDeployIn()); } txn.commit(); } catch (final Exception e) { @@ -509,7 +509,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian // Can reboot domain router only in Running state if (router == null || router.getState() != State.Running) { s_logger.warn("Unable to reboot, virtual router is not in the right state " + router.getState()); - throw new ResourceUnavailableException("Unable to reboot domR, it is not in right state " + router.getState(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to reboot domR, it is not in right state " + router.getState(), DataCenter.class, router.getDataCenterIdToDeployIn()); } UserVO user = _userDao.findById(UserContext.current().getCallerUserId()); @@ -651,7 +651,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian continue; } txn.start(); - UserStatisticsVO stats = _statsDao.lock(router.getAccountId(), router.getDataCenterId(), router.getNetworkId(), null, router.getId(), router.getType().toString()); + UserStatisticsVO stats = _statsDao.lock(router.getAccountId(), router.getDataCenterIdToDeployIn(), router.getNetworkId(), null, router.getId(), router.getType().toString()); if (stats == null) { s_logger.warn("unable to find stats for account: " + router.getAccountId()); continue; @@ -1042,7 +1042,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian s_logger.debug("Resending ipAssoc, port forwarding, load balancing rules as a part of Virtual router start"); long networkId = router.getNetworkId(); long ownerId = router.getAccountId(); - long zoneId = router.getDataCenterId(); + long zoneId = router.getDataCenterIdToDeployIn(); final List userIps = _networkMgr.listPublicIpAddressesInVirtualNetwork(ownerId, zoneId, null, null); List publicIps = new ArrayList(); @@ -1176,17 +1176,17 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } Answer answer = cmds.getAnswer("users"); if (!answer.getResult()) { - s_logger.error("Unable to start vpn: unable add users to vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + s_logger.error("Unable to start vpn: unable add users to vpn in zone " + router.getDataCenterIdToDeployIn() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to " + answer.getDetails()); - throw new ResourceUnavailableException("Unable to start vpn: Unable to add users to vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " - + router.getInstanceName() + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to start vpn: Unable to add users to vpn in zone " + router.getDataCenterIdToDeployIn() + " for account " + vpn.getAccountId() + " on domR: " + + router.getInstanceName() + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterIdToDeployIn()); } answer = cmds.getAnswer("startVpn"); if (!answer.getResult()) { - s_logger.error("Unable to start vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to " + s_logger.error("Unable to start vpn in zone " + router.getDataCenterIdToDeployIn() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to " + answer.getDetails()); - throw new ResourceUnavailableException("Unable to start vpn in zone " + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() - + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to start vpn in zone " + router.getDataCenterIdToDeployIn() + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterIdToDeployIn()); } return true; } @@ -1291,19 +1291,19 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian Answer answer = cmds.getAnswer("dhcp"); if (!answer.getResult()) { s_logger.error("Unable to set dhcp entry for " + profile + " on domR: " + router.getHostName() + " due to " + answer.getDetails()); - throw new ResourceUnavailableException("Unable to set dhcp entry for " + profile + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to set dhcp entry for " + profile + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterIdToDeployIn()); } answer = cmds.getAnswer("password"); if (answer != null && !answer.getResult()) { s_logger.error("Unable to set password for " + profile + " due to " + answer.getDetails()); - throw new ResourceUnavailableException("Unable to set password due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to set password due to " + answer.getDetails(), DataCenter.class, router.getDataCenterIdToDeployIn()); } answer = cmds.getAnswer("vmdata"); if (answer != null && !answer.getResult()) { s_logger.error("Unable to set VM data for " + profile + " due to " + answer.getDetails()); - throw new ResourceUnavailableException("Unable to set VM data due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to set VM data due to " + answer.getDetails(), DataCenter.class, router.getDataCenterIdToDeployIn()); } return router; } @@ -1386,10 +1386,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian Account owner = _accountMgr.getAccount(router.getAccountId()); // Check if all networks are implemented for the domR; if not - implement them - DataCenter dc = _dcDao.findById(router.getDataCenterId()); + DataCenter dc = _dcDao.findById(router.getDataCenterIdToDeployIn()); HostPodVO pod = null; - if (router.getPodId() != null) { - pod = _podDao.findById(router.getPodId()); + if (router.getPodIdToDeployIn() != null) { + pod = _podDao.findById(router.getPodIdToDeployIn()); } DeployDestination dest = new DeployDestination(dc, pod, null, null); @@ -1560,7 +1560,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (nic != null) { s_logger.debug("Creating user data entry for vm " + vm + " on domR " + router); String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText(); - String zoneName = _dcDao.findById(router.getDataCenterId()).getName(); + String zoneName = _dcDao.findById(router.getDataCenterIdToDeployIn()).getName(); cmds.addCommand("vmdata", generateVmDataCommand(router, nic.getIp4Address(), vm.getUserData(), serviceOffering, zoneName, nic.getIp4Address(), vm.getHostName(), vm.getInstanceName(), vm.getId(), null)); } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index e39afd25beb..bac109589ed 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -164,7 +164,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } // validate that userVM is in the same availability zone as the IP address - if (ipAddress.getDataCenterId() != userVm.getDataCenterId()) { + if (ipAddress.getDataCenterId() != userVm.getDataCenterIdToDeployIn()) { throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress + " is not in the same availability zone as virtual machine " + userVm.toString()); } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 3dc5ac081e0..a2f5a51e3e0 100644 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -525,7 +525,8 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId()); if (Host.Type.SecondaryStorage.equals(host.getType())) { - return _secondaryStorageMgr.destroySecStorageVm(hostId); + _secondaryStorageMgr.deleteHost(hostId); + return true; } else { return _agentMgr.deleteHost(hostId, isForced, caller); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 8194cc7eab0..ba2a83516a9 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -771,7 +771,7 @@ public class ManagementServerImpl implements ManagementServer { DataCenterVO dc = iter.next(); boolean found = false; for (DomainRouterVO router : routers) { - if (dc.getId() == router.getDataCenterId()) { + if (dc.getId() == router.getDataCenterIdToDeployIn()) { found = true; break; } @@ -1011,12 +1011,18 @@ public class ManagementServerImpl implements ManagementServer { // if a domainId is provided, we just return the so associated with this domain if (domainId != null) { if (account.getType() == Account.ACCOUNT_TYPE_ADMIN) { + if (account.getDomainId() != 1 && issystem){ //NON ROOT admin + throw new InvalidParameterValueException("Non ROOT admins cannot access system's offering"); + } return _offeringsDao.findServiceOfferingByDomainIdAndIsSystem(domainId, issystem);// no perm check } else { + if (issystem){ + throw new InvalidParameterValueException("Non root users cannot access system's offering"); + } // check if the user's domain == so's domain || user's domain is a child of so's domain if (isPermissible(account.getDomainId(), domainId)) { // perm check succeeded - return _offeringsDao.findServiceOfferingByDomainId(domainId); + return _offeringsDao.findServiceOfferingByDomainIdAndIsSystem(domainId, false); } else { throw new PermissionDeniedException("The account:" + account.getAccountName() + " does not fall in the same domain hierarchy as the service offering"); } @@ -1025,10 +1031,17 @@ public class ManagementServerImpl implements ManagementServer { // For non-root users if ((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + if (issystem){ + throw new InvalidParameterValueException("Only root admins can access system's offering"); + } return searchServiceOfferingsInternal(account, name, id, vmId, keyword, searchFilter); } // for root users, the existing flow + if (account.getDomainId() != 1 && issystem){ //NON ROOT admin + throw new InvalidParameterValueException("Non ROOT admins cannot access system's offering"); + } + if (keyword != null) { SearchCriteria ssc = _offeringsDao.createSearchCriteria(); ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -1061,7 +1074,7 @@ public class ManagementServerImpl implements ManagementServer { if (name != null) { sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); } - sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); + sc.addAnd("systemUse", SearchCriteria.Op.EQ, issystem); return _offeringsDao.search(sc, searchFilter); @@ -1307,7 +1320,7 @@ public class ManagementServerImpl implements ManagementServer { sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); } if (type != null) { - sc.addAnd("type", SearchCriteria.Op.LIKE, "%" + type + "%"); + sc.addAnd("type", SearchCriteria.Op.LIKE, "%" + type); } if (state != null) { sc.addAnd("status", SearchCriteria.Op.EQ, state); @@ -1611,7 +1624,7 @@ public class ManagementServerImpl implements ManagementServer { HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, - isAccountSpecific, true); + isAccountSpecific, true, cmd.listInReadyState()); } @Override @@ -1633,11 +1646,11 @@ public class ManagementServerImpl implements ManagementServer { HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, - isAccountSpecific, showDomr); + isAccountSpecific, showDomr, cmd.listInReadyState()); } private Set> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Long pageSize, - Long startIndex, Long zoneId, HypervisorType hyperType, boolean isAccountSpecific, boolean showDomr) { + Long startIndex, Long zoneId, HypervisorType hyperType, boolean isAccountSpecific, boolean showDomr, boolean onlyReady) { Account caller = UserContext.current().getCaller(); VMTemplateVO template = null; @@ -1656,10 +1669,6 @@ public class ManagementServerImpl implements ManagementServer { } } - // Show only those that are downloaded. - boolean onlyReady = (templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.selfexecutable) || (templateFilter == TemplateFilter.sharedexecutable) - || (templateFilter == TemplateFilter.executable && isAccountSpecific) || (templateFilter == TemplateFilter.community); - Account account = null; DomainVO domain = null; if (accountId != null) { @@ -2185,8 +2194,8 @@ public class ManagementServerImpl implements ManagementServer { sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); + sb.and("podId", sb.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ); if ((accountId == null) && (domainId != null)) { @@ -2745,7 +2754,7 @@ public class ManagementServerImpl implements ManagementServer { public String getConsoleAccessUrlRoot(long vmId) { VMInstanceVO vm = this.findVMInstanceById(vmId); if (vm != null) { - ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId); + ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterIdToDeployIn(), vmId); if (proxy != null) { return proxy.getProxyImageUrl(); } @@ -3914,8 +3923,8 @@ public class ManagementServerImpl implements ManagementServer { sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getHostName(), SearchCriteria.Op.LIKE); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); + sb.and("podId", sb.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ); sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ); sb.and("nulltype", sb.entity().getType(), SearchCriteria.Op.IN); diff --git a/server/src/com/cloud/servlet/RegisterCompleteServlet.java b/server/src/com/cloud/servlet/RegisterCompleteServlet.java index 63b7af6fd16..c5b4e49ffda 100644 --- a/server/src/com/cloud/servlet/RegisterCompleteServlet.java +++ b/server/src/com/cloud/servlet/RegisterCompleteServlet.java @@ -18,6 +18,7 @@ package com.cloud.servlet; +import java.net.URLEncoder; import java.util.List; import javax.servlet.ServletContextEvent; @@ -86,6 +87,7 @@ public class RegisterCompleteServlet extends HttpServlet implements ServletConte statusCode = 503; responseMessage = "{ \"registration_info\" : { \"errorcode\" : \"503\", \"errortext\" : \"Missing token\" } }"; } else { + s_logger.info("Attempting to register user account with token = "+registrationToken); User resourceAdminUser = _accountSvc.getActiveUserByRegistrationToken(registrationToken); if (resourceAdminUser != null) { if(!resourceAdminUser.isRegistered()){ @@ -101,12 +103,12 @@ public class RegisterCompleteServlet extends HttpServlet implements ServletConte Configuration config = _configDao.findByName("endpointe.url"); StringBuffer sb = new StringBuffer(); - sb.append("{ \"registration_info\" : { \"endpoint_url\" : \""+config.getValue()+"\", "); + sb.append("{ \"registration_info\" : { \"endpoint_url\" : \""+encodeParam(config.getValue())+"\", "); sb.append("\"domain_id\" : \""+resourceAdminAccount.getDomainId()+"\", "); - sb.append("\"admin_account\" : \""+resourceAdminUser.getUsername()+"\", "); + sb.append("\"admin_account\" : \""+encodeParam(resourceAdminUser.getUsername())+"\", "); sb.append("\"admin_account_api_key\" : \""+resourceAdminUser.getApiKey()+"\", "); sb.append("\"admin_account_secret_key\" : \""+resourceAdminUser.getSecretKey()+"\", "); - sb.append("\"user_account\" : \""+rsUser.getUsername()+"\", "); + sb.append("\"user_account\" : \""+encodeParam(rsUser.getUsername())+"\", "); sb.append("\"user_account_api_key\" : \""+rsUser.getApiKey()+"\", "); sb.append("\"user_account_secret_key\" : \""+rsUser.getSecretKey()+"\" "); sb.append("} }"); @@ -125,4 +127,13 @@ public class RegisterCompleteServlet extends HttpServlet implements ServletConte s_logger.error("unknown exception writing register complete response", ex); } } + + private String encodeParam(String value) { + try { + return URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20"); + } catch (Exception e) { + s_logger.warn("Unable to encode: " + value); + } + return value; + } } diff --git a/server/src/com/cloud/storage/StorageManager.java b/server/src/com/cloud/storage/StorageManager.java index e1210cb5e42..463e9d836d1 100755 --- a/server/src/com/cloud/storage/StorageManager.java +++ b/server/src/com/cloud/storage/StorageManager.java @@ -195,5 +195,9 @@ public interface StorageManager extends Manager { boolean delPoolFromHost(long hostId); - HostVO getSecondaryStorageHost(long zoneId, long tmpltId); + HostVO getSecondaryStorageHost(long zoneId, long tmpltId); + + List getSecondaryStorageHosts(long zoneId); + + List ListByDataCenterHypervisor(long datacenterId, HypervisorType type); } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index aabb44848e7..07d54421bec 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -298,7 +298,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag protected int _pingInterval = 60; // seconds protected int _hostRetry; protected float _overProvisioningFactor = 1; - private int _maxVolumeSizeInGb; + private long _maxVolumeSizeInGb; private long _serverId; private int _snapshotTimeout; @@ -353,6 +353,23 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag return true; } } + + @Override + public List ListByDataCenterHypervisor(long datacenterId, HypervisorType type) { + List pools = _storagePoolDao.listByDataCenterId(datacenterId); + List retPools = new ArrayList(); + for (StoragePoolVO pool : pools ) { + if( pool.getStatus() != StoragePoolStatus.Up) { + continue; + } + ClusterVO cluster = _clusterDao.findById(pool.getClusterId()); + if( type == cluster.getHypervisorType()) { + retPools.add(pool); + } + } + Collections.shuffle(retPools); + return retPools; + } @Override public boolean isLocalStorageActiveOnHost(Host host) { @@ -834,7 +851,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } String maxVolumeSizeInGbString = configDao.getValue("storage.max.volume.size"); - _maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString, 2000); + _maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000); HostTemplateStatesSearch = _vmTemplateHostDao.createSearchBuilder(); HostTemplateStatesSearch.and("id", HostTemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); @@ -970,6 +987,18 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag int index = rn.nextInt(size); return hosts.get(index); } + + @Override + public List getSecondaryStorageHosts(long zoneId) { + List hosts = _hostDao.listSecondaryStorageHosts(zoneId); + if( hosts == null || hosts.size() == 0) { + hosts = _hostDao.listLocalSecondaryStorageHosts(zoneId); + if (hosts.isEmpty()) { + return new ArrayList(); + } + } + return hosts; + } @Override public String getStoragePoolTags(long poolId) { @@ -1582,7 +1611,14 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } diskOfferingId = cmd.getDiskOfferingId(); - size = cmd.getSize() * 1024 * 1024 * 1024; // user specify size in GB + size = cmd.getSize(); + if ( size != null ) { + if ( size > 0 ) { + size = size * 1024 * 1024 * 1024; // user specify size in GB + } else { + throw new InvalidParameterValueException("Disk size must be larger than 0"); + } + } if (diskOfferingId == null) { throw new InvalidParameterValueException("Missing parameter(s),either a positive volume size or a valid disk offering id must be specified."); } @@ -2410,8 +2446,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag private boolean validateVolumeSizeRange(long size) { if (size < 0 || (size > 0 && size < (1024 * 1024 * 1024))) { throw new InvalidParameterValueException("Please specify a size of at least 1 Gb."); - } else if (size > _maxVolumeSizeInGb) { - throw new InvalidParameterValueException("The maximum size allowed is " + _maxVolumeSizeInGb + " Gb."); + } else if (size > (_maxVolumeSizeInGb * 1024 * 1024 * 1024) ) { + throw new InvalidParameterValueException("volume size " + size + ", but the maximum size allowed is " + _maxVolumeSizeInGb + " Gb."); } return true; @@ -2429,7 +2465,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } else { size = (size * 1024 * 1024 * 1024); } - VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size); + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterIdToDeployIn(), owner.getDomainId(), owner.getId(), offering.getId(), size); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -2460,15 +2496,15 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag SearchCriteria sc = HostTemplateStatesSearch.create(); sc.setParameters("id", template.getId()); sc.setParameters("state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED); - sc.setJoinParameters("host", "dcId", vm.getDataCenterId()); + sc.setJoinParameters("host", "dcId", vm.getDataCenterIdToDeployIn()); List sss = _vmTemplateHostDao.search(sc, null); if (sss.size() == 0) { - throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + vm.getDataCenterId()); + throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + vm.getDataCenterIdToDeployIn()); } VMTemplateHostVO ss = sss.get(0); - VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), ss.getSize()); + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterIdToDeployIn(), owner.getDomainId(), owner.getId(), offering.getId(), ss.getSize()); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -2518,7 +2554,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag if (vm.getType() == VirtualMachine.Type.User) { UserVmVO userVM = (UserVmVO) vm.getVirtualMachine(); if (userVM.getIsoId() != null) { - Pair isoPathPair = getAbsoluteIsoPath(userVM.getIsoId(), userVM.getDataCenterId()); + Pair isoPathPair = getAbsoluteIsoPath(userVM.getIsoId(), userVM.getDataCenterIdToDeployIn()); if (isoPathPair != null) { String isoPath = isoPathPair.first(); VolumeTO iso = new VolumeTO(vm.getId(), Volume.Type.ISO, StoragePoolType.ISO, null, null, null, isoPath, 0, null, null); diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java index a0bcfa8c8e3..5875feb0312 100644 --- a/server/src/com/cloud/storage/dao/SnapshotDao.java +++ b/server/src/com/cloud/storage/dao/SnapshotDao.java @@ -37,5 +37,7 @@ public interface SnapshotDao extends GenericDao { List listByVolumeIdVersion(long volumeId, String version); Long getSecHostId(long volumeId); long updateSnapshotSecHost(long dcId, long secHostId); + List listByHostId(Filter filter, long hostId); + List listByHostId(long hostId); } diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java index 45dd79e3e5a..bc1285802c3 100644 --- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java +++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Snapshot.Type; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -47,6 +48,7 @@ public class SnapshotDaoImpl extends GenericDaoBase implements private final SearchBuilder ParentIdSearch; private final SearchBuilder backupUuidSearch; private final SearchBuilder VolumeIdVersionSearch; + private final SearchBuilder HostIdSearch; @Override public SnapshotVO findNextSnapshot(long snapshotId) { @@ -85,6 +87,19 @@ public class SnapshotDaoImpl extends GenericDaoBase implements return listBy(sc, filter); } + @Override + public List listByHostId(long hostId) { + return listByHostId(null, hostId); + } + + @Override + public List listByHostId(Filter filter, long hostId ) { + SearchCriteria sc = HostIdSearch.create(); + sc.setParameters("hostId", hostId); + sc.setParameters("status", Status.DOWNLOADED); + return listBy(sc, filter); + } + @Override public List listByVolumeIdIncludingRemoved(long volumeId) { SearchCriteria sc = VolumeIdSearch.create(); @@ -111,6 +126,11 @@ public class SnapshotDaoImpl extends GenericDaoBase implements VolumeIdSearch.and("volumeId", VolumeIdSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdSearch.done(); + HostIdSearch = createSearchBuilder(); + HostIdSearch.and("hostId", HostIdSearch.entity().getSecHostId(), SearchCriteria.Op.EQ); + HostIdSearch.and("status", HostIdSearch.entity().getStatus(), SearchCriteria.Op.EQ); + HostIdSearch.done(); + VolumeIdTypeSearch = createSearchBuilder(); VolumeIdTypeSearch.and("volumeId", VolumeIdTypeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeIdTypeSearch.and("type", VolumeIdTypeSearch.entity().getsnapshotType(), SearchCriteria.Op.EQ); diff --git a/server/src/com/cloud/storage/dao/StoragePoolDaoImpl.java b/server/src/com/cloud/storage/dao/StoragePoolDaoImpl.java index 8ec1e6948ab..a22f07435c8 100644 --- a/server/src/com/cloud/storage/dao/StoragePoolDaoImpl.java +++ b/server/src/com/cloud/storage/dao/StoragePoolDaoImpl.java @@ -280,7 +280,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp sql.delete(sql.length() - 4, sql.length()); sql.append(DetailsSqlSuffix); Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { pstmt = txn.prepareAutoCloseStatement(sql.toString()); int i = 1; @@ -297,7 +297,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp } return pools; } catch (SQLException e) { - throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e); + throw new CloudRuntimeException("Unable to execute " + pstmt, e); } } @@ -351,7 +351,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase imp while (rs.next()) { tags.add(rs.getString("name")); - } + } return tags; } catch (SQLException e) { throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e); diff --git a/server/src/com/cloud/storage/dao/VMTemplateDao.java b/server/src/com/cloud/storage/dao/VMTemplateDao.java index 5aea418bb17..18c802bef26 100644 --- a/server/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDao.java @@ -71,5 +71,6 @@ public interface VMTemplateDao extends GenericDao { VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType); VMTemplateVO findRoutingTemplate(HypervisorType type); + List listPrivateTemplatesByHost(Long hostId); } diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index 2164b13f4f7..8814ee086ef 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -21,11 +21,13 @@ package com.cloud.storage.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +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.TimeZone; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -39,6 +41,7 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.info.RunningHostCountInfo; import com.cloud.storage.Storage; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; @@ -46,6 +49,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; +import com.cloud.utils.DateUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; @@ -139,6 +143,30 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return listBy(sc, filter); } + @Override + public List listPrivateTemplatesByHost(Long hostId) { + + String sql = "select * from template_host_ref as thr INNER JOIN vm_template as t ON t.id=thr.template_id " + + "where thr.host_id=? and t.public=0 and t.featured=0 and t.type='USER' and t.removed is NULL"; + + List l = new ArrayList(); + + Transaction txn = Transaction.currentTxn(); + + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql); + pstmt.setLong(1, hostId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + l.add(rs.getLong(1)); + } + } catch (SQLException e) { + } catch (Throwable e) { + } + return l; + } + @Override public List listReadyTemplates() { SearchCriteria sc = createSearchCriteria(); diff --git a/server/src/com/cloud/storage/dao/VMTemplateHostDao.java b/server/src/com/cloud/storage/dao/VMTemplateHostDao.java index cefe359cff0..d03ac1322b8 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateHostDao.java +++ b/server/src/com/cloud/storage/dao/VMTemplateHostDao.java @@ -56,6 +56,8 @@ public interface VMTemplateHostDao extends GenericDao { boolean templateAvailable(long templateId, long hostId); - List listByZoneTemplate(long dcId, long templateId); + List listByZoneTemplate(long dcId, long templateId, boolean readyOnly); + + void deleteByHost(Long hostId); } diff --git a/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java index a9387fc1c0c..15021f7f0fb 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateHostDaoImpl.java @@ -24,15 +24,22 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.TimeZone; import javax.ejb.Local; +import javax.naming.ConfigurationException; import org.apache.log4j.Logger; + +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.DateUtil; +import com.cloud.utils.component.Inject; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; @@ -40,7 +47,8 @@ import com.cloud.utils.db.Transaction; @Local(value={VMTemplateHostDao.class}) public class VMTemplateHostDaoImpl extends GenericDaoBase implements VMTemplateHostDao { public static final Logger s_logger = Logger.getLogger(VMTemplateHostDaoImpl.class.getName()); - + @Inject + HostDao _hostDao; protected final SearchBuilder HostSearch; protected final SearchBuilder TemplateSearch; protected final SearchBuilder HostTemplateSearch; @@ -49,10 +57,11 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase HostTemplatePoolSearch; protected final SearchBuilder TemplateStatusSearch; protected final SearchBuilder TemplateStatesSearch; + protected SearchBuilder ZONE_TEMPLATE_SEARCH; protected static final String UPDATE_TEMPLATE_HOST_REF = - "UPDATE type_host_ref SET download_state = ?, download_pct= ?, last_updated = ? " + "UPDATE template_host_ref SET download_state = ?, download_pct= ?, last_updated = ? " + ", error_str = ?, local_path = ?, job_id = ? " + "WHERE host_id = ? and type_id = ?"; @@ -71,12 +80,6 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase params) throws ConfigurationException { + boolean result = super.configure(name, params); + ZONE_TEMPLATE_SEARCH = createSearchBuilder(); + ZONE_TEMPLATE_SEARCH.and("template_id", ZONE_TEMPLATE_SEARCH.entity().getTemplateId(), SearchCriteria.Op.EQ); + ZONE_TEMPLATE_SEARCH.and("state", ZONE_TEMPLATE_SEARCH.entity().getDownloadState(), SearchCriteria.Op.EQ); + SearchBuilder hostSearch = _hostDao.createSearchBuilder(); + hostSearch.and("zone_id", hostSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + ZONE_TEMPLATE_SEARCH.join("tmplHost", hostSearch, hostSearch.entity().getId(), ZONE_TEMPLATE_SEARCH.entity().getHostId(), JoinBuilder.JoinType.INNER); + ZONE_TEMPLATE_SEARCH.done(); + return result; } - @Override public void update(VMTemplateHostVO instance) { Transaction txn = Transaction.currentTxn(); @@ -275,25 +290,18 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase listByZoneTemplate(long dcId, long templateId) { - Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = null; - List result = new ArrayList(); - try { - String sql = ZONE_TEMPLATE_SEARCH; - pstmt = txn.prepareStatement(sql); - - pstmt.setLong(1, dcId); - pstmt.setLong(2, templateId); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) { - result.add(toEntityBean(rs, false)); - } - - } catch (Exception e) { - s_logger.warn("Exception: ", e); + public List listByZoneTemplate(long dcId, long templateId, boolean readyOnly) { + SearchCriteria sc = ZONE_TEMPLATE_SEARCH.create(); + sc.setParameters("template_id", templateId); + sc.setJoinParameters("tmplHost", "zone_id", dcId); + if (readyOnly) { + sc.setParameters("state", VMTemplateHostVO.Status.DOWNLOADED); + List tmplHost = new ArrayList(); + tmplHost.add(findOneBy(sc)); + return tmplHost; + } else { + return listBy(sc); } - return result; } @Override @@ -321,6 +329,14 @@ public class VMTemplateHostDaoImpl extends GenericDaoBase tmpltHosts = listByHostId(hostId); + for (VMTemplateHostVO tmpltHost : tmpltHosts ) { + remove(tmpltHost.getId()); + } + } } diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 7d4cdd07f35..37d1c91a404 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -535,11 +535,11 @@ public class DownloadMonitorImpl implements DownloadMonitor { if( tmplt.isPublicTemplate() || tmplt.isFeatured() ) { continue; } - List tmpltHosts = _vmTemplateHostDao.listByZoneTemplate(dcId, tmplt.getId()); + List tmpltHosts = _vmTemplateHostDao.listByZoneTemplate(dcId, tmplt.getId(), false); for ( VMTemplateHostVO tmpltHost : tmpltHosts ) { if ( tmpltHost.getDownloadState() == Status.DOWNLOADED || tmpltHost.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { iter.remove(); - continue; + break; } } } @@ -659,6 +659,10 @@ public class DownloadMonitorImpl implements DownloadMonitor { if (toBeDownloaded.size() > 0) { /*Only download templates whose hypervirsor type is in the zone*/ List availHypers = _clusterDao.getAvailableHypervisorInZone(ssHost.getDataCenterId()); + if (availHypers.isEmpty()) { + /*This is for cloudzone, local secondary storage resource started before cluster created*/ + availHypers.add(HypervisorType.KVM); + } /* Baremetal need not to download any template */ availHypers.remove(HypervisorType.BareMetal); availHypers.add(HypervisorType.None); //bug 9809: resume ISO download. diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index e7caa4ca1db..1d80a1f8cef 100644 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -71,9 +71,11 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.SnapshotVO; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; @@ -162,7 +164,9 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V private AgentManager _agentMgr; @Inject private NetworkManager _networkMgr; - + @Inject + protected SnapshotDao _snapshotDao; + @Inject private ClusterManager _clusterMgr; @@ -282,6 +286,26 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V return true; } + + @Override + public boolean deleteHost(Long hostId) { + List snapshots = _snapshotDao.listByHostId(hostId); + if( snapshots != null && !snapshots.isEmpty()) { + throw new CloudRuntimeException("Can not delete this secondary storage due to there are still snapshots on it "); + } + List list = _templateDao.listPrivateTemplatesByHost(hostId); + if( list != null && !list.isEmpty()) { + throw new CloudRuntimeException("Can not delete this secondary storage due to there are still private template on it "); + } + _vmTemplateHostDao.deleteByHost(hostId); + HostVO host = _hostDao.findById(hostId); + host.setGuid(null); + _hostDao.update(hostId, host); + _hostDao.remove(hostId); + + return true; + } + @Override public boolean generateVMSetupCommand(Long ssAHostId) { HostVO ssAHost = _hostDao.findById(ssAHostId); @@ -356,7 +380,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V SecStorageFirewallCfgCommand thiscpc = new SecStorageFirewallCfgCommand(); thiscpc.addPortConfig(thisSecStorageVm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF); for (SecondaryStorageVmVO ssVm : alreadyRunning) { - if ( ssVm.getDataCenterId() == zoneId ) { + if ( ssVm.getDataCenterIdToDeployIn() == zoneId ) { continue; } if (ssVm.getPublicIpAddress() != null) { @@ -844,7 +868,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V } SubscriptionMgr.getInstance().notifySubscribers(ALERT_SUBJECT, this, - new SecStorageVmAlertEventArgs(SecStorageVmAlertEventArgs.SSVM_REBOOTED, secStorageVm.getDataCenterId(), secStorageVm.getId(), secStorageVm, null)); + new SecStorageVmAlertEventArgs(SecStorageVmAlertEventArgs.SSVM_REBOOTED, secStorageVm.getDataCenterIdToDeployIn(), secStorageVm.getId(), secStorageVm, null)); return true; } else { @@ -971,7 +995,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V buf.append(" bootproto=dhcp"); } - DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterId()); + DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterIdToDeployIn()); buf.append(" internaldns1=").append(dc.getInternalDns1()); if (dc.getInternalDns2() != null) { buf.append(" internaldns2=").append(dc.getInternalDns2()); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java index 885ba5c14ce..891a73a23fa 100644 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java @@ -43,5 +43,6 @@ public interface SecondaryStorageVmManager extends Manager { public boolean generateVMSetupCommand(Long hostId); public Pair assignSecStorageVm(long zoneId, Command cmd); - boolean generateSetupCommand(Long hostId); + boolean generateSetupCommand(Long hostId); + boolean deleteHost(Long hostId); } diff --git a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java index 3b87f714fa9..c5a1e1bb446 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java +++ b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java @@ -194,17 +194,26 @@ public class UploadMonitorImpl implements UploadMonitor { String errorString = ""; boolean success = false; List storageServers = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorage, dataCenterId); - if(storageServers == null ) { + if(storageServers == null || storageServers.size() == 0) { throw new CloudRuntimeException("No Storage Server found at the datacenter - " +dataCenterId); } Type type = (template.getFormat() == ImageFormat.ISO) ? Type.ISO : Type.TEMPLATE ; - //Check if ssvm is up - HostVO sserver = storageServers.get(0); - if(sserver.getStatus() != com.cloud.host.Status.Up){ - throw new CloudRuntimeException("Couldnt create extract link - Secondary Storage Vm is not up"); - } + List storageServerVMs = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorageVM, dataCenterId); + //Check if one ssvm is up + boolean no_vm_up = true; + HostVO use_ssvm = null; + for (HostVO ssvm: storageServerVMs){ + if(ssvm.getStatus() == com.cloud.host.Status.Up){ + no_vm_up = false; + use_ssvm = ssvm; + break; + } + } + if(no_vm_up){ + throw new CloudRuntimeException("Couldnt create extract link - Secondary Storage Vm is not up"); + } //Check if it already exists. List extractURLList = _uploadDao.listByTypeUploadStatus(template.getId(), type, UploadVO.Status.DOWNLOAD_URL_CREATED); @@ -213,15 +222,15 @@ public class UploadMonitorImpl implements UploadMonitor { } // It doesn't exist so create a DB entry. - UploadVO uploadTemplateObj = new UploadVO(sserver.getId(), template.getId(), new Date(), + UploadVO uploadTemplateObj = new UploadVO(use_ssvm.getId(), template.getId(), new Date(), Status.DOWNLOAD_URL_NOT_CREATED, 0, type, Mode.HTTP_DOWNLOAD); uploadTemplateObj.setInstallPath(vmTemplateHost.getInstallPath()); _uploadDao.persist(uploadTemplateObj); try{ // Create Symlink at ssvm String uuid = UUID.randomUUID().toString() + ".vhd"; - CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(vmTemplateHost.getInstallPath(), uuid); - long result = send(sserver.getId(), cmd, null); + CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(storageServers.get(0).getParent(), vmTemplateHost.getInstallPath(), uuid); + long result = send(use_ssvm.getId(), cmd, null); if (result == -1){ errorString = "Unable to create a link for " +type+ " id:"+template.getId(); s_logger.error(errorString); @@ -230,7 +239,7 @@ public class UploadMonitorImpl implements UploadMonitor { //Construct actual URL locally now that the symlink exists at SSVM List ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running); - if (ssVms.size() > 0) { + if (ssVms.size() > 0) { SecondaryStorageVmVO ssVm = ssVms.get(0); if (ssVm.getPublicIpAddress() == null) { errorString = "A running secondary storage vm has a null public ip?"; diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 32d9d4355d1..c5e80bf262d 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -262,12 +262,20 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe } } - HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId); + List sservers = _storageMgr.getSecondaryStorageHosts(zoneId); + VMTemplateHostVO tmpltHostRef = null; - if (secondaryStorageHost != null) { - tmpltHostRef = _tmpltHostDao.findByHostTemplate(secondaryStorageHost.getId(), templateId); - if (tmpltHostRef != null && tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - throw new InvalidParameterValueException("The " + desc + " has not been downloaded "); + if (sservers != null) { + for(HostVO secondaryStorageHost: sservers){ + tmpltHostRef = _tmpltHostDao.findByHostTemplate(secondaryStorageHost.getId(), templateId); + if (tmpltHostRef != null){ + if (tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + throw new InvalidParameterValueException("The " + desc + " has not been downloaded "); + } + else { + break; + } + } } } @@ -819,7 +827,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe vm.setIsoId(iso.getId()); _userVmDao.update(vmId, vm); } - if ( !attach ) { + if ( success && !attach ) { vm.setIsoId(null); _userVmDao.update(vmId, vm); } diff --git a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index 374f55a1ac9..c926e15eb8c 100644 --- a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -75,10 +75,9 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { _upgradeMap.put("2.2.5", new DbUpgrade[] { new Upgrade225to226()}); } - protected void runScript(File file) { + protected void runScript(Connection conn, File file) { try { FileReader reader = new FileReader(file); - Connection conn = Transaction.getStandaloneConnection(); ScriptRunner runner = new ScriptRunner(conn, false, true); runner.runScript(reader); } catch (FileNotFoundException e) { @@ -142,7 +141,7 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { File[] scripts = upgrade.getPrepareScripts(); if (scripts != null) { for (File script : scripts) { - runScript(script); + runScript(conn, script); } } @@ -203,11 +202,19 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { + upgrade.getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion()); txn.start(); + + Connection conn; + try { + conn = txn.getConnection(); + } catch (SQLException e) { + s_logger.error("Unable to cleanup the database", e); + throw new CloudRuntimeException("Unable to cleanup the database", e); + } File[] scripts = upgrade.getCleanupScripts(); if (scripts != null) { for (File script : scripts) { - runScript(script); + runScript(conn, script); s_logger.debug("Cleanup script " + script.getAbsolutePath() + " is executed successfully"); } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index ce0c677cf52..01c51146a87 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -511,23 +511,34 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag throw new InvalidParameterValueException("Failed to list limits for account " + accountName + " no domain id specified."); } - Account userAccount = _accountDao.findActiveAccount(accountName, domainId); + DomainVO domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + Account userAccount = _accountDao.findActiveAccount(accountName, domainId); if (userAccount == null) { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); - } else if (account != null - && (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN || account.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) { - // If this is a non-root admin, make sure that the admin and the user account belong in the same domain or - // that the user account's domain is a child domain of the parent - if (account.getDomainId() != userAccount.getDomainId() && !_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) { - throw new PermissionDeniedException("You do not have permission to access limits for this account: " + accountName); - } + } + + if (account != null) { + checkAccess(account, domain); } accountId = userAccount.getId(); domainId = null; } else if (domainId != null) { // Look up limits for the specified domain + + DomainVO domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + + if (account != null) { + checkAccess(account, domain); + } + accountId = null; } else if (account == null) { // Look up limits for the ROOT domain @@ -934,7 +945,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag s_logger.error("Unable to destroy vm: " + vm.getId()); accountCleanupNeeded = true; } - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm.getHypervisorType().toString()); _usageEventDao.persist(usageEvent); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index aa6dbecd35a..32325f27740 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -523,7 +523,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } // Check that the VM and the volume are in the same zone - if (vm.getDataCenterId() != volume.getDataCenterId()) { + if (vm.getDataCenterIdToDeployIn() != volume.getDataCenterId()) { throw new InvalidParameterValueException("Please specify a VM that is in the same zone as the volume."); } @@ -561,8 +561,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (volume.getState().equals(Volume.State.Allocated)) { /* Need to create the volume */ VMTemplateVO rootDiskTmplt = _templateDao.findById(vm.getTemplateId()); - DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterId()); - HostPodVO pod = _podDao.findById(vm.getPodId()); + DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn()); + HostPodVO pod = _podDao.findById(vm.getPodIdToDeployIn()); StoragePoolVO rootDiskPool = _storagePoolDao.findById(rootVolumeOfVm.getPoolId()); ServiceOfferingVO svo = _serviceOfferingDao.findById(vm.getServiceOfferingId()); DiskOfferingVO diskVO = _diskOfferingDao.findById(volume.getDiskOfferingId()); @@ -838,7 +838,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (tmplt.getTemplateType() == TemplateType.PERHOST) { isoPath = tmplt.getName(); } else { - isoPathPair = _storageMgr.getAbsoluteIsoPath(isoId, vm.getDataCenterId()); + isoPathPair = _storageMgr.getAbsoluteIsoPath(isoId, vm.getDataCenterIdToDeployIn()); if (isoPathPair == null) { s_logger.warn("Couldn't get absolute iso path"); return false; @@ -1105,7 +1105,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager _accountMgr.incrementResourceCount(account.getId(), ResourceType.volume, new Long(volumes.size())); - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm .getHypervisorType().toString()); _usageEventDao.persist(usageEvent); txn.commit(); @@ -1456,11 +1456,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager volumeId = snapshot.getVolumeId(); String origTemplateInstallPath = null; - List storagePools = _storagePoolDao.listByDataCenterId(zoneId); - if (storagePools == null || storagePools.size() == 0) { + List pools = _storageMgr.ListByDataCenterHypervisor(zoneId, snapshot.getHypervisorType()); + if (pools == null || pools.size() == 0 ) { throw new CloudRuntimeException("Unable to find storage pools in zone " + zoneId); } - pool = storagePools.get(0); + pool = pools.get(0); if (snapshot.getVersion() != null && snapshot.getVersion().equalsIgnoreCase("2.1")) { VolumeVO volume = _volsDao.findByIdIncludingRemoved(volumeId); if (volume == null) { @@ -1625,7 +1625,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager s_logger.warn("Unable to delete volume:" + volume.getId() + " for vm:" + vmId + " whilst transitioning to error state"); } } - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName()); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName()); _usageEventDao.persist(usageEvent); } } @@ -2192,7 +2192,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (virtualNetworks.isEmpty()) { s_logger.debug("Creating default Virtual network for account " + owner + " as a part of deployVM process"); Network newNetwork = _networkMgr.createNetwork(defaultVirtualOffering.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, null, - zone.getId(), null, null, null, null, owner, false, null); + zone.getId(), null, null, null, null, owner, false, null, null); defaultNetwork = _networkDao.findById(newNetwork.getId()); } else if (virtualNetworks.size() > 1) { throw new InvalidParameterValueException("More than 1 default Virtaul networks are found for account " + owner + "; please specify networkIds"); @@ -2205,7 +2205,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (defaultVirtualOffering.get(0).getAvailability() == Availability.Optional) { s_logger.debug("Creating default Virtual network for account " + owner + " as a part of deployVM process"); Network newNetwork = _networkMgr.createNetwork(defaultVirtualOffering.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, null, - zone.getId(), null, null, null, null, owner, false, null); + zone.getId(), null, null, null, null, owner, false, null, null); defaultNetwork = _networkDao.findById(newNetwork.getId()); } else { throw new InvalidParameterValueException("Unable to find default networks for account " + owner); @@ -2400,7 +2400,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager sshPublicKey = pair.getPublicKey(); } - _accountMgr.checkAccess(caller, template); + // _accountMgr.checkAccess(caller, template); DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); @@ -2569,7 +2569,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager DataCenterDeployment plan = null; if (destinationHost != null) { s_logger.debug("Destination Host to deploy the VM is specified, specifying a deployment plan to deploy the VM"); - plan = new DataCenterDeployment(vm.getDataCenterId(), destinationHost.getPodId(), destinationHost.getClusterId(), destinationHost.getId(), null); + plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), destinationHost.getPodId(), destinationHost.getClusterId(), destinationHost.getId(), null); } vm = _itMgr.start(vm, params, caller, owner, plan); @@ -2604,7 +2604,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } if (template != null && template.getFormat() == ImageFormat.ISO && vm.getIsoId() != null) { String isoPath = null; - Pair isoPathPair = _storageMgr.getAbsoluteIsoPath(template.getId(), vm.getDataCenterId()); + Pair isoPathPair = _storageMgr.getAbsoluteIsoPath(template.getId(), vm.getDataCenterIdToDeployIn()); if (isoPathPair == null) { s_logger.warn("Couldn't get absolute iso path"); return false; @@ -2656,7 +2656,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { UserVmVO vm = profile.getVirtualMachine(); - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), vm.getTemplateId(), vm .getHypervisorType().toString()); _usageEventDao.persist(usageEvent); Answer startAnswer = cmds.getAnswer(StartAnswer.class); @@ -2677,7 +2677,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); long isDefault = (nic.isDefaultNic()) ? 1 : 0; - usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), network.getNetworkOfferingId(), null, isDefault); + usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName(), network.getNetworkOfferingId(), null, isDefault); _usageEventDao.persist(usageEvent); if (network.getTrafficType() == TrafficType.Guest) { originalIp = nic.getIp4Address(); @@ -2698,7 +2698,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } if (ipChanged) { - DataCenterVO dc = _dcDao.findById(vm.getDataCenterId()); + DataCenterVO dc = _dcDao.findById(vm.getDataCenterIdToDeployIn()); UserVmVO userVm = profile.getVirtualMachine(); if (dc.getDhcpProvider().equalsIgnoreCase(Provider.ExternalDhcpServer.getName())){ _nicDao.update(guestNic.getId(), guestNic); @@ -2769,13 +2769,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { VMInstanceVO vm = profile.getVirtualMachine(); - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_STOP, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName()); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_STOP, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName()); _usageEventDao.persist(usageEvent); List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); - usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), null, network.getNetworkOfferingId(), null, 0L); + usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), null, network.getNetworkOfferingId(), null, 0L); _usageEventDao.persist(usageEvent); } } @@ -2853,7 +2853,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager _usageEventDao.persist(usageEvent); } } - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName()); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterIdToDeployIn(), vm.getId(), vm.getHostName()); _usageEventDao.persist(usageEvent); if (vmState != State.Error) { @@ -2990,8 +2990,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ); sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ); sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN); - sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); + sb.and("podId", sb.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ); sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ); sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 5f114ae0b63..e3e99835beb 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -586,7 +586,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); - DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vm.getPodId(), null, null, null); + DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), null, null, null); if(planToDeploy != null){ if (s_logger.isDebugEnabled()) { s_logger.debug("advanceStart: DeploymentPlan is provided, using that plan to deploy"); @@ -1318,13 +1318,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene ConcurrentOperationException, ResourceUnavailableException { T rebootedVm = null; - DataCenter dc = _configMgr.getZone(vm.getDataCenterId()); - HostPodVO pod = _configMgr.getPod(vm.getPodId()); + DataCenter dc = _configMgr.getZone(vm.getDataCenterIdToDeployIn()); Host host = _hostDao.findById(vm.getHostId()); Cluster cluster = null; if (host != null) { cluster = _configMgr.getCluster(host.getClusterId()); } + HostPodVO pod = _configMgr.getPod(host.getPodId()); DeployDestination dest = new DeployDestination(dc, pod, cluster, host); try { @@ -1433,7 +1433,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene Command command = null; if (s_logger.isDebugEnabled()) { - s_logger.debug("VM " + serverName + ": server state = " + serverState.toString() + " and agent state = " + agentState.toString()); + s_logger.debug("VM " + serverName + ": server state = " + serverState + " and agent state = " + agentState); } if (agentState == State.Error) { @@ -1446,12 +1446,12 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY; } - HostPodVO podVO = _podDao.findById(vm.getPodId()); - DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterId()); + HostPodVO podVO = _podDao.findById(vm.getPodIdToDeployIn()); + DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn()); HostVO hostVO = _hostDao.findById(vm.getHostId()); String hostDesc = "name: " + hostVO.getName() + " (id:" + hostVO.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName(); - _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodId(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc + " due to storage failure", + _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure."); } diff --git a/server/src/com/cloud/vm/dao/ConsoleProxyDaoImpl.java b/server/src/com/cloud/vm/dao/ConsoleProxyDaoImpl.java index 401d004dc52..a9f8dcc7f5e 100644 --- a/server/src/com/cloud/vm/dao/ConsoleProxyDaoImpl.java +++ b/server/src/com/cloud/vm/dao/ConsoleProxyDaoImpl.java @@ -117,7 +117,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im public ConsoleProxyDaoImpl() { DataCenterStatusSearch = createSearchBuilder(); - DataCenterStatusSearch.and("dc", DataCenterStatusSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + DataCenterStatusSearch.and("dc", DataCenterStatusSearch.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); DataCenterStatusSearch.and("states", DataCenterStatusSearch.entity().getState(), SearchCriteria.Op.IN); DataCenterStatusSearch.done(); @@ -137,7 +137,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im HostUpSearch = createSearchBuilder(); HostUpSearch.and("host", HostUpSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostUpSearch.and("states", HostUpSearch.entity().getState(), SearchCriteria.Op.NIN); - HostUpSearch.done(); + HostUpSearch.done(); StateChangeSearch = createSearchBuilder(); StateChangeSearch.and("id", StateChangeSearch.entity().getId(), SearchCriteria.Op.EQ); @@ -171,7 +171,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im UpdateBuilder ub = getUpdateBuilder(proxy); ub.set(proxy, "state", State.Destroyed); ub.set(proxy, "privateIpAddress", null); - update(id, ub); + update(id, ub, proxy); boolean result = super.remove(id); txn.commit(); @@ -204,7 +204,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im public List listUpByHostId(long hostId) { SearchCriteria sc = HostUpSearch.create(); sc.setParameters("host", hostId); - sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); + sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); return listBy(sc); } diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index 8d6f311183f..da441354699 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -29,9 +29,9 @@ import com.cloud.network.dao.NetworkDaoImpl; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder.JoinType; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.JoinBuilder.JoinType; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; @@ -49,7 +49,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im protected DomainRouterDaoImpl() { AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("dc", AllFieldsSearch.entity().getDataCenterId(), Op.EQ); + AllFieldsSearch.and("dc", AllFieldsSearch.entity().getDataCenterIdToDeployIn(), Op.EQ); AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), Op.EQ); AllFieldsSearch.and("role", AllFieldsSearch.entity().getRole(), Op.EQ); AllFieldsSearch.and("domainId", AllFieldsSearch.entity().getDomainId(), Op.EQ); @@ -57,7 +57,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im AllFieldsSearch.and("lastHost", AllFieldsSearch.entity().getLastHostId(), Op.EQ); AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); AllFieldsSearch.and("network", AllFieldsSearch.entity().getNetworkId(), Op.EQ); - AllFieldsSearch.and("podId", AllFieldsSearch.entity().getPodId(), Op.EQ); + AllFieldsSearch.and("podId", AllFieldsSearch.entity().getPodIdToDeployIn(), Op.EQ); AllFieldsSearch.done(); IdStatesSearch = createSearchBuilder(); @@ -83,7 +83,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im router.setPublicIpAddress(null); UpdateBuilder ub = getUpdateBuilder(router); ub.set(router, "state", State.Destroyed); - update(id, ub); + update(id, ub, router); boolean result = super.remove(id); txn.commit(); diff --git a/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java b/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java index 3d33a4b8704..7f77548f3c6 100644 --- a/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java +++ b/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java @@ -54,7 +54,7 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase sc = DataCenterStatusSearch.create(); sc.setParameters("states", (Object[])states); sc.setParameters("dc", dataCenterId); - if(role != null) - sc.setParameters("role", role); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -134,8 +135,9 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase getSecStorageVmListInStates(SecondaryStorageVm.Role role, State... states) { SearchCriteria sc = StateSearch.create(); sc.setParameters("states", (Object[])states); - if(role != null) - sc.setParameters("role", role); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -144,8 +146,9 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase listByHostId(SecondaryStorageVm.Role role, long hostId) { SearchCriteria sc = HostSearch.create(); sc.setParameters("host", hostId); - if(role != null) - sc.setParameters("role", role); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -153,9 +156,10 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase listUpByHostId(SecondaryStorageVm.Role role, long hostId) { SearchCriteria sc = HostUpSearch.create(); sc.setParameters("host", hostId); - sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); - if(role != null) - sc.setParameters("role", role); + sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging}); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -166,12 +170,13 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase listByZoneId(SecondaryStorageVm.Role role, long zoneId) { SearchCriteria sc = ZoneSearch.create(); sc.setParameters("zone", zoneId); - if(role != null) - sc.setParameters("role", role); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -219,8 +225,9 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase sc = LastHostSearch.create(); sc.setParameters("lastHost", hostId); sc.setParameters("state", State.Stopped); - if(role != null) - sc.setParameters("role", role); + if(role != null) { + sc.setParameters("role", role); + } return listBy(sc); } @@ -233,10 +240,11 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase implements Use AccountPodSearch = createSearchBuilder(); AccountPodSearch.and("account", AccountPodSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountPodSearch.and("pod", AccountPodSearch.entity().getPodId(), SearchCriteria.Op.EQ); + AccountPodSearch.and("pod", AccountPodSearch.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); AccountPodSearch.done(); AccountDataCenterSearch = createSearchBuilder(); AccountDataCenterSearch.and("account", AccountDataCenterSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountDataCenterSearch.and("dc", AccountDataCenterSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + AccountDataCenterSearch.and("dc", AccountDataCenterSearch.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); AccountDataCenterSearch.done(); StateChangeSearch = createSearchBuilder(); @@ -125,7 +125,7 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use CountByAccountPod = createSearchBuilder(Long.class); CountByAccountPod.select(null, Func.COUNT, null); CountByAccountPod.and("account", CountByAccountPod.entity().getAccountId(), SearchCriteria.Op.EQ); - CountByAccountPod.and("pod", CountByAccountPod.entity().getPodId(), SearchCriteria.Op.EQ); + CountByAccountPod.and("pod", CountByAccountPod.entity().getPodIdToDeployIn(), SearchCriteria.Op.EQ); CountByAccountPod.done(); _updateTimeAttr = _allAttributes.get("updateTime"); @@ -211,7 +211,7 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use AccountDataCenterVirtualSearch = createSearchBuilder(); AccountDataCenterVirtualSearch.and("account", AccountDataCenterVirtualSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - AccountDataCenterVirtualSearch.and("dc", AccountDataCenterVirtualSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + AccountDataCenterVirtualSearch.and("dc", AccountDataCenterVirtualSearch.entity().getDataCenterIdToDeployIn(), SearchCriteria.Op.EQ); AccountDataCenterVirtualSearch.join("nicSearch", nicSearch, AccountDataCenterVirtualSearch.entity().getId(), nicSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER); AccountDataCenterVirtualSearch.done(); } diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index d4979cc6a10..de8d76f11bc 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -67,13 +67,13 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem AllFieldsSearch.and("host", AllFieldsSearch.entity().getHostId(), Op.EQ); AllFieldsSearch.and("lastHost", AllFieldsSearch.entity().getLastHostId(), Op.EQ); AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); - AllFieldsSearch.and("zone", AllFieldsSearch.entity().getDataCenterId(), Op.EQ); + AllFieldsSearch.and("zone", AllFieldsSearch.entity().getDataCenterIdToDeployIn(), Op.EQ); AllFieldsSearch.and("type", AllFieldsSearch.entity().getType(), Op.EQ); AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), Op.EQ); AllFieldsSearch.done(); ZoneTemplateNonExpungedSearch = createSearchBuilder(); - ZoneTemplateNonExpungedSearch.and("zone", ZoneTemplateNonExpungedSearch.entity().getDataCenterId(), Op.EQ); + ZoneTemplateNonExpungedSearch.and("zone", ZoneTemplateNonExpungedSearch.entity().getDataCenterIdToDeployIn(), Op.EQ); ZoneTemplateNonExpungedSearch.and("template", ZoneTemplateNonExpungedSearch.entity().getTemplateId(), Op.EQ); ZoneTemplateNonExpungedSearch.and("state", ZoneTemplateNonExpungedSearch.entity().getState(), Op.NEQ); ZoneTemplateNonExpungedSearch.done(); diff --git a/server/test/com/cloud/network/dao/NetworkDaoTest.java b/server/test/com/cloud/network/dao/NetworkDaoTest.java new file mode 100644 index 00000000000..1d51fc45433 --- /dev/null +++ b/server/test/com/cloud/network/dao/NetworkDaoTest.java @@ -0,0 +1,57 @@ +package com.cloud.network.dao; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import com.cloud.network.Network.GuestIpType; +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.utils.component.ComponentLocator; + + +public class NetworkDaoTest extends TestCase { + public void testTags() { + NetworkDaoImpl dao = ComponentLocator.inject(NetworkDaoImpl.class); + + dao.expunge(1001l); + NetworkVO network = new NetworkVO(1001, TrafficType.Control, GuestIpType.Direct, Mode.Dhcp, BroadcastDomainType.Native, 1, 1, 1, 1, 1001, "Name", "DisplayText", false, true); + network.setGuruName("guru_name"); + List tags = new ArrayList(); + + tags.add("a"); + tags.add("b"); + network.setTags(tags); + + network = dao.persist(network); + List saveTags = network.getTags(); + assert(saveTags.size() == 2 && saveTags.contains("a") && saveTags.contains("b")); + + NetworkVO retrieved = dao.findById(1001l); + List retrievedTags = retrieved.getTags(); + assert(retrievedTags.size() == 2 && retrievedTags.contains("a") && retrievedTags.contains("b")); + + List updateTags = new ArrayList(); + updateTags.add("e"); + updateTags.add("f"); + retrieved.setTags(updateTags); + dao.update(retrieved.getId(), retrieved); + + retrieved = dao.findById(1001l); + retrievedTags = retrieved.getTags(); + assert(retrievedTags.size() == 2 && retrievedTags.contains("e") && retrievedTags.contains("f")); + + + dao.expunge(1001l); + } + + public void testListBy() { + NetworkDaoImpl dao = ComponentLocator.inject(NetworkDaoImpl.class); + + dao.listBy(1l, 1l, 1l, "192.168.192.0/24"); + } + +} diff --git a/server/test/com/cloud/vm/dao/UserVmDaoImplTest.java b/server/test/com/cloud/vm/dao/UserVmDaoImplTest.java new file mode 100644 index 00000000000..7c0ff80cd07 --- /dev/null +++ b/server/test/com/cloud/vm/dao/UserVmDaoImplTest.java @@ -0,0 +1,24 @@ +package com.cloud.vm.dao; + +import junit.framework.TestCase; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; + + +public class UserVmDaoImplTest extends TestCase { + public void testPersist() { + UserVmDao dao = ComponentLocator.inject(UserVmDaoImpl.class); + + dao.expunge(1000l); + + UserVmVO vo = new UserVmVO(1000l, "instancename", "displayname", 1, HypervisorType.XenServer, 1, true, true, 1, 1, 1, "userdata", "name"); + dao.persist(vo); + + vo = dao.findById(1000l); + assert (vo.getType() == VirtualMachine.Type.User) : "Incorrect type " + vo.getType(); + } + +} diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 3b6ab9132be..5f06f195342 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -185,7 +185,7 @@ CREATE TABLE `cloud`.`networks` ( `is_security_group_enabled` tinyint NOT NULL DEFAULT 0 COMMENT '1: enabled, 0: not', PRIMARY KEY (`id`), CONSTRAINT `fk_networks__network_offering_id` FOREIGN KEY (`network_offering_id`) REFERENCES `network_offerings`(`id`), - CONSTRAINT `fk_networks__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `data_center`(`id`), + CONSTRAINT `fk_networks__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_networks__related` FOREIGN KEY(`related`) REFERENCES `networks`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_networks__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`), CONSTRAINT `fk_networks__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`), @@ -197,7 +197,7 @@ CREATE TABLE `cloud`.`network_tags` ( `network_id` bigint unsigned NOT NULL COMMENT 'id of the network', `tag` varchar(255) NOT NULL COMMENT 'tag', PRIMARY KEY (`id`), - CONSTRAINT `fk_network_tags__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks`(`id`), + CONSTRAINT `fk_network_tags__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks`(`id`) ON DELETE CASCADE, UNIQUE KEY(`network_id`, `tag`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -280,7 +280,7 @@ CREATE TABLE `cloud`.`cluster` ( `allocation_state` varchar(32) NOT NULL DEFAULT 'Enabled' COMMENT 'Is this cluster enabled for allocation for new resources', `removed` datetime COMMENT 'date removed if not null', PRIMARY KEY (`id`), - CONSTRAINT `fk_cluster__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`), + CONSTRAINT `fk_cluster__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_cluster__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`), UNIQUE `i_cluster__pod_id__name`(`pod_id`, `name`), INDEX `i_cluster__allocation_state`(`allocation_state`) @@ -490,6 +490,7 @@ CREATE TABLE `cloud`.`data_center` ( `is_security_group_enabled` tinyint NOT NULL DEFAULT 0 COMMENT '1: enabled, 0: not', `allocation_state` varchar(32) NOT NULL DEFAULT 'Enabled' COMMENT 'Is this data center enabled for allocation for new resources', `zone_token` varchar(255), + `removed` datetime COMMENT 'date removed if not null', PRIMARY KEY (`id`), CONSTRAINT `fk_data_center__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`), INDEX `i_data_center__domain_id`(`domain_id`), @@ -839,6 +840,7 @@ CREATE TABLE `cloud`.`vm_instance` ( `created` datetime NOT NULL COMMENT 'date created', `removed` datetime COMMENT 'date removed if not null', `type` varchar(32) NOT NULL COMMENT 'type of vm it is', + `vm_type` varchar(32) NOT NULL COMMENT 'vm type', `account_id` bigint unsigned NOT NULL COMMENT 'user id of owner', `domain_id` bigint unsigned NOT NULL, `service_offering_id` bigint unsigned NOT NULL COMMENT 'service offering id', diff --git a/setup/db/db/schema-21to22.sql b/setup/db/db/schema-21to22.sql index 8f546c845dc..8cd483f4495 100755 --- a/setup/db/db/schema-21to22.sql +++ b/setup/db/db/schema-21to22.sql @@ -953,7 +953,7 @@ INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (7, 'centos53-x64', 'CentOS 5.3(64-bit) no GUI (vSphere)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/CentOS5.3-x86_64.ova', 'f6f881b7f2292948d8494db837fe0f47', 0, 'CentOS 5.3(64-bit) no GUI (vSphere)', 'OVA', 12, 1, 1, 'VMware', 1); UPDATE vm_instance SET guest_os_id=15 where vm_template_id=1; -UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE unique_name='routing-xenserver-2.2.4') where vm_template_id=1; +UPDATE vm_instance SET vm_template_id=(SELECT id FROM vm_template WHERE unique_name='routing-xenserver-2.2.4' AND removed IS NULL) where vm_template_id=1; ALTER TABLE `cloud`.`instance_group` ADD CONSTRAINT `fk_instance_group__account_id` FOREIGN KEY `fk_instance_group__account_id` (`account_id`) REFERENCES `account` (`id`); diff --git a/setup/db/db/schema-222to224.sql b/setup/db/db/schema-222to224.sql index b281534a5c1..dafd73fbd74 100644 --- a/setup/db/db/schema-222to224.sql +++ b/setup/db/db/schema-222to224.sql @@ -43,7 +43,6 @@ ALTER TABLE `cloud`.`domain_router` MODIFY `guest_ip_address` char(40); ALTER TABLE `cloud`.`console_proxy` MODIFY `public_ip_address` char(40) UNIQUE; ALTER TABLE `cloud`.`secondary_storage_vm` MODIFY `public_ip_address` char(40) UNIQUE; ALTER TABLE `cloud`.`remote_access_vpn` MODIFY `local_ip` char(40) NOT NULL; -ALTER TABLE `cloud`.`storage_pool` MODIFY `host_address` char(40) NOT NULL; ALTER TABLE `cloud`.`user_ip_address` MODIFY `public_ip_address` char(40) NOT NULL; #Commented out these lines because they have to be done inside java.; diff --git a/setup/db/db/schema-225to226.sql b/setup/db/db/schema-225to226.sql index b4b10d139a7..dd7b7bbd484 100644 --- a/setup/db/db/schema-225to226.sql +++ b/setup/db/db/schema-225to226.sql @@ -6,6 +6,7 @@ ALTER TABLE `cloud`.`mshost` ADD COLUMN `runid` bigint NOT NULL DEFAULT 0 COMMEN ALTER TABLE `cloud`.`mshost` ADD COLUMN `state` varchar(10) NOT NULL default 'Down'; ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `limit_cpu_use` tinyint(1) NOT NULL DEFAULT 0 ; ALTER TABLE `cloud`.`service_offering` ADD COLUMN `limit_cpu_use` tinyint(1) NOT NULL DEFAULT 0 ; +ALTER TABLE `cloud`.`storage_pool` MODIFY `host_address` varchar(255) NOT NULL; DROP TABLE IF EXISTS `cloud`.`certificate`; CREATE TABLE `cloud`.`keystore` ( @@ -109,4 +110,5 @@ CREATE TABLE `cloud`.`swift` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - +ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `vm_type` varchar(32) NOT NULL; +UPDATE vm_instance set vm_type=type; diff --git a/tools/test/cloudkit.py b/tools/test/cloudkit.py index 2b5f6e2ef61..b8ec1b75b74 100644 --- a/tools/test/cloudkit.py +++ b/tools/test/cloudkit.py @@ -15,7 +15,7 @@ def fix_default_db(): database.update(statement % ('http://nfs1.lab.vmops.com/templates/dummy/systemvm.ova', 'routing-8')) database.update(statement % ('http://nfs1.lab.vmops.com/templates/dummy/builtin.vhd', 'centos53-x86_64')) - database.update(statement % ('http://nfs1.lab.vmops.com/templates/dummy/builtin.qcow2', 'centos55-x86_64')) + database.update(statement % ('http://nfs1.lab.vmops.com/templates/rightscale/RightImage_CentOS_5.4_x64_v5.6.32.qcow2.bz2', 'centos55-x86_64')) database.update(statement % ('http://nfs1.lab.vmops.com/templates/dummy/builtin.ova', 'centos53-x64')) statement="""UPDATE vm_template SET checksum=NULL""" database.update(statement) diff --git a/ui/index.jsp b/ui/index.jsp index f09613bcb3a..8286c509ff0 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -44,7 +44,8 @@ - + + @@ -718,6 +719,20 @@ +
+
+
+
+
+ + +
+
+
+ + + +
diff --git a/ui/jsp/instance.jsp b/ui/jsp/instance.jsp index 12b5616fd7a..74b58f73f82 100644 --- a/ui/jsp/instance.jsp +++ b/ui/jsp/instance.jsp @@ -47,7 +47,7 @@ dictionary = { 'label.full': '', 'label.available': '', 'message.launch.vm.on.private.network': '', - 'message.action.change.service.warning': '', + 'message.action.change.service.warning.for.instance': '', 'message.action.reset.password.warning': '', 'message.action.reset.password.off': '' }; diff --git a/ui/jsp/ipaddress.jsp b/ui/jsp/ipaddress.jsp index 742383ac996..13515967e25 100644 --- a/ui/jsp/ipaddress.jsp +++ b/ui/jsp/ipaddress.jsp @@ -316,12 +316,22 @@ dictionary = {
- + + + - + + +
- + + + - + + +
+ +
+
+
:
@@ -395,7 +407,7 @@ dictionary = {
-
+
:
@@ -1308,6 +1320,13 @@ dictionary = {
+ +
  • + + +
  • diff --git a/ui/jsp/router.jsp b/ui/jsp/router.jsp index 75c308cbdbf..97e327b431e 100644 --- a/ui/jsp/router.jsp +++ b/ui/jsp/router.jsp @@ -15,7 +15,10 @@ dictionary = { 'message.action.stop.router' : '', 'label.action.reboot.router' : '', 'label.action.reboot.router.processing' : '', - 'message.action.reboot.router' : '' + 'message.action.reboot.router' : '', + 'label.action.change.service': '', + 'label.action.change.service.processing': '', + 'message.action.change.service.warning.for.router': '', }; @@ -154,6 +157,16 @@ dictionary = {
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    :
    @@ -164,7 +177,7 @@ dictionary = {
    -
    +
    :
    @@ -175,7 +188,7 @@ dictionary = {
    -
    +
    :
    @@ -185,7 +198,7 @@ dictionary = {
    -
    +
    :
    @@ -210,6 +223,26 @@ dictionary = {
    + +
    diff --git a/ui/jsp/systemserviceoffering.jsp b/ui/jsp/systemserviceoffering.jsp new file mode 100644 index 00000000000..3521e55dd46 --- /dev/null +++ b/ui/jsp/systemserviceoffering.jsp @@ -0,0 +1,309 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + + + + + + + +
    + +
    +
    + +

    + +

    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    (title)
    + +
    +
    +
    +

    +

    +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + :
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    + :
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + Add System Service Offering
    + +
    +
    +
    + + + + + + +
    + + + +
    \ No newline at end of file diff --git a/ui/scripts/cloud.core.init.js b/ui/scripts/cloud.core.init.js index f6c7b9f768a..b40a5285e05 100644 --- a/ui/scripts/cloud.core.init.js +++ b/ui/scripts/cloud.core.init.js @@ -235,9 +235,10 @@ $(document).ready(function() { bindAndListMidMenuItems($("#leftmenu_submenu_systemvm"), "listSystemVms", systemVmGetSearchParams, "listsystemvmsresponse", "systemvm", "jsp/systemvm.jsp", afterLoadSystemVmJSP, systemvmToMidmenu, systemvmToRightPanel, getMidmenuId, false); //configuration - bindAndListMidMenuItems($("#leftmenu_service_offering"), "listServiceOfferings", serviceOfferingGetSearchParams, "listserviceofferingsresponse", "serviceoffering", "jsp/serviceoffering.jsp", afterLoadServiceOfferingJSP, serviceOfferingToMidmenu, serviceOfferingToRightPanel, getMidmenuId, false); + bindAndListMidMenuItems($("#leftmenu_service_offering"), "listServiceOfferings&issystem=false", serviceOfferingGetSearchParams, "listserviceofferingsresponse", "serviceoffering", "jsp/serviceoffering.jsp", afterLoadServiceOfferingJSP, serviceOfferingToMidmenu, serviceOfferingToRightPanel, getMidmenuId, false); + bindAndListMidMenuItems($("#leftmenu_system_service_offering"), "listServiceOfferings&issystem=true", systemServiceOfferingGetSearchParams, "listserviceofferingsresponse", "serviceoffering", "jsp/systemserviceoffering.jsp", afterLoadSystemServiceOfferingJSP, systemServiceOfferingToMidmenu, systemServiceOfferingToRightPanel, getMidmenuId, false); bindAndListMidMenuItems($("#leftmenu_disk_offering"), "listDiskOfferings", diskOfferingGetSearchParams, "listdiskofferingsresponse", "diskoffering", "jsp/diskoffering.jsp", afterLoadDiskOfferingJSP, diskOfferingToMidmenu, diskOfferingToRightPanel, getMidmenuId, false); - bindAndListMidMenuItems($("#leftmenu_network_offering"), "listNetworkOfferings&&guestiptype=Virtual", networkOfferingGetSearchParams, "listnetworkofferingsresponse", "networkoffering", "jsp/networkoffering.jsp", afterLoadNetworkOfferingJSP, networkOfferingToMidmenu, networkOfferingToRightPanel, getMidmenuId, false); + bindAndListMidMenuItems($("#leftmenu_network_offering"), "listNetworkOfferings&guestiptype=Virtual", networkOfferingGetSearchParams, "listnetworkofferingsresponse", "networkoffering", "jsp/networkoffering.jsp", afterLoadNetworkOfferingJSP, networkOfferingToMidmenu, networkOfferingToRightPanel, getMidmenuId, false); } $("#leftmenu_global_setting").bind("click", function(event) { diff --git a/ui/scripts/cloud.core.instance.js b/ui/scripts/cloud.core.instance.js index 80080608d59..ef6139f20e2 100644 --- a/ui/scripts/cloud.core.instance.js +++ b/ui/scripts/cloud.core.instance.js @@ -399,7 +399,7 @@ function initVMWizard() { }); $.ajax({ - data: createURL("command=listServiceOfferings"), + data: createURL("command=listServiceOfferings&issystem=false"), dataType: "json", async: false, success: function(json) { @@ -1665,7 +1665,7 @@ function doChangeService($actionLink, $detailsTab, $midmenuItem1) { if (jsonObj.state != 'Stopped') { $("#dialog_info") - .text(dictionary['message.action.change.service.warning']) + .text(dictionary['message.action.change.service.warning.for.instance']) .dialog('option', 'buttons', { "OK": function() { $(this).dialog("close"); diff --git a/ui/scripts/cloud.core.ipaddress.js b/ui/scripts/cloud.core.ipaddress.js index bf7f125791c..5f656b0773a 100644 --- a/ui/scripts/cloud.core.ipaddress.js +++ b/ui/scripts/cloud.core.ipaddress.js @@ -255,12 +255,37 @@ function afterLoadIpJSP() { //*** Port Forwarding tab (begin) *** var $createPortForwardingRow = $("#tab_content_port_forwarding").find("#create_port_forwarding_row"); - + + // If public end port gets filled, disable private ports and copy public ports over to private ports + $createPortForwardingRow.find("#public_end_port").bind("keyup", function(event) { + if($(this).val() != null && $(this).val().length > 0) { + $createPortForwardingRow.find("#private_port").attr("readonly", true); + $createPortForwardingRow.find("#private_end_port").attr("readonly", true); + + $createPortForwardingRow.find("#private_port").val($createPortForwardingRow.find("#public_port").val()); + $createPortForwardingRow.find("#private_end_port").val($(this).val()); + } + else { + $createPortForwardingRow.find("#private_port").removeAttr("readonly"); + $createPortForwardingRow.find("#private_end_port").removeAttr("readonly"); + } + return true; + }); + $createPortForwardingRow.find("#public_port").bind("keyup", function(event) { + if($createPortForwardingRow.find("#private_port").attr("readonly") == true) + $createPortForwardingRow.find("#private_port").val($(this).val()); + return true; + }); + $createPortForwardingRow.find("#add_link").bind("click", function(event){ var isValid = true; - isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg")); - isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535); - isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535); + isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg")); + + isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535, false); //required + isValid &= validateInteger("Public End Port", $createPortForwardingRow.find("#public_end_port"), $createPortForwardingRow.find("#public_end_port_errormsg"), 1, 65535, true); //optional + + isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required + isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional if (!isValid) return; @@ -273,17 +298,26 @@ function afterLoadIpJSP() { var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1"); var ipObj = $midmenuItem1.data("jsonObj"); - - var publicPort = $createPortForwardingRow.find("#public_port").val(); - var privatePort = $createPortForwardingRow.find("#private_port").val(); - var protocol = $createPortForwardingRow.find("#protocol").val(); - var virtualMachineId = $createPortForwardingRow.find("#vm").val(); - - var array1 = []; - array1.push("&ipaddressid="+ipObj.id); - array1.push("&publicport="+publicPort); - array1.push("&privateport="+privatePort); - array1.push("&protocol="+protocol); + + var array1 = []; + array1.push("&ipaddressid="+ipObj.id); + + var publicPort = $createPortForwardingRow.find("#public_port").val(); + array1.push("&publicport="+publicPort); + var publicEndPort = $createPortForwardingRow.find("#public_end_port").val(); + if(publicEndPort != null && publicEndPort.length > 0) + array1.push("&publicendport="+publicEndPort); + + var privatePort = $createPortForwardingRow.find("#private_port").val(); + array1.push("&privateport="+privatePort); + var privateEndPort = $createPortForwardingRow.find("#private_end_port").val(); + if(privateEndPort != null && privateEndPort.length > 0) + array1.push("&privateendport="+privateEndPort); + + var protocol = $createPortForwardingRow.find("#protocol").val(); + array1.push("&protocol="+protocol); + + var virtualMachineId = $createPortForwardingRow.find("#vm").val(); array1.push("&virtualmachineid=" + virtualMachineId); $.ajax({ @@ -1221,23 +1255,27 @@ function ipJsonToDetailsTab() { function ipFindNetworkServiceByName(pName, networkObj) { if(networkObj == null) - return null; - for(var i=0; i 0) + publicPort += (" - " + fromdb(jsonObj.publicendport)); + $template.find("#public_port").text(publicPort); + + var privatePort = fromdb(jsonObj.privateport); + if(jsonObj.privateendport != null && jsonObj.privateendport.length > 0) + privatePort += (" - " + fromdb(jsonObj.privateendport)); + $template.find("#private_port").text(privatePort); - $template.find("#row_container #private_port").text(fromdb(jsonObj.privateport)); - $template.find("#row_container_edit #private_port").val(fromdb(jsonObj.privateport)); - - $template.find("#row_container #protocol").text(fromdb(jsonObj.protocol)); - $template.find("#row_container_edit #protocol").text(fromdb(jsonObj.protocol)); + $template.find("#protocol").text(fromdb(jsonObj.protocol)); var vmName = getVmName(jsonObj.virtualmachinename, jsonObj.virtualmachinedisplayname); - $template.find("#row_container #vm_name").text(vmName); + $template.find("#vm_name").text(vmName); var virtualMachineId = fromdb(jsonObj.virtualmachineid); - ipSetRuleState(fromdb(jsonObj.state), $template.find("#row_container #state")); + ipSetRuleState(fromdb(jsonObj.state), $template.find("#state")); var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1"); if($midmenuItem1 == null) @@ -1513,17 +1554,10 @@ function portForwardingJsonToTemplate(jsonObj, $template) { var ipObj = $midmenuItem1.data("jsonObj"); if(ipObj == null) return; - var ipAddress = fromdb(ipObj.ipaddress); - - var $vmSelect = $template.find("#row_container_edit #vm").empty(); - ipPopulateVMDropdown($vmSelect); - $vmSelect.val(virtualMachineId); - - var $rowContainer = $template.find("#row_container"); - var $rowContainerEdit = $template.find("#row_container_edit"); - + var ipAddress = fromdb(ipObj.ipaddress); + $template.find("#delete_link").unbind("click").bind("click", function(event){ - var $spinningWheel = $rowContainer.find("#spinning_wheel"); + var $spinningWheel = $template.find("#spinning_wheel"); $spinningWheel.find("#description").text(g_dictionary["label.deleting.processing"]); $spinningWheel.show(); @@ -1579,8 +1613,10 @@ function portForwardingJsonToTemplate(jsonObj, $template) { function refreshCreatePortForwardingRow() { var $createPortForwardingRow = $("#create_port_forwarding_row"); - $createPortForwardingRow.find("#public_port").val(""); - $createPortForwardingRow.find("#private_port").val(""); + $createPortForwardingRow.find("#public_port").val(""); + $createPortForwardingRow.find("#public_end_port").val(""); + $createPortForwardingRow.find("#private_port").val(""); + $createPortForwardingRow.find("#private_end_port").val(""); var $vmSelect = $createPortForwardingRow.find("#vm").empty(); ipPopulateVMDropdown($vmSelect); diff --git a/ui/scripts/cloud.core.iso.js b/ui/scripts/cloud.core.iso.js index d7038ec50a2..12d8a5fe352 100644 --- a/ui/scripts/cloud.core.iso.js +++ b/ui/scripts/cloud.core.iso.js @@ -249,7 +249,7 @@ function initCreateVmFromIsoDialog() { var $dialogCreateVmFromIso = $("#dialog_create_vm_from_iso"); $.ajax({ - data: createURL("command=listServiceOfferings"), + data: createURL("command=listServiceOfferings&issystem=false"), dataType: "json", success: function(json) { var items = json.listserviceofferingsresponse.serviceoffering; diff --git a/ui/scripts/cloud.core.network.js b/ui/scripts/cloud.core.network.js index 22e51c1116e..deb6db2ed4c 100644 --- a/ui/scripts/cloud.core.network.js +++ b/ui/scripts/cloud.core.network.js @@ -89,8 +89,8 @@ function afterLoadNetworkJSP($leftmenuItem1) { networkPopulateMiddleMenu($leftmenuItem1); bindAddNetworkButton(); - $readonlyFields = $("#direct_network_page").find("#tab_content_details").find("#name, #displaytext"); - $editFields = $("#direct_network_page").find("#tab_content_details").find("#name_edit, #displaytext_edit"); + $readonlyFields = $("#direct_network_page").find("#tab_content_details").find("#name, #displaytext, #tags"); + $editFields = $("#direct_network_page").find("#tab_content_details").find("#name_edit, #displaytext_edit, #tags_edit"); } function networkPopulateMiddleMenu($leftmenuItem1) { @@ -724,13 +724,13 @@ function bindAddExternalFirewallButton() { var array1 = []; - array1.push("&zoneid=" + zoneObj.id); + array1.push("&zoneid=" + todb(zoneObj.id)); var username = $thisDialog.find("#username").val(); - array1.push("&username="+username); + array1.push("&username=" + todb(username)); var password = $thisDialog.find("#password").val(); - array1.push("&password="+password); + array1.push("&password=" + todb(password)); //*** construct URL (begin) *** var url = []; @@ -904,13 +904,13 @@ function bindAddLoadBalancerButton() { var array1 = []; - array1.push("&zoneid=" + zoneObj.id); + array1.push("&zoneid=" + todb(zoneObj.id)); var username = $thisDialog.find("#username").val(); - array1.push("&username="+username); + array1.push("&username=" + todb(username)); var password = $thisDialog.find("#password").val(); - array1.push("&password="+password); + array1.push("&password=" + todb(password)); //*** construct URL (begin) *** var url = []; @@ -1070,7 +1070,8 @@ function directNetworkJsonToDetailsTab() { $thisTab.find("#vlan").text(fromdb(jsonObj.vlan)); $thisTab.find("#gateway").text(fromdb(jsonObj.gateway)); $thisTab.find("#netmask").text(fromdb(jsonObj.netmask)); - + $thisTab.find("#tags").text(fromdb(jsonObj.tags)); + $thisTab.find("#tags_edit").val(fromdb(jsonObj.tags)); $thisTab.find("#domain").text(fromdb(jsonObj.domain)); //might be null $thisTab.find("#account").text(fromdb(jsonObj.account)); //might be null @@ -1079,7 +1080,8 @@ function directNetworkJsonToDetailsTab() { bindActionLink($actionLink); var $actionMenu = $actionLink.find("#action_menu"); - $actionMenu.find("#action_list").empty(); + $actionMenu.find("#action_list").empty(); + buildActionLinkForTab("label.action.edit.network", directNetworkActionMap, $actionMenu, $midmenuItem1, $thisTab); buildActionLinkForTab("label.action.delete.network", directNetworkActionMap, $actionMenu, $midmenuItem1, $thisTab); @@ -1092,11 +1094,15 @@ function directNetworkJsonClearDetailsTab() { $thisTab.find("#grid_header_title").text(""); $thisTab.find("#id").text(""); $thisTab.find("#name").text(""); - $thisTab.find("#displaytext").text(""); + $thisTab.find("#name_edit").val(""); + $thisTab.find("#displaytext").text(""); + $thisTab.find("#displaytext_edit").val(""); $thisTab.find("#default").text(""); $thisTab.find("#vlan").text(""); $thisTab.find("#gateway").text(""); - $thisTab.find("#netmask").text(""); + $thisTab.find("#netmask").text(""); + $thisTab.find("#tags").text(""); + $thisTab.find("#tags_edit").val(""); $thisTab.find("#domain").text(""); $thisTab.find("#account").text(""); @@ -1253,7 +1259,8 @@ function bindAddNetworkButton() { isValid &= validateIp("Netmask", $thisDialog.find("#add_publicip_vlan_netmask"), $thisDialog.find("#add_publicip_vlan_netmask_errormsg")); isValid &= validateIp("Start IP Range", $thisDialog.find("#add_publicip_vlan_startip"), $thisDialog.find("#add_publicip_vlan_startip_errormsg")); //required isValid &= validateIp("End IP Range", $thisDialog.find("#add_publicip_vlan_endip"), $thisDialog.find("#add_publicip_vlan_endip_errormsg"), true); //optional - + isValid &= validateString("Tags", $thisDialog.find("#tags"), $thisDialog.find("#tags_errormsg"), true); //optional + if($thisDialog.find("#domain_container").css("display") != "none") { isValid &= validateString("Domain", $thisDialog.find("#domain"), $thisDialog.find("#domain_errormsg"), false); //required var domainName = $thisDialog.find("#domain").val(); @@ -1285,13 +1292,23 @@ function bindAddNetworkButton() { $thisDialog.find("#spinning_wheel").show() + var array1 = []; + array1.push("&zoneId="+zoneObj.id); + + var name = todb($thisDialog.find("#add_publicip_vlan_network_name").val()); + array1.push("&name="+name); + + var desc = todb($thisDialog.find("#add_publicip_vlan_network_desc").val()); + array1.push("&displayText="+desc); + var vlan = trim($thisDialog.find("#add_publicip_vlan_vlan").val()); if (isTagged) { vlan = "&vlan="+vlan; } else { vlan = "&vlan=untagged"; } - + array1.push(vlan); + var scopeParams = ""; if($thisDialog.find("#domain_container").css("display") != "none") { if ($thisDialog.find("#add_publicip_vlan_account_container").css("display") != "none") { @@ -1301,17 +1318,28 @@ function bindAddNetworkButton() { } } else if (isDirect) { scopeParams = "&isshared=true"; - } + } + array1.push(scopeParams); - var isDefault = trim($thisDialog.find("#add_publicip_vlan_default").val()); - var gateway = trim($thisDialog.find("#add_publicip_vlan_gateway").val()); - var netmask = trim($thisDialog.find("#add_publicip_vlan_netmask").val()); - var startip = trim($thisDialog.find("#add_publicip_vlan_startip").val()); - var endip = trim($thisDialog.find("#add_publicip_vlan_endip").val()); - - // Creating network for the direct networking - var name = todb($thisDialog.find("#add_publicip_vlan_network_name").val()); - var desc = todb($thisDialog.find("#add_publicip_vlan_network_desc").val()); + var isDefault = $thisDialog.find("#add_publicip_vlan_default").val(); + array1.push("isDefault="+isDefault); + + var gateway = $thisDialog.find("#add_publicip_vlan_gateway").val(); + array1.push("&gateway="+todb(gateway)); + + var netmask = $thisDialog.find("#add_publicip_vlan_netmask").val(); + array1.push("&netmask="+todb(netmask)); + + var startip = $thisDialog.find("#add_publicip_vlan_startip").val(); + array1.push("&startip="+todb(startip)); + + var endip = $thisDialog.find("#add_publicip_vlan_endip").val(); + array1.push("&endip="+todb(endip)); + + var tags = $thisDialog.find("#add_publicip_vlan_endip").val(); + array1.push("&tags="+todb(tags)); + + // Creating network for the direct networking $.ajax({ data: createURL("command=listNetworkOfferings&guestiptype=Direct"), dataType: "json", @@ -1321,9 +1349,11 @@ function bindAddNetworkButton() { if (networkOfferings != null && networkOfferings.length > 0) { for (var i = 0; i < networkOfferings.length; i++) { if (networkOfferings[i].isdefault) { + array1.push("&networkOfferingId="+networkOfferings[i].id); + // Create a network from this. $.ajax({ - data: createURL("command=createNetwork&isDefault="+isDefault+"&name="+name+"&displayText="+desc+"&networkOfferingId="+networkOfferings[i].id+"&zoneId="+zoneObj.id+vlan+scopeParams+"&gateway="+todb(gateway)+"&netmask="+todb(netmask)+"&startip="+todb(startip)+"&endip="+todb(endip)), + data: createURL("command=createNetwork"+array1.join("")), dataType: "json", success: function(json) { $thisDialog.find("#spinning_wheel").hide(); @@ -1501,7 +1531,10 @@ function doEditDirectNetwork2($actionLink, $detailsTab, $midmenuItem1, $readonly var displaytext = $detailsTab.find("#displaytext_edit").val(); array1.push("&displayText="+todb(displaytext)); - + + var tags = $detailsTab.find("#tags_edit").val(); + array1.push("&tags="+todb(tags)); + $.ajax({ data: createURL("command=updateNetwork&id="+id+array1.join("")), dataType: "json", diff --git a/ui/scripts/cloud.core.pod.js b/ui/scripts/cloud.core.pod.js index 4daa29b3ec8..7b84838e4d0 100644 --- a/ui/scripts/cloud.core.pod.js +++ b/ui/scripts/cloud.core.pod.js @@ -997,26 +997,26 @@ function bindAddNetworkDeviceButton($leftmenuItem1) { $thisDialog.find("#spinning_wheel").show(); var array1 = []; - array1.push("&networkdevicetype="+$thisDialog.find("#network_device_type").val()); - array1.push("&networkdeviceparameterlist[0].zoneid=" + zoneId); - array1.push("&networkdeviceparameterlist[0].podid=" + podId); - array1.push("&networkdeviceparameterlist[0].url="+$thisDialog.find("#url").val()); - array1.push("&networkdeviceparameterlist[0].username="+$thisDialog.find("#username").val()); - array1.push("&networkdeviceparameterlist[0].password="+$thisDialog.find("#password").val()); + array1.push("&networkdevicetype=" + todb($thisDialog.find("#network_device_type").val())); + array1.push("&networkdeviceparameterlist[0].zoneid=" + todb(zoneId)); + array1.push("&networkdeviceparameterlist[0].podid=" + todb(podId)); + array1.push("&networkdeviceparameterlist[0].url=" + todb($thisDialog.find("#url").val())); + array1.push("&networkdeviceparameterlist[0].username=" + todb($thisDialog.find("#username").val())); + array1.push("&networkdeviceparameterlist[0].password=" + todb($thisDialog.find("#password").val())); if($("#DHCP_server_type_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].dhcpservertype=" + $thisDialog.find("#DHCP_server_type").val()); + array1.push("&networkdeviceparameterlist[0].dhcpservertype=" + todb($thisDialog.find("#DHCP_server_type").val())); if($("#Pxe_server_type_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].pxeservertype=" + $thisDialog.find("#Pxe_server_type").val()); + array1.push("&networkdeviceparameterlist[0].pxeservertype=" + todb($thisDialog.find("#Pxe_server_type").val())); if($("#PING_storage_IP_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].pingstorageserverip=" + $thisDialog.find("#PING_storage_IP").val()); + array1.push("&networkdeviceparameterlist[0].pingstorageserverip=" + todb($thisDialog.find("#PING_storage_IP").val())); if($("#PING_dir_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].pingdir=" + $thisDialog.find("#PING_dir").val()); + array1.push("&networkdeviceparameterlist[0].pingdir=" + todb($thisDialog.find("#PING_dir").val())); if($("#TFTP_dir_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].tftpdir=" + $thisDialog.find("#TFTP_dir").val()); + array1.push("&networkdeviceparameterlist[0].tftpdir=" + todb($thisDialog.find("#TFTP_dir").val())); if($("#PING_CIFS_username_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].pingcifsusername=" + $thisDialog.find("#PING_CIFS_username").val()); + array1.push("&networkdeviceparameterlist[0].pingcifsusername=" + todb($thisDialog.find("#PING_CIFS_username").val())); if($("#PING_CIFS_password_container").css("display") != "none") - array1.push("&networkdeviceparameterlist[0].pingcifspassword=" + $thisDialog.find("#PING_CIFS_password").val()); + array1.push("&networkdeviceparameterlist[0].pingcifspassword=" + todb($thisDialog.find("#PING_CIFS_password").val())); $.ajax({ data: createURL("command=addNetworkDevice" + array1.join("")), diff --git a/ui/scripts/cloud.core.router.js b/ui/scripts/cloud.core.router.js index 8e1dce7d909..6dcb63de640 100644 --- a/ui/scripts/cloud.core.router.js +++ b/ui/scripts/cloud.core.router.js @@ -75,7 +75,8 @@ function routerGetSearchParams() { } function afterLoadRouterJSP() { - + // dialogs + initDialog("dialog_change_system_service_offering", 600); } function routerToMidmenu(jsonObj, $midmenuItem1) { @@ -176,7 +177,8 @@ function routerJsonToDetailsTab() { $thisTab.find("#publicip").text(fromdb(jsonObj.publicip)); $thisTab.find("#privateip").text(fromdb(jsonObj.linklocalip)); $thisTab.find("#guestipaddress").text(fromdb(jsonObj.guestipaddress)); - $thisTab.find("#hostname").text(fromdb(jsonObj.hostname)); + $thisTab.find("#hostname").text(fromdb(jsonObj.hostname)); + $thisTab.find("#serviceOfferingName").text(fromdb(jsonObj.serviceofferingname)); $thisTab.find("#networkdomain").text(fromdb(jsonObj.networkdomain)); $thisTab.find("#domain").text(fromdb(jsonObj.domain)); $thisTab.find("#account").text(fromdb(jsonObj.account)); @@ -198,11 +200,13 @@ function routerBuildActionMenu(jsonObj, $thisTab, $midmenuItem1) { if (jsonObj.state == 'Running') { buildActionLinkForTab("label.action.stop.router", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); - buildActionLinkForTab("label.action.reboot.router", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); + buildActionLinkForTab("label.action.reboot.router", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); + buildActionLinkForTab("label.action.change.service", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); noAvailableActions = false; } else if (jsonObj.state == 'Stopped') { - buildActionLinkForTab("label.action.start.router", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); + buildActionLinkForTab("label.action.start.router", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); + buildActionLinkForTab("label.action.change.service", routerActionMap, $actionMenu, $midmenuItem1, $thisTab); noAvailableActions = false; } @@ -222,7 +226,8 @@ function routerClearDetailsTab() { $thisTab.find("#publicip").text(""); $thisTab.find("#privateip").text(""); $thisTab.find("#guestipaddress").text(""); - $thisTab.find("#hostname").text(""); + $thisTab.find("#hostname").text(""); + $thisTab.find("#serviceOfferingName").text(""); $thisTab.find("#networkdomain").text(""); $thisTab.find("#domain").text(""); $thisTab.find("#account").text(""); @@ -291,6 +296,64 @@ function doRebootRouter($actionLink, $detailsTab, $midmenuItem1) { }).dialog("open"); } +function doChangeSystemServiceOffering($actionLink, $detailsTab, $midmenuItem1) { + var jsonObj = $midmenuItem1.data("jsonObj"); + var id = jsonObj.id; + + if (jsonObj.state != 'Stopped') { + $("#dialog_info") + .text(dictionary['message.action.change.service.warning.for.router']) + .dialog('option', 'buttons', { + "OK": function() { + $(this).dialog("close"); + } + }).dialog("open"); + return; + } + + $.ajax({ + data: createURL("command=listServiceOfferings&issystem=true"), + dataType: "json", + async: false, + success: function(json) { + var offerings = json.listserviceofferingsresponse.serviceoffering; + var offeringSelect = $("#dialog_change_system_service_offering #change_service_offerings").empty(); + + if (offerings != null && offerings.length > 0) { + for (var i = 0; i < offerings.length; i++) { + var option = $("").data("name", fromdb(offerings[i].name)); + offeringSelect.append(option); + } + } + } + }); + + $("#dialog_change_system_service_offering") + .dialog('option', 'buttons', { + "OK": function() { + var $thisDialog = $(this); + + var isValid = true; + isValid &= validateDropDownBox("Service Offering", $thisDialog.find("#change_service_offerings"), $thisDialog.find("#change_service_offerings_errormsg")); + if (!isValid) + return; + + $thisDialog.dialog("close"); + var serviceOfferingId = $thisDialog.find("#change_service_offerings").val(); + + if(jsonObj.state != "Stopped") { + $midmenuItem1.find("#info_icon").addClass("error").show(); + $midmenuItem1.data("afterActionInfo", ($actionLink.data("label") + " action failed. Reason: virtual instance needs to be stopped before you can change its service.")); + } + var apiCommand = "command=changeServiceForRouter&id="+id+"&serviceofferingid="+serviceOfferingId; + doActionToTab(id, $actionLink, apiCommand, $midmenuItem1, $detailsTab); + }, + "Cancel": function() { + $(this).dialog("close"); + } + }).dialog("open"); +} + var routerActionMap = { "label.action.start.router": { isAsyncJob: true, @@ -321,5 +384,14 @@ var routerActionMap = { var item = json.queryasyncjobresultresponse.jobresult.domainrouter; routerToMidmenu(item, $midmenuItem1); } + }, + "label.action.change.service": { + isAsyncJob: false, + inProcessText: "label.action.change.service", + dialogBeforeActionFn : doChangeSystemServiceOffering, + afterActionSeccessFn: function(json, $midmenuItem1, id) { + var jsonObj = json.changeserviceforrouterresponse.domainrouter; + vmToMidmenu(jsonObj, $midmenuItem1); + } } } \ No newline at end of file diff --git a/ui/scripts/cloud.core.serviceoffering.js b/ui/scripts/cloud.core.serviceoffering.js index 8da1185d0b9..e05d58e8f31 100644 --- a/ui/scripts/cloud.core.serviceoffering.js +++ b/ui/scripts/cloud.core.serviceoffering.js @@ -159,7 +159,7 @@ function initAddServiceOfferingDialog() { } $.ajax({ - data: createURL("command=createServiceOffering"+array1.join("")), + data: createURL("command=createServiceOffering&issystem=false"+array1.join("")), dataType: "json", success: function(json) { var item = json.createserviceofferingresponse.serviceoffering; @@ -362,7 +362,8 @@ function serviceOfferingClearDetailsTab() { $thisTab.find("#cpu").text(""); $thisTab.find("#memory").text(""); $thisTab.find("#offerha").text(""); - $thisTab.find("#offerha_edit").val(""); + $thisTab.find("#offerha_edit").val(""); + $thisTab.find("#limitcpuuse").text(""); $thisTab.find("#tags").text(""); $thisTab.find("#domain").text(""); $thisTab.find("#domain_edit").val(""); diff --git a/ui/scripts/cloud.core.systemserviceoffering.js b/ui/scripts/cloud.core.systemserviceoffering.js new file mode 100644 index 00000000000..0e61edbb300 --- /dev/null +++ b/ui/scripts/cloud.core.systemserviceoffering.js @@ -0,0 +1,396 @@ + /** + * 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 . + * + */ + +function systemServiceOfferingGetSearchParams() { + var moreCriteria = []; + + var searchInput = $("#basic_search").find("#search_input").val(); + if (searchInput != null && searchInput.length > 0) { + moreCriteria.push("&keyword="+todb(searchInput)); + } + + var $advancedSearchPopup = getAdvancedSearchPopupInSearchContainer(); + if ($advancedSearchPopup.length > 0 && $advancedSearchPopup.css("display") != "none" ) { + if ($advancedSearchPopup.find("#adv_search_domain_li").css("display") != "none" + && $advancedSearchPopup.find("#domain").hasClass("textwatermark") == false) { + var domainName = $advancedSearchPopup.find("#domain").val(); + if (domainName != null && domainName.length > 0) { + var domainId; + if(autoCompleteDomains != null && autoCompleteDomains.length > 0) { + for(var i=0; i < autoCompleteDomains.length; i++) { + if(fromdb(autoCompleteDomains[i].name).toLowerCase() == domainName.toLowerCase()) { + domainId = autoCompleteDomains[i].id; + break; + } + } + } + if(domainId == null) { + showError(false, $advancedSearchPopup.find("#domain"), $advancedSearchPopup.find("#domain_errormsg"), g_dictionary["label.not.found"]); + } + else { //e.g. domainId == 5 (number) + showError(true, $advancedSearchPopup.find("#domain"), $advancedSearchPopup.find("#domain_errormsg"), null) + moreCriteria.push("&domainid="+todb(domainId)); + } + } + } + } + + return moreCriteria.join(""); +} + +function afterLoadSystemServiceOfferingJSP() { + initAddSystemServiceOfferingDialog(); + + $readonlyFields = $("#tab_content_details").find("#name, #displaytext"); + $editFields = $("#tab_content_details").find("#name_edit, #displaytext_edit"); +} + +function initAddSystemServiceOfferingDialog() { + initDialog("dialog_add_systemserviceoffering"); + + var $dialogAddSystemServiceOffering = $("#dialog_add_systemserviceoffering"); + $dialogAddSystemServiceOffering.find("#public_dropdown").unbind("change").bind("change", function(event) { + if($(this).val() == "true") { //public zone + $dialogAddSystemServiceOffering.find("#domain_container").hide(); + } + else { //private zone + $dialogAddSystemServiceOffering.find("#domain_container").show(); + } + return false; + }); + + applyAutoCompleteToDomainField($dialogAddSystemServiceOffering.find("#domain")); + + $("#add_systemserviceoffering_button").unbind("click").bind("click", function(event) { + $dialogAddSystemServiceOffering.find("#add_service_name").val(""); + $dialogAddSystemServiceOffering.find("#add_service_display").val(""); + $dialogAddSystemServiceOffering.find("#add_service_cpucore").val(""); + $dialogAddSystemServiceOffering.find("#add_service_cpu").val(""); + $dialogAddSystemServiceOffering.find("#add_service_memory").val(""); + $dialogAddSystemServiceOffering.find("#add_service_offerha").val("false"); + + $dialogAddSystemServiceOffering + .dialog('option', 'buttons', { + "Add": function() { + var $thisDialog = $(this); + + // validate values + var isValid = true; + isValid &= validateString("Name", $thisDialog.find("#add_service_name"), $thisDialog.find("#add_service_name_errormsg")); + isValid &= validateString("Display Text", $thisDialog.find("#add_service_display"), $thisDialog.find("#add_service_display_errormsg")); + isValid &= validateInteger("# of CPU Core", $thisDialog.find("#add_service_cpucore"), $thisDialog.find("#add_service_cpucore_errormsg"), 1, 1000); + isValid &= validateInteger("CPU", $thisDialog.find("#add_service_cpu"), $thisDialog.find("#add_service_cpu_errormsg"), 100, 100000); + isValid &= validateInteger("Memory", $thisDialog.find("#add_service_memory"), $thisDialog.find("#add_service_memory_errormsg"), 64, 1000000); + isValid &= validateString("Tags", $thisDialog.find("#add_service_tags"), $thisDialog.find("#add_service_tags_errormsg"), true); //optional + + if($thisDialog.find("#domain_container").css("display") != "none") { + isValid &= validateString("Domain", $thisDialog.find("#domain"), $thisDialog.find("#domain_errormsg"), false); //required + var domainName = $thisDialog.find("#domain").val(); + var domainId; + if(domainName != null && domainName.length > 0) { + if(autoCompleteDomains != null && autoCompleteDomains.length > 0) { + for(var i=0; i < autoCompleteDomains.length; i++) { + if(fromdb(autoCompleteDomains[i].name).toLowerCase() == domainName.toLowerCase()) { + domainId = autoCompleteDomains[i].id; + break; + } + } + } + if(domainId == null) { + showError(false, $thisDialog.find("#domain"), $thisDialog.find("#domain_errormsg"), g_dictionary["label.not.found"]); + isValid &= false; + } + } + } + + if (!isValid) + return; + $thisDialog.dialog("close"); + + var $midmenuItem1 = beforeAddingMidMenuItem() ; + + var array1 = []; + var name = $thisDialog.find("#add_service_name").val(); + array1.push("&name="+todb(name)); + + var display = $thisDialog.find("#add_service_display").val(); + array1.push("&displayText="+todb(display)); + + var storagetype = $thisDialog.find("#add_service_storagetype").val(); + array1.push("&storageType="+storagetype); + + var core = $thisDialog.find("#add_service_cpucore").val(); + array1.push("&cpuNumber="+core); + + var cpu = $thisDialog.find("#add_service_cpu").val(); + array1.push("&cpuSpeed="+cpu); + + var memory = $thisDialog.find("#add_service_memory").val(); + array1.push("&memory="+memory); + + var offerha = $thisDialog.find("#add_service_offerha").val(); + array1.push("&offerha="+offerha); + + var tags = $thisDialog.find("#add_service_tags").val(); + if(tags != null && tags.length > 0) + array1.push("&tags="+todb(tags)); + + if($thisDialog.find("#cpu_cap_dropdown_container").css("display") != "none") { + array1.push("&limitcpuuse="+$thisDialog.find("#cpu_cap_dropdown").val()); + } + + if($thisDialog.find("#domain_container").css("display") != "none") { + array1.push("&domainid="+domainId); + } + + $.ajax({ + data: createURL("command=createServiceOffering&issystem=true"+array1.join("")), + dataType: "json", + success: function(json) { + var item = json.createserviceofferingresponse.serviceoffering; + systemServiceOfferingToMidmenu(item, $midmenuItem1); + bindClickToMidMenu($midmenuItem1, systemServiceOfferingToRightPanel, getMidmenuId); + afterAddingMidMenuItem($midmenuItem1, true); + + }, + error: function(XMLHttpResponse) { + handleError(XMLHttpResponse, function() { + afterAddingMidMenuItem($midmenuItem1, false, parseXMLHttpResponse(XMLHttpResponse)); + }); + } + }); + }, + "Cancel": function() { + $(this).dialog("close"); + } + }).dialog("open"); + return false; + }); +} + +function doEditSystemServiceOffering($actionLink, $detailsTab, $midmenuItem1) { + $readonlyFields.hide(); + $editFields.show(); + $detailsTab.find("#cancel_button, #save_button").show(); + + $detailsTab.find("#cancel_button").unbind("click").bind("click", function(event){ + cancelEditMode($detailsTab); + return false; + }); + $detailsTab.find("#save_button").unbind("click").bind("click", function(event){ + doEditSystemServiceOffering2($actionLink, $detailsTab, $midmenuItem1, $readonlyFields, $editFields); + return false; + }); +} + +function doEditSystemServiceOffering2($actionLink, $detailsTab, $midmenuItem1, $readonlyFields, $editFields) { + var jsonObj = $midmenuItem1.data("jsonObj"); + var id = jsonObj.id; + + // validate values + var isValid = true; + isValid &= validateString("Name", $detailsTab.find("#name_edit"), $detailsTab.find("#name_edit_errormsg"), true); + isValid &= validateString("Display Text", $detailsTab.find("#displaytext_edit"), $detailsTab.find("#displaytext_edit_errormsg"), true); + if (!isValid) + return; + + var array1 = []; + var name = $detailsTab.find("#name_edit").val(); + array1.push("&name="+todb(name)); + var displaytext = $detailsTab.find("#displaytext_edit").val(); + array1.push("&displayText="+todb(displaytext)); + var offerha = $detailsTab.find("#offerha_edit").val(); + array1.push("&offerha="+offerha); + + var tags = $detailsTab.find("#tags_edit").val(); + array1.push("&tags="+todb(tags)); + + var domainid = $detailsTab.find("#domain_edit").val(); + array1.push("&domainid="+todb(domainid)); + + $.ajax({ + data: createURL("command=updateServiceOffering&id="+id+array1.join("")), + dataType: "json", + success: function(json) { + var jsonObj = json.updateserviceofferingresponse.serviceoffering; + systemServiceOfferingToMidmenu(jsonObj, $midmenuItem1); + systemServiceOfferingToRightPanel($midmenuItem1); + + $editFields.hide(); + $readonlyFields.show(); + $("#save_button, #cancel_button").hide(); + } + }); +} + +function doDeleteSystemServiceOffering($actionLink, $detailsTab, $midmenuItem1) { + var jsonObj = $midmenuItem1.data("jsonObj"); + var id = jsonObj.id; + + $("#dialog_confirmation") + .text(dictionary["message.action.delete.service.offering"]) + .dialog('option', 'buttons', { + "Confirm": function() { + $(this).dialog("close"); + var apiCommand = "command=deleteServiceOffering&id="+id; + doActionToTab(id, $actionLink, apiCommand, $midmenuItem1, $detailsTab); + }, + "Cancel": function() { + $(this).dialog("close"); + } + }).dialog("open"); +} + +function systemServiceOfferingToMidmenu(jsonObj, $midmenuItem1) { + $midmenuItem1.attr("id", getMidmenuId(jsonObj)); + $midmenuItem1.data("jsonObj", jsonObj); + + var $iconContainer = $midmenuItem1.find("#icon_container").show(); + $iconContainer.find("#icon").attr("src", "images/midmenuicon_system_serviceoffering.png"); + + var firstRowText = fromdb(jsonObj.name); + $midmenuItem1.find("#first_row").text(firstRowText); + $midmenuItem1.find("#first_row_container").attr("title", firstRowText); + + var secondRowText = jsonObj.cpunumber + " x " + convertHz(jsonObj.cpuspeed); + $midmenuItem1.find("#second_row").text(secondRowText); + $midmenuItem1.find("#second_row_container").attr("title", secondRowText); +} + +function systemServiceOfferingToRightPanel($midmenuItem1) { + copyActionInfoFromMidMenuToRightPanel($midmenuItem1); + $("#right_panel_content").data("$midmenuItem1", $midmenuItem1); + systemServiceOfferingJsonToDetailsTab(); +} + +function systemServiceOfferingJsonToDetailsTab() { + var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1"); + if($midmenuItem1 == null) { + systemServiceOfferingClearDetailsTab(); + return; + } + + var jsonObj = $midmenuItem1.data("jsonObj"); + if(jsonObj == null) { + systemServiceOfferingClearDetailsTab(); + return; + } + + var $thisTab = $("#right_panel_content #tab_content_details"); + $thisTab.find("#tab_container").hide(); + $thisTab.find("#tab_spinning_wheel").show(); + + var id = jsonObj.id; + + $.ajax({ + data: createURL("command=listServiceOfferings&id="+id), + dataType: "json", + async: false, + success: function(json) { + var items = json.listserviceofferingsresponse.serviceoffering; + if(items != null && items.length > 0) { + jsonObj = items[0]; + $midmenuItem1.data("jsonObj", jsonObj); + } + } + }); + + $thisTab.find("#id").text(fromdb(jsonObj.id)); + + $thisTab.find("#grid_header_title").text(fromdb(jsonObj.name)); + $thisTab.find("#name").text(fromdb(jsonObj.name)); + $thisTab.find("#name_edit").val(fromdb(jsonObj.name)); + + $thisTab.find("#displaytext").text(fromdb(jsonObj.displaytext)); + $thisTab.find("#displaytext_edit").val(fromdb(jsonObj.displaytext)); + + $thisTab.find("#storagetype").text(fromdb(jsonObj.storagetype)); + $thisTab.find("#cpu").text(jsonObj.cpunumber + " x " + convertHz(jsonObj.cpuspeed)); + $thisTab.find("#memory").text(convertBytes(parseInt(jsonObj.memory)*1024*1024)); + + setBooleanReadField(jsonObj.offerha, $thisTab.find("#offerha")); + setBooleanEditField(jsonObj.offerha, $thisTab.find("#offerha_edit")); + + setBooleanReadField(jsonObj.limitcpuuse, $thisTab.find("#limitcpuuse")); + + $thisTab.find("#tags").text(fromdb(jsonObj.tags)); + $thisTab.find("#tags_edit").val(fromdb(jsonObj.tags)); + + $thisTab.find("#domain").text(fromdb(jsonObj.domain)); + $thisTab.find("#domain_edit").val(fromdb(jsonObj.domainid)); + + setDateField(jsonObj.created, $thisTab.find("#created")); + + //actions *** + var $actionMenu = $("#right_panel_content #tab_content_details #action_link #action_menu"); + $actionMenu.find("#action_list").empty(); + buildActionLinkForTab("label.action.edit.service.offering", systemServiceOfferingActionMap, $actionMenu, $midmenuItem1, $thisTab); + buildActionLinkForTab("label.action.delete.service.offering", systemServiceOfferingActionMap, $actionMenu, $midmenuItem1, $thisTab); + + $thisTab.find("#tab_spinning_wheel").hide(); + $thisTab.find("#tab_container").show(); +} + +function systemServiceOfferingClearRightPanel() { + systemServiceOfferingClearDetailsTab(); +} + +function systemServiceOfferingClearDetailsTab() { + var $thisTab = $("#right_panel_content #tab_content_details"); + $thisTab.find("#id").text(""); + $thisTab.find("#grid_header_title").text(""); + $thisTab.find("#name").text(""); + $thisTab.find("#name_edit").val(""); + $thisTab.find("#displaytext").text(""); + $thisTab.find("#displaytext_edit").val(""); + $thisTab.find("#storagetype").text(""); + $thisTab.find("#cpu").text(""); + $thisTab.find("#memory").text(""); + $thisTab.find("#offerha").text(""); + $thisTab.find("#offerha_edit").val(""); + $thisTab.find("#limitcpuuse").text(""); + $thisTab.find("#tags").text(""); + $thisTab.find("#domain").text(""); + $thisTab.find("#domain_edit").val(""); + $thisTab.find("#created").text(""); + + var $actionMenu = $("#right_panel_content #tab_content_details #action_link #action_menu"); + $actionMenu.find("#action_list").empty(); + $actionMenu.find("#action_list").append($("#no_available_actions").clone().show()); +} + +var systemServiceOfferingActionMap = { + "label.action.edit.service.offering": { + dialogBeforeActionFn: doEditSystemServiceOffering + }, + "label.action.delete.service.offering": { + api: "deleteServiceOffering", + isAsyncJob: false, + dialogBeforeActionFn : doDeleteSystemServiceOffering, + inProcessText: "label.action.delete.service.offering.processing", + afterActionSeccessFn: function(json, $midmenuItem1, id) { + $midmenuItem1.slideUp("slow", function() { + $(this).remove(); + if(id.toString() == $("#right_panel_content").find("#tab_content_details").find("#id").text()) { + clearRightPanel(); + systemServiceOfferingClearRightPanel(); + } + }); + } + } +} \ No newline at end of file diff --git a/ui/scripts/cloud.core.template.js b/ui/scripts/cloud.core.template.js index f93146daf58..943cfe08770 100644 --- a/ui/scripts/cloud.core.template.js +++ b/ui/scripts/cloud.core.template.js @@ -148,7 +148,7 @@ function afterLoadTemplateJSP() { var $midmenuItem1 = beforeAddingMidMenuItem() ; $.ajax({ - data: createURL("command=registerTemplate&name="+todb(name)+"&displayText="+todb(desc)+"&url="+todb(url)+"&zoneid="+zoneId+"&ispublic="+isPublic+moreCriteria.join("")+"&format="+format+"&passwordEnabled="+password+"&osTypeId="+osType+"&hypervisor="+hypervisor+"&response=json"), + data: createURL("command=registerTemplate&name="+todb(name)+"&displayText="+todb(desc)+"&url="+todb(url)+"&zoneid="+zoneId+"&ispublic="+isPublic+moreCriteria.join("")+"&format="+format+"&passwordEnabled="+password+"&osTypeId="+osType+"&hypervisor="+hypervisor+""), dataType: "json", success: function(json) { var items = json.registertemplateresponse.template; @@ -233,7 +233,7 @@ function afterLoadTemplateJSP() { //zone dropdown (end) $.ajax({ - data: createURL("command=listOsTypes&response=json"), + data: createURL("command=listOsTypes"), dataType: "json", async: false, success: function(json) { @@ -253,7 +253,7 @@ function afterLoadTemplateJSP() { }); $.ajax({ - data: createURL("command=listServiceOfferings&response=json"), + data: createURL("command=listServiceOfferings&issystem=false"), dataType: "json", success: function(json) { var items = json.listserviceofferingsresponse.serviceoffering; @@ -266,7 +266,7 @@ function afterLoadTemplateJSP() { }); $.ajax({ - data: createURL("command=listDiskOfferings&response=json"), + data: createURL("command=listDiskOfferings"), dataType: "json", success: function(json) { var items = json.listdiskofferingsresponse.diskoffering; diff --git a/utils/src/com/cloud/utils/component/ComponentLocator.java b/utils/src/com/cloud/utils/component/ComponentLocator.java index a709a02fa5f..8ac6dcc8eba 100755 --- a/utils/src/com/cloud/utils/component/ComponentLocator.java +++ b/utils/src/com/cloud/utils/component/ComponentLocator.java @@ -90,6 +90,7 @@ public class ComponentLocator implements ComponentLocatorMBean { protected static Callback[] s_callbacks = new Callback[] { NoOp.INSTANCE, new DatabaseCallback()}; protected static CallbackFilter s_callbackFilter = new DatabaseCallbackFilter(); protected static final List> s_interceptors = new ArrayList>(); + protected static CleanupThread s_janitor = null; protected HashMap> _adapterMap; protected HashMap> _managerMap; @@ -99,12 +100,18 @@ public class ComponentLocator implements ComponentLocatorMBean { protected HashMap, Class> _factories; static { - Runtime.getRuntime().addShutdownHook(new CleanupThread()); + if (s_janitor == null) { + s_janitor = new CleanupThread(); + Runtime.getRuntime().addShutdownHook(new CleanupThread()); + } } public ComponentLocator(String server) { _serverName = server; - Runtime.getRuntime().addShutdownHook(new CleanupThread()); + if (s_janitor == null) { + s_janitor = new CleanupThread(); + Runtime.getRuntime().addShutdownHook(new CleanupThread()); + } } public String getLocatorName() { @@ -237,7 +244,7 @@ public class ComponentLocator implements ComponentLocatorMBean { if (singleton.state == Singleton.State.Instantiated) { inject(info.clazz, info.instance); singleton.state = Singleton.State.Injected; - } + } if (singleton.state == Singleton.State.Injected) { if (!info.instance.configure(info.name, info.params)) { s_logger.error("Unable to configure DAO: " + info.name); @@ -398,7 +405,7 @@ public class ComponentLocator implements ComponentLocatorMBean { System.exit(1); } s.state = Singleton.State.Configured; - } + } } else { s_logger.info("Configuring Manager: " + info.name); try { @@ -526,7 +533,7 @@ public class ComponentLocator implements ComponentLocatorMBean { s_logger.info("Injecting singleton Adapter: " + info.getName()); inject(info.clazz, info.instance); singleton.state = Singleton.State.Injected; - } + } if (singleton.state == Singleton.State.Injected) { s_logger.info("Configuring singleton Adapter: " + info.getName()); if (!info.instance.configure(info.name, info.params)) { @@ -551,7 +558,7 @@ public class ComponentLocator implements ComponentLocatorMBean { s_logger.error("Unable to configure adapter: " + info.name, e); System.exit(1); } - } + } } } @@ -1015,43 +1022,45 @@ public class ComponentLocator implements ComponentLocatorMBean { protected static class CleanupThread extends Thread { @Override - public synchronized void run() { - for (ComponentLocator locator : s_locators.values()) { - Iterator> itAdapters = locator._adapterMap.values().iterator(); - while (itAdapters.hasNext()) { - Adapters adapters = itAdapters.next(); - itAdapters.remove(); - for (ComponentInfo adapter : adapters._infos) { - if (adapter.singleton) { - Singleton singleton = s_singletons.get(adapter.clazz); - if (singleton.state == Singleton.State.Started) { + public void run() { + synchronized (CleanupThread.class) { + for (ComponentLocator locator : s_locators.values()) { + Iterator> itAdapters = locator._adapterMap.values().iterator(); + while (itAdapters.hasNext()) { + Adapters adapters = itAdapters.next(); + itAdapters.remove(); + for (ComponentInfo adapter : adapters._infos) { + if (adapter.singleton) { + Singleton singleton = s_singletons.get(adapter.clazz); + if (singleton.state == Singleton.State.Started) { + s_logger.info("Asking " + adapter.getName() + " to shutdown."); + adapter.instance.stop(); + singleton.state = Singleton.State.Stopped; + } else { + s_logger.debug("Skippng " + adapter.getName() + " because it has already stopped"); + } + } else { s_logger.info("Asking " + adapter.getName() + " to shutdown."); adapter.instance.stop(); - singleton.state = Singleton.State.Stopped; - } else { - s_logger.debug("Skippng " + adapter.getName() + " because it has already stopped"); } - } else { - s_logger.info("Asking " + adapter.getName() + " to shutdown."); - adapter.instance.stop(); } } } - } - - for (ComponentLocator locator : s_locators.values()) { - Iterator> itManagers = locator._managerMap.values().iterator(); - while (itManagers.hasNext()) { - ComponentInfo manager = itManagers.next(); - itManagers.remove(); - if (manager.singleton == true) { - Singleton singleton = s_singletons.get(manager.clazz); - if (singleton != null && singleton.state == Singleton.State.Started) { - s_logger.info("Asking Manager " + manager.getName() + " to shutdown."); - manager.instance.stop(); - singleton.state = Singleton.State.Stopped; - } else { - s_logger.info("Skipping Manager " + manager.getName() + " because it is not in a state to shutdown."); + + for (ComponentLocator locator : s_locators.values()) { + Iterator> itManagers = locator._managerMap.values().iterator(); + while (itManagers.hasNext()) { + ComponentInfo manager = itManagers.next(); + itManagers.remove(); + if (manager.singleton == true) { + Singleton singleton = s_singletons.get(manager.clazz); + if (singleton != null && singleton.state == Singleton.State.Started) { + s_logger.info("Asking Manager " + manager.getName() + " to shutdown."); + manager.instance.stop(); + singleton.state = Singleton.State.Stopped; + } else { + s_logger.info("Skipping Manager " + manager.getName() + " because it is not in a state to shutdown."); + } } } } diff --git a/utils/src/com/cloud/utils/db/Attribute.java b/utils/src/com/cloud/utils/db/Attribute.java index aefb02dd139..ee13be3f42d 100755 --- a/utils/src/com/cloud/utils/db/Attribute.java +++ b/utils/src/com/cloud/utils/db/Attribute.java @@ -21,6 +21,7 @@ import java.lang.reflect.Field; import javax.persistence.AttributeOverride; import javax.persistence.Column; +import javax.persistence.ElementCollection; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -54,49 +55,50 @@ public class Attribute { CharDT(0x100000), StringDT(0x200000), IntegerDT(0x400000); - + int place; Flag(int place) { this.place = place; } - + public int place() { return place; } - + public boolean check(int value) { return (value & place) == place; } - + public int setTrue(int value) { return (value | place); } - + public int setFalse(int value) { return (value & ~place); } } - + protected String table; protected String columnName; protected Field field; protected int flags; protected Column column; - + protected Object attache; + public Attribute(Class clazz, AttributeOverride[] overrides, Field field, String tableName, boolean isEmbedded, boolean isId) { this.field = field; flags = 0; table = tableName; setupColumnInfo(clazz, overrides, tableName, isEmbedded, isId); } - + public Attribute(String table, String columnName) { this.table = table; this.columnName = columnName; this.field = null; this.column = null; } - + protected void setupColumnInfo(Class clazz, AttributeOverride[] overrides, String tableName, boolean isEmbedded, boolean isId) { flags = Flag.Selectable.setTrue(flags); GeneratedValue gv = field.getAnnotation(GeneratedValue.class); @@ -122,7 +124,7 @@ public class Attribute { if (isEmbedded) { flags = Flag.Embedded.setTrue(flags); } - + if (isId) { flags = Flag.Id.setTrue(flags); } else { @@ -143,6 +145,12 @@ public class Attribute { flags = Flag.Nullable.setTrue(flags); } } + ElementCollection ec = field.getAnnotation(ElementCollection.class); + if (ec != null) { + flags = Flag.Insertable.setFalse(flags); + flags = Flag.Selectable.setFalse(flags); + } + Temporal temporal = field.getAnnotation(Temporal.class); if (temporal != null) { if (temporal.value() == TemporalType.DATE) { @@ -153,50 +161,50 @@ public class Attribute { flags = Flag.TimeStamp.setTrue(flags); } } - + if (column != null && column.table().length() > 0) { table = column.table(); } - + columnName = DbUtil.getColumnName(field, overrides); } - + public final boolean isInsertable() { return Flag.Insertable.check(flags); } - + public final boolean isUpdatable() { return Flag.Updatable.check(flags); } - + public final boolean isNullable() { return Flag.Nullable.check(flags); } - + public final boolean isId() { return Flag.Id.check(flags); } - + public final boolean isSelectable() { return Flag.Selectable.check(flags); } - + public final boolean is(Flag flag) { return flag.check(flags); } - + public final void setTrue(Flag flag) { flags = flag.setTrue(flags); } - + public final void setFalse(Flag flag) { flags = flag.setFalse(flags); } - + public Field getField() { return field; } - + public Object get(Object entity) { try { return field.get(entity); @@ -205,23 +213,23 @@ public class Attribute { return null; } } - + @Override public int hashCode() { - return columnName.hashCode(); + return columnName.hashCode(); } - + @Override public boolean equals(Object obj) { - if (!(obj instanceof Attribute)) { - return false; - } - - Attribute that = (Attribute)obj; - - return columnName.equals(that.columnName) && table.equals(that.table); + if (!(obj instanceof Attribute)) { + return false; + } + + Attribute that = (Attribute)obj; + + return columnName.equals(that.columnName) && table.equals(that.table); } - + @Override public String toString() { return table + "." + columnName; diff --git a/utils/src/com/cloud/utils/db/EcInfo.java b/utils/src/com/cloud/utils/db/EcInfo.java new file mode 100644 index 00000000000..cdbeb2441fa --- /dev/null +++ b/utils/src/com/cloud/utils/db/EcInfo.java @@ -0,0 +1,107 @@ +/** + * 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.utils.db; + +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.JoinColumn; + +import com.cloud.utils.exception.CloudRuntimeException; + +public class EcInfo { + protected String insertSql; + protected String selectSql; + protected String clearSql; + protected Class targetClass; + protected Class rawClass; + + public EcInfo(Attribute attr, Attribute idAttr) { + attr.attache = this; + ElementCollection ec = attr.field.getAnnotation(ElementCollection.class); + targetClass = ec.targetClass(); + Class type = attr.field.getType(); + if (type.isArray()) { + rawClass = null; + } else { + ParameterizedType pType = (ParameterizedType)attr.field.getGenericType(); + Type rawType = pType.getRawType(); + Class rawClazz = (Class)rawType; + try { + if (!Modifier.isAbstract(rawClazz.getModifiers()) && !rawClazz.isInterface() && rawClazz.getConstructors().length != 0 && rawClazz.getConstructor() != null) { + rawClass = rawClazz; + } else if (Set.class == rawClazz) { + rawClass = HashSet.class; + } else if (List.class == rawClazz) { + rawClass = ArrayList.class; + } else if (Collection.class == Collection.class) { + rawClass = ArrayList.class; + } else { + assert (false) : " We don't know how to create this calss " + rawType.toString() + " for " + attr.field.getName(); + } + } catch (NoSuchMethodException e) { + throw new CloudRuntimeException("Write your own support for " + rawClazz + " defined by " + attr.field.getName()); + } + } + + CollectionTable ct = attr.field.getAnnotation(CollectionTable.class); + assert (ct.name().length() > 0) : "Please sepcify the table for " + attr.field.getName(); + StringBuilder selectBuf = new StringBuilder("SELECT "); + StringBuilder insertBuf = new StringBuilder("INSERT INTO "); + StringBuilder clearBuf = new StringBuilder("DELETE FROM "); + + clearBuf.append(ct.name()).append(" WHERE "); + selectBuf.append(attr.columnName); + selectBuf.append(" FROM ").append(ct.name()).append(", ").append(attr.table); + selectBuf.append(" WHERE "); + + insertBuf.append(ct.name()).append("("); + StringBuilder valuesBuf = new StringBuilder("SELECT "); + + for (JoinColumn jc : ct.joinColumns()) { + selectBuf.append(ct.name()).append(".").append(jc.name()).append("="); + if (jc.referencedColumnName().length() == 0) { + selectBuf.append(idAttr.table).append(".").append(idAttr.columnName); + valuesBuf.append(idAttr.table).append(".").append(idAttr.columnName); + clearBuf.append(ct.name()).append(".").append(jc.name()).append("=?"); + } else { + selectBuf.append(attr.table).append(".").append(jc.referencedColumnName()); + valuesBuf.append(attr.table).append(".").append(jc.referencedColumnName()).append(","); + } + selectBuf.append(" AND "); + insertBuf.append(jc.name()).append(", "); + valuesBuf.append(", "); + } + + selectSql = selectBuf.append(idAttr.table).append(".").append(idAttr.columnName).append("=?").toString(); + insertBuf.append(attr.columnName).append(") "); + valuesBuf.append("? FROM ").append(attr.table); + valuesBuf.append(" WHERE ").append(idAttr.table).append(".").append(idAttr.columnName).append("=?"); + + insertSql = insertBuf.append(valuesBuf).toString(); + clearSql = clearBuf.toString(); + } +} diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index 1be42c4f5d9..2a31e6f84c6 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -19,6 +19,7 @@ package com.cloud.utils.db; import java.io.Serializable; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -26,7 +27,6 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; @@ -36,11 +36,13 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.naming.ConfigurationException; import javax.persistence.AttributeOverride; @@ -49,7 +51,6 @@ import javax.persistence.EmbeddedId; import javax.persistence.EntityExistsException; import javax.persistence.EnumType; import javax.persistence.Enumerated; -import javax.persistence.OneToMany; import javax.persistence.TableGenerator; import net.sf.cglib.proxy.Callback; @@ -72,6 +73,9 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; +import edu.emory.mathcs.backport.java.util.Arrays; +import edu.emory.mathcs.backport.java.util.Collections; + /** * GenericDaoBase is a simple way to implement DAOs. It DOES NOT * support the full EJB3 spec. It borrows some of the annotations from @@ -111,7 +115,7 @@ public abstract class GenericDaoBase implements Gene protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT"); - protected final static Map, GenericDao> s_daoMaps = new HashMap, GenericDao>(71); + protected final static Map, GenericDao> s_daoMaps = new ConcurrentHashMap, GenericDao>(71); protected Class _entityBeanType; protected String _table; @@ -132,10 +136,10 @@ public abstract class GenericDaoBase implements Gene protected Pair _removed; protected Pair _removeSql; protected List> _deleteSqls; - protected Map _idAttributes; - protected Map _tgs; + protected final Map _idAttributes; + protected final Map _tgs; protected final Map _allAttributes; - protected List _oneToManyAttributes; + protected final List _ecAttributes; protected final Map, Attribute> _allColumns; protected Enhancer _enhancer; protected Factory _factory; @@ -150,21 +154,6 @@ public abstract class GenericDaoBase implements Gene protected static final SequenceFetcher s_seqFetcher = SequenceFetcher.getInstance(); - protected static PreparedStatement s_initStmt; - static { - Connection conn = Transaction.getStandaloneConnection(); - try { - s_initStmt = conn.prepareStatement("SELECT 1"); - } catch (final SQLException e) { - } finally { - try { - conn.close(); - } catch (SQLException e) { - } - } - - } - protected String _name; public static GenericDao getDao(Class entityType) { @@ -224,7 +213,7 @@ public abstract class GenericDaoBase implements Gene _deleteSqls = generator.buildDeleteSqls(); _removed = generator.getRemovedAttribute(); _tgs = generator.getTableGenerators(); - _oneToManyAttributes = generator.getOneToManyAttributes(); + _ecAttributes = generator.getElementCollectionAttributes(); TableGenerator tg = this.getClass().getAnnotation(TableGenerator.class); if (tg != null) { @@ -235,7 +224,7 @@ public abstract class GenericDaoBase implements Gene _tgs.put(tg.name(), tg); } - Callback[] callbacks = new Callback[] { NoOp.INSTANCE, new UpdateBuilder(_allAttributes) }; + Callback[] callbacks = new Callback[] { NoOp.INSTANCE, new UpdateBuilder(this) }; _enhancer = new Enhancer(); _enhancer.setSuperclass(_entityBeanType); @@ -245,7 +234,7 @@ public abstract class GenericDaoBase implements Gene _searchEnhancer = new Enhancer(); _searchEnhancer.setSuperclass(_entityBeanType); - _searchEnhancer.setCallback(new UpdateBuilder(_allAttributes)); + _searchEnhancer.setCallback(new UpdateBuilder(this)); if (s_logger.isTraceEnabled()) { s_logger.trace("Select SQL: " + _partialSelectSql.first().toString()); @@ -261,13 +250,20 @@ public abstract class GenericDaoBase implements Gene for (final Pair deletSql : _deleteSqls) { s_logger.trace(deletSql.first()); } + + s_logger.trace("Collection SQLs"); + for (Attribute attr : _ecAttributes) { + EcInfo info = (EcInfo)attr.attache; + s_logger.trace(info.insertSql); + s_logger.trace(info.selectSql); + } } } @Override @DB(txn=false) @SuppressWarnings("unchecked") public T createForUpdate(final ID id) { - final T entity = (T)_factory.newInstance(new Callback[] {NoOp.INSTANCE, new UpdateBuilder(_allAttributes)}); + final T entity = (T)_factory.newInstance(new Callback[] {NoOp.INSTANCE, new UpdateBuilder(this)}); if (id != null) { try { _idField.set(entity, id); @@ -345,7 +341,7 @@ public abstract class GenericDaoBase implements Gene final String sql = str.toString(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; final List result = new ArrayList(); try { pstmt = txn.prepareAutoCloseStatement(sql); @@ -375,9 +371,9 @@ public abstract class GenericDaoBase implements Gene } return result; } catch (final SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } catch (final Throwable e) { - throw new CloudRuntimeException("Caught: " + pstmt.toString(), e); + throw new CloudRuntimeException("Caught: " + pstmt, e); } } @@ -407,7 +403,7 @@ public abstract class GenericDaoBase implements Gene final String sql = str.toString(); final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { pstmt = txn.prepareAutoCloseStatement(sql); int i = 0; @@ -447,9 +443,9 @@ public abstract class GenericDaoBase implements Gene return results; } catch (final SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } catch (final Throwable e) { - throw new CloudRuntimeException("Caught: " + pstmt.toString(), e); + throw new CloudRuntimeException("Caught: " + pstmt, e); } } @@ -610,7 +606,7 @@ public abstract class GenericDaoBase implements Gene return (M)new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new CloudRuntimeException("UnsupportedEncodingException exception while converting UTF-8 data"); - } + } } else { return null; } @@ -708,26 +704,38 @@ public abstract class GenericDaoBase implements Gene } if (s_logger.isTraceEnabled()) { - s_logger.trace("join search statement is " + pstmt.toString()); + s_logger.trace("join search statement is " + pstmt); } return count; } - @DB(txn=false) - protected int update(final ID id, final UpdateBuilder ub) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd(_idAttributes.get(_table)[0], SearchCriteria.Op.EQ, id); - int rowsUpdated = update(ub, sc, null); + protected int update(ID id, UpdateBuilder ub, T entity) { if (_cache != null) { _cache.remove(id); } + SearchCriteria sc = createSearchCriteria(); + sc.addAnd(_idAttributes.get(_table)[0], SearchCriteria.Op.EQ, id); + Transaction txn = Transaction.currentTxn(); + txn.start(); + + int rowsUpdated = update(ub, sc, null); + + try { + if (ub.getCollectionChanges() != null) { + insertElementCollection(entity, _idAttributes.get(_table)[0], id, ub.getCollectionChanges()); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to persist element collection", e); + } + txn.commit(); + return rowsUpdated; } // @Override - public int update(final UpdateBuilder ub, final SearchCriteria sc, Integer rows) { + public int update(UpdateBuilder ub, final SearchCriteria sc, Integer rows) { StringBuilder sql = null; - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; final Transaction txn = Transaction.currentTxn(); try { final String searchClause = sc.getWhereClause(); @@ -765,9 +773,8 @@ public abstract class GenericDaoBase implements Gene if (e.getSQLState().equals("23000") && e.getErrorCode() == 1062) { throw new EntityExistsException("Entity already exists ", e); } - final String sqlStr = pstmt.toString(); - throw new CloudRuntimeException("DB Exception on: " + sqlStr, e); - } + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); + } } @DB(txn=false) @@ -881,7 +888,7 @@ public abstract class GenericDaoBase implements Gene sql.append(lock ? FOR_UPDATE_CLAUSE : SHARE_MODE_CLAUSE); } Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { pstmt = txn.prepareAutoCloseStatement(sql.toString()); @@ -892,8 +899,8 @@ public abstract class GenericDaoBase implements Gene ResultSet rs = pstmt.executeQuery(); return rs.next() ? toEntityBean(rs, true) : null; } catch (SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e); - } + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); + } } @Override @DB(txn=false) @@ -986,7 +993,7 @@ public abstract class GenericDaoBase implements Gene protected List executeList(final String sql, final Object... params) { final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; final List result = new ArrayList(); try { pstmt = txn.prepareAutoCloseStatement(sql); @@ -1001,9 +1008,9 @@ public abstract class GenericDaoBase implements Gene } return result; } catch (final SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } catch (final Throwable e) { - throw new CloudRuntimeException("Caught: " + pstmt.toString(), e); + throw new CloudRuntimeException("Caught: " + pstmt, e); } } @@ -1028,7 +1035,7 @@ public abstract class GenericDaoBase implements Gene @Override public boolean expunge(final ID id) { final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; String sql = null; try { txn.start(); @@ -1050,8 +1057,7 @@ public abstract class GenericDaoBase implements Gene } return true; } catch (final SQLException e) { - final String sqlStr = pstmt.toString(); - throw new CloudRuntimeException("DB Exception on: " + sqlStr, e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } } @@ -1069,7 +1075,7 @@ public abstract class GenericDaoBase implements Gene final String sql = str.toString(); final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { pstmt = txn.prepareAutoCloseStatement(sql); int i = 0; @@ -1078,9 +1084,9 @@ public abstract class GenericDaoBase implements Gene } return pstmt.executeUpdate(); } catch (final SQLException e) { - throw new CloudRuntimeException("DB Exception on: " + pstmt.toString(), e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } catch (final Throwable e) { - throw new CloudRuntimeException("Caught: " + pstmt.toString(), e); + throw new CloudRuntimeException("Caught: " + pstmt, e); } } @@ -1139,11 +1145,11 @@ public abstract class GenericDaoBase implements Gene } @Override @DB(txn=false) - public boolean update(final ID id, final T entity) { + public boolean update(ID id, T entity) { assert Enhancer.isEnhanced(entity.getClass()) : "Entity is not generated by this dao"; - final UpdateBuilder ub = getUpdateBuilder(entity); - final boolean result = update(id, ub) != 0; + UpdateBuilder ub = getUpdateBuilder(entity); + boolean result = update(id, ub, entity) != 0; return result; } @@ -1179,7 +1185,7 @@ public abstract class GenericDaoBase implements Gene ID id = null; final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; String sql = null; try { txn.start(); @@ -1212,19 +1218,63 @@ public abstract class GenericDaoBase implements Gene } } } + HashMap ecAttributes = new HashMap(); + for (Attribute attr : _ecAttributes) { + Object ec = attr.field.get(entity); + if (ec != null) { + ecAttributes.put(attr, ec); + } + } + + insertElementCollection(entity, _idAttributes.get(_table)[0], id, ecAttributes); txn.commit(); } catch (final SQLException e) { if (e.getSQLState().equals("23000") && e.getErrorCode() == 1062) { throw new EntityExistsException("Entity already exists: ", e); } else { - final String sqlStr = pstmt.toString(); - throw new CloudRuntimeException("DB Exception on: " + sqlStr, e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } + } catch (IllegalArgumentException e) { + throw new CloudRuntimeException("Problem with getting the ec attribute ", e); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("Problem with getting the ec attribute ", e); } return _idField != null ? findByIdIncludingRemoved(id) : null; } + protected void insertElementCollection(T entity, Attribute idAttribute, ID id, Map ecAttributes) throws SQLException { + Transaction txn = Transaction.currentTxn(); + txn.start(); + for (Map.Entry entry : ecAttributes.entrySet()) { + Attribute attr = entry.getKey(); + Object obj = entry.getValue(); + + EcInfo ec = (EcInfo)attr.attache; + Enumeration en = null; + if (ec.rawClass == null) { + en = Collections.enumeration(Arrays.asList((Object[])obj)); + } else { + en = Collections.enumeration((Collection)obj); + } + PreparedStatement pstmt = txn.prepareAutoCloseStatement(ec.clearSql); + prepareAttribute(1, pstmt, idAttribute, id); + pstmt.executeUpdate(); + + while (en.hasMoreElements()) { + pstmt = txn.prepareAutoCloseStatement(ec.insertSql); + if (ec.targetClass == Date.class) { + pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), (Date)en.nextElement())); + } else { + pstmt.setObject(1, en.nextElement()); + } + prepareAttribute(2, pstmt, idAttribute, id); + pstmt.executeUpdate(); + } + } + txn.commit(); + } + @DB(txn=false) protected Object generateValue(final Attribute attr) { if (attr.is(Attribute.Flag.Created) || attr.is(Attribute.Flag.Removed)) { @@ -1235,7 +1285,7 @@ public abstract class GenericDaoBase implements Gene } else if (attr.is(Attribute.Flag.AutoGV)) { if (attr.columnName.equals(GenericDao.XID_COLUMN)) { return UUID.randomUUID().toString(); - } + } assert (false) : "Auto generation is not supported."; return null; } else if (attr.is(Attribute.Flag.SequenceGV)) { @@ -1268,7 +1318,7 @@ public abstract class GenericDaoBase implements Gene final Column column = attr.field.getAnnotation(Column.class); final int length = column != null ? column.length() : 255; - // to support generic localization, utilize MySql UTF-8 support + // to support generic localization, utilize MySql UTF-8 support if (length < str.length()) { try { pstmt.setBytes(j, str.substring(0, column.length()).getBytes("UTF-8")); @@ -1358,7 +1408,7 @@ public abstract class GenericDaoBase implements Gene @SuppressWarnings("unchecked") @DB(txn=false) protected T toEntityBean(final ResultSet result, final boolean cache) throws SQLException { - final T entity = (T)_factory.newInstance(new Callback[] {NoOp.INSTANCE, new UpdateBuilder(_allAttributes)}); + final T entity = (T)_factory.newInstance(new Callback[] {NoOp.INSTANCE, new UpdateBuilder(this)}); toEntityBean(result, entity); @@ -1379,9 +1429,90 @@ public abstract class GenericDaoBase implements Gene for (int index = 1, max = meta.getColumnCount(); index <= max; index++) { setField(entity, result, meta, index); } - for (Attribute attr : _oneToManyAttributes) { - OneToMany otm = attr.field.getAnnotation(OneToMany.class); + for (Attribute attr : _ecAttributes) { + loadCollection(entity, attr); + } + } + @DB(txn = true) + @SuppressWarnings("unchecked") + protected void loadCollection(T entity, Attribute attr) { + EcInfo ec = (EcInfo)attr.attache; + + Transaction txn = Transaction.currentTxn(); + ResultSet rs = null; + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareStatement(ec.selectSql); + pstmt.setObject(1, _idField.get(entity)); + rs = pstmt.executeQuery(); + ArrayList lst = new ArrayList(); + if (ec.targetClass == Integer.class) { + while (rs.next()) { + lst.add(rs.getInt(1)); + } + } else if (ec.targetClass == Long.class) { + while (rs.next()) { + lst.add(rs.getLong(1)); + } + } else if (ec.targetClass == String.class) { + while (rs.next()) { + lst.add(rs.getString(1)); + } + } else if (ec.targetClass == Short.class) { + while (rs.next()) { + lst.add(rs.getShort(1)); + } + } else if (ec.targetClass == Date.class) { + while (rs.next()) { + lst.add(DateUtil.parseDateString(s_gmtTimeZone, rs.getString(1))); + } + } else if (ec.targetClass == Boolean.class) { + while (rs.next()) { + lst.add(rs.getBoolean(1)); + } + } else { + assert (false) : "You'll need to add more classeses"; + } + + if (ec.rawClass == null) { + Object[] array = (Object[])Array.newInstance(ec.targetClass); + lst.toArray(array); + try { + attr.field.set(entity, array); + } catch (IllegalArgumentException e) { + throw new CloudRuntimeException("Come on we screen for this stuff, don't we?", e); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("Come on we screen for this stuff, don't we?", e); + } + } else { + try { + Collection coll = (Collection)ec.rawClass.newInstance(); + coll.addAll(lst); + attr.field.set(entity, coll); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("Come on we screen for this stuff, don't we?", e); + } catch (InstantiationException e) { + throw new CloudRuntimeException("Never should happen", e); + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Error executing " + pstmt, e); + } catch (IllegalArgumentException e) { + throw new CloudRuntimeException("Error executing " + pstmt, e); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("Error executing " + pstmt, e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + s_logger.error("Why are we getting an exception at close? ", e); + } } } @@ -1393,7 +1524,7 @@ public abstract class GenericDaoBase implements Gene final StringBuilder sql = new StringBuilder("DELETE FROM "); sql.append(_table).append(" WHERE ").append(_removed.first()).append(" IS NOT NULL"); final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { txn.start(); pstmt = txn.prepareAutoCloseStatement(sql.toString()); @@ -1401,8 +1532,7 @@ public abstract class GenericDaoBase implements Gene pstmt.executeUpdate(); txn.commit(); } catch (final SQLException e) { - final String sqlStr = pstmt.toString(); - throw new CloudRuntimeException("DB Exception on " + sqlStr, e); + throw new CloudRuntimeException("DB Exception on " + pstmt, e); } } @@ -1420,7 +1550,7 @@ public abstract class GenericDaoBase implements Gene } final Transaction txn = Transaction.currentTxn(); - PreparedStatement pstmt = s_initStmt; + PreparedStatement pstmt = null; try { txn.start(); @@ -1438,8 +1568,7 @@ public abstract class GenericDaoBase implements Gene } return result > 0; } catch (final SQLException e) { - final String sqlStr = pstmt.toString(); - throw new CloudRuntimeException("DB Exception on: " + sqlStr, e); + throw new CloudRuntimeException("DB Exception on: " + pstmt, e); } } diff --git a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java index 9bf346f32f4..f0e27e8a54d 100644 --- a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java +++ b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java @@ -97,9 +97,14 @@ public class GenericSearchBuilder implements MethodInterceptor { return this; } +// public GenericSearchBuilder selectField(String joinName, Object... entityFields) { +// JoinBuilder> jb = _joins.get(joinName); +// +// } + /** * Specifies the field to select. - * + * * @param fieldName The field name of the result object to put the value of the field selected. This can be null if you're selecting only one field and the result is not a complex object. * @param func function to place. * @param useless column to select. Call this with this.entity() method. @@ -137,6 +142,10 @@ public class GenericSearchBuilder implements MethodInterceptor { return this; } +// public GenericSearchBuilder select(String joinName, String fieldName, Func func, Object useless, Object... params) { +// +// } + @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { String name = method.getName(); @@ -157,7 +166,7 @@ public class GenericSearchBuilder implements MethodInterceptor { } } assert false : "Perhaps you need to make the method start with get or is?"; - } + } return methodProxy.invokeSuper(object, args); } diff --git a/utils/src/com/cloud/utils/db/SqlGenerator.java b/utils/src/com/cloud/utils/db/SqlGenerator.java index 9928dc1caec..bcb6db86890 100755 --- a/utils/src/com/cloud/utils/db/SqlGenerator.java +++ b/utils/src/com/cloud/utils/db/SqlGenerator.java @@ -29,16 +29,16 @@ import java.util.List; import java.util.Map; import javax.persistence.AttributeOverride; -import javax.persistence.CascadeType; +import javax.persistence.CollectionTable; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; +import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.OneToMany; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.SecondaryTable; import javax.persistence.TableGenerator; @@ -54,13 +54,13 @@ public class SqlGenerator { ArrayList> _tables; LinkedHashMap> _ids; HashMap _generators; - ArrayList _otmAttrs; + ArrayList _ecAttrs; public SqlGenerator(Class clazz) { _clazz = clazz; _tables = new ArrayList>(); _attributes = new ArrayList(); - _otmAttrs = new ArrayList(); + _ecAttrs = new ArrayList(); _embeddeds = new ArrayList(); _ids = new LinkedHashMap>(); _generators = new HashMap(); @@ -68,6 +68,7 @@ public class SqlGenerator { buildAttributes(clazz, DbUtil.getTableName(clazz), DbUtil.getAttributeOverrides(clazz), false, false); assert (_tables.size() > 0) : "Did you forget to put @Entity on " + clazz.getName(); handleDaoAttributes(clazz); + findEcAttributes(); } protected boolean checkMethods(Class clazz, Map attrs) { @@ -140,27 +141,36 @@ public class SqlGenerator { attrs.add(attr); } - if (field.getAnnotation(OneToMany.class) != null) { - assert supportsOneToMany(field) : "Doesn't support One To Many"; - _otmAttrs.add(attr); - } else { - _attributes.add(attr); + _attributes.add(attr); + } + } + + protected void findEcAttributes() { + for (Attribute attr : _attributes) { + if (attr.field == null) { + continue; + } + ElementCollection ec = attr.field.getAnnotation(ElementCollection.class); + if (ec != null) { + Attribute idAttr = _ids.get(attr.table).get(0); + assert supportsElementCollection(attr.field) : "Doesn't support ElementCollection for " + attr.field.getName(); + attr.attache = new EcInfo(attr, idAttr); + _ecAttrs.add(attr); } } } - protected boolean supportsOneToMany(Field field) { - OneToMany otm = field.getAnnotation(OneToMany.class); + protected boolean supportsElementCollection(Field field) { + ElementCollection otm = field.getAnnotation(ElementCollection.class); if (otm.fetch() == FetchType.LAZY) { - assert (false) : "Doesn't support laz fetch: " + field.getName(); - return false; + assert (false) : "Doesn't support laz fetch: " + field.getName(); + return false; } - for (CascadeType cascade : otm.cascade()) { - if (cascade == CascadeType.ALL || cascade == CascadeType.PERSIST || cascade == CascadeType.MERGE || cascade == CascadeType.REMOVE) { - assert (false) : "Doesn't support " + cascade + " for " + field.getName(); - return false; - } + CollectionTable ct = field.getAnnotation(CollectionTable.class); + if (ct == null) { + assert (false) : "No collection table sepcified for " + field.getName(); + return false; } return true; @@ -264,8 +274,8 @@ public class SqlGenerator { } } - public List getOneToManyAttributes() { - return _otmAttrs; + public List getElementCollectionAttributes() { + return _ecAttrs; } public Attribute findAttribute(String name) { diff --git a/utils/src/com/cloud/utils/db/Transaction.java b/utils/src/com/cloud/utils/db/Transaction.java index 1ad60816d95..5d846bd8bd7 100755 --- a/utils/src/com/cloud/utils/db/Transaction.java +++ b/utils/src/com/cloud/utils/db/Transaction.java @@ -109,7 +109,7 @@ public class Transaction { // Usage of this transaction setup should be limited, it will always open a new transaction context regardless of whether or not there is other // transaction context in the stack. It is used in special use cases that we want to control DB connection explicitly and in the mean time utilize // the existing DAO features - // + // public static Transaction openNew(final String name, Connection conn) { assert(conn != null); Transaction txn = new Transaction(name, false, CONNECTED_DB); @@ -191,7 +191,7 @@ public class Transaction { s_logger.warn("Unexpected exception: ", e); return null; } - } + } protected void attach(TransactionAttachment value) { _stack.push(new StackElement(ATTACHMENT, value)); @@ -452,7 +452,6 @@ public class Transaction { * @throws SQLException */ public Connection getConnection() throws SQLException { - closePreviousStatement(); if (_conn == null) { if (s_logger.isTraceEnabled()) { s_logger.trace("conn: Creating a DB connection with " + (_txn ? " txn: " : " no txn: ") + buildName()); @@ -653,8 +652,9 @@ public class Transaction { try { s_logger.trace("conn: Closing DB connection"); - if(this._dbId != CONNECTED_DB) - _conn.close(); + if(this._dbId != CONNECTED_DB) { + _conn.close(); + } _conn = null; } catch (final SQLException e) { diff --git a/utils/src/com/cloud/utils/db/UpdateBuilder.java b/utils/src/com/cloud/utils/db/UpdateBuilder.java index 4ea4b0ae791..3ce48b912ff 100755 --- a/utils/src/com/cloud/utils/db/UpdateBuilder.java +++ b/utils/src/com/cloud/utils/db/UpdateBuilder.java @@ -29,11 +29,12 @@ import com.cloud.utils.Ternary; import com.cloud.utils.exception.CloudRuntimeException; public class UpdateBuilder implements MethodInterceptor { - protected final Map _attrs; protected Map> _changes; + protected HashMap _collectionChanges; + protected GenericDaoBase _dao; - protected UpdateBuilder(Map attrs) { - _attrs = attrs; + protected UpdateBuilder(GenericDaoBase dao) { + _dao = dao; _changes = new HashMap>(); } @@ -47,7 +48,7 @@ public class UpdateBuilder implements MethodInterceptor { makeIncrChange(name, args); } else if (name.startsWith("decr")) { makeDecrChange(name, args); - } + } return methodProxy.invokeSuper(object, args); } @@ -58,25 +59,32 @@ public class UpdateBuilder implements MethodInterceptor { } protected Attribute makeChange(String field, Object value) { - Attribute attr = _attrs.get(field); + Attribute attr = _dao._allAttributes.get(field); assert (attr == null || attr.isUpdatable()) : "Updating an attribute that's not updatable: " + field; if (attr != null) { - _changes.put(field, new Ternary(attr, null, value)); + if (attr.attache == null) { + _changes.put(field, new Ternary(attr, null, value)); + } else { + if (_collectionChanges == null) { + _collectionChanges = new HashMap(); + } + _collectionChanges.put(attr, value); + } } return attr; } protected void makeIncrChange(String method, Object[] args) { String field = methodToField(method, 4); - Attribute attr = _attrs.get(field); + Attribute attr = _dao._allAttributes.get(field); assert (attr != null && attr.isUpdatable()) : "Updating an attribute that's not updatable: " + field; incr(attr, args == null || args.length == 0 ? 1 : args[0]); } protected void makeDecrChange(String method, Object[] args) { String field = methodToField(method, 4); - Attribute attr = _attrs.get(field); + Attribute attr = _dao._allAttributes.get(field); assert (attr != null && attr.isUpdatable()) : "Updating an attribute that's not updatable: " + field; decr(attr, args == null || args.length == 0 ? 1 : args[0]); } @@ -107,19 +115,23 @@ public class UpdateBuilder implements MethodInterceptor { } public boolean hasChanges() { - return _changes.size() != 0; + return (_changes.size() + (_collectionChanges != null ? _collectionChanges.size() : 0)) != 0; } public boolean has(String name) { return _changes.containsKey(name); } - public Object get(String name) { - return _changes.get(name).second(); + public Map getCollectionChanges() { + return _collectionChanges; } protected void clear() { _changes.clear(); + if (_collectionChanges != null) { + _collectionChanges.clear(); + _collectionChanges = null; + } } public StringBuilder toSql(String tables) { diff --git a/utils/src/javax/persistence/CollectionTable.java b/utils/src/javax/persistence/CollectionTable.java new file mode 100644 index 00000000000..2b6ab84816d --- /dev/null +++ b/utils/src/javax/persistence/CollectionTable.java @@ -0,0 +1,39 @@ +/** + * 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 javax.persistence; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value = { METHOD, FIELD }) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface CollectionTable { + String catalog() default ""; + + JoinColumn[] joinColumns() default {}; + + String name() default ""; + + String schema() default ""; + + UniqueConstraint[] uniqueConstraints() default {}; +} diff --git a/utils/src/javax/persistence/ElementCollection.java b/utils/src/javax/persistence/ElementCollection.java index aaaa96edf25..622bab2fba8 100644 --- a/utils/src/javax/persistence/ElementCollection.java +++ b/utils/src/javax/persistence/ElementCollection.java @@ -17,6 +17,17 @@ */ package javax.persistence; -public interface ElementCollection { +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value = { METHOD, FIELD }) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface ElementCollection { + FetchType fetch() default FetchType.LAZY; + + Class targetClass() default void.class; } diff --git a/utils/test/com/cloud/utils/db/ElementCollectionTest.java b/utils/test/com/cloud/utils/db/ElementCollectionTest.java new file mode 100644 index 00000000000..c1e766f17fb --- /dev/null +++ b/utils/test/com/cloud/utils/db/ElementCollectionTest.java @@ -0,0 +1,56 @@ +package com.cloud.utils.db; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import junit.framework.TestCase; + +import org.apache.log4j.Logger; + + +public class ElementCollectionTest extends TestCase { + static final Logger s_logger = Logger.getLogger(ElementCollectionTest.class); + ArrayList ar = null; + List lst = null; + Collection coll = null; + String[] array = null; + + public void testArrayList() throws Exception { + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + Class type1 = field.getType(); + Object collection = null; + if (!type1.isArray()) { + ParameterizedType type = (ParameterizedType)field.getGenericType(); + Type rawType = type.getRawType(); + Class rawClazz = (Class)rawType; + if (!Modifier.isAbstract(rawClazz.getModifiers()) && !rawClazz.isInterface() && rawClazz.getConstructors().length != 0 && rawClazz.getConstructor() != null) { + collection = rawClazz.newInstance(); + } + + if (collection == null) { + if (Collection.class.isAssignableFrom(rawClazz)) { + collection = new ArrayList(); + } else if (Set.class.isAssignableFrom(rawClazz)) { + collection = new HashSet(); + } + } + } else { + collection = Array.newInstance(String.class, 1); + } + field.set(this, collection); + assert (field.get(this) != null); + } + } +}