diff --git a/api/src/com/cloud/dao/EntityManager.java b/api/src/com/cloud/dao/EntityManager.java index b8fdaa7e9a7..8e6a438d011 100644 --- a/api/src/com/cloud/dao/EntityManager.java +++ b/api/src/com/cloud/dao/EntityManager.java @@ -38,6 +38,16 @@ public interface EntityManager { */ public T findById(Class entityType, K id); + /** + * Finds an entity by its id including removed. + * @param class of the entity you're trying to find. + * @param class of the id that the entity uses. + * @param entityType Type of the entity. + * @param id id value + * @return T if found; null if not. + */ + public T findByIdIncludingRemoved(Class entityType, K id); + /** * Finds a unique entity by uuid string * @param entity class diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java index 7e17405f434..57eeb290c05 100644 --- a/api/src/com/cloud/network/NetworkModel.java +++ b/api/src/com/cloud/network/NetworkModel.java @@ -250,4 +250,6 @@ public interface NetworkModel { boolean isNetworkInlineMode(Network network); Vlan getVlanForNetwork(long networkId); + + boolean isIP6AddressAvailable(long networkId); } \ No newline at end of file diff --git a/api/src/com/cloud/network/NetworkUsageService.java b/api/src/com/cloud/network/NetworkUsageService.java new file mode 100644 index 00000000000..1cfea24d05a --- /dev/null +++ b/api/src/com/cloud/network/NetworkUsageService.java @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; + +import java.util.List; + +import com.cloud.host.Host; + +import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; +import org.apache.cloudstack.api.command.admin.usage.DeleteTrafficMonitorCmd; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficMonitorsCmd; +import org.apache.cloudstack.api.response.TrafficMonitorResponse; +import com.cloud.utils.component.Manager; + +public interface NetworkUsageService extends Manager { + + Host addTrafficMonitor(AddTrafficMonitorCmd cmd); + + boolean deleteTrafficMonitor(DeleteTrafficMonitorCmd cmd); + + List listTrafficMonitors(ListTrafficMonitorsCmd cmd); + +} diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index d8e2bffed3a..a9ac489671b 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.region.RegionService; +import org.apache.cloudstack.usage.UsageService; import org.apache.log4j.Logger; import com.cloud.configuration.ConfigurationService; @@ -43,6 +44,7 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.NetworkService; +import com.cloud.network.NetworkUsageService; import com.cloud.network.StorageNetworkService; import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.as.AutoScaleService; @@ -124,6 +126,8 @@ public abstract class BaseCmd { @Inject public Site2SiteVpnService _s2sVpnService; @Inject public QueryService _queryService; + @Inject public UsageService _usageService; + @Inject public NetworkUsageService _networkUsageService; public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index b95f182c32f..0dc85de1647 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -83,7 +83,9 @@ import org.apache.cloudstack.api.response.SystemVmInstanceResponse; import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.api.response.TemplatePermissionsResponse; import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.TrafficMonitorResponse; import org.apache.cloudstack.api.response.TrafficTypeResponse; +import org.apache.cloudstack.api.response.UsageRecordResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VirtualRouterProviderResponse; @@ -94,6 +96,7 @@ import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.VpnUsersResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.usage.Usage; import com.cloud.async.AsyncJob; import com.cloud.capacity.Capacity; @@ -375,4 +378,8 @@ public interface ResponseGenerator { GuestOSResponse createGuestOSResponse(GuestOS os); SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule sched); + + UsageRecordResponse createUsageResponse(Usage usageRecord); + + TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor); } diff --git a/server/src/com/cloud/api/commands/AddTrafficMonitorCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java similarity index 93% rename from server/src/com/cloud/api/commands/AddTrafficMonitorCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java index 8728959017f..48424fef246 100644 --- a/server/src/com/cloud/api/commands/AddTrafficMonitorCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.api.commands; +package org.apache.cloudstack.api.command.admin.usage; import javax.inject.Inject; @@ -30,7 +30,6 @@ import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; -import com.cloud.network.NetworkUsageManager; import com.cloud.user.Account; import com.cloud.utils.exception.CloudRuntimeException; @@ -38,7 +37,6 @@ import com.cloud.utils.exception.CloudRuntimeException; public class AddTrafficMonitorCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(AddTrafficMonitorCmd.class.getName()); private static final String s_name = "addtrafficmonitorresponse"; - @Inject NetworkUsageManager networkUsageMgr; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -94,8 +92,8 @@ public class AddTrafficMonitorCmd extends BaseCmd { @Override public void execute(){ try { - Host trafficMonitor = networkUsageMgr.addTrafficMonitor(this); - TrafficMonitorResponse response = networkUsageMgr.getApiResponse(trafficMonitor); + Host trafficMonitor = _networkUsageService.addTrafficMonitor(this); + TrafficMonitorResponse response = _responseGenerator.createTrafficMonitorResponse(trafficMonitor); response.setObjectName("trafficmonitor"); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/server/src/com/cloud/api/commands/DeleteTrafficMonitorCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java similarity index 94% rename from server/src/com/cloud/api/commands/DeleteTrafficMonitorCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java index 081d0be9e24..e3bb299dc30 100644 --- a/server/src/com/cloud/api/commands/DeleteTrafficMonitorCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.api.commands; +package org.apache.cloudstack.api.command.admin.usage; import javax.inject.Inject; @@ -29,14 +29,12 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.NetworkUsageManager; import com.cloud.user.Account; @APICommand(name = "deleteTrafficMonitor", description="Deletes an traffic monitor host.", responseObject = SuccessResponse.class) public class DeleteTrafficMonitorCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteTrafficMonitorCmd.class.getName()); private static final String s_name = "deletetrafficmonitorresponse"; - @Inject NetworkUsageManager _networkUsageMgr; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -71,7 +69,7 @@ public class DeleteTrafficMonitorCmd extends BaseCmd { @Override public void execute(){ try { - boolean result = _networkUsageMgr.deleteTrafficMonitor(this); + boolean result = _networkUsageService.deleteTrafficMonitor(this); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); diff --git a/server/src/com/cloud/api/commands/GenerateUsageRecordsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java similarity index 94% rename from server/src/com/cloud/api/commands/GenerateUsageRecordsCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java index 4206cf82885..13710f97490 100644 --- a/server/src/com/cloud/api/commands/GenerateUsageRecordsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.api.commands; +package org.apache.cloudstack.api.command.admin.usage; import java.util.Date; @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.response.SuccessResponse; -import com.cloud.server.ManagementServerExt; import com.cloud.user.Account; @APICommand(name = "generateUsageRecords", description="Generates usage records. This will generate records only if there any records to be generated, i.e if the scheduled usage job was not run or failed", responseObject=SuccessResponse.class) @@ -79,8 +78,7 @@ public class GenerateUsageRecordsCmd extends BaseCmd { @Override public void execute(){ - ManagementServerExt _mgrExt = (ManagementServerExt)_mgr; - boolean result = _mgrExt.generateUsageRecords(this); + boolean result = _usageService.generateUsageRecords(this); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java new file mode 100644 index 00000000000..f4960dd0e08 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java @@ -0,0 +1,126 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.usage; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.UsageRecordResponse; +import org.apache.cloudstack.usage.Usage; +import org.apache.log4j.Logger; + +@APICommand(name = "listUsageRecords", description="Lists usage records for accounts", responseObject=UsageRecordResponse.class) +public class GetUsageRecordsCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(GetUsageRecordsCmd.class.getName()); + + private static final String s_name = "listusagerecordsresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="List usage records for the specified user.") + private String accountName; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class, + description="List usage records for the specified domain.") + private Long domainId; + + @Parameter(name=ApiConstants.END_DATE, type=CommandType.DATE, required=true, description="End date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") + private Date endDate; + + @Parameter(name=ApiConstants.START_DATE, type=CommandType.DATE, required=true, description="Start date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.") + private Date startDate; + + @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class, + description="List usage records for the specified account") + private Long accountId; + + @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, + description="List usage records for specified project") + private Long projectId; + + @Parameter(name=ApiConstants.TYPE, type=CommandType.LONG, description="List usage records for the specified usage type") + private Long usageType; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Date getEndDate() { + return endDate; + } + + public Date getStartDate() { + return startDate; + } + + public Long getAccountId() { + return accountId; + } + + public Long getUsageType() { + return usageType; + } + + public Long getProjectId() { + return projectId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute(){ + List usageRecords = _usageService.getUsageRecords(this); + ListResponse response = new ListResponse(); + List usageResponses = new ArrayList(); + for(Usage usageRecord: usageRecords){ + UsageRecordResponse usageResponse = _responseGenerator.createUsageResponse(usageRecord); + usageResponse.setObjectName("usagerecord"); + usageResponses.add(usageResponse); + } + + response.setResponses(usageResponses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/server/src/com/cloud/api/commands/ListTrafficMonitorsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java similarity index 91% rename from server/src/com/cloud/api/commands/ListTrafficMonitorsCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java index 645bf3b7307..e8e3b22c15b 100644 --- a/server/src/com/cloud/api/commands/ListTrafficMonitorsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.api.commands; +package org.apache.cloudstack.api.command.admin.usage; import java.util.ArrayList; import java.util.List; @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; import com.cloud.host.Host; -import com.cloud.network.NetworkUsageManager; @APICommand(name = "listTrafficMonitors", description="List traffic monitor Hosts.", responseObject = TrafficMonitorResponse.class) @@ -40,7 +39,6 @@ public class ListTrafficMonitorsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListServiceOfferingsCmd.class.getName()); private static final String s_name = "listtrafficmonitorsresponse"; - @Inject NetworkUsageManager networkUsageMgr; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -68,12 +66,12 @@ public class ListTrafficMonitorsCmd extends BaseListCmd { @Override public void execute(){ - List trafficMonitors = networkUsageMgr.listTrafficMonitors(this); + List trafficMonitors = _networkUsageService.listTrafficMonitors(this); ListResponse listResponse = new ListResponse(); List responses = new ArrayList(); for (Host trafficMonitor : trafficMonitors) { - TrafficMonitorResponse response = networkUsageMgr.getApiResponse(trafficMonitor); + TrafficMonitorResponse response = _responseGenerator.createTrafficMonitorResponse(trafficMonitor); response.setObjectName("trafficmonitor"); response.setResponseName(getCommandName()); responses.add(response); diff --git a/server/src/com/cloud/api/commands/ListUsageTypesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java similarity index 90% rename from server/src/com/cloud/api/commands/ListUsageTypesCmd.java rename to api/src/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java index dfa5dc1bb20..bc029117350 100644 --- a/server/src/com/cloud/api/commands/ListUsageTypesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.api.commands; +package org.apache.cloudstack.api.command.admin.usage; import java.util.List; @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.response.ListResponse; -import com.cloud.server.ManagementServerExt; import org.apache.cloudstack.api.response.UsageTypeResponse; import com.cloud.user.Account; @@ -43,8 +42,7 @@ public class ListUsageTypesCmd extends BaseCmd { @Override public void execute() { - ManagementServerExt _mgrExt = (ManagementServerExt)_mgr; - List result = _mgrExt.listUsageTypes(); + List result = _usageService.listUsageTypes(); ListResponse response = new ListResponse(); response.setResponses(result); response.setResponseName(getCommandName()); diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index 99c17f1984e..0277d5b6fe9 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -123,13 +123,13 @@ public class AccountResponse extends BaseResponse { @SerializedName("networkavailable") @Param(description="the total number of networks available to be created for this account", since="3.0.1") private String networkAvailable; - @SerializedName("vpclimit") @Param(description="the total number of vpcs the account can own", since="3.0.5") + @SerializedName("vpclimit") @Param(description="the total number of vpcs the account can own", since="4.0.0") private String vpcLimit; - @SerializedName("vpctotal") @Param(description="the total number of vpcs owned by account", since="3.0.5") + @SerializedName("vpctotal") @Param(description="the total number of vpcs owned by account", since="4.0.0") private Long vpcTotal; - @SerializedName("vpcavailable") @Param(description="the total number of vpcs available to be created for this account", since="3.0.5") + @SerializedName("vpcavailable") @Param(description="the total number of vpcs available to be created for this account", since="4.0.0") private String vpcAvailable; diff --git a/api/src/org/apache/cloudstack/usage/Usage.java b/api/src/org/apache/cloudstack/usage/Usage.java new file mode 100644 index 00000000000..c74d3b7273e --- /dev/null +++ b/api/src/org/apache/cloudstack/usage/Usage.java @@ -0,0 +1,69 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.usage; + +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +public interface Usage { + + public long getId(); + + public Long getZoneId(); + + public Long getAccountId(); + + public Long getDomainId(); + + public String getDescription(); + + public String getUsageDisplay(); + + public int getUsageType(); + + public Double getRawUsage(); + + public Long getVmInstanceId(); + + public String getVmName(); + + public Long getOfferingId(); + + public Long getTemplateId(); + + public Long getUsageId(); + + public String getType(); + + public Long getNetworkId(); + + public Long getSize(); + + public Date getStartDate(); + + public Date getEndDate(); +} diff --git a/server/src/com/cloud/server/ManagementServerExt.java b/api/src/org/apache/cloudstack/usage/UsageService.java old mode 100644 new mode 100755 similarity index 89% rename from server/src/com/cloud/server/ManagementServerExt.java rename to api/src/org/apache/cloudstack/usage/UsageService.java index 4e506a3bc4a..383822592bc --- a/server/src/com/cloud/server/ManagementServerExt.java +++ b/api/src/org/apache/cloudstack/usage/UsageService.java @@ -14,16 +14,16 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.server; +package org.apache.cloudstack.usage; import java.util.List; import java.util.TimeZone; -import com.cloud.api.commands.GenerateUsageRecordsCmd; -import com.cloud.api.commands.GetUsageRecordsCmd; +import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd; +import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd; import org.apache.cloudstack.api.response.UsageTypeResponse; -import com.cloud.usage.UsageVO; -public interface ManagementServerExt extends ManagementServer { + +public interface UsageService { /** * Generate Billing Records from the last time it was generated to the * time specified. @@ -50,7 +50,7 @@ public interface ManagementServerExt extends ManagementServer { * the appropriate page number) * @return a list of usage records */ - List getUsageRecords(GetUsageRecordsCmd cmd); + List getUsageRecords(GetUsageRecordsCmd cmd); /** * Retrieves the timezone used for usage aggregation. One day is represented as midnight to 11:59:59pm @@ -60,4 +60,5 @@ public interface ManagementServerExt extends ManagementServer { TimeZone getUsageTimezone(); List listUsageTypes(); + } diff --git a/server/src/com/cloud/usage/UsageTypes.java b/api/src/org/apache/cloudstack/usage/UsageTypes.java similarity index 98% rename from server/src/com/cloud/usage/UsageTypes.java rename to api/src/org/apache/cloudstack/usage/UsageTypes.java index e5a48d5c143..2baa1d20057 100644 --- a/server/src/com/cloud/usage/UsageTypes.java +++ b/api/src/org/apache/cloudstack/usage/UsageTypes.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.usage; +package org.apache.cloudstack.usage; import java.util.ArrayList; import java.util.List; diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index eda07782196..bb845d8e8e4 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -1545,3 +1545,9 @@ label.nicira.controller.address=Controller Address label.nicira.transportzoneuuid=Transport Zone Uuid label.nicira.l3gatewayserviceuuid=L3 Gateway Service Uuid +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK \ No newline at end of file diff --git a/client/WEB-INF/classes/resources/messages_fr_FR.properties b/client/WEB-INF/classes/resources/messages_fr_FR.properties index 4ba3c725892..51bf95fe349 100644 --- a/client/WEB-INF/classes/resources/messages_fr_FR.properties +++ b/client/WEB-INF/classes/resources/messages_fr_FR.properties @@ -1510,3 +1510,9 @@ error.menu.select=Echec de l\'action car il n\'y a aucun error.mgmt.server.inaccessible=Le serveur de management est indisponible. Essayez plus tard. error.session.expired=Votre session a expir. error.unresolved.internet.name=Votre nom internet ne peut pas tre rsolu. +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK \ No newline at end of file diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties index 7555b83dd78..8397a8dc59d 100644 --- a/client/WEB-INF/classes/resources/messages_ja.properties +++ b/client/WEB-INF/classes/resources/messages_ja.properties @@ -1509,4 +1509,10 @@ error.login=ユーザー名/パスワードが記録と一致しません。 error.menu.select=項目が選択されていないため操作を実行できません。 error.mgmt.server.inaccessible=管理サーバーにアクセスできません。後で再実行してください。 error.session.expired=セッションの有効期限が切れました。 -error.unresolved.internet.name=インターネット名を解決できません。 + +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK \ No newline at end of file diff --git a/client/WEB-INF/classes/resources/messages_pt_BR.properties b/client/WEB-INF/classes/resources/messages_pt_BR.properties index 3bc435b9717..23ba5b9402d 100644 --- a/client/WEB-INF/classes/resources/messages_pt_BR.properties +++ b/client/WEB-INF/classes/resources/messages_pt_BR.properties @@ -1510,3 +1510,9 @@ error.menu.select=N error.mgmt.server.inaccessible=O servidor de gerenciamento está inacessível. Tente novamente mais tarde. error.session.expired=Sua sessão expirou. error.unresolved.internet.name=Impossível resolver DNS +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK \ No newline at end of file diff --git a/client/WEB-INF/classes/resources/messages_ru_RU.properties b/client/WEB-INF/classes/resources/messages_ru_RU.properties index dd7e7460744..024b552df7c 100644 --- a/client/WEB-INF/classes/resources/messages_ru_RU.properties +++ b/client/WEB-INF/classes/resources/messages_ru_RU.properties @@ -1510,3 +1510,11 @@ error.menu.select=Не удается выполнить действие из- error.mgmt.server.inaccessible=Сервер управления недоступна. Попробуйте обратиться к нему позже. error.session.expired=Ваша сессия была завершена error.unresolved.internet.name=Ваше интернет-имя определить не удалось + +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK + diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties index 62160d98488..2e2e725d190 100644 --- a/client/WEB-INF/classes/resources/messages_zh_CN.properties +++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties @@ -1511,3 +1511,9 @@ error.mgmt.server.inaccessible=无法访问管理服务器。请稍后再试。 error.session.expired=您的会话已过期。 error.unresolved.internet.name=无法解析您的 Internet 名称。 +#resizeVolumes +label.resize.new.size=New Size(GB) +label.action.resize.volume=Resize Volume +label.action.resize.volume.processing=Resizing Volume.... +label.resize.new.offering.id=New Offering +label.resize.shrink.ok=Shrink OK \ No newline at end of file diff --git a/client/bindir/cloud-setup-management.in b/client/bindir/cloud-setup-management.in index ca1327ae725..aa9a46ba6ba 100755 --- a/client/bindir/cloud-setup-management.in +++ b/client/bindir/cloud-setup-management.in @@ -24,7 +24,7 @@ from cloudutils.globalEnv import globalEnv from cloudutils.serviceConfigServer import cloudManagementConfig from optparse import OptionParser if __name__ == '__main__': - initLoging("/var/log/cloud/setupManagement.log") + initLoging("@MSLOGDIR@/setupManagement.log") glbEnv = globalEnv() parser = OptionParser() diff --git a/client/pom.xml b/client/pom.xml index 3ae9dc5b2cf..3651b79bbb3 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -230,7 +230,7 @@ -XX:MaxPermSize=512m -Xmx2g /client - ${basedir}/WEB-INF/web.xml + ${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml ${project.build.directory}/${project.build.finalName} diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in index d2e3edee792..de013de60de 100644 --- a/client/tomcatconf/componentContext.xml.in +++ b/client/tomcatconf/componentContext.xml.in @@ -35,9 +35,10 @@ Compose a CloudStack deployment with selected components here --> + - - + + @@ -50,7 +51,6 @@ - diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index 7dbb5490c02..b306f521beb 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -37,8 +37,8 @@ --> - - + + @@ -51,6 +51,11 @@ + + + + + @@ -92,8 +97,7 @@ - - + diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java index 413083e01fa..0aa489be7c4 100644 --- a/core/src/com/cloud/storage/SnapshotVO.java +++ b/core/src/com/cloud/storage/SnapshotVO.java @@ -59,7 +59,7 @@ public class SnapshotVO implements Snapshot { @Expose @Column(name="status", updatable = true, nullable=false) @Enumerated(value=EnumType.STRING) - private State status; + private State state; @Column(name="snapshot_type") short snapshotType; @@ -117,7 +117,7 @@ public class SnapshotVO implements Snapshot { this.snapshotType = snapshotType; this.typeDescription = typeDescription; this.size = size; - this.status = State.Creating; + this.state = State.Creating; this.prevSnapshotId = 0; this.hypervisorType = hypervisorType; this.version = "2.2"; @@ -245,11 +245,11 @@ public class SnapshotVO implements Snapshot { @Override public State getState() { - return status; + return state; } - public void setStatus(State status) { - this.status = status; + public void setStatus(State state) { + this.state = state; } public String getBackupSnapshotId(){ diff --git a/docs/en-US/change-network-offering-on-guest-network.xml b/docs/en-US/change-network-offering-on-guest-network.xml index 3810b875a71..2c7db3e9176 100644 --- a/docs/en-US/change-network-offering-on-guest-network.xml +++ b/docs/en-US/change-network-offering-on-guest-network.xml @@ -28,7 +28,9 @@ Log in to the &PRODUCT; UI as an administrator or end user. If you are changing from a network offering that uses the &PRODUCT; virtual router to one that uses external devices as network service providers, you must first stop all the - VMs on the network. See . + VMs on the network. + See "Stopping and Starting Virtual Machines" in the Administrator's Guide. + See . In the left navigation, choose Network. Click the name of the network you want to modify. In the Details tab, click Edit. diff --git a/docs/en-US/creating-network-offerings.xml b/docs/en-US/creating-network-offerings.xml index d733924ba70..0269ce024cb 100644 --- a/docs/en-US/creating-network-offerings.xml +++ b/docs/en-US/creating-network-offerings.xml @@ -138,7 +138,7 @@ &PRODUCT; default system service offering and any custom system service offerings that have been defined by the &PRODUCT; root administrator. For more information, see System Service Offerings. - Redundant router capability. (v3.0.3 and greater) Available + Redundant router capability. Available only when Virtual Router is selected as the Source NAT provider. Select this option if you want to use two virtual routers in the network for uninterrupted connection: one operating as the master virtual router and the @@ -160,7 +160,7 @@ Tags. Network tag to specify which physical network to use. - Click Add. + Click Add. diff --git a/docs/en-US/host-add.xml b/docs/en-US/host-add.xml index ebac7656d8d..74509d69be7 100644 --- a/docs/en-US/host-add.xml +++ b/docs/en-US/host-add.xml @@ -26,7 +26,8 @@ Adding a Host Before adding a host to the &PRODUCT; configuration, you must first install your chosen hypervisor on the host. &PRODUCT; can manage hosts running VMs under a variety of hypervisors. - The &PRODUCT; Installation Guide provides instructions on how to install each supported hypervisor + The &PRODUCT; Installation Guide provides instructions on how to install each supported hypervisor + and configure it for use with &PRODUCT;. See the appropriate section in the Installation Guide for information about which version of your chosen hypervisor is supported, as well as crucial additional steps to configure the hypervisor hosts for use with &PRODUCT;. Be sure you have performed the additional &PRODUCT;-specific configuration steps described in the hypervisor installation section for your particular hypervisor. Now add the hypervisor host to &PRODUCT;. The technique to use varies depending on the hypervisor. diff --git a/docs/en-US/network-offerings.xml b/docs/en-US/network-offerings.xml index 7386e109883..0a7b8e78e3b 100644 --- a/docs/en-US/network-offerings.xml +++ b/docs/en-US/network-offerings.xml @@ -42,5 +42,5 @@ If you create load balancing rules while using a network service offering that includes an external load balancer device such as NetScaler, and later change the network service offering to one that uses the &PRODUCT; virtual router, you must create a firewall rule on the virtual router for each of your existing load balancing rules so that they continue to function. When creating a new virtual network, the &PRODUCT; administrator chooses which network offering to enable for that network. Each virtual network is associated with one network offering. A virtual network can be upgraded or downgraded by changing its associated network offering. If you do this, be sure to reprogram the physical network to match. &PRODUCT; also has internal network offerings for use by &PRODUCT; system VMs. These network offerings are not visible to users but can be modified by administrators. - + diff --git a/docs/en-US/prepare-system-vm-template.xml b/docs/en-US/prepare-system-vm-template.xml index 22674d47952..b53a509b4a1 100644 --- a/docs/en-US/prepare-system-vm-template.xml +++ b/docs/en-US/prepare-system-vm-template.xml @@ -26,22 +26,28 @@ Secondary storage must be seeded with a template that is used for &PRODUCT; system VMs. Citrix provides you with the necessary binary package of the system VM. - When copying and pasting a command, be sure the command has pasted as a single line before - executing. Some document viewers may introduce unwanted line breaks in copied text. + When copying and pasting a command, ensure that the command has pasted as a single line + before executing. Some document viewers may introduce unwanted line breaks in copied + text. - + + + If you are using a separate NFS server, mount the secondary storage on your Management + Server. Replace the example NFS server name and NFS share paths below with your own. + # mount -t nfs nfsservername:/nfs/share/secondary /mnt/secondary + If your secondary storage mount point is not named /mnt/secondary, substitute your own + mount point name. + On the Management Server, run one or more of the following cloud-install-sys-tmplt commands to retrieve and decompress the system VM template. Run the command for each hypervisor type that you expect end users to run in this Zone. - If your secondary storage mount point is not named /mnt/secondary, substitute your own - mount point name. - If you set the &PRODUCT; database encryption type to "web" when you set up the database, + If you set the &PRODUCT; database encryption type to "web" when you set up the database, you must now add the parameter -s <management-server-secret-key>. See . This process will require approximately 5 GB of free space on the local file system and - up to 30 minutes each time it runs. - + up to 30 minutes each time it runs. + For XenServer: # /usr/lib64/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.vhd.bz2 -h xenserver -s <optional-management-server-secret-key> -F @@ -57,12 +63,7 @@ - If you are using a separate NFS server, perform this step. - - Do not perform this step if you are using the Management Server as the NFS - server. - - When the script has finished, unmount secondary storage and remove the created + When the script has finished, unmount secondary storage and remove the created directory. # umount /mnt/secondary # rmdir /mnt/secondary diff --git a/docs/en-US/upgrade-virtual-router-with-service-offering.xml b/docs/en-US/upgrade-virtual-router-with-service-offering.xml index a6d0d0fb99e..dad1d906c5f 100644 --- a/docs/en-US/upgrade-virtual-router-with-service-offering.xml +++ b/docs/en-US/upgrade-virtual-router-with-service-offering.xml @@ -27,7 +27,10 @@ When &PRODUCT; creates a virtual router, it uses default settings which are defined in a default system service offering. See . All the virtual routers in a single guest network use the same system service offering. You can upgrade the capabilities of the virtual router by creating and applying a custom system service offering. Define your custom system service offering. See . In System VM Type, choose Domain Router. - Associate the system service offering with a network offering. See + Associate the system service offering with a network offering. + See "Creating Network Offerings" in the Administrator's Guide. + See . + Apply the network offering to the network where you want the virtual routers to use the new system service offering. If this is a new network, follow the steps in Adding an Additional Guest Network on page 66. To change the service offering for existing virtual routers, follow the steps in . diff --git a/packaging/centos63/cloud-management.rc b/packaging/centos63/cloud-management.rc index 48c2ab44a62..6fd435b555d 100755 --- a/packaging/centos63/cloud-management.rc +++ b/packaging/centos63/cloud-management.rc @@ -46,8 +46,8 @@ NAME="$(basename $0)" stop() { SHUTDOWN_WAIT="30" count="0" - if [ -f /var/run/cloud-management.pid ]; then - pid=`cat /var/run/cloud-management.pid` + if [ -f /var/run/${NAME}.pid ]; then + pid=`cat /var/run/${NAME}.pid` kill $pid &>/dev/null until [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ] || \ [ "$count" -gt "$SHUTDOWN_WAIT" ] @@ -78,8 +78,8 @@ set_ulimit() { handle_pid_file() { if [ "$1" -ne 0 ] ; then - echo "The pid file locates at /var/run/cloud-management.pid and lock file at /var/lock/subsys/cloud-management. - Starting cloud-management will take care of them or you can manually clean up." + echo "The pid file locates at /var/run/${NAME}.pid and lock file at /var/lock/subsys/${NAME}. + Starting ${NAME} will take care of them or you can manually clean up." fi } diff --git a/packaging/centos63/cloud-management.sysconfig b/packaging/centos63/cloud-management.sysconfig index 15df8cdab92..cbc8b8b36c1 100644 --- a/packaging/centos63/cloud-management.sysconfig +++ b/packaging/centos63/cloud-management.sysconfig @@ -18,6 +18,6 @@ # This file is loaded in /etc/init.d/vmopsmanagement # ATM we only do two things here: -dummy=1 ; export TOMCAT_CFG=/etc/cloud/management/tomcat6.conf ; . /etc/cloud/management/tomcat6.conf +dummy=1 ; export TOMCAT_CFG=/etc/cloudstack/management/tomcat6.conf ; . /etc/cloudstack/management/tomcat6.conf #-------------------------- diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index 18fac49c3f7..8a296877f52 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -193,6 +193,7 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/webapps/client mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/awsapi mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management # Specific for tomcat @@ -316,6 +317,7 @@ fi %dir %attr(0770,root,cloud) %{_localstatedir}/cache/%{name}/management/temp %dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/management %dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/agent +%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/awsapi %config(noreplace) %{_sysconfdir}/sysconfig/%{name}-management %config(noreplace) %{_sysconfdir}/%{name}/management %config(noreplace) %attr(0640,root,cloud) %{_sysconfdir}/%{name}/management/db.properties diff --git a/packaging/centos63/replace.properties b/packaging/centos63/replace.properties index e58e19bf0ed..bcc4d4a0087 100644 --- a/packaging/centos63/replace.properties +++ b/packaging/centos63/replace.properties @@ -43,13 +43,13 @@ LOCKDIR=/var/lock MSCLASSPATH= MSCONF=/etc/cloudstack/management MSENVIRON=/usr/share/cloudstack-management -MSLOG=/var/log/cloudstack-management/management-server.log -MSLOGDIR=/var/log/cloudstack-management/ +MSLOG=/var/log/cloudstack/management/management-server.log +MSLOGDIR=/var/log/cloudstack/management/ MSMNTDIR=/var/lib/cloud/mnt MSUSER=cloud PIDDIR=/var/run -PLUGINJAVADIR= -PREMIUMJAVADIR= +PLUGINJAVADIR=/usr/share/cloudstack-management/plugin +PREMIUMJAVADIR=/usr/share/cloudstack-management/premium PYTHONDIR=/usr/lib/python2.6/site-packages/ SERVERSYSCONFDIR=/etc/sysconfig SETUPDATADIR=/usr/share/cloudstack-management/setup diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java index 7689ba4b3d8..087b166575a 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.inject.Inject; @@ -54,19 +55,24 @@ import com.google.gson.annotations.SerializedName; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - @Inject protected List s_apiAccessCheckers = null; + @Inject protected List _apiAccessCheckers = null; + @Inject protected List _services = null; private static Map s_apiNameDiscoveryResponseMap = null; - @Inject List _services; - protected ApiDiscoveryServiceImpl() { super(); + } + + @PostConstruct + void init() { if (s_apiNameDiscoveryResponseMap == null) { long startTime = System.nanoTime(); s_apiNameDiscoveryResponseMap = new HashMap(); //TODO: Fix and use PluggableService to get the classes Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + for(PluggableService service: _services) + cmdClasses.addAll(service.getCommands()); cacheResponseMap(cmdClasses); long endTime = System.nanoTime(); s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms"); @@ -180,7 +186,7 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { if (!s_apiNameDiscoveryResponseMap.containsKey(name)) return null; - for (APIChecker apiChecker : s_apiAccessCheckers) { + for (APIChecker apiChecker : _apiAccessCheckers) { try { apiChecker.checkAccess(user, name); } catch (Exception ex) { @@ -192,7 +198,7 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } else { for (String apiName : s_apiNameDiscoveryResponseMap.keySet()) { boolean isAllowed = true; - for (APIChecker apiChecker : s_apiAccessCheckers) { + for (APIChecker apiChecker : _apiAccessCheckers) { try { apiChecker.checkAccess(user, apiName); } catch (Exception ex) { diff --git a/plugins/api/discovery/test/org/apache/cloudstack/discovery/ApiDiscoveryTest.java b/plugins/api/discovery/test/org/apache/cloudstack/discovery/ApiDiscoveryTest.java index 3b526dd485d..320d20aa71d 100644 --- a/plugins/api/discovery/test/org/apache/cloudstack/discovery/ApiDiscoveryTest.java +++ b/plugins/api/discovery/test/org/apache/cloudstack/discovery/ApiDiscoveryTest.java @@ -22,6 +22,7 @@ import com.cloud.user.UserVO; import java.util.*; import javax.naming.ConfigurationException; +import com.cloud.utils.component.PluggableService; import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.command.user.discovery.ListApisCmd; @@ -35,9 +36,9 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class ApiDiscoveryTest { - - private static ApiDiscoveryServiceImpl _discoveryService = new ApiDiscoveryServiceImpl(); private static APIChecker _apiChecker = mock(APIChecker.class); + private static PluggableService _pluggableService = mock(PluggableService.class); + private static ApiDiscoveryServiceImpl _discoveryService = new ApiDiscoveryServiceImpl(); private static Class testCmdClass = ListApisCmd.class; private static User testUser; @@ -54,13 +55,18 @@ public class ApiDiscoveryTest { testApiAsync = false; testUser = new UserVO(); - Set> cmdClasses = new HashSet>(); - cmdClasses.add(ListApisCmd.class); - _discoveryService.cacheResponseMap(cmdClasses); - _discoveryService.s_apiAccessCheckers = (List) mock(List.class); + _discoveryService._apiAccessCheckers = (List) mock(List.class); + _discoveryService._services = (List) mock(List.class); when(_apiChecker.checkAccess(any(User.class), anyString())).thenReturn(true); - when(_discoveryService.s_apiAccessCheckers.iterator()).thenReturn(Arrays.asList(_apiChecker).iterator()); + when(_pluggableService.getCommands()).thenReturn(new ArrayList>()); + when(_discoveryService._apiAccessCheckers.iterator()).thenReturn(Arrays.asList(_apiChecker).iterator()); + when(_discoveryService._services.iterator()).thenReturn(Arrays.asList(_pluggableService).iterator()); + + Set> cmdClasses = new HashSet>(); + cmdClasses.add(ListApisCmd.class); + _discoveryService.init(); + _discoveryService.cacheResponseMap(cmdClasses); } @Test diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index d3a4a229b49..f320a66b487 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -211,6 +211,7 @@ import com.cloud.storage.template.TemplateInfo; import com.cloud.storage.template.TemplateLocation; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.FileUtil; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -1429,6 +1430,8 @@ ServerResource { if (type == null) { return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); + } else if (type.equals("QCOW2") && shrinkOk) { + return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); } s_logger.debug("got to the stage where we execute the volume resize, params:" @@ -4592,44 +4595,20 @@ ServerResource { private Pair getNicStats(String nicName) { double rx = 0.0; - File rxFile = new File("/sys/class/net/" + nicName + "/statistics/rx_bytes"); - try { - FileInputStream rxStream = new FileInputStream(rxFile); - StringBuffer rxContent = new StringBuffer(""); - byte[] rxBuffer = new byte[1024]; - int rxLength; - - while ((rxLength = rxStream.read(rxBuffer)) != -1) { - rxContent.append(new String(rxBuffer)); - } - rx = Double.parseDouble(rxContent.toString()); - } catch (final FileNotFoundException e) { - throw new CloudRuntimeException("Cannot find the file: " - + rxFile.getAbsolutePath(), e); - } catch (final IOException e) { - throw new CloudRuntimeException("IOException in reading " - + rxFile.getAbsolutePath(), e); + String rxFile = "/sys/class/net/" + nicName + "/statistics/rx_bytes"; + String rxContent = FileUtil.readFileAsString(rxFile); + if (rxContent == null) { + s_logger.warn("Failed to read the rx_bytes for " + nicName + " from " + rxFile); } + rx = Double.parseDouble(rxContent); double tx = 0.0; - File txFile = new File("/sys/class/net/" + nicName + "/statistics/tx_bytes"); - try { - FileInputStream txStream = new FileInputStream(txFile); - StringBuffer txContent = new StringBuffer(""); - byte[] txBuffer = new byte[1024]; - int txLength; - - while((txLength = txStream.read(txBuffer)) != -1) { - txContent.append(new String(txBuffer)); - } - tx = Double.parseDouble(txContent.toString()); - } catch (final FileNotFoundException e) { - throw new CloudRuntimeException("Cannot find the file: " - + txFile.getAbsolutePath(), e); - } catch (final IOException e) { - throw new CloudRuntimeException("IOException in reading " - + txFile.getAbsolutePath(), e); + String txFile = "/sys/class/net/" + nicName + "/statistics/tx_bytes"; + String txContent = FileUtil.readFileAsString(txFile); + if (txContent == null) { + s_logger.warn("Failed to read the tx_bytes for " + nicName + " from " + txFile); } + tx = Double.parseDouble(txContent); return new Pair(rx, tx); } diff --git a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java index db4b619e6ca..728271c41f0 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java @@ -21,7 +21,7 @@ import java.util.List; import com.cloud.api.commands.ConfigureSimulator; -public class ManagementServerSimulatorImpl extends ManagementServerExtImpl { +public class ManagementServerSimulatorImpl extends ManagementServerImpl { @Override public List> getCommands() { List> cmdList = super.getCommands(); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index ac0f6f46518..ddbce661239 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -94,7 +95,11 @@ public class VmwareServerDiscoverer extends DiscovererBase implements CiscoNexusVSMDeviceDao _nexusDao; @Inject NetworkModel _netmgr; - + + public VmwareServerDiscoverer() { + s_logger.info("VmwareServerDiscoverer is constructed"); + } + @Override public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java index ab10e5e5ef1..8324bcf0d30 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java @@ -11,12 +11,16 @@ // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor.vmware.resource; +import javax.annotation.PostConstruct; +import javax.inject.Inject; + import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.manager.VmwareManagerImpl; @@ -25,18 +29,25 @@ import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentContext; import com.vmware.apputils.version.ExtendedAppUtil; - +@Component public class VmwareContextFactory { - + private static final Logger s_logger = Logger.getLogger(VmwareContextFactory.class); - + private static volatile int s_seq = 1; private static VmwareManager s_vmwareMgr; - + + @Inject VmwareManager _vmwareMgr; + static { // skip certificate check System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory"); - s_vmwareMgr = ComponentContext.inject(VmwareManagerImpl.class); + //s_vmwareMgr = ComponentContext.inject(VmwareManagerImpl.class); + } + + @PostConstruct + void init() { + s_vmwareMgr = _vmwareMgr; } public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception { @@ -49,13 +60,13 @@ public class VmwareContextFactory { if(s_logger.isDebugEnabled()) s_logger.debug("initialize VmwareContext. url: " + serviceUrl + ", username: " + vCenterUserName + ", password: " + StringUtils.getMaskedPasswordForDisplay(vCenterPassword)); - + ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params); - + appUtil.connect(); VmwareContext context = new VmwareContext(appUtil, vCenterAddress); context.registerStockObject(VmwareManager.CONTEXT_STOCK_NAME, s_vmwareMgr); - + context.registerStockObject("serviceconsole", s_vmwareMgr.getServiceConsolePortGroupName()); context.registerStockObject("manageportgroup", s_vmwareMgr.getManagementPortGroupName()); diff --git a/plugins/network-elements/dns-notifier/resources/components-example.xml b/plugins/network-elements/dns-notifier/resources/components-example.xml index 412da0e289e..36441bd667b 100755 --- a/plugins/network-elements/dns-notifier/resources/components-example.xml +++ b/plugins/network-elements/dns-notifier/resources/components-example.xml @@ -29,7 +29,7 @@ under the License. - + true diff --git a/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java b/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java index d2f43471366..52e7cb3e297 100644 --- a/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java +++ b/plugins/user-authenticators/plain-text/src/com/cloud/server/auth/PlainTextUserAuthenticator.java @@ -25,16 +25,13 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; -import com.cloud.server.ManagementServer; import com.cloud.user.UserAccount; import com.cloud.user.dao.UserAccountDao; import com.cloud.utils.exception.CloudRuntimeException; -@Component @Local(value={UserAuthenticator.class}) public class PlainTextUserAuthenticator extends DefaultUserAuthenticator { public static final Logger s_logger = Logger.getLogger(PlainTextUserAuthenticator.class); diff --git a/scripts/storage/qcow2/resizevolume.sh b/scripts/storage/qcow2/resizevolume.sh index 2de1f9ec5ca..d15513e250f 100755 --- a/scripts/storage/qcow2/resizevolume.sh +++ b/scripts/storage/qcow2/resizevolume.sh @@ -177,7 +177,7 @@ resizeqcow2() { fi ##### end sanity ##### - $actualsize=`qemu-img info $path | grep "virtual size" | sed -re 's/^.*\(([0-9]+).*$/\1/g'` + actualsize=`qemu-img info $path | grep "virtual size" | sed -re 's/^.*\(([0-9]+).*$/\1/g'` if [ $actualsize -ne $currentsize ] then diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 21c73ac8dc2..db6f6d63ac9 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -594,6 +594,7 @@ def destroy_network_rules_for_vm(session, args): util.SMlog("Ignoring failure to delete chain " + vmchain_default) destroy_ebtables_rules(vmchain) + destroy_arptables_rules(vmchain) try: util.pread2(['iptables', '-F', vmchain]) diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 8e950ab2356..83132c6aa76 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -83,8 +83,6 @@ import com.cloud.api.query.vo.StoragePoolJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; -import com.cloud.api.query.dao.*; -import com.cloud.api.query.vo.*; import com.cloud.async.AsyncJob; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; @@ -108,6 +106,7 @@ import com.cloud.host.Host; import com.cloud.host.HostStats; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress; import com.cloud.network.Network; @@ -156,10 +155,6 @@ import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.dao.Site2SiteCustomerGatewayVO; import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.Site2SiteVpnGatewayVO; -import com.cloud.network.*; -import com.cloud.network.as.*; -import com.cloud.network.as.dao.*; -import com.cloud.network.dao.*; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.security.SecurityGroup; @@ -313,6 +308,7 @@ public class ApiDBUtils { static VpcOfferingDao _vpcOfferingDao; static SnapshotPolicyDao _snapshotPolicyDao; static AsyncJobDao _asyncJobDao; + static HostDetailsDao _hostDetailsDao; @Inject private ManagementServer ms; @Inject public AsyncJobManager asyncMgr; @@ -410,6 +406,7 @@ public class ApiDBUtils { @Inject private VpcOfferingDao vpcOfferingDao; @Inject private SnapshotPolicyDao snapshotPolicyDao; @Inject private AsyncJobDao asyncJobDao; + @Inject private HostDetailsDao hostDetailsDao; @PostConstruct void init() { @@ -507,6 +504,7 @@ public class ApiDBUtils { _vpcOfferingDao = vpcOfferingDao; _snapshotPolicyDao = snapshotPolicyDao; _asyncJobDao = asyncJobDao; + _hostDetailsDao = hostDetailsDao; // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned _statsCollector = StatsCollector.getInstance(); @@ -1493,4 +1491,8 @@ public class ApiDBUtils { public static DataCenterJoinVO newDataCenterView(DataCenter dc){ return _dcJoinDao.newDataCenterView(dc); } + + public static Map findHostDetailsById(long hostId){ + return _hostDetailsDao.findDetails(hostId); + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 411de946f56..8c9761520bb 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -81,7 +81,9 @@ import org.apache.cloudstack.api.response.SystemVmInstanceResponse; import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.api.response.TemplatePermissionsResponse; import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.TrafficMonitorResponse; import org.apache.cloudstack.api.response.TrafficTypeResponse; +import org.apache.cloudstack.api.response.UsageRecordResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VirtualRouterProviderResponse; @@ -103,6 +105,7 @@ import com.cloud.configuration.Configuration; import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.ResourceCount; import com.cloud.configuration.ResourceLimit; +import com.cloud.dao.EntityManager; import com.cloud.dc.*; import com.cloud.dc.Vlan.VlanType; import com.cloud.domain.Domain; @@ -139,6 +142,7 @@ import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.*; import com.cloud.network.security.SecurityGroup; +import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.network.vpc.PrivateGateway; @@ -148,6 +152,7 @@ import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; +import com.cloud.offerings.NetworkOfferingVO; import com.cloud.org.Cluster; import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; @@ -155,6 +160,7 @@ import com.cloud.projects.ProjectInvitation; import com.cloud.server.Criteria; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.*; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; @@ -174,6 +180,7 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.InstanceGroup; import com.cloud.vm.NicProfile; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import org.apache.cloudstack.acl.ControlledEntity; @@ -185,11 +192,16 @@ import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; import org.apache.cloudstack.api.response.*; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.usage.Usage; +import org.apache.cloudstack.usage.UsageService; +import org.apache.cloudstack.usage.UsageTypes; import org.apache.log4j.Logger; import java.text.DecimalFormat; import java.util.*; +import javax.inject.Inject; + import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -198,6 +210,8 @@ public class ApiResponseHelper implements ResponseGenerator { public final Logger s_logger = Logger.getLogger(ApiResponseHelper.class); private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##"); + @Inject private EntityManager _entityMgr = null; + @Inject private UsageService _usageSvc = null; @Override public UserResponse createUserResponse(User user) { @@ -3118,4 +3132,243 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + + + @Override + public UsageRecordResponse createUsageResponse(Usage usageRecord) { + UsageRecordResponse usageRecResponse = new UsageRecordResponse(); + + Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + //find the project + Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); + usageRecResponse.setProjectId(project.getUuid()); + usageRecResponse.setProjectName(project.getName()); + } else { + usageRecResponse.setAccountId(account.getUuid()); + usageRecResponse.setAccountName(account.getAccountName()); + } + + Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); + if (domain != null) { + usageRecResponse.setDomainId(domain.getUuid()); + } + + if (usageRecord.getZoneId() != null) { + DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); + if (zone != null) { + usageRecResponse.setZoneId(zone.getUuid()); + } + } + usageRecResponse.setDescription(usageRecord.getDescription()); + usageRecResponse.setUsage(usageRecord.getUsageDisplay()); + usageRecResponse.setUsageType(usageRecord.getUsageType()); + if (usageRecord.getVmInstanceId() != null) { + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); + usageRecResponse.setVirtualMachineId(vm.getUuid()); + } + usageRecResponse.setVmName(usageRecord.getVmName()); + if (usageRecord.getTemplateId() != null) { + VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); + if (template != null) { + usageRecResponse.setTemplateId(template.getUuid()); + } + } + + if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ + ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString()); + //Service Offering Id + usageRecResponse.setOfferingId(svcOffering.getUuid()); + //VM Instance ID + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + //Hypervisor Type + usageRecResponse.setType(usageRecord.getType()); + + } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ + //isSourceNAT + usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); + //isSystem + usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); + //IP Address ID + IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(ip.getUuid()); + + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ + //Device Type + usageRecResponse.setType(usageRecord.getType()); + if(usageRecord.getType().equals("DomainRouter")){ + //Domain Router Id + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vm.getUuid()); + } else { + //External Device Host Id + HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(host.getUuid()); + } + //Network ID + NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); + usageRecResponse.setNetworkId(network.getUuid()); + + } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ + //Volume ID + VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(volume.getUuid()); + //Volume Size + usageRecResponse.setSize(usageRecord.getSize()); + //Disk Offering Id + if(usageRecord.getOfferingId() != null){ + DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(diskOff.getUuid()); + } + + } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ + //Template/ISO ID + VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(tmpl.getUuid()); + //Template/ISO Size + usageRecResponse.setSize(usageRecord.getSize()); + + } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ + //Snapshot ID + SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(snap.getUuid()); + //Snapshot Size + usageRecResponse.setSize(usageRecord.getSize()); + + } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ + //Load Balancer Policy ID + usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + + } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ + //Port Forwarding Rule ID + usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + + } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ + //Network Offering Id + NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); + usageRecResponse.setOfferingId(netOff.getUuid()); + //is Default + usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); + + } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ + //VPN User ID + usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + + } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ + //Security Group Id + SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(sg.getUuid()); + } + + if (usageRecord.getRawUsage() != null) { + DecimalFormat decimalFormat = new DecimalFormat("###########.######"); + usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); + } + + if (usageRecord.getStartDate() != null) { + usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); + } + if (usageRecord.getEndDate() != null) { + usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); + } + + return usageRecResponse; + } + + + public String getDateStringInternal(Date inputDate) { + if (inputDate == null) return null; + + TimeZone tz = _usageSvc.getUsageTimezone(); + Calendar cal = Calendar.getInstance(tz); + cal.setTime(inputDate); + + StringBuffer sb = new StringBuffer(); + sb.append(cal.get(Calendar.YEAR)+"-"); + + int month = cal.get(Calendar.MONTH) + 1; + if (month < 10) { + sb.append("0" + month + "-"); + } else { + sb.append(month+"-"); + } + + int day = cal.get(Calendar.DAY_OF_MONTH); + if (day < 10) { + sb.append("0" + day); + } else { + sb.append(""+day); + } + + sb.append("'T'"); + + int hour = cal.get(Calendar.HOUR_OF_DAY); + if (hour < 10) { + sb.append("0" + hour + ":"); + } else { + sb.append(hour+":"); + } + + int minute = cal.get(Calendar.MINUTE); + if (minute < 10) { + sb.append("0" + minute + ":"); + } else { + sb.append(minute+":"); + } + + int seconds = cal.get(Calendar.SECOND); + if (seconds < 10) { + sb.append("0" + seconds); + } else { + sb.append(""+seconds); + } + + double offset = cal.get(Calendar.ZONE_OFFSET); + if (tz.inDaylightTime(inputDate)) { + offset += (1.0*tz.getDSTSavings()); // add the timezone's DST value (typically 1 hour expressed in milliseconds) + } + + offset = offset / (1000d*60d*60d); + int hourOffset = (int)offset; + double decimalVal = Math.abs(offset) - Math.abs(hourOffset); + int minuteOffset = (int)(decimalVal * 60); + + if (hourOffset < 0) { + if (hourOffset > -10) { + sb.append("-0"+Math.abs(hourOffset)); + } else { + sb.append("-"+Math.abs(hourOffset)); + } + } else { + if (hourOffset < 10) { + sb.append("+0" + hourOffset); + } else { + sb.append("+" + hourOffset); + } + } + + sb.append(":"); + + if (minuteOffset == 0) { + sb.append("00"); + } else if (minuteOffset < 10) { + sb.append("0" + minuteOffset); + } else { + sb.append("" + minuteOffset); + } + + return sb.toString(); + } + + @Override + public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) { + Map tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId()); + TrafficMonitorResponse response = new TrafficMonitorResponse(); + response.setId(trafficMonitor.getUuid()); + response.setIpAddress(trafficMonitor.getPrivateIpAddress()); + response.setNumRetries(tmDetails.get("numRetries")); + response.setTimeout(tmDetails.get("timeout")); + return response; + } } diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 233da158643..e41fcb50513 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -222,6 +222,9 @@ public class ApiServer implements HttpRequestHandler { Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + for(PluggableService pluggableService: _pluggableServices) + cmdClasses.addAll(pluggableService.getCommands()); + for(Class cmdClass: cmdClasses) { String apiName = cmdClass.getAnnotation(APICommand.class).name(); if (_apiNameCmdClassMap.containsKey(apiName)) { diff --git a/server/src/com/cloud/api/commands/GetUsageRecordsCmd.java b/server/src/com/cloud/api/commands/GetUsageRecordsCmd.java deleted file mode 100644 index 7f96b0c9f8a..00000000000 --- a/server/src/com/cloud/api/commands/GetUsageRecordsCmd.java +++ /dev/null @@ -1,370 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.api.commands; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.TimeZone; - -import org.apache.cloudstack.api.response.AccountResponse; -import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.ApiConstants; -import com.cloud.api.ApiDBUtils; -import com.cloud.dc.DataCenter; -import com.cloud.domain.Domain; - -import org.apache.cloudstack.api.BaseListCmd; -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.ListResponse; -import com.cloud.projects.Project; -import com.cloud.server.ManagementServerExt; -import org.apache.cloudstack.api.response.UsageRecordResponse; -import com.cloud.storage.VMTemplateVO; -import com.cloud.usage.UsageTypes; -import com.cloud.usage.UsageVO; -import com.cloud.user.Account; -import com.cloud.uuididentity.dao.IdentityDao; -import com.cloud.uuididentity.dao.IdentityDaoImpl; -import com.cloud.vm.VMInstanceVO; - -@APICommand(name = "listUsageRecords", description="Lists usage records for accounts", responseObject=UsageRecordResponse.class) -public class GetUsageRecordsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(GetUsageRecordsCmd.class.getName()); - - private static final String s_name = "listusagerecordsresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="List usage records for the specified user.") - private String accountName; - - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class, - description="List usage records for the specified domain.") - private Long domainId; - - @Parameter(name=ApiConstants.END_DATE, type=CommandType.DATE, required=true, description="End date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") - private Date endDate; - - @Parameter(name=ApiConstants.START_DATE, type=CommandType.DATE, required=true, description="Start date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.") - private Date startDate; - - @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class, - description="List usage records for the specified account") - private Long accountId; - - @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, - description="List usage records for specified project") - private Long projectId; - - @Parameter(name=ApiConstants.TYPE, type=CommandType.LONG, description="List usage records for the specified usage type") - private Long usageType; - - ///////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public String getAccountName() { - return accountName; - } - - public Long getDomainId() { - return domainId; - } - - public Date getEndDate() { - return endDate; - } - - public Date getStartDate() { - return startDate; - } - - public Long getAccountId() { - return accountId; - } - - public Long getUsageType() { - return usageType; - } - - public Long getProjectId() { - return projectId; - } - - ///////////////////////////////////////////////////// - /////////////// Misc parameters /////////////////// - ///////////////////////////////////////////////////// - - private TimeZone usageTimezone; - - public TimeZone getUsageTimezone() { - return usageTimezone; - } - - public void setUsageTimezone(TimeZone tz) { - this.usageTimezone = tz; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public String getCommandName() { - return s_name; - } - - public String getDateStringInternal(Date inputDate) { - if (inputDate == null) return null; - - TimeZone tz = getUsageTimezone(); - Calendar cal = Calendar.getInstance(tz); - cal.setTime(inputDate); - - StringBuffer sb = new StringBuffer(); - sb.append(cal.get(Calendar.YEAR)+"-"); - - int month = cal.get(Calendar.MONTH) + 1; - if (month < 10) { - sb.append("0" + month + "-"); - } else { - sb.append(month+"-"); - } - - int day = cal.get(Calendar.DAY_OF_MONTH); - if (day < 10) { - sb.append("0" + day); - } else { - sb.append(""+day); - } - - sb.append("'T'"); - - int hour = cal.get(Calendar.HOUR_OF_DAY); - if (hour < 10) { - sb.append("0" + hour + ":"); - } else { - sb.append(hour+":"); - } - - int minute = cal.get(Calendar.MINUTE); - if (minute < 10) { - sb.append("0" + minute + ":"); - } else { - sb.append(minute+":"); - } - - int seconds = cal.get(Calendar.SECOND); - if (seconds < 10) { - sb.append("0" + seconds); - } else { - sb.append(""+seconds); - } - - double offset = cal.get(Calendar.ZONE_OFFSET); - if (tz.inDaylightTime(inputDate)) { - offset += (1.0*tz.getDSTSavings()); // add the timezone's DST value (typically 1 hour expressed in milliseconds) - } - - offset = offset / (1000d*60d*60d); - int hourOffset = (int)offset; - double decimalVal = Math.abs(offset) - Math.abs(hourOffset); - int minuteOffset = (int)(decimalVal * 60); - - if (hourOffset < 0) { - if (hourOffset > -10) { - sb.append("-0"+Math.abs(hourOffset)); - } else { - sb.append("-"+Math.abs(hourOffset)); - } - } else { - if (hourOffset < 10) { - sb.append("+0" + hourOffset); - } else { - sb.append("+" + hourOffset); - } - } - - sb.append(":"); - - if (minuteOffset == 0) { - sb.append("00"); - } else if (minuteOffset < 10) { - sb.append("0" + minuteOffset); - } else { - sb.append("" + minuteOffset); - } - - return sb.toString(); - } - - @Override - public void execute(){ - ManagementServerExt _mgrExt = (ManagementServerExt)_mgr; - List usageRecords = _mgrExt.getUsageRecords(this); - IdentityDao identityDao = new IdentityDaoImpl(); - ListResponse response = new ListResponse(); - List usageResponses = new ArrayList(); - for (Object usageRecordGeneric : usageRecords) { - UsageRecordResponse usageRecResponse = new UsageRecordResponse(); - if (usageRecordGeneric instanceof UsageVO) { - UsageVO usageRecord = (UsageVO)usageRecordGeneric; - - Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()); - if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - //find the project - Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId()); - usageRecResponse.setProjectId(project.getUuid()); - usageRecResponse.setProjectName(project.getName()); - } else { - usageRecResponse.setAccountId(account.getUuid()); - usageRecResponse.setAccountName(account.getAccountName()); - } - - Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId()); - if (domain != null) { - usageRecResponse.setDomainId(domain.getUuid()); - } - - if (usageRecord.getZoneId() != null) { - DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId()); - if (zone != null) { - usageRecResponse.setZoneId(zone.getUuid()); - } - } - usageRecResponse.setDescription(usageRecord.getDescription()); - usageRecResponse.setUsage(usageRecord.getUsageDisplay()); - usageRecResponse.setUsageType(usageRecord.getUsageType()); - if (usageRecord.getVmInstanceId() != null) { - VMInstanceVO vm = ApiDBUtils.findVMInstanceById(usageRecord.getVmInstanceId()); - if (vm != null) { - usageRecResponse.setVirtualMachineId(vm.getUuid()); - } - } - usageRecResponse.setVmName(usageRecord.getVmName()); - if (usageRecord.getTemplateId() != null) { - VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId()); - if (template != null) { - usageRecResponse.setTemplateId(template.getUuid()); - } - } - - if(usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM){ - //Service Offering Id - usageRecResponse.setOfferingId(identityDao.getIdentityUuid("disk_offering", usageRecord.getOfferingId().toString())); - //VM Instance ID - usageRecResponse.setUsageId(identityDao.getIdentityUuid("vm_instance", usageRecord.getUsageId().toString())); - //Hypervisor Type - usageRecResponse.setType(usageRecord.getType()); - - } else if(usageRecord.getUsageType() == UsageTypes.IP_ADDRESS){ - //isSourceNAT - usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat"))?true:false); - //isSystem - usageRecResponse.setSystem((usageRecord.getSize() == 1)?true:false); - //IP Address ID - usageRecResponse.setUsageId(identityDao.getIdentityUuid("user_ip_address", usageRecord.getUsageId().toString())); - - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED){ - //Device Type - usageRecResponse.setType(usageRecord.getType()); - if(usageRecord.getType().equals("DomainRouter")){ - //Domain Router Id - usageRecResponse.setUsageId(identityDao.getIdentityUuid("vm_instance", usageRecord.getUsageId().toString())); - } else { - //External Device Host Id - usageRecResponse.setUsageId(identityDao.getIdentityUuid("host", usageRecord.getUsageId().toString())); - } - //Network ID - usageRecResponse.setNetworkId(identityDao.getIdentityUuid("networks", usageRecord.getNetworkId().toString())); - - } else if(usageRecord.getUsageType() == UsageTypes.VOLUME){ - //Volume ID - usageRecResponse.setUsageId(identityDao.getIdentityUuid("volumes", usageRecord.getUsageId().toString())); - //Volume Size - usageRecResponse.setSize(usageRecord.getSize()); - //Disk Offering Id - if(usageRecord.getOfferingId() != null){ - usageRecResponse.setOfferingId(identityDao.getIdentityUuid("disk_offering", usageRecord.getOfferingId().toString())); - } - - } else if(usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO){ - //Template/ISO ID - usageRecResponse.setUsageId(identityDao.getIdentityUuid("vm_template", usageRecord.getUsageId().toString())); - //Template/ISO Size - usageRecResponse.setSize(usageRecord.getSize()); - - } else if(usageRecord.getUsageType() == UsageTypes.SNAPSHOT){ - //Snapshot ID - usageRecResponse.setUsageId(identityDao.getIdentityUuid("snapshots", usageRecord.getUsageId().toString())); - //Snapshot Size - usageRecResponse.setSize(usageRecord.getSize()); - - } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ - //Load Balancer Policy ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); - - } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ - //Port Forwarding Rule ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); - - } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ - //Network Offering Id - usageRecResponse.setOfferingId(identityDao.getIdentityUuid("network_offerings", usageRecord.getOfferingId().toString())); - //is Default - usageRecResponse.setDefault((usageRecord.getUsageId() == 1)? true:false); - - } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ - //VPN User ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); - - } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ - //Security Group Id - usageRecResponse.setUsageId(identityDao.getIdentityUuid("security_group", usageRecord.getUsageId().toString())); - } - - if (usageRecord.getRawUsage() != null) { - DecimalFormat decimalFormat = new DecimalFormat("###########.######"); - usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage())); - } - - if (usageRecord.getStartDate() != null) { - usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); - } - if (usageRecord.getEndDate() != null) { - usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); - } - } - - usageRecResponse.setObjectName("usagerecord"); - usageResponses.add(usageRecResponse); - } - - response.setResponses(usageResponses); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } -} diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 5e4996b144c..7592b6bdfca 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -97,7 +97,6 @@ public enum Config { VmNetworkThrottlingRate("Network", ManagementServer.class, Integer.class, "vm.network.throttling.rate", "200", "Default data transfer rate in megabits per second allowed in User vm's default network.", null), NetworkLockTimeout("Network", ManagementServer.class, Integer.class, "network.lock.timeout", "600", "Lock wait timeout (seconds) while implementing network", null), - SecurityGroupWorkCleanupInterval("Network", ManagementServer.class, Integer.class, "network.securitygroups.work.cleanup.interval", "120", "Time interval (seconds) in which finished work is cleaned up from the work table", null), SecurityGroupWorkerThreads("Network", ManagementServer.class, Integer.class, "network.securitygroups.workers.pool.size", "50", "Number of worker threads processing the security group update work queue", null), SecurityGroupWorkGlobalLockTimeout("Network", ManagementServer.class, Integer.class, "network.securitygroups.work.lock.timeout", "300", "Lock wait timeout (seconds) while updating the security group work queue", null), @@ -356,9 +355,9 @@ public enum Config { VpcCleanupInterval("Advanced", ManagementServer.class, Integer.class, "vpc.cleanup.interval", "3600", "The interval (in seconds) between cleanup for Inactive VPCs", null), VpcMaxNetworks("Advanced", ManagementServer.class, Integer.class, "vpc.max.networks", "3", "Maximum number of networks per vpc", null), DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, "detail.batch.query.size", "2000", "Default entity detail batch query size for listing", null), - ConcurrentSnapshotsThresholdPerHost("Advanced", ManagementServer.class, Long.class, "concurrent.snapshots.threshold.perhost", null, "Limits number of snapshots that can be handled by the host concurrently; default is NULL - unlimited", null), + NetworkIPv6SearchRetryMax("Network", ManagementServer.class, Integer.class, "network.ipv6.search.retry.max", "10000", "The maximum number of retrying times to search for an available IPv6 address in the table", null), ExternalBaremetalSystemUrl("Advanced", ManagementServer.class, String.class, "external.baremetal.system.url", null, "url of external baremetal system that CloudStack will talk to", null), ExternalBaremetalResourceClassName("Advanced", ManagementServer.class, String.class, "external,baremetal.resource.classname", null, "class name for handling external baremetal resource", null), diff --git a/server/src/com/cloud/dao/EntityManagerImpl.java b/server/src/com/cloud/dao/EntityManagerImpl.java index a7685882b6c..a3ab5b362e8 100644 --- a/server/src/com/cloud/dao/EntityManagerImpl.java +++ b/server/src/com/cloud/dao/EntityManagerImpl.java @@ -27,7 +27,6 @@ import org.springframework.stereotype.Component; import net.sf.ehcache.Cache; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDaoBase; @@ -47,6 +46,12 @@ public class EntityManagerImpl extends ManagerBase implements EntityManager { GenericDao dao = (GenericDao)GenericDaoBase.getDao(entityType); return dao.findById(id); } + + @Override + public T findByIdIncludingRemoved(Class entityType, K id) { + GenericDao dao = (GenericDao)GenericDaoBase.getDao(entityType); + return dao.findByIdIncludingRemoved(id); + } @Override public T findByUuid(Class entityType, String uuid) { diff --git a/server/src/com/cloud/network/Ipv6AddressManagerImpl.java b/server/src/com/cloud/network/Ipv6AddressManagerImpl.java index 01227721614..f5ad7da1d14 100644 --- a/server/src/com/cloud/network/Ipv6AddressManagerImpl.java +++ b/server/src/com/cloud/network/Ipv6AddressManagerImpl.java @@ -25,14 +25,19 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.Vlan; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.user.Account; import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -40,6 +45,9 @@ import com.cloud.utils.net.NetUtils; public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressManager { public static final Logger s_logger = Logger.getLogger(Ipv6AddressManagerImpl.class.getName()); + String _name = null; + int _ipv6RetryMax = 0; + @Inject DataCenterDao _dcDao; @Inject @@ -48,30 +56,50 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa NetworkModel _networkModel; @Inject UserIpv6AddressDao _ipv6Dao; + @Inject + NetworkDao _networkDao; + @Inject + ConfigurationDao _configDao; @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + _name = name; + Map configs = _configDao.getConfiguration(params); + _ipv6RetryMax = NumbersUtil.parseInt(configs.get(Config.NetworkIPv6SearchRetryMax.key()), 10000); + return true; + } + public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, Long networkId, String requestedIp6) throws InsufficientAddressCapacityException { + Network network = _networkDao.findById(networkId); + if (network == null) { + return null; + } Vlan vlan = _networkModel.getVlanForNetwork(networkId); if (vlan == null) { s_logger.debug("Cannot find related vlan or too many vlan attached to network " + networkId); return null; } - String ip = null; + String ip = null; if (requestedIp6 == null) { + if (!_networkModel.isIP6AddressAvailable(networkId)) { + throw new InsufficientAddressCapacityException("There is no more address available in the network " + network.getName(), DataCenter.class, network.getDataCenterId()); + } + ip = NetUtils.getIp6FromRange(vlan.getIp6Range()); int count = 0; - while (ip == null || count >= 10) { - ip = NetUtils.getIp6FromRange(vlan.getIp6Range()); - //Check for duplicate IP - if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) == null) { - break; - } else { - ip = null; - } + while (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) { + ip = NetUtils.getNextIp6InRange(ip, vlan.getIp6Range()); count ++; + // It's an arbitrate number to prevent the infinite loop + if (count > _ipv6RetryMax) { + ip = null; + break; + } } if (ip == null) { - throw new CloudRuntimeException("Fail to get unique ipv6 address after 10 times trying!"); + throw new InsufficientAddressCapacityException("Cannot find a usable IP in the network " + network.getName() + " after network.ipv6.search.retry.max = " + _ipv6RetryMax + " times retry!", + DataCenter.class, network.getDataCenterId()); } } else { if (!NetUtils.isIp6InRange(requestedIp6, vlan.getIp6Range())) { diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index ff97911493e..f8d0addd1da 100644 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -17,6 +17,7 @@ package com.cloud.network; +import java.math.BigInteger; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.HashMap; @@ -526,7 +527,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { return false; } if (network.getIp6Gateway() != null) { - hasFreeIps = isIP6AddressAvailable(network); + hasFreeIps = isIP6AddressAvailable(network.getId()); } } else { hasFreeIps = (getAvailableIps(network, null)).size() > 0; @@ -544,15 +545,21 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } return vlans.get(0); } - - private boolean isIP6AddressAvailable(Network network) { + + @Override + public boolean isIP6AddressAvailable(long networkId) { + Network network = _networksDao.findById(networkId); + if (network == null) { + return false; + } if (network.getIp6Gateway() == null) { return false; } Vlan vlan = getVlanForNetwork(network.getId()); long existedCount = _ipv6Dao.countExistedIpsInNetwork(network.getId()); - long rangeCount = NetUtils.countIp6InRange(vlan.getIp6Range()); - return (existedCount < rangeCount); + BigInteger existedInt = BigInteger.valueOf(existedCount); + BigInteger rangeInt = NetUtils.countIp6InRange(vlan.getIp6Range()); + return (existedInt.compareTo(rangeInt) < 0); } @Override @@ -1868,4 +1875,4 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { return offering.isInline(); } -} \ No newline at end of file +} diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 235762e66e6..d38d1f8a0be 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -780,14 +780,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!NetUtils.isValidIp6Cidr(ip6Cidr)) { throw new InvalidParameterValueException("Invalid ip6cidr"); } - if (!NetUtils.isIp6InRange(startIPv6, ip6Cidr)) { - throw new InvalidParameterValueException("startIPv6 is not in ip6cidr indicated network range!"); + if (!NetUtils.isIp6InNetwork(startIPv6, ip6Cidr)) { + throw new InvalidParameterValueException("startIPv6 is not in ip6cidr indicated network!"); } - if (!NetUtils.isIp6InRange(endIPv6, ip6Cidr)) { - throw new InvalidParameterValueException("endIPv6 is not in ip6cidr indicated network range!"); + if (!NetUtils.isIp6InNetwork(endIPv6, ip6Cidr)) { + throw new InvalidParameterValueException("endIPv6 is not in ip6cidr indicated network!"); } - if (!NetUtils.isIp6InRange(ip6Gateway, ip6Cidr)) { - throw new InvalidParameterValueException("ip6Gateway is not in ip6cidr indicated network range!"); + if (!NetUtils.isIp6InNetwork(ip6Gateway, ip6Cidr)) { + throw new InvalidParameterValueException("ip6Gateway is not in ip6cidr indicated network!"); } int cidrSize = NetUtils.getIp6CidrSize(ip6Cidr); diff --git a/server/src/com/cloud/network/NetworkUsageManager.java b/server/src/com/cloud/network/NetworkUsageManager.java index 1f0638b3c20..86bec554a6e 100644 --- a/server/src/com/cloud/network/NetworkUsageManager.java +++ b/server/src/com/cloud/network/NetworkUsageManager.java @@ -18,26 +18,12 @@ package com.cloud.network; import java.util.List; -import com.cloud.api.commands.AddTrafficMonitorCmd; -import com.cloud.api.commands.DeleteTrafficMonitorCmd; -import com.cloud.api.commands.ListTrafficMonitorsCmd; -import com.cloud.host.Host; -import com.cloud.host.HostVO; import com.cloud.network.dao.IPAddressVO; -import org.apache.cloudstack.api.response.TrafficMonitorResponse; import com.cloud.utils.component.Manager; public interface NetworkUsageManager extends Manager { - Host addTrafficMonitor(AddTrafficMonitorCmd cmd); - - TrafficMonitorResponse getApiResponse(Host trafficMonitor); - - boolean deleteTrafficMonitor(DeleteTrafficMonitorCmd cmd); - - List listTrafficMonitors(ListTrafficMonitorsCmd cmd); - List listAllocatedDirectIps(long zoneId); } diff --git a/server/src/com/cloud/network/NetworkUsageManagerImpl.java b/server/src/com/cloud/network/NetworkUsageManagerImpl.java index e148e2c123c..80f898b0d7a 100755 --- a/server/src/com/cloud/network/NetworkUsageManagerImpl.java +++ b/server/src/com/cloud/network/NetworkUsageManagerImpl.java @@ -44,9 +44,6 @@ import com.cloud.agent.api.RecurringNetworkUsageCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupTrafficMonitorCommand; import com.cloud.agent.manager.Commands; -import com.cloud.api.commands.AddTrafficMonitorCmd; -import com.cloud.api.commands.DeleteTrafficMonitorCmd; -import com.cloud.api.commands.ListTrafficMonitorsCmd; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; @@ -71,6 +68,10 @@ import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; + +import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; +import org.apache.cloudstack.api.command.admin.usage.DeleteTrafficMonitorCmd; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficMonitorsCmd; import org.apache.cloudstack.api.response.TrafficMonitorResponse; import com.cloud.usage.UsageIPAddressVO; import com.cloud.user.AccountManager; @@ -93,7 +94,7 @@ import com.cloud.utils.net.MacAddress; @Component @Local(value = {NetworkUsageManager.class}) -public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsageManager, ResourceStateAdapter { +public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsageService, NetworkUsageManager, ResourceStateAdapter { public enum NetworkUsageResourceName { TrafficSentinel; } @@ -211,17 +212,6 @@ public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsage return _resourceMgr.listAllHostsInOneZoneByType(Host.Type.TrafficMonitor, zoneId); } - @Override - public TrafficMonitorResponse getApiResponse(Host trafficMonitor) { - Map tmDetails = _detailsDao.findDetails(trafficMonitor.getId()); - TrafficMonitorResponse response = new TrafficMonitorResponse(); - response.setId(trafficMonitor.getUuid()); - response.setIpAddress(trafficMonitor.getPrivateIpAddress()); - response.setNumRetries(tmDetails.get("numRetries")); - response.setTimeout(tmDetails.get("timeout")); - return response; - } - @Override public boolean configure(String name, Map params) throws ConfigurationException { AllocatedIpSearch = _ipAddressDao.createSearchBuilder(); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index f4fa13b8754..82013d4380d 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -1869,11 +1869,29 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return isFirstHost; } + private void markHostAsDisconnected(HostVO host, StartupCommand[] cmds) { + if (host == null) { // in case host is null due to some errors, try reloading the host from db + if (cmds != null) { + StartupCommand firstCmd = cmds[0]; + host = findHostByGuid(firstCmd.getGuid()); + if (host == null) { + host = findHostByGuid(firstCmd.getGuidWithoutResource()); + } + } + } + + if (host != null) { + // Change agent status to Alert, so that host is considered for reconnection next time + _agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId); + } + } + private Host createHostAndAgent(ServerResource resource, Map details, boolean old, List hostTags, boolean forRebalance) { HostVO host = null; AgentAttache attache = null; StartupCommand[] cmds = null; + boolean hostExists = false; try { cmds = resource.initialize(); @@ -1902,10 +1920,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (host == null) { host = findHostByGuid(firstCmd.getGuidWithoutResource()); } - if (host != null && host.getRemoved() == null) { - s_logger.debug("Found the host " + host.getId() - + " by guid: " + firstCmd.getGuid() - + ", old host reconnected as new"); + if (host != null && host.getRemoved() == null) { // host already added, no need to add again + s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new"); + hostExists = true; // ensures that host status is left unchanged in case of adding same one again return null; } } @@ -1925,35 +1942,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } catch (Exception e) { s_logger.warn("Unable to connect due to ", e); } finally { - if (attache == null) { + if (hostExists) { if (cmds != null) { resource.disconnected(); } - // In case of some db errors, we may land with the sitaution - // that host is null. We need to reload host from db and call - // disconnect on it so that it will be loaded for reconnection - // next time - HostVO tempHost = host; - if (tempHost == null) { + } else { + if (attache == null) { if (cmds != null) { - StartupCommand firstCmd = cmds[0]; - tempHost = findHostByGuid(firstCmd.getGuid()); - if (tempHost == null) { - tempHost = findHostByGuid(firstCmd - .getGuidWithoutResource()); - } + resource.disconnected(); } - } - - if (tempHost != null) { - /* Change agent status to Alert */ - _agentMgr.agentStatusTransitTo(tempHost, - Status.Event.AgentDisconnected, _nodeId); - /* - * Don't change resource state here since HostVO is already - * in database, which means resource state has had an - * appropriate value - */ + markHostAsDisconnected(host, cmds); } } } @@ -2060,23 +2058,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (cmds != null) { resource.disconnected(); } - - // In case of some db errors, we may land with the situation that host is null. We need to reload host from db and call disconnect on it so that it will be loaded for reconnection next time - HostVO tempHost = host; - if (tempHost == null) { - if (cmds != null) { - StartupCommand firstCmd = cmds[0]; - tempHost = findHostByGuid(firstCmd.getGuid()); - if (tempHost == null) { - tempHost = findHostByGuid(firstCmd.getGuidWithoutResource()); - } - } - } - if (tempHost != null) { - /* Change agent status to Alert */ - _agentMgr.agentStatusTransitTo(tempHost, Status.Event.AgentDisconnected, _nodeId); - /* Don't change resource state here since HostVO is already in database, which means resource state has had an appropriate value*/ - } + markHostAsDisconnected(host, cmds); } } } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index a1d12c5f24c..5306bc0928d 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1819,8 +1819,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Override public List> getCommands() { + List> cmdList = new ArrayList>(); //TODO: Add cmd classes - return null; + return cmdList; } protected class EventPurgeTask implements Runnable { diff --git a/server/src/com/cloud/server/ManagementServerExtImpl.java b/server/src/com/cloud/usage/UsageServiceImpl.java old mode 100644 new mode 100755 similarity index 89% rename from server/src/com/cloud/server/ManagementServerExtImpl.java rename to server/src/com/cloud/usage/UsageServiceImpl.java index 52ad3dfa848..ae0a585e906 --- a/server/src/com/cloud/server/ManagementServerExtImpl.java +++ b/server/src/com/cloud/usage/UsageServiceImpl.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.server; +package com.cloud.usage; import java.util.ArrayList; import java.util.Calendar; @@ -23,45 +23,59 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; +import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.api.commands.GenerateUsageRecordsCmd; -import com.cloud.api.commands.GetUsageRecordsCmd; +import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd; +import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd; +import org.apache.cloudstack.api.response.UsageTypeResponse; +import org.apache.cloudstack.usage.UsageService; +import org.apache.cloudstack.usage.UsageTypes; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.projects.Project; -import org.apache.cloudstack.api.response.UsageTypeResponse; - -import com.cloud.usage.UsageJobVO; -import com.cloud.usage.UsageTypes; -import com.cloud.usage.UsageVO; +import com.cloud.projects.ProjectManager; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageJobDao; import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.Manager; +import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; -public class ManagementServerExtImpl extends ManagementServerImpl implements ManagementServerExt { +@Component +@Local(value = { UsageService.class }) +public class UsageServiceImpl extends ManagerBase implements UsageService, Manager { + public static final Logger s_logger = Logger.getLogger(UsageServiceImpl.class); + + //ToDo: Move implementation to ManagaerImpl + @Inject private AccountDao _accountDao; @Inject private DomainDao _domainDao; @Inject private UsageDao _usageDao; @Inject private UsageJobDao _usageJobDao; + @Inject private ConfigurationDao _configDao; + @Inject private ProjectManager _projectMgr; private TimeZone _usageTimezone; - public ManagementServerExtImpl() { + public UsageServiceImpl() { } @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - Map configs = getConfigs(); - String timeZoneStr = configs.get("usage.aggregation.timezone"); + String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString()); if (timeZoneStr == null) { timeZoneStr = "GMT"; } @@ -195,9 +209,6 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man swap.close(); } - // now that we are done with the records, update the command with the correct timezone so it can write the proper response - cmd.setUsageTimezone(getUsageTimezone()); - return usageRecords; } @@ -206,12 +217,6 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man return _usageTimezone; } - @Override - public List> getCommands() { - //TODO: Add api cmd classes - return null; - } - private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) { Calendar cal = Calendar.getInstance(); cal.setTime(initialDate); @@ -251,4 +256,6 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man public List listUsageTypes() { return UsageTypes.listUsageTypes(); } + + } diff --git a/server/src/com/cloud/usage/UsageVO.java b/server/src/com/cloud/usage/UsageVO.java index bcb9c2d6363..18a3a6b3811 100644 --- a/server/src/com/cloud/usage/UsageVO.java +++ b/server/src/com/cloud/usage/UsageVO.java @@ -17,6 +17,7 @@ package com.cloud.usage; import org.apache.cloudstack.api.InternalIdentity; +import org.apache.cloudstack.usage.Usage; import java.util.Date; @@ -31,7 +32,7 @@ import javax.persistence.TemporalType; @Entity @Table(name="cloud_usage") -public class UsageVO implements InternalIdentity { +public class UsageVO implements Usage, InternalIdentity { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") @@ -167,74 +168,92 @@ public class UsageVO implements InternalIdentity { this.endDate = endDate; } + @Override public long getId() { return id; } + @Override public Long getZoneId() { return zoneId; } + @Override public Long getAccountId() { return accountId; } + @Override public Long getDomainId() { return domainId; } + @Override public String getDescription() { return description; } - + + @Override public String getUsageDisplay() { return usageDisplay; } + @Override public int getUsageType() { return usageType; } + @Override public Double getRawUsage() { return rawUsage; } + @Override public Long getVmInstanceId() { return vmInstanceId; } + @Override public String getVmName() { return vmName; } + @Override public Long getOfferingId() { return offeringId; } + @Override public Long getTemplateId() { return templateId; } + @Override public Long getUsageId() { return usageId; } + @Override public String getType() { return type; } + @Override public Long getNetworkId() { return networkId; } + @Override public Long getSize() { return size; } + @Override public Date getStartDate() { return startDate; } + @Override public Date getEndDate() { return endDate; } diff --git a/server/src/org/apache/cloudstack/region/RegionManagerImpl.java b/server/src/org/apache/cloudstack/region/RegionManagerImpl.java index 190c69c5b91..c7bca5b00cb 100755 --- a/server/src/org/apache/cloudstack/region/RegionManagerImpl.java +++ b/server/src/org/apache/cloudstack/region/RegionManagerImpl.java @@ -33,6 +33,7 @@ import org.apache.cloudstack.region.dao.RegionDao; import org.apache.cloudstack.region.dao.RegionSyncDao; import org.apache.commons.httpclient.NameValuePair; import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -54,6 +55,7 @@ import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.uuididentity.dao.IdentityDao; +@Component @Local(value = { RegionManager.class }) public class RegionManagerImpl extends ManagerBase implements RegionManager, Manager{ public static final Logger s_logger = Logger.getLogger(RegionManagerImpl.class); diff --git a/server/src/org/apache/cloudstack/region/RegionServiceImpl.java b/server/src/org/apache/cloudstack/region/RegionServiceImpl.java index f10f638127f..7aed881d215 100755 --- a/server/src/org/apache/cloudstack/region/RegionServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/RegionServiceImpl.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; import org.apache.cloudstack.region.dao.RegionDao; import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; @@ -52,6 +53,7 @@ import com.cloud.user.dao.UserDao; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; +@Component @Local(value = { RegionService.class }) public class RegionServiceImpl extends ManagerBase implements RegionService, Manager { public static final Logger s_logger = Logger.getLogger(RegionServiceImpl.class); diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java index 1c36364f418..502354ea108 100644 --- a/server/test/com/cloud/network/MockNetworkModelImpl.java +++ b/server/test/com/cloud/network/MockNetworkModelImpl.java @@ -815,4 +815,9 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + @Override + public boolean isIP6AddressAvailable(long networkId) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java index 8097c346970..1080d48f1be 100644 --- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java @@ -829,4 +829,10 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + @Override + public boolean isIP6AddressAvailable(long networkId) { + // TODO Auto-generated method stub + return false; + } + } diff --git a/tools/appliance/.rvmrc b/tools/appliance/.rvmrc new file mode 100644 index 00000000000..3c8c66c97f9 --- /dev/null +++ b/tools/appliance/.rvmrc @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +rvm use ruby-1.9.3@vagrant-release-cloudstack --create +export VAGRANT_HOME=$HOME/.vagrant.d-release-cloudstack +bundle check > /dev/null 2>&1 +RETVAL=$? +if [ $RETVAL -ne 0 ]; then + bundle install +fi diff --git a/tools/appliance/Gemfile b/tools/appliance/Gemfile new file mode 100644 index 00000000000..dae53be6dd0 --- /dev/null +++ b/tools/appliance/Gemfile @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +source 'https://rubygems.org' +gem 'veewee', :git => 'https://github.com/jedi4ever/veewee.git' +gem 'em-winrm' diff --git a/tools/appliance/README.md b/tools/appliance/README.md new file mode 100644 index 00000000000..aa1001e1b1b --- /dev/null +++ b/tools/appliance/README.md @@ -0,0 +1,52 @@ +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +=========================================================== + +# Setting up Tools and Environment + + - Install [RVM](https://rvm.io/rvm/install) + - Setup paths: + export PATH=~/.rvm/bin:$PATH + - Install Ruby 1.9.3, if it installed some other version: + rvm install 1.9.3 + +All the dependencies will be fetched automatically. + +Vagrant: https://github.com/chipchilders/vagrant.git + +To save some time if you've downloaded iso of your distro, put the isos in: +tools/appliance/iso/ + +Note, gem may require gcc-4.2, make sure link exists: + + sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2 + +# How to build SystemVM template appliance + +List available appliances one can build: + + veewee vbox list + +Modify scripts in definitions/systemvmtemplate/ as per needs. +Build systemvm template appliance: + + veewee vbox build 'systemvmtemplate' + +Start the box: + + veewee vbox up 'systemvmtemplate' diff --git a/tools/appliance/definitions/systemvmtemplate/base.sh b/tools/appliance/definitions/systemvmtemplate/base.sh new file mode 100644 index 00000000000..acd72c3d0c7 --- /dev/null +++ b/tools/appliance/definitions/systemvmtemplate/base.sh @@ -0,0 +1,42 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# Update the box +apt-get -y update +apt-get -y install linux-headers-$(uname -r) build-essential +apt-get -y install zlib1g-dev libssl-dev libreadline-gplv2-dev +apt-get -y install curl unzip +apt-get clean + +# Set up sudo +echo 'vagrant ALL=NOPASSWD:ALL' > /etc/sudoers.d/vagrant + +# Tweak sshd to prevent DNS resolution (speed up logins) +echo 'UseDNS no' >> /etc/ssh/sshd_config + +# Remove 5s grub timeout to speed up booting +echo < /etc/default/grub +# If you change this file, run 'update-grub' afterwards to update +# /boot/grub/grub.cfg. + +GRUB_DEFAULT=0 +GRUB_TIMEOUT=0 +GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` +GRUB_CMDLINE_LINUX_DEFAULT="quiet" +GRUB_CMDLINE_LINUX="debian-installer=en_US" +EOF + +update-grub diff --git a/tools/appliance/definitions/systemvmtemplate/cleanup.sh b/tools/appliance/definitions/systemvmtemplate/cleanup.sh new file mode 100644 index 00000000000..4aab193a3af --- /dev/null +++ b/tools/appliance/definitions/systemvmtemplate/cleanup.sh @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Clean up +apt-get -y remove linux-headers-$(uname -r) build-essential +apt-get -y autoremove + +# Removing leftover leases and persistent rules +echo "cleaning up dhcp leases" +rm /var/lib/dhcp/* + +# Make sure Udev doesn't block our network +echo "cleaning up udev rules" +rm /etc/udev/rules.d/70-persistent-net.rules +mkdir /etc/udev/rules.d/70-persistent-net.rules +rm -rf /dev/.udev/ +rm /lib/udev/rules.d/75-persistent-net-generator.rules + +echo "Adding a 2 sec delay to the interface up, to make the dhclient happy" +echo "pre-up sleep 2" >> /etc/network/interfaces diff --git a/tools/appliance/definitions/systemvmtemplate/definition.rb b/tools/appliance/definitions/systemvmtemplate/definition.rb new file mode 100644 index 00000000000..de23bef451f --- /dev/null +++ b/tools/appliance/definitions/systemvmtemplate/definition.rb @@ -0,0 +1,60 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +Veewee::Definition.declare({ + :cpu_count => '1', + :memory_size=> '256', + :disk_size => '2048', :disk_format => 'VMDK', :hostiocache => 'off', + :os_type_id => 'Debian', + :iso_file => "debian-wheezy-DI-b4-i386-netinst.iso", + :iso_src => "http://cdimage.debian.org/cdimage/wheezy_di_beta4/i386/iso-cd/debian-wheezy-DI-b4-i386-netinst.iso", + :iso_md5 => "34d0ae973715c7a31646281c70839809", + :iso_download_timeout => "1000", + :boot_wait => "10", :boot_cmd_sequence => [ + '', + 'install ', + 'preseed/url=http://%IP%:%PORT%/preseed.cfg ', + 'debian-installer=en_US ', + 'auto ', + 'locale=en_US ', + 'kbd-chooser/method=us ', + 'netcfg/get_hostname=systemvm ', + 'netcfg/get_domain=apache.org ', + 'fb=false ', + 'debconf/frontend=noninteractive ', + 'console-setup/ask_detect=false ', + 'console-keymaps-at/keymap=us ', + '' + ], + :kickstart_port => "7122", + :kickstart_timeout => "10000", + :kickstart_file => "preseed.cfg", + :ssh_login_timeout => "10000", + :ssh_user => "root", + :ssh_password => "password", + :ssh_key => "", + :ssh_host_port => "7222", + :ssh_guest_port => "22", + :sudo_cmd => "echo '%p'|sudo -S sh '%f'", + :shutdown_cmd => "halt -p", + :postinstall_files => [ + "base.sh", + "cleanup.sh", + "zerodisk.sh" + ], + :postinstall_timeout => "10000" +}) diff --git a/tools/appliance/definitions/systemvmtemplate/preseed.cfg b/tools/appliance/definitions/systemvmtemplate/preseed.cfg new file mode 100644 index 00000000000..2b956e11cdb --- /dev/null +++ b/tools/appliance/definitions/systemvmtemplate/preseed.cfg @@ -0,0 +1,332 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#### Contents of the preconfiguration file (for squeeze) +### Localization +# Locale sets language and country. +d-i debian-installer/locale string en_US + +# Keyboard selection. +#d-i console-tools/archs select at +d-i console-keymaps-at/keymap select us +# Example for a different keyboard architecture +#d-i console-keymaps-usb/keymap select mac-usb-us + +### Network configuration +# netcfg will choose an interface that has link if possible. This makes it +# skip displaying a list if there is more than one interface. +d-i netcfg/choose_interface select auto + +# To pick a particular interface instead: +#d-i netcfg/choose_interface select eth1 + +# If you have a slow dhcp server and the installer times out waiting for +# it, this might be useful. +#d-i netcfg/dhcp_timeout string 60 + +# If you prefer to configure the network manually, uncomment this line and +# the static network configuration below. +#d-i netcfg/disable_dhcp boolean true + +# If you want the preconfiguration file to work on systems both with and +# without a dhcp server, uncomment these lines and the static network +# configuration below. +#d-i netcfg/dhcp_failed note +#d-i netcfg/dhcp_options select Configure network manually + +# Static network configuration. +#d-i netcfg/get_nameservers string 192.168.1.1 +#d-i netcfg/get_ipaddress string 192.168.1.42 +#d-i netcfg/get_netmask string 255.255.255.0 +#d-i netcfg/get_gateway string 192.168.1.1 +#d-i netcfg/confirm_static boolean true + +# Any hostname and domain names assigned from dhcp take precedence over +# values set here. However, setting the values still prevents the questions +# from being shown, even if values come from dhcp. +#d-i netcfg/get_hostname string vagrant +d-i netcfg/get_domain string vagrantup.com + +# Disable that annoying WEP key dialog. +d-i netcfg/wireless_wep string +# The wacky dhcp hostname that some ISPs use as a password of sorts. +#d-i netcfg/dhcp_hostname string radish + +# If non-free firmware is needed for the network or other hardware, you can +# configure the installer to always try to load it, without prompting. Or +# change to false to disable asking. +#d-i hw-detect/load_firmware boolean true + +### Network console +# Use the following settings if you wish to make use of the network-console +# component for remote installation over SSH. This only makes sense if you +# intend to perform the remainder of the installation manually. +#d-i anna/choose_modules string network-console +#d-i network-console/password password r00tme +#d-i network-console/password-again password r00tme + +### Mirror settings +# If you select ftp, the mirror/country string does not need to be set. +#d-i mirror/protocol string ftp +d-i mirror/country string manual +d-i mirror/http/hostname string http.us.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string + +# Suite to install. +#d-i mirror/suite string testing +# Suite to use for loading installer components (optional). +#d-i mirror/udeb/suite string testing + +### Clock and time zone setup +# Controls whether or not the hardware clock is set to UTC. +d-i clock-setup/utc boolean true + +# You may set this to any valid setting for $TZ; see the contents of +# /usr/share/zoneinfo/ for valid values. +d-i time/zone string UTC + +# Controls whether to use NTP to set the clock during the install +d-i clock-setup/ntp boolean true +# NTP server to use. The default is almost always fine here. +#d-i clock-setup/ntp-server string ntp.example.com + +### Partitioning +# If the system has free space you can choose to only partition that space. +#d-i partman-auto/init_automatically_partition select biggest_free + +# Alternatively, you can specify a disk to partition. The device name must +# be given in traditional non-devfs format. +# Note: A disk must be specified, unless the system has only one disk. +# For example, to use the first SCSI/SATA hard disk: +d-i partman-auto/disk string /dev/sda +# In addition, you'll need to specify the method to use. +# The presently available methods are: "regular", "lvm" and "crypto" +d-i partman-auto/method string lvm + +# If one of the disks that are going to be automatically partitioned +# contains an old LVM configuration, the user will normally receive a +# warning. This can be preseeded away... +d-i partman-lvm/device_remove_lvm boolean true +# The same applies to pre-existing software RAID array: +d-i partman-md/device_remove_md boolean true + +# And the same goes for the confirmation to write the lvm partitions. +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true + + +d-i partman/choose_partition select finish +d-i partman-auto-lvm/guided_size string max + +# You can choose one of the three predefined partitioning recipes: +# - atomic: all files in one partition +# - home: separate /home partition +# - multi: separate /home, /usr, /var, and /tmp partitions +d-i partman-auto/choose_recipe select atomic +d-i partman/default_filesystem string ext3 + +# Or provide a recipe of your own... +# The recipe format is documented in the file devel/partman-auto-recipe.txt. +# If you have a way to get a recipe file into the d-i environment, you can +# just point at it. +#d-i partman-auto/expert_recipe_file string /hd-media/recipe + +# If not, you can put an entire recipe into the preconfiguration file in one +# (logical) line. This example creates a small /boot partition, suitable +# swap, and uses the rest of the space for the root partition: +#d-i partman-auto/expert_recipe string \ +# boot-root :: \ +# 40 50 100 ext3 \ +# $primary{ } $bootable{ } \ +# method{ format } format{ } \ +# use_filesystem{ } filesystem{ ext3 } \ +# mountpoint{ /boot } \ +# . \ +# 500 10000 1000000000 ext3 \ +# method{ format } format{ } \ +# use_filesystem{ } filesystem{ ext3 } \ +# mountpoint{ / } \ +# . \ +# 64 512 300% linux-swap \ +# method{ swap } format{ } \ +# . + +#The preseed line that "selects finish" needs to be in a certain order in your preseed, the example-preseed does not follow this. +#http://ubuntuforums.org/archive/index.php/t-1504045.html + +# This makes partman automatically partition without confirmation, provided +# that you told it what to do using one of the methods above. +d-i partman/confirm_write_new_label boolean true +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + + +### Base system installation +# Select the initramfs generator used to generate the initrd for 2.6 kernels. +#d-i base-installer/kernel/linux/initramfs-generators string yaird + +# The kernel image (meta) package to be installed; "none" can be used if no +# kernel is to be installed. +#d-i base-installer/kernel/image string linux-image-2.6-486 + +### Account setup +# Skip creation of a root account (normal user account will be able to +# use sudo). +d-i passwd/root-login boolean false +# Alternatively, to skip creation of a normal user account. +#d-i passwd/make-user boolean false + +# Root password, either in clear text +d-i passwd/root-password password vagrant +d-i passwd/root-password-again password vagrant +# or encrypted using an MD5 hash. +#d-i passwd/root-password-crypted password [MD5 hash] + +# To create a normal user account. +d-i passwd/user-fullname string Vagrant User +d-i passwd/username string vagrant +# Normal user's password, either in clear text +d-i passwd/user-password password vagrant +d-i passwd/user-password-again password vagrant +# or encrypted using an MD5 hash. +#d-i passwd/user-password-crypted password [MD5 hash] +# Create the first user with the specified UID instead of the default. +#d-i passwd/user-uid string 1010 +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true + +# The user account will be added to some standard initial groups. To +# override that, use this. +d-i passwd/user-default-groups string audio cdrom video admin + +### Apt setup +# You can choose to install non-free and contrib software. +#d-i apt-setup/non-free boolean true +#d-i apt-setup/contrib boolean true +# Uncomment this if you don't want to use a network mirror. +#d-i apt-setup/use_mirror boolean false +# Select which update services to use; define the mirrors to be used. +# Values shown below are the normal defaults. +#d-i apt-setup/services-select multiselect security, volatile +#d-i apt-setup/security_host string security.debian.org +#d-i apt-setup/volatile_host string volatile.debian.org + + +# By default the installer requires that repositories be authenticated +# using a known gpg key. This setting can be used to disable that +# authentication. Warning: Insecure, not recommended. +#d-i debian-installer/allow_unauthenticated string true + +### Package selection +tasksel tasksel/first multiselect standard +# If the desktop task is selected, install the kde and xfce desktops +# instead of the default gnome desktop. +#tasksel tasksel/desktop multiselect kde, xfce + +# Individual additional packages to install +d-i pkgsel/include string openssh-server ntp acpid sudo bzip2 + +# Whether to upgrade packages after debootstrap. +# Allowed values: none, safe-upgrade, full-upgrade +d-i pkgsel/upgrade select none + +# Some versions of the installer can report back on what software you have +# installed, and what software you use. The default is not to report back, +# but sending reports helps the project determine what software is most +# popular and include it on CDs. +popularity-contest popularity-contest/participate boolean false + +### Boot loader installation +# Grub is the default boot loader (for x86). If you want lilo installed +# instead, uncomment this: +#d-i grub-installer/skip boolean true +# To also skip installing lilo, and install no bootloader, uncomment this +# too: +#d-i lilo-installer/skip boolean true + +# This is fairly safe to set, it makes grub install automatically to the MBR +# if no other operating system is detected on the machine. +d-i grub-installer/only_debian boolean true + +# This one makes grub-installer install to the MBR if it also finds some other +# OS, which is less safe as it might not be able to boot that other OS. +d-i grub-installer/with_other_os boolean true + +# Alternatively, if you want to install to a location other than the mbr, +# uncomment and edit these lines: +#d-i grub-installer/only_debian boolean false +#d-i grub-installer/with_other_os boolean false +#d-i grub-installer/bootdev string (hd0,0) +# To install grub to multiple disks: +#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0) + +# Optional password for grub, either in clear text +#d-i grub-installer/password password r00tme +#d-i grub-installer/password-again password r00tme +# or encrypted using an MD5 hash, see grub-md5-crypt(8). +#d-i grub-installer/password-crypted password [MD5 hash] + +### Finishing up the installation +# During installations from serial console, the regular virtual consoles +# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next +# line to prevent this. +#d-i finish-install/keep-consoles boolean true + +# Avoid that last message about the install being complete. +d-i finish-install/reboot_in_progress note + +# This will prevent the installer from ejecting the CD during the reboot, +# which is useful in some situations. +#d-i cdrom-detect/eject boolean false + +# This is how to make the installer shutdown when finished, but not +# reboot into the installed system. +#d-i debian-installer/exit/halt boolean true +# This will power off the machine instead of just halting it. +#d-i debian-installer/exit/poweroff boolean true + +### Preseeding other packages +# Depending on what software you choose to install, or if things go wrong +# during the installation process, it's possible that other questions may +# be asked. You can preseed those too, of course. To get a list of every +# possible question that could be asked during an install, do an +# installation, and then run these commands: +# debconf-get-selections --installer > file +# debconf-get-selections >> file + + +#### Advanced options +### Running custom commands during the installation +# d-i preseeding is inherently not secure. Nothing in the installer checks +# for attempts at buffer overflows or other exploits of the values of a +# preconfiguration file like this one. Only use preconfiguration files from +# trusted locations! To drive that home, and because it's generally useful, +# here's a way to run any shell command you'd like inside the installer, +# automatically. + +# This first command is run as early as possible, just after +# preseeding is read. +# Prevent packaged version of VirtualBox Guest Additions being installed: +d-i preseed/early_command string sed -i \ + '/in-target/idiscover(){/sbin/discover|grep -v VirtualBox;}' \ + /usr/lib/pre-pkgsel.d/20install-hwpackages + +# This command is run just before the install finishes, but when there is +# still a usable /target directory. You can chroot to /target and use it +# directly, or use the apt-install and in-target commands to easily install +# packages and run commands in the target system. diff --git a/tools/appliance/definitions/systemvmtemplate/zerodisk.sh b/tools/appliance/definitions/systemvmtemplate/zerodisk.sh new file mode 100644 index 00000000000..81850921dba --- /dev/null +++ b/tools/appliance/definitions/systemvmtemplate/zerodisk.sh @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Zero out the free space to save space in the final image: +dd if=/dev/zero of=/EMPTY bs=1M +rm -f /EMPTY diff --git a/tools/cli/cloudmonkey/cloudmonkey.py b/tools/cli/cloudmonkey/cloudmonkey.py index db7104a781d..53f73bd3e72 100644 --- a/tools/cli/cloudmonkey/cloudmonkey.py +++ b/tools/cli/cloudmonkey/cloudmonkey.py @@ -65,6 +65,7 @@ class CloudMonkeyShell(cmd.Cmd, object): ruler = "=" cache_file = cache_file config_options = [] + verbs = [] def __init__(self, pname): self.program_name = pname @@ -246,7 +247,7 @@ class CloudMonkeyShell(cmd.Cmd, object): args_dict.pop('filter').split(','))) missing_args = [] - if verb in self.apicache: + if verb in self.apicache and subject in self.apicache[verb]: missing_args = filter(lambda x: x not in args_dict.keys(), self.apicache[verb][subject]['requiredparams']) @@ -388,7 +389,6 @@ class CloudMonkeyShell(cmd.Cmd, object): if subject in self.apicache[verb]: api = self.apicache[verb][subject] helpdoc = "(%s) %s" % (api['name'], api['description']) - helpdoc = api['description'] if api['isasync']: helpdoc += "\nThis API is asynchronous." required = api['requiredparams'] diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index eb4284374de..6cb82f2ea25 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -11159,10 +11159,12 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: -100px -614px; } +.resize .icon, .updateResourceCount .icon { background-position: -167px -66px; } +.resize:hover .icon, .updateResourceCount:hover .icon { background-position: -167px -648px; } diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 77dfdc9055f..d2cb67fc8a5 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -1432,6 +1432,10 @@ dictionary = { 'label.delete.NiciraNvp': '', 'label.nicira.controller.address': '', 'label.nicira.transportzoneuuid': '', -'label.nicira.l3gatewayserviceuuid': '' +'label.nicira.l3gatewayserviceuuid': '', +'label.resize.new.size': '', +'label.action.resize.volume': '', +'label.resize.new.offering.id': '', +'label.resize.shrink.ok': '' }; diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index dd813781522..73a496e4df6 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -1005,6 +1005,102 @@ args.complete(); } } + }, + + resize: { + label: 'label.action.resize.volume', + messages: { + notification: function(args) { + return 'label.action.resize.volume'; + } + }, + createForm: { + title: 'label.action.resize.volume', + fields: { + newdiskoffering: { + label: 'label.resize.new.offering.id', + select: function(args) { + $.ajax({ + url: createURL("listDiskOfferings"), + dataType: "json", + async: false, + success: function(json) { + diskofferingObjs = json.listdiskofferingsresponse.diskoffering; + var items = []; + $(diskofferingObjs).each(function(){ + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({data: items}); + } + }); + + args.$select.change(function() { + var diskOfferingId = $(this).val(); + $(diskofferingObjs).each(function(){ + if(this.id == diskOfferingId) { + selectedDiskOfferingObj = this; + return false; //break the $.each() loop + } + }); + if(selectedDiskOfferingObj == null) + return; + + var $form = $(this).closest('form'); + var $newsize = $form.find('.form-item[rel=newsize]'); + if (selectedDiskOfferingObj.iscustomized == true) { + $newsize.css('display', 'inline-block'); + } + else { + $newsize.hide(); + } + }); + } + }, + newsize: { + label: 'label.resize.new.size', + validation: { required: true, number: true }, + isHidden: true + }, + shrinkok: {label: 'label.resize.shrink.ok', isBoolean: true, isChecked: false} + } + }, + action: function(args){ + var array1 = []; + array1.push("&shrinkok=" + (args.data.shrinkok == "on")); + var newDiskOffering = args.data.newdiskoffering; + var newSize; + if (selectedDiskOfferingObj.iscustomized == true) { + newSize = args.data.newsize; + } + if (newDiskOffering != null && newDiskOffering.length > 0){ + array1.push("&diskofferingid=" + todb(newDiskOffering)); + } + if (newSize != null && newSize.length > 0){ + array1.push("&size=" + todb(newSize)); + } + $.ajax({ + url: createURL("resizeVolume&id=" + args.context.volumes[0].id + array1.join("")), + dataType: "json", + async: true, + success: function(json){ + var jid = json.resizevolumeresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.volume; + }, + getActionFilter: function() { + return volumeActionfilter; + } + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } } }, tabs: { @@ -1430,6 +1526,9 @@ if(jsonObj.hypervisor != "Ovm" && jsonObj.state == "Ready") { allowedActions.push("takeSnapshot"); allowedActions.push("recurringSnapshot"); + if((jsonObj.hypervisor == "XenServer" || jsonObj.hypervisor == "KVM" || jsonObj.hypervisor == "VMware") && jsonObj.type == "DATADISK") { + allowedActions.push("resize"); + } } if(jsonObj.state != "Allocated") { if((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state == "Ready") { diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java b/usage/src/com/cloud/usage/UsageManagerImpl.java index 3e143b1359b..1ebe892d8f0 100644 --- a/usage/src/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/com/cloud/usage/UsageManagerImpl.java @@ -34,6 +34,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.alert.AlertManager; import com.cloud.configuration.dao.ConfigurationDao; diff --git a/usage/src/com/cloud/usage/parser/IPAddressUsageParser.java b/usage/src/com/cloud/usage/parser/IPAddressUsageParser.java index a5a40c0fa04..08892036d8d 100644 --- a/usage/src/com/cloud/usage/parser/IPAddressUsageParser.java +++ b/usage/src/com/cloud/usage/parser/IPAddressUsageParser.java @@ -26,11 +26,11 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import org.springframework.stereotype.Component; import com.cloud.usage.UsageIPAddressVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageIPAddressDao; diff --git a/usage/src/com/cloud/usage/parser/LoadBalancerUsageParser.java b/usage/src/com/cloud/usage/parser/LoadBalancerUsageParser.java index edea320aa08..84d0b32825e 100644 --- a/usage/src/com/cloud/usage/parser/LoadBalancerUsageParser.java +++ b/usage/src/com/cloud/usage/parser/LoadBalancerUsageParser.java @@ -26,11 +26,11 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import org.springframework.stereotype.Component; import com.cloud.usage.UsageLoadBalancerPolicyVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageLoadBalancerPolicyDao; diff --git a/usage/src/com/cloud/usage/parser/NetworkOfferingUsageParser.java b/usage/src/com/cloud/usage/parser/NetworkOfferingUsageParser.java index f6ddf9f1bbb..d026b76a448 100644 --- a/usage/src/com/cloud/usage/parser/NetworkOfferingUsageParser.java +++ b/usage/src/com/cloud/usage/parser/NetworkOfferingUsageParser.java @@ -26,10 +26,10 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageNetworkOfferingVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageNetworkOfferingDao; diff --git a/usage/src/com/cloud/usage/parser/NetworkUsageParser.java b/usage/src/com/cloud/usage/parser/NetworkUsageParser.java index fb673d73c5f..a891fdd037d 100644 --- a/usage/src/com/cloud/usage/parser/NetworkUsageParser.java +++ b/usage/src/com/cloud/usage/parser/NetworkUsageParser.java @@ -25,9 +25,9 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageNetworkVO; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageNetworkDao; diff --git a/usage/src/com/cloud/usage/parser/PortForwardingUsageParser.java b/usage/src/com/cloud/usage/parser/PortForwardingUsageParser.java index 16921804aa8..4780d14b4db 100644 --- a/usage/src/com/cloud/usage/parser/PortForwardingUsageParser.java +++ b/usage/src/com/cloud/usage/parser/PortForwardingUsageParser.java @@ -26,10 +26,10 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsagePortForwardingRuleVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsagePortForwardingRuleDao; diff --git a/usage/src/com/cloud/usage/parser/SecurityGroupUsageParser.java b/usage/src/com/cloud/usage/parser/SecurityGroupUsageParser.java index ed7acf348e1..df859b8a737 100644 --- a/usage/src/com/cloud/usage/parser/SecurityGroupUsageParser.java +++ b/usage/src/com/cloud/usage/parser/SecurityGroupUsageParser.java @@ -26,10 +26,10 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageSecurityGroupVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageSecurityGroupDao; diff --git a/usage/src/com/cloud/usage/parser/StorageUsageParser.java b/usage/src/com/cloud/usage/parser/StorageUsageParser.java index 7542063fca3..4e3817e8c13 100644 --- a/usage/src/com/cloud/usage/parser/StorageUsageParser.java +++ b/usage/src/com/cloud/usage/parser/StorageUsageParser.java @@ -26,11 +26,11 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.StorageTypes; import com.cloud.usage.UsageServer; import com.cloud.usage.UsageStorageVO; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageStorageDao; diff --git a/usage/src/com/cloud/usage/parser/VMInstanceUsageParser.java b/usage/src/com/cloud/usage/parser/VMInstanceUsageParser.java index 8d2e465aa89..2e7ee59e32e 100644 --- a/usage/src/com/cloud/usage/parser/VMInstanceUsageParser.java +++ b/usage/src/com/cloud/usage/parser/VMInstanceUsageParser.java @@ -26,9 +26,9 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVMInstanceVO; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; diff --git a/usage/src/com/cloud/usage/parser/VPNUserUsageParser.java b/usage/src/com/cloud/usage/parser/VPNUserUsageParser.java index c9a863b99d6..c76de285c36 100644 --- a/usage/src/com/cloud/usage/parser/VPNUserUsageParser.java +++ b/usage/src/com/cloud/usage/parser/VPNUserUsageParser.java @@ -26,10 +26,10 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageVPNUserVO; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; import com.cloud.usage.dao.UsageVPNUserDao; diff --git a/usage/src/com/cloud/usage/parser/VolumeUsageParser.java b/usage/src/com/cloud/usage/parser/VolumeUsageParser.java index e797f1c5f2f..6d9fe5d1e12 100644 --- a/usage/src/com/cloud/usage/parser/VolumeUsageParser.java +++ b/usage/src/com/cloud/usage/parser/VolumeUsageParser.java @@ -26,9 +26,9 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.log4j.Logger; +import org.apache.cloudstack.usage.UsageTypes; import com.cloud.usage.UsageServer; -import com.cloud.usage.UsageTypes; import com.cloud.usage.UsageVO; import com.cloud.usage.UsageVolumeVO; import com.cloud.usage.dao.UsageDao; diff --git a/utils/src/com/cloud/utils/component/ComponentContext.java b/utils/src/com/cloud/utils/component/ComponentContext.java index 1b15f00e301..716abb3fe30 100644 --- a/utils/src/com/cloud/utils/component/ComponentContext.java +++ b/utils/src/com/cloud/utils/component/ComponentContext.java @@ -19,6 +19,7 @@ package com.cloud.utils.component; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; @@ -64,6 +65,13 @@ public class ComponentContext implements ApplicationContextAware { } public static void initComponentsLifeCycle() { + // Run the SystemIntegrityCheckers first + Map integrityCheckers = getApplicationContext().getBeansOfType(SystemIntegrityChecker.class); + for (Entry entry : integrityCheckers.entrySet() ){ + s_logger.info ("Running SystemIntegrityChecker " + entry.getKey()); + entry.getValue().check(); + } + Map lifecyleComponents = getApplicationContext().getBeansOfType(ComponentLifecycle.class); Map[] classifiedComponents = new Map[ComponentLifecycle.MAX_RUN_LEVELS]; diff --git a/utils/src/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java b/utils/src/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java index 63f841dbb7b..c717a3a705d 100755 --- a/utils/src/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java +++ b/utils/src/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java @@ -45,7 +45,9 @@ public class EncryptionSecretKeyChecker extends AdapterBase implements SystemInt private static final Logger s_logger = Logger.getLogger(EncryptionSecretKeyChecker.class); - private static final String s_keyFile = "/etc/cloud/management/key"; + // Two possible locations with the new packaging naming + private static final String s_altKeyFile = "/etc/cloud/management/key"; + private static final String s_keyFile = "/etc/cloudstack/management/key"; private static final String s_envKey = "CLOUD_SECRET_KEY"; private static StandardPBEStringEncryptor s_encryptor = new StandardPBEStringEncryptor(); private static boolean s_useEncryption = false; @@ -76,8 +78,12 @@ public class EncryptionSecretKeyChecker extends AdapterBase implements SystemInt SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig(); if(encryptionType.equals("file")){ + File keyFile = new File(s_keyFile); + if (!keyFile.exists()) { + keyFile = new File(s_altKeyFile); + } try { - BufferedReader in = new BufferedReader(new FileReader(s_keyFile)); + BufferedReader in = new BufferedReader(new FileReader(keyFile)); secretKey = in.readLine(); //Check for null or empty secret key } catch (FileNotFoundException e) { diff --git a/utils/src/com/cloud/utils/db/Transaction.java b/utils/src/com/cloud/utils/db/Transaction.java index 73f5bb100ea..d596de23016 100755 --- a/utils/src/com/cloud/utils/db/Transaction.java +++ b/utils/src/com/cloud/utils/db/Transaction.java @@ -1006,10 +1006,7 @@ public class Transaction { public static void initDataSource(String propsFileName) { try { - File dbPropsFile = new File(propsFileName); - if (!dbPropsFile.exists()) { - dbPropsFile = PropertiesUtil.findConfigFile(propsFileName); - } + File dbPropsFile = PropertiesUtil.findConfigFile(propsFileName); final Properties dbProps; if (EncryptionSecretKeyChecker.useEncryption()) { StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor(); @@ -1022,6 +1019,9 @@ public class Transaction { } catch (IOException e) { s_logger.fatal("Unable to load db properties file, pl. check the classpath and file path configuration", e); return; + } catch (NullPointerException e) { + s_logger.fatal("Unable to locate db properties file within classpath or absolute path: " + propsFileName); + return; } // FIXME: If params are missing...default them???? diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index deb1d054cb1..f6b62de1a7b 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -19,6 +19,7 @@ package com.cloud.utils.net; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Array; +import java.math.BigInteger; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; @@ -1151,19 +1152,25 @@ public class NetUtils { return network.getNetmask().asPrefixLength(); } - //FIXME: only able to cover lower 32 bits + // Can cover 127 bits public static String getIp6FromRange(String ip6Range) { String[] ips = ip6Range.split("-"); String startIp = ips[0]; IPv6Address start = IPv6Address.fromString(startIp); - // Find a random number based on lower 32 bits - long gap = countIp6InRange(ip6Range); - if (gap > Integer.MAX_VALUE) { - gap = Integer.MAX_VALUE; + BigInteger gap = countIp6InRange(ip6Range); + BigInteger next = new BigInteger(gap.bitLength(), _rand); + while (next.compareTo(gap) >= 0) { + next = new BigInteger(gap.bitLength(), _rand); } - int next = _rand.nextInt((int)(gap)); - // And a number based on the difference of lower 32 bits - IPv6Address ip = start.add(next); + BigInteger startInt = convertIPv6AddressToBigInteger(start); + BigInteger resultInt = startInt.add(next); + InetAddress resultAddr; + try { + resultAddr = InetAddress.getByAddress(resultInt.toByteArray()); + } catch (UnknownHostException e) { + return null; + } + IPv6Address ip = IPv6Address.fromInetAddress(resultAddr); return ip.toString(); } @@ -1173,11 +1180,21 @@ public class NetUtils { return duid; } - //FIXME: only able to cover lower 64 bits - public static long countIp6InRange(String ip6Range) { + private static BigInteger convertIPv6AddressToBigInteger(IPv6Address addr) { + InetAddress inetAddr; + try { + inetAddr = addr.toInetAddress(); + } catch (UnknownHostException e) { + return null; + } + return new BigInteger(inetAddr.getAddress()); + } + + // Can cover 127 bits + public static BigInteger countIp6InRange(String ip6Range) { String[] ips = ip6Range.split("-"); String startIp = ips[0]; - String endIp = null; + String endIp = ips[0]; if (ips.length > 1) { endIp = ips[1]; } @@ -1186,13 +1203,14 @@ public class NetUtils { start = IPv6Address.fromString(startIp); end = IPv6Address.fromString(endIp); } catch (IllegalArgumentException ex) { - return 0; + return null; } - long startLow = start.getLowBits(), endLow = end.getLowBits(); - if (startLow > endLow) { - return 0; + BigInteger startInt = convertIPv6AddressToBigInteger(start); + BigInteger endInt = convertIPv6AddressToBigInteger(end); + if (startInt.compareTo(endInt) > 0) { + return null; } - return endLow - startLow + 1; + return endInt.subtract(startInt).add(BigInteger.ONE); } public static boolean isIp6InRange(String ip6, String ip6Range) { @@ -1211,6 +1229,17 @@ public class NetUtils { return false; } + public static boolean isIp6InNetwork(String ip6, String ip6Cidr) { + IPv6Network network = null; + try { + network = IPv6Network.fromString(ip6Cidr); + } catch (IllegalArgumentException ex) { + return false; + } + IPv6Address ip = IPv6Address.fromString(ip6); + return network.contains(ip); + } + public static boolean isIp6RangeOverlap(String ipRange1, String ipRange2) { String[] ips = ipRange1.split("-"); String startIp1 = ips[0]; @@ -1232,4 +1261,27 @@ public class NetUtils { IPv6AddressRange range2 = IPv6AddressRange.fromFirstAndLast(start2, end2); return range1.overlaps(range2); } + + public static String getNextIp6InRange(String currentIp, String ipRange) { + String[] ips = ipRange.split("-"); + String startIp = ips[0]; + String endIp = null; + if (ips.length > 1) { + endIp = ips[1]; + } + IPv6Address start = IPv6Address.fromString(startIp); + IPv6Address end = IPv6Address.fromString(endIp); + IPv6Address current = IPv6Address.fromString(currentIp); + IPv6Address result = null; + if (current.equals(end)) { + result = start; + } else{ + result = current.add(1); + } + String resultIp = null; + if (result != null) { + resultIp = result.toString(); + } + return resultIp; + } } diff --git a/utils/test/com/cloud/utils/net/NetUtilsTest.java b/utils/test/com/cloud/utils/net/NetUtilsTest.java index 08b4816a992..09c6f60ea3e 100644 --- a/utils/test/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.utils.net; +import java.math.BigInteger; import java.util.SortedSet; import java.util.TreeSet; @@ -84,12 +85,18 @@ public class NetUtilsTest extends TestCase { assertFalse(NetUtils.isValidIp6Cidr("1234:5678::1")); assertEquals(NetUtils.getIp6CidrSize("1234:5678::1/32"), 32); assertEquals(NetUtils.getIp6CidrSize("1234:5678::1"), 0); - assertEquals(NetUtils.countIp6InRange("1234:5678::1-1234:5678::2"), 2); - assertEquals(NetUtils.countIp6InRange("1234:5678::2-1234:5678::0"), 0); + BigInteger two = new BigInteger("2"); + assertEquals(NetUtils.countIp6InRange("1234:5678::1-1234:5678::2"), two); + assertEquals(NetUtils.countIp6InRange("1234:5678::2-1234:5678::0"), null); assertEquals(NetUtils.getIp6FromRange("1234:5678::1-1234:5678::1"), "1234:5678::1"); + for (int i = 0; i < 5; i ++) { + String ip = NetUtils.getIp6FromRange("1234:5678::1-1234:5678::2"); + assertTrue(ip.equals("1234:5678::1") || ip.equals("1234:5678::2")); + s_logger.info("IP is " + ip); + } String ipString = null; IPv6Address ipStart = IPv6Address.fromString("1234:5678::1"); - IPv6Address ipEnd = IPv6Address.fromString("1234:5678::8000:0000"); + IPv6Address ipEnd = IPv6Address.fromString("1234:5678::ffff:ffff:ffff:ffff"); for (int i = 0; i < 10; i ++) { ipString = NetUtils.getIp6FromRange(ipStart.toString() + "-" + ipEnd.toString()); s_logger.info("IP is " + ipString); @@ -97,10 +104,23 @@ public class NetUtilsTest extends TestCase { assertTrue(ip.compareTo(ipStart) >= 0); assertTrue(ip.compareTo(ipEnd) <= 0); } + //Test isIp6RangeOverlap assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", "1234:5678:1::1-1234:5678:1::ffff")); assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", "1234:5678::2-1234:5678::f")); assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", "1234:5678::2-1234:5678::f")); assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", "1234:5678::2-1234:5678::e")); assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::f", "1234:5678::2-1234:5678::e")); + //Test getNextIp6InRange + String range = "1234:5678::1-1234:5678::8000:0000"; + assertEquals(NetUtils.getNextIp6InRange("1234:5678::8000:0", range), "1234:5678::1"); + assertEquals(NetUtils.getNextIp6InRange("1234:5678::7fff:ffff", range), "1234:5678::8000:0"); + assertEquals(NetUtils.getNextIp6InRange("1234:5678::1", range), "1234:5678::2"); + range = "1234:5678::1-1234:5678::ffff:ffff:ffff:ffff"; + assertEquals(NetUtils.getNextIp6InRange("1234:5678::ffff:ffff:ffff:ffff", range), "1234:5678::1"); + //Test isIp6InNetwork + assertFalse(NetUtils.isIp6InNetwork("1234:5678:abcd::1", "1234:5678::/64")); + assertTrue(NetUtils.isIp6InNetwork("1234:5678::1", "1234:5678::/64")); + assertTrue(NetUtils.isIp6InNetwork("1234:5678::ffff:ffff:ffff:ffff", "1234:5678::/64")); + assertTrue(NetUtils.isIp6InNetwork("1234:5678::", "1234:5678::/64")); } }