From 72693ea382bd064f4e227faab2f61561b7683149 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 9 Jan 2013 17:10:36 -0800 Subject: [PATCH 01/92] server: Fix ApiServer init method, we won't use cfg files and it's not used there Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 9 ++++----- server/src/com/cloud/servlet/CloudStartupServlet.java | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 56cef123e2c..dfb47faa011 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -166,23 +166,22 @@ public class ApiServer implements HttpRequestHandler { super(); } - public static void initApiServer(String[] apiConfig) { + public static void initApiServer() { if (s_instance == null) { //Injection will create ApiServer and all its fields which have @Inject s_instance = ComponentLocator.inject(ApiServer.class); - s_instance.init(apiConfig); + s_instance.init(); } } public static ApiServer getInstance() { - // Assumption: CloudStartupServlet would initialize ApiServer if (s_instance == null) { - s_logger.fatal("ApiServer instance failed to initialize"); + ApiServer.initApiServer(); } return s_instance; } - public void init(String[] apiConfig) { + public void init() { BaseCmd.setComponents(new ApiResponseHelper()); BaseListCmd.configure(); diff --git a/server/src/com/cloud/servlet/CloudStartupServlet.java b/server/src/com/cloud/servlet/CloudStartupServlet.java index 389bd26bc4b..484c7bf56aa 100755 --- a/server/src/com/cloud/servlet/CloudStartupServlet.java +++ b/server/src/com/cloud/servlet/CloudStartupServlet.java @@ -48,7 +48,7 @@ public class CloudStartupServlet extends HttpServlet implements ServletContextLi s_locator = ComponentLocator.getLocator(ManagementServer.Name); ManagementServer ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name); ms.enableAdminUser("password"); - ApiServer.initApiServer(ms.getPropertiesFiles()); + ApiServer.initApiServer(); } catch (InvalidParameterValueException ipve) { s_logger.error("Exception starting management server ", ipve); throw new ServletException (ipve.getMessage()); From 3dc7626ebc80c5bf87e43fbf341039e027237f27 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 9 Jan 2013 17:18:06 -0800 Subject: [PATCH 02/92] api: Comment out @APICommand annotation for api cmd classes that are unknown Signed-off-by: Rohit Yadav --- api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java | 2 +- api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java | 2 +- .../cloud/api/commands/ListRecurringSnapshotScheduleCmd.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java b/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java index 92c7ac58be0..b140ac75ec3 100644 --- a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java @@ -31,7 +31,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.network.Network; import com.cloud.user.UserContext; -@APICommand(description="Creates a private network", responseObject=NetworkResponse.class) +//@APICommand(description="Creates a private network", responseObject=NetworkResponse.class) public class CreatePrivateNetworkCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreatePrivateNetworkCmd.class.getName()); diff --git a/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java b/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java index 17bafb1918d..80269075744 100644 --- a/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java +++ b/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java @@ -25,7 +25,7 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.user.UserContext; -@APICommand(description="Destroys console proxy", responseObject=SuccessResponse.class) +//@APICommand(description="Destroys console proxy", responseObject=SuccessResponse.class) public class DestroyConsoleProxyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroyConsoleProxyCmd.class.getName()); diff --git a/api/src/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java b/api/src/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java index 41f28f93110..709da6af30c 100644 --- a/api/src/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java +++ b/api/src/com/cloud/api/commands/ListRecurringSnapshotScheduleCmd.java @@ -27,7 +27,7 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.SnapshotScheduleResponse; import com.cloud.storage.snapshot.SnapshotSchedule; -@APICommand(description="Lists recurring snapshot schedule", responseObject=SnapshotScheduleResponse.class) +//@APICommand(description="Lists recurring snapshot schedule", responseObject=SnapshotScheduleResponse.class) public class ListRecurringSnapshotScheduleCmd extends BaseListCmd { private static final String s_name = "listrecurringsnapshotscheduleresponse"; From 657fb6ac0becd99ea7a1e99e0423c12e9657d0ae Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 9 Jan 2013 17:19:14 -0800 Subject: [PATCH 03/92] ApiServer: Don't depend on plugin for apiname:cmd class mapping Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index dfb47faa011..519908daf25 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -60,7 +60,6 @@ import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; -import org.apache.cloudstack.discovery.ApiDiscoveryService; import org.apache.commons.codec.binary.Base64; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.ConnectionClosedException; @@ -134,8 +133,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CSExceptionErrorCode; import com.cloud.uuididentity.dao.IdentityDao; -import org.reflections.Reflections; - public class ApiServer implements HttpRequestHandler { private static final Logger s_logger = Logger.getLogger(ApiServer.class.getName()); private static final Logger s_accessLogger = Logger.getLogger("apiserver." + ApiServer.class.getName()); @@ -150,15 +147,13 @@ public class ApiServer implements HttpRequestHandler { @Inject(adapter = APIAccessChecker.class) protected Adapters _apiAccessCheckers; - @Inject(adapter = ApiDiscoveryService.class) - protected Adapters _apiDiscoveryServices; private Account _systemAccount = null; private User _systemUser = null; private static int _workerCount = 0; private static ApiServer s_instance = null; private static final DateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - private Map> _apiNameCmdClassMap = new HashMap>(); + private static Map> _apiNameCmdClassMap = new HashMap>(); private static ExecutorService _executor = new ThreadPoolExecutor(10, 150, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("ApiServer")); @@ -202,13 +197,16 @@ public class ApiServer implements HttpRequestHandler { } } - for (ApiDiscoveryService discoveryService: _apiDiscoveryServices) { - _apiNameCmdClassMap.putAll(discoveryService.getApiNameCmdClassMapping()); - } + Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, + new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); - if (_apiNameCmdClassMap.size() == 0) { - s_logger.fatal("ApiServer failed to generate apiname, cmd class mappings." - + "Please check and enable at least one ApiDiscovery adapter."); + for(Class cmdClass: cmdClasses) { + String apiName = cmdClass.getAnnotation(APICommand.class).name(); + if (_apiNameCmdClassMap.containsKey(apiName)) { + s_logger.error("API Cmd class " + cmdClass.getName() + " has non-unique apiname" + apiName); + continue; + } + _apiNameCmdClassMap.put(apiName, cmdClass); } encodeApiResponse = Boolean.valueOf(configDao.getValue(Config.EncodeApiResponse.key())); From d13cc7e7e49a54e2fdd177c4fe4ce45739b4736d Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 9 Jan 2013 17:19:49 -0800 Subject: [PATCH 04/92] ApiDiscoveryService: Use only as pluggable service Remove usage and impl as adapter. We have duplicate code that generates apiname:cmd class maps which is unavoidable right now as: - Plugin should not depend on ApiServer or any other component - cloud-utils cannot depend on cloud-api for the APICommand annotation - Use java reflect to create a static method in cloud-utils that does the job would be unsafe. Signed-off-by: Rohit Yadav --- .../discovery/ApiDiscoveryService.java | 6 +-- client/tomcatconf/components.xml.in | 3 -- .../discovery/ApiDiscoveryServiceImpl.java | 51 +++++-------------- 3 files changed, 14 insertions(+), 46 deletions(-) diff --git a/api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index 12206949db3..96ea3ee4d34 100644 --- a/api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -16,14 +16,10 @@ // under the License. package org.apache.cloudstack.discovery; -import com.cloud.utils.component.Adapter; import com.cloud.utils.component.PluggableService; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; -import java.util.Map; - -public interface ApiDiscoveryService extends Adapter, PluggableService { +public interface ApiDiscoveryService extends PluggableService { ListResponse listApis(); - Map> getApiNameCmdClassMapping(); } diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index b9feed15a88..b779c860cc2 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -56,9 +56,6 @@ under the License. - - - 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 5363e559a5f..ea6b206fa44 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.discovery; import com.cloud.utils.ReflectUtil; -import com.cloud.utils.component.AdapterBase; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -30,7 +29,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.log4j.Logger; import javax.ejb.Local; -import javax.naming.ConfigurationException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; @@ -39,36 +37,28 @@ import java.util.Map; import java.util.Set; @Local(value = ApiDiscoveryService.class) -public class ApiDiscoveryServiceImpl extends AdapterBase implements ApiDiscoveryService { - +public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - private Map> _apiNameCmdClassMap; - private ListResponse _discoveryResponse; + + private ListResponse _discoveryResponse = new ListResponse(); + + private Map> _apiNameCmdClassMap = new HashMap>(); protected ApiDiscoveryServiceImpl() { super(); + generateApiNameCmdClassMap(); + cacheListApiResponse(); } - private void generateApiNameCmdClassMapping() { - _apiNameCmdClassMap = new HashMap>(); - Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + private void generateApiNameCmdClassMap() { + Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, + new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); - for(Class cmdClass: cmdClasses) { - String apiName = cmdClass.getAnnotation(APICommand.class).name(); - if (_apiNameCmdClassMap.containsKey(apiName)) { - s_logger.error("API Cmd class " + cmdClass.getName() + " has non-unique apiname" + apiName); - continue; - } - _apiNameCmdClassMap.put(apiName, cmdClass); - } + for(Class cmdClass: cmdClasses) + _apiNameCmdClassMap.put(cmdClass.getAnnotation(APICommand.class).name(), cmdClass); } - private void precacheListApiResponse() { - - if(_apiNameCmdClassMap == null) - return; - - _discoveryResponse = new ListResponse(); + private void cacheListApiResponse() { List apiDiscoveryResponses = new ArrayList(); @@ -117,21 +107,6 @@ public class ApiDiscoveryServiceImpl extends AdapterBase implements ApiDiscovery _discoveryResponse.setResponses(apiDiscoveryResponses); } - @Override - public boolean configure(String name, Map params) - throws ConfigurationException { - super.configure(name, params); - - generateApiNameCmdClassMapping(); - precacheListApiResponse(); - - return true; - } - - public Map> getApiNameCmdClassMapping() { - return _apiNameCmdClassMap; - } - @Override public ListResponse listApis() { return _discoveryResponse; From 7f8262d45e9f2cdaa5d8f1aee0df61dab9573dd7 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Wed, 9 Jan 2013 17:40:58 -0800 Subject: [PATCH 05/92] Remove IdentityProxy and IdentityTypeAdapter class. Signed-off-by: Min Chen --- .../api/commands/CreatePrivateNetworkCmd.java | 5 +- .../com/cloud/exception/CloudException.java | 2 - .../cloudstack/api/BaseAsyncCreateCmd.java | 15 +++- .../org/apache/cloudstack/api/BaseCmd.java | 2 - .../apache/cloudstack/api/BaseResponse.java | 6 +- .../admin/autoscale/CreateCounterCmd.java | 6 +- .../network/AddNetworkServiceProviderCmd.java | 5 +- .../network/CreatePhysicalNetworkCmd.java | 5 +- .../router/CreateVirtualRouterElementCmd.java | 6 +- .../admin/usage/AddTrafficTypeCmd.java | 5 +- .../admin/vpc/CreatePrivateGatewayCmd.java | 5 +- .../admin/vpc/CreateVPCOfferingCmd.java | 5 +- .../user/address/AssociateIPAddrCmd.java | 4 +- .../autoscale/CreateAutoScalePolicyCmd.java | 5 +- .../autoscale/CreateAutoScaleVmGroupCmd.java | 5 +- .../CreateAutoScaleVmProfileCmd.java | 6 +- .../user/autoscale/CreateConditionCmd.java | 6 +- .../user/firewall/CreateFirewallRuleCmd.java | 4 +- .../firewall/CreatePortForwardingRuleCmd.java | 4 +- .../CreateLBStickinessPolicyCmd.java | 5 +- .../CreateLoadBalancerRuleCmd.java | 4 +- .../user/nat/CreateIpForwardingRuleCmd.java | 4 +- .../user/network/CreateNetworkACLCmd.java | 5 +- .../user/project/CreateProjectCmd.java | 4 +- .../user/snapshot/CreateSnapshotCmd.java | 4 +- .../user/template/CreateTemplateCmd.java | 7 +- .../api/command/user/vm/DeployVMCmd.java | 4 +- .../command/user/volume/CreateVolumeCmd.java | 4 +- .../user/vpc/CreateStaticRouteCmd.java | 5 +- .../api/command/user/vpc/CreateVPCCmd.java | 6 +- .../api/command/user/vpn/AddVpnUserCmd.java | 4 +- .../user/vpn/CreateRemoteAccessVpnCmd.java | 9 ++- .../user/vpn/CreateVpnConnectionCmd.java | 4 +- .../user/vpn/CreateVpnCustomerGatewayCmd.java | 3 - .../command/user/vpn/CreateVpnGatewayCmd.java | 4 - .../user/vpn/DeleteVpnConnectionCmd.java | 3 - .../user/vpn/DeleteVpnCustomerGatewayCmd.java | 3 - .../command/user/vpn/DeleteVpnGatewayCmd.java | 3 - .../user/vpn/ResetVpnConnectionCmd.java | 3 - .../user/vpn/UpdateVpnCustomerGatewayCmd.java | 6 +- .../api/response/CapacityResponse.java | 1 - .../api/response/CreateCmdResponse.java | 18 ++--- .../api/response/ResourceCountResponse.java | 1 - .../cloudstack/api/response/S3Response.java | 9 +-- server/src/com/cloud/api/ApiGsonHelper.java | 2 - .../com/cloud/api/ApiResponseGsonHelper.java | 4 +- .../src/com/cloud/api/ApiResponseHelper.java | 2 +- server/src/com/cloud/api/ApiServer.java | 9 ++- .../com/cloud/api/IdentityTypeAdapter.java | 80 ------------------- .../api/response/ApiResponseSerializer.java | 46 +++-------- .../cloud/server/ConfigurationServerImpl.java | 2 - utils/src/com/cloud/utils/IdentityProxy.java | 60 -------------- .../exception/RuntimeCloudException.java | 1 - 53 files changed, 84 insertions(+), 346 deletions(-) delete mode 100644 server/src/com/cloud/api/IdentityTypeAdapter.java delete mode 100644 utils/src/com/cloud/utils/IdentityProxy.java diff --git a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java b/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java index b140ac75ec3..263f023b3e5 100644 --- a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java @@ -153,6 +153,7 @@ public class CreatePrivateNetworkCmd extends BaseAsyncCreateCmd { if (result != null) { this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a Private network"); } @@ -190,8 +191,4 @@ public class CreatePrivateNetworkCmd extends BaseAsyncCreateCmd { } - @Override - public String getEntityTable() { - return "networks"; - } } diff --git a/api/src/com/cloud/exception/CloudException.java b/api/src/com/cloud/exception/CloudException.java index 8f1fa37aac6..036cb1b8adc 100644 --- a/api/src/com/cloud/exception/CloudException.java +++ b/api/src/com/cloud/exception/CloudException.java @@ -16,10 +16,8 @@ // under the License. package com.cloud.exception; -import com.cloud.utils.IdentityProxy; import java.util.ArrayList; import com.cloud.utils.exception.CSExceptionErrorCode; -import com.cloud.utils.AnnotationHelper; /** * by the API response serializer. Any exceptions that are thrown by diff --git a/api/src/org/apache/cloudstack/api/BaseAsyncCreateCmd.java b/api/src/org/apache/cloudstack/api/BaseAsyncCreateCmd.java index ad9f4c6b31f..1f2d3f17beb 100644 --- a/api/src/org/apache/cloudstack/api/BaseAsyncCreateCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseAsyncCreateCmd.java @@ -25,6 +25,8 @@ public abstract class BaseAsyncCreateCmd extends BaseAsyncCmd { @Parameter(name = "id", type = CommandType.LONG) private Long id; + private String uuid; + public abstract void create() throws ResourceAllocationException; public Long getEntityId() { @@ -35,14 +37,19 @@ public abstract class BaseAsyncCreateCmd extends BaseAsyncCmd { this.id = id; } - public abstract String getEntityTable(); + public String getEntityUuid() { + return uuid; + } - public String getResponse(long jobId, long objectId, String objectEntityTable) { + public void setEntityUuid(String uuid) { + this.uuid = uuid; + } + + public String getResponse(long jobId, String objectUuid) { CreateCmdResponse response = new CreateCmdResponse(); AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId); response.setJobId(job.getUuid()); - response.setId(objectId); - response.setIdEntityTable(objectEntityTable); + response.setId(objectUuid); response.setResponseName(getCommandName()); return _responseGenerator.toSerializedString(response, getResponseType()); } diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index d964e70b84f..3399784d2a2 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -64,7 +63,6 @@ import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.DomainService; import com.cloud.user.ResourceLimitService; -import com.cloud.utils.IdentityProxy; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentLocator; import com.cloud.vm.BareMetalVmService; diff --git a/api/src/org/apache/cloudstack/api/BaseResponse.java b/api/src/org/apache/cloudstack/api/BaseResponse.java index 28ca6b8c2de..01f1be3253b 100644 --- a/api/src/org/apache/cloudstack/api/BaseResponse.java +++ b/api/src/org/apache/cloudstack/api/BaseResponse.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api; import org.apache.cloudstack.api.ApiConstants; -import com.cloud.utils.IdentityProxy; import org.apache.cloudstack.api.ResponseObject; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @@ -46,6 +45,7 @@ public abstract class BaseResponse implements ResponseObject { this.objectName = objectName; } + @Override public String getObjectId() { return null; } @@ -56,18 +56,22 @@ public abstract class BaseResponse implements ResponseObject { @SerializedName(ApiConstants.JOB_STATUS) @Param(description="the current status of the latest async job acting on this object") private Integer jobStatus; + @Override public String getJobId() { return jobId; } + @Override public void setJobId(String jobId) { this.jobId = jobId; } + @Override public Integer getJobStatus() { return jobStatus; } + @Override public void setJobStatus(Integer jobStatus) { this.jobStatus = jobStatus; } diff --git a/api/src/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java index 7369a6f6d08..a119d0f44bf 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java @@ -81,6 +81,7 @@ public class CreateCounterCmd extends BaseAsyncCreateCmd { if (ctr != null) { this.setEntityId(ctr.getId()); + this.setEntityUuid(ctr.getUuid()); CounterResponse response = _responseGenerator.createCounterResponse(ctr); response.setResponseName(getCommandName()); this.setResponseObject(response); @@ -113,8 +114,5 @@ public class CreateCounterCmd extends BaseAsyncCreateCmd { return Account.ACCOUNT_ID_SYSTEM; } - @Override - public String getEntityTable() { - return "counter"; - } + } diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java index b6518d8eb59..6d4b962d4a1 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java @@ -59,10 +59,6 @@ public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { @Parameter(name=ApiConstants.SERVICE_LIST, type=CommandType.LIST, collectionType = CommandType.STRING, description="the list of services to be enabled for this physical network service provider") private List enabledServices; - @Override - public String getEntityTable() { - return "physical_network_service_providers"; - } ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -116,6 +112,7 @@ public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { PhysicalNetworkServiceProvider result = _networkService.addProviderToPhysicalNetwork(getPhysicalNetworkId(), getProviderName(), getDestinationPhysicalNetworkId(), getEnabledServices()); if (result != null) { setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to add service provider entity to physical network"); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java index dd3f3231351..f56ae7dbf50 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java @@ -79,10 +79,6 @@ public class CreatePhysicalNetworkCmd extends BaseAsyncCreateCmd { return tags; } - @Override - public String getEntityTable() { - return "physical_network"; - } public Long getZoneId() { return zoneId; @@ -164,6 +160,7 @@ public class CreatePhysicalNetworkCmd extends BaseAsyncCreateCmd { PhysicalNetwork result = _networkService.createPhysicalNetwork(getZoneId(),getVlan(),getNetworkSpeed(), getIsolationMethods(),getBroadcastDomainRange(),getDomainId(), getTags(), getNetworkName()); if (result != null) { setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create physical network entity"); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java index 545218f0364..f6a7b744ca3 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java @@ -53,10 +53,7 @@ public class CreateVirtualRouterElementCmd extends BaseAsyncCreateCmd { this.nspId = nspId; } - @Override - public String getEntityTable() { - return "virtual_router_providers"; - } + public Long getNspId() { return nspId; @@ -94,6 +91,7 @@ public class CreateVirtualRouterElementCmd extends BaseAsyncCreateCmd { VirtualRouterProvider result = _service.addElement(getNspId(), VirtualRouterProviderType.VirtualRouter); if (result != null) { setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to add Virtual Router entity to physical network"); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java index 1759ff7e8e6..5dca9d2d4c1 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java @@ -66,10 +66,6 @@ public class AddTrafficTypeCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - @Override - public String getEntityTable() { - return "physical_network_traffic_types"; - } public Long getPhysicalNetworkId() { return physicalNetworkId; @@ -136,6 +132,7 @@ public class AddTrafficTypeCmd extends BaseAsyncCreateCmd { PhysicalNetworkTrafficType result = _networkService.addTrafficTypeToPhysicalNetwork(getPhysicalNetworkId(), getTrafficType(), getXenLabel(), getKvmLabel(), getVmwareLabel(), getSimulatorLabel(), getVlan()); if (result != null) { setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to add traffic type to physical network"); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java index 7950b877cec..5bb76ab034b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java @@ -123,6 +123,7 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd { if (result != null) { this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create private gateway"); } @@ -156,10 +157,6 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd { return "creating private gateway"; } - @Override - public String getEntityTable() { - return "vpc_gateways"; - } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java index a0abe99f826..273f7c05233 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java @@ -70,6 +70,7 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd{ VpcOffering vpcOff = _vpcService.createVpcOffering(getVpcOfferingName(), getDisplayText(), getSupportedServices()); if (vpcOff != null) { this.setEntityId(vpcOff.getId()); + this.setEntityUuid(vpcOff.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a VPC offering"); } @@ -87,10 +88,6 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd{ } } - @Override - public String getEntityTable() { - return "vpc_offerings"; - } @Override public String getEventType() { diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 7d4e44bb507..024ba74e8b4 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -87,9 +87,6 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "user_ip_address"; - } public String getAccountName() { if (accountName != null) { @@ -220,6 +217,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { if (ip != null) { this.setEntityId(ip.getId()); + this.setEntityUuid(ip.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to allocate ip address"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java index db3aaa6dc5d..e92721d77bf 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java @@ -62,10 +62,6 @@ public class CreateAutoScalePolicyCmd extends BaseAsyncCreateCmd { private Long conditionDomainId; private Long conditionAccountId; - @Override - public String getEntityTable() { - return "autoscale_policies"; - } public int getDuration() { return duration; @@ -159,6 +155,7 @@ public class CreateAutoScalePolicyCmd extends BaseAsyncCreateCmd { AutoScalePolicy result = _autoScaleService.createAutoScalePolicy(this); if (result != null) { this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create AutoScale Policy"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java index 6297888f5d3..e3d47a09c7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java @@ -72,10 +72,6 @@ public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - @Override - public String getEntityTable() { - return "autoscale_vmgroups"; - } public int getMinMembers() { return minMembers; @@ -161,6 +157,7 @@ public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { AutoScaleVmGroup result = _autoScaleService.createAutoScaleVmGroup(this); if (result != null) { this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create Autoscale Vm Group"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java index daa48501c53..25bb03b778f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java @@ -86,10 +86,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd { private Long domainId; private Long accountId; - @Override - public String getEntityTable() { - return "autoscale_vmprofiles"; - } + public Long getDomainId() { if (domainId == null) { @@ -232,6 +229,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd { AutoScaleVmProfile result = _autoScaleService.createAutoScaleVmProfile(this); if (result != null) { this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create Autoscale Vm Profile"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java index a9524714ffa..58926f2a4ff 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java @@ -72,6 +72,7 @@ public class CreateConditionCmd extends BaseAsyncCreateCmd { if (condition != null) { this.setEntityId(condition.getId()); + this.setEntityUuid(condition.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create condition."); } @@ -146,8 +147,5 @@ public class CreateConditionCmd extends BaseAsyncCreateCmd { return accountId; } - @Override - public String getEntityTable() { - return "conditions"; - } + } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java index 803301febe9..7039b417ced 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java @@ -80,9 +80,6 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "firewall_rules"; - } public Long getIpAddressId() { return ipAddressId; @@ -242,6 +239,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal try { FirewallRule result = _firewallService.createFirewallRule(this); setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { s_logger.info("Network rule conflict: " + ex.getMessage()); s_logger.trace("Network Rule Conflict: ", ex); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index ecccf032ace..1feefde9a1a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -94,9 +94,6 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "firewall_rules"; - } public Long getIpAddressId() { return ipAddressId; @@ -301,6 +298,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P try { PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, getOpenFirewall()); setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { s_logger.info("Network rule conflict: " , ex); s_logger.trace("Network Rule Conflict: ", ex); diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java index dc80d312769..c01e138c1d1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java @@ -91,9 +91,7 @@ public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd { return paramList; } - public String getEntityTable() { - return "firewall_rules"; - } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// @@ -141,6 +139,7 @@ public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd { try { StickinessPolicy result = _lbService.createLBStickinessPolicy(this); this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { s_logger.warn("Exception: ", e); throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java index 4aacc8e19b2..4e76a6b676f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java @@ -120,9 +120,6 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements return privatePort; } - public String getEntityTable() { - return "firewall_rules"; - } public Long getSourceIpAddressId() { if (publicIpId != null) { @@ -283,6 +280,7 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements try { LoadBalancer result = _lbService.createLoadBalancerRule(this, getOpenFirewall()); this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { s_logger.warn("Exception: ", e); throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java index e612b84c835..1ce3458dde3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java @@ -75,9 +75,6 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "firewall_rules"; - } public Long getIpAddressId() { return ipAddressId; @@ -151,6 +148,7 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta try { StaticNatRule rule = _rulesService.createStaticNatRule(this, getOpenFirewall()); this.setEntityId(rule.getId()); + this.setEntityUuid(rule.getUuid()); } catch (NetworkRuleConflictException e) { s_logger.info("Unable to create Static Nat Rule due to ", e); throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index e2aba5b321e..16843b56d67 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -86,10 +86,6 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd implements FirewallR // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "firewall_rules"; - } - public Long getIpAddressId() { return null; } @@ -262,6 +258,7 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd implements FirewallR try { FirewallRule result = _networkACLService.createNetworkACL(this); setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { s_logger.info("Network rule conflict: " + ex.getMessage()); s_logger.trace("Network Rule Conflict: ", ex); diff --git a/api/src/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java b/api/src/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java index 9500a972b36..865f7a0aa99 100644 --- a/api/src/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java @@ -56,9 +56,6 @@ public class CreateProjectCmd extends BaseAsyncCreateCmd { // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "projects"; - } public String getAccountName() { if (accountName != null) { @@ -127,6 +124,7 @@ public class CreateProjectCmd extends BaseAsyncCreateCmd { Project project = _projectService.createProject(getName(), getDisplayText(), getAccountName(), getDomainId()); if (project != null) { this.setEntityId(project.getId()); + this.setEntityUuid(project.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a project"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 33469ac4882..14f46540cc3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -65,9 +65,6 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "snapshots"; - } public String getAccountName() { return accountName; @@ -153,6 +150,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { Snapshot snapshot = _snapshotService.allocSnapshot(getVolumeId(), getPolicyId()); if (snapshot != null) { this.setEntityId(snapshot.getId()); + this.setEntityUuid(snapshot.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index 65cc8b9e9a4..e72b49b4e4d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -102,9 +102,6 @@ import com.cloud.user.UserContext; // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public String getEntityTable() { - return "vm_template"; - } public Integer getBits() { return bits; @@ -240,13 +237,15 @@ import com.cloud.user.UserContext; public void create() throws ResourceAllocationException { if (isBareMetal()) { _bareMetalVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); - /*Baremetal creates template record after taking image proceeded, use vmId as entity id here*/ + /*Baremetal creates template record after taking image proceeded, use vmId as entity id and uuid here*/ this.setEntityId(vmId); + this.setEntityUuid(vmId.toString()); } else { VirtualMachineTemplate template = null; template = _userVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); if (template != null) { this.setEntityId(template.getId()); + this.setEntityUuid(template.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a template"); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 349f4a12d16..28bb80f72d3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -171,9 +171,6 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "vm_instance"; - } public String getAccountName() { if (accountName == null) { @@ -446,6 +443,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { if (vm != null) { setEntityId(vm.getId()); + setEntityUuid(vm.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to deploy vm"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java index 512685f77f6..04541b9fda7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java @@ -76,9 +76,6 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "volumes"; - } public String getAccountName() { return accountName; @@ -154,6 +151,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { Volume volume = _storageService.allocVolume(this); if (volume != null) { this.setEntityId(volume.getId()); + this.setEntityUuid(volume.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create volume"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java index 85a0ae45ae8..96de56a5be5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java @@ -67,6 +67,7 @@ public class CreateStaticRouteCmd extends BaseAsyncCreateCmd{ try { StaticRoute result = _vpcService.createStaticRoute(getGatewayId(), getCidr()); setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { s_logger.info("Network rule conflict: " + ex.getMessage()); s_logger.trace("Network rule conflict: ", ex); @@ -74,10 +75,6 @@ public class CreateStaticRouteCmd extends BaseAsyncCreateCmd{ } } - @Override - public String getEntityTable() { - return "static_routes"; - } @Override public String getEventType() { diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index df16c8edc88..8a2e1f641fb 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -124,6 +124,7 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd{ getCidr(), getNetworkDomain()); if (vpc != null) { this.setEntityId(vpc.getId()); + this.setEntityUuid(vpc.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a VPC"); } @@ -157,11 +158,6 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd{ } } - @Override - public String getEntityTable() { - return "vpc"; - } - @Override public String getEventType() { diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java index 674dc6a5809..f2d19a7cce6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java @@ -103,9 +103,6 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { return accountId; } - public String getEntityTable() { - return "vpn_users"; - } @Override public String getEventDescription() { @@ -150,5 +147,6 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to add vpn user"); } setEntityId(vpnUser.getId()); + setEntityUuid(vpnUser.getUuid()); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java index 37952f8777a..b517af883c3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java @@ -62,10 +62,6 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "user_ip_address"; - } - public Long getPublicIpId() { return publicIpId; } @@ -146,6 +142,11 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), getNetworkId()); if (vpn != null) { this.setEntityId(vpn.getServerAddressId()); + // find uuid for server ip address + IpAddress ipAddr = _entityMgr.findById(IpAddress.class, vpn.getServerAddressId()); + if (ipAddr != null) { + this.setEntityUuid(ipAddr.getUuid()); + } } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create remote access vpn"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java index 7f85fb4ebf6..3dc334d0e2a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java @@ -51,9 +51,6 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_vpn_connection"; - } public Long getVpnGatewayId() { return vpnGatewayId; @@ -95,6 +92,7 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { Site2SiteVpnConnection conn = _s2sVpnService.createVpnConnection(this); if (conn != null) { this.setEntityId(conn.getId()); + this.setEntityUuid(conn.getUuid()); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create site to site vpn connection"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java index 65085182e0c..bde98b0b44b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java @@ -78,9 +78,6 @@ public class CreateVpnCustomerGatewayCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_customer_gateway"; - } public String getName() { return name; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java index 89965bd842c..4b405541a90 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java @@ -47,10 +47,6 @@ public class CreateVpnGatewayCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_vpn_gateway"; - } - public Long getVpcId() { return vpcId; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java index a079e8bcc30..23a7793ef88 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java @@ -44,9 +44,6 @@ public class DeleteVpnConnectionCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_vpn_connection"; - } public Long getId() { return id; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java index ef5ff3db438..181ee3bbc68 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java @@ -43,9 +43,6 @@ public class DeleteVpnCustomerGatewayCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_customer_gateway"; - } public Long getId() { return id; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java index f9b9e35a420..9ac27d07664 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java @@ -43,9 +43,6 @@ public class DeleteVpnGatewayCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_vpn_gateway"; - } public Long getId() { return id; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java index 0d7632ac1aa..ed28ea5610f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java @@ -53,9 +53,6 @@ public class ResetVpnConnectionCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_vpn_connection"; - } public Long getDomainId() { return domainId; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java index f2778e06103..7564129c38f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java @@ -78,11 +78,7 @@ public class UpdateVpnCustomerGatewayCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public String getEntityTable() { - return "s2s_customer_gateway"; - } - - public Long getId() { + public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/response/CapacityResponse.java b/api/src/org/apache/cloudstack/api/response/CapacityResponse.java index 000705813fb..2c98dc9d6ca 100644 --- a/api/src/org/apache/cloudstack/api/response/CapacityResponse.java +++ b/api/src/org/apache/cloudstack/api/response/CapacityResponse.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.response; import org.apache.cloudstack.api.ApiConstants; -import com.cloud.utils.IdentityProxy; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; diff --git a/api/src/org/apache/cloudstack/api/response/CreateCmdResponse.java b/api/src/org/apache/cloudstack/api/response/CreateCmdResponse.java index 3c26324e10b..e4c6c60c5ba 100644 --- a/api/src/org/apache/cloudstack/api/response/CreateCmdResponse.java +++ b/api/src/org/apache/cloudstack/api/response/CreateCmdResponse.java @@ -16,24 +16,16 @@ // under the License. package org.apache.cloudstack.api.response; -import org.apache.cloudstack.api.ApiConstants; -import com.cloud.utils.IdentityProxy; -import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; public class CreateCmdResponse extends BaseResponse { - @SerializedName(ApiConstants.ID) - private IdentityProxy id = new IdentityProxy(); + private String id; - public Long getId() { - return id.getValue(); + public String getId() { + return id; } - public void setId(Long id) { - this.id.setValue(id); - } - - public void setIdEntityTable(String entityTable) { - this.id.setTableName(entityTable); + public void setId(String id) { + this.id = id; } } diff --git a/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java b/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java index 9e62f4ff7f5..7a291945f76 100644 --- a/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ResourceCountResponse.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.response; import org.apache.cloudstack.api.ApiConstants; -import com.cloud.utils.IdentityProxy; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; diff --git a/api/src/org/apache/cloudstack/api/response/S3Response.java b/api/src/org/apache/cloudstack/api/response/S3Response.java index 5dd0ef0e041..4dab2175a3a 100644 --- a/api/src/org/apache/cloudstack/api/response/S3Response.java +++ b/api/src/org/apache/cloudstack/api/response/S3Response.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.response; import com.cloud.serializer.Param; -import com.cloud.utils.IdentityProxy; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; @@ -29,7 +28,7 @@ public class S3Response extends BaseResponse { @SerializedName(ID) @Param(description = "The ID of the S3 configuration") - private IdentityProxy id = new IdentityProxy("s3"); + private String id; @SerializedName(S3_ACCESS_KEY) @Param(description = "The S3 access key") @@ -135,11 +134,11 @@ public class S3Response extends BaseResponse { @Override public String getObjectId() { - return this.id.getValue().toString(); + return this.id; } - public void setObjectId(Long id) { - this.id.setValue(id); + public void setObjectId(String id) { + this.id = id; } public String getAccessKey() { diff --git a/server/src/com/cloud/api/ApiGsonHelper.java b/server/src/com/cloud/api/ApiGsonHelper.java index 6e64f7124e0..6163860f0c8 100644 --- a/server/src/com/cloud/api/ApiGsonHelper.java +++ b/server/src/com/cloud/api/ApiGsonHelper.java @@ -17,7 +17,6 @@ package com.cloud.api; import com.google.gson.GsonBuilder; -import com.cloud.utils.IdentityProxy; import org.apache.cloudstack.api.ResponseObject; import java.util.Map; @@ -28,7 +27,6 @@ public class ApiGsonHelper { s_gBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); s_gBuilder.setVersion(1.3); s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter()); - s_gBuilder.registerTypeAdapter(IdentityProxy.class, new IdentityTypeAdapter()); s_gBuilder.registerTypeAdapter(Map.class, new StringMapTypeAdapter()); } diff --git a/server/src/com/cloud/api/ApiResponseGsonHelper.java b/server/src/com/cloud/api/ApiResponseGsonHelper.java index c71193e8908..6bccf9a12af 100644 --- a/server/src/com/cloud/api/ApiResponseGsonHelper.java +++ b/server/src/com/cloud/api/ApiResponseGsonHelper.java @@ -17,7 +17,6 @@ package com.cloud.api; import com.google.gson.GsonBuilder; -import com.cloud.utils.IdentityProxy; import org.apache.cloudstack.api.ResponseObject; /** @@ -25,13 +24,12 @@ import org.apache.cloudstack.api.ResponseObject; */ public class ApiResponseGsonHelper { private static final GsonBuilder s_gBuilder; - + static { s_gBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); s_gBuilder.setVersion(1.3); s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter()); s_gBuilder.registerTypeAdapter(String.class, new EncodedStringTypeAdapter()); - s_gBuilder.registerTypeAdapter(IdentityProxy.class, new IdentityTypeAdapter()); } public static GsonBuilder getBuilder() { diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 47754395e7a..edb798b812e 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -482,7 +482,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setEndPoint(result.getEndPoint()); response.setHttpsFlag(result.getHttpsFlag()); response.setMaxErrorRetry(result.getMaxErrorRetry()); - response.setObjectId(result.getId()); + response.setObjectId(result.getUuid()); response.setSecretKey(result.getSecretKey()); response.setSocketTimeout(result.getSocketTimeout()); response.setTemplateBucketName(result.getBucketName()); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 519908daf25..17a2b29638b 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -400,12 +400,12 @@ public class ApiServer implements HttpRequestHandler { // BaseAsyncCmd: cmd is processed and submitted as an AsyncJob, job related info is serialized and returned. if (cmdObj instanceof BaseAsyncCmd) { Long objectId = null; - String objectEntityTable = null; + String objectUuid = null; if (cmdObj instanceof BaseAsyncCreateCmd) { BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd) cmdObj; _dispatcher.dispatchCreateCmd(createCmd, params); objectId = createCmd.getEntityId(); - objectEntityTable = createCmd.getEntityTable(); + objectUuid = createCmd.getEntityUuid(); params.put("id", objectId.toString()); } else { ApiDispatcher.processParameters(cmdObj, params); @@ -449,8 +449,8 @@ public class ApiServer implements HttpRequestHandler { } if (objectId != null) { - SerializationContext.current().setUuidTranslation(true); - return ((BaseAsyncCreateCmd) asyncCmd).getResponse(jobId, objectId, objectEntityTable); + String objUuid = (objectUuid == null) ? objectId.toString() : objectUuid; + return ((BaseAsyncCreateCmd) asyncCmd).getResponse(jobId, objUuid); } SerializationContext.current().setUuidTranslation(true); @@ -460,6 +460,7 @@ public class ApiServer implements HttpRequestHandler { // if the command is of the listXXXCommand, we will need to also return the // the job id and status if possible + // For those listXXXCommand which we have already created DB views, this step is not needed since async job is joined in their db views. if (cmdObj instanceof BaseListCmd && !(cmdObj instanceof ListVMsCmd) && !(cmdObj instanceof ListRoutersCmd) && !(cmdObj instanceof ListSecurityGroupsCmd) && !(cmdObj instanceof ListTagsCmd) diff --git a/server/src/com/cloud/api/IdentityTypeAdapter.java b/server/src/com/cloud/api/IdentityTypeAdapter.java deleted file mode 100644 index 369c2020c24..00000000000 --- a/server/src/com/cloud/api/IdentityTypeAdapter.java +++ /dev/null @@ -1,80 +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; - -import java.lang.reflect.Type; - -import com.cloud.uuididentity.dao.IdentityDao; -import com.cloud.uuididentity.dao.IdentityDaoImpl; -import com.google.gson.Gson; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import com.cloud.utils.IdentityProxy; - - -public class IdentityTypeAdapter implements JsonSerializer, JsonDeserializer { - - @Override - public JsonElement serialize(IdentityProxy src, Type srcType, JsonSerializationContext context) { - if(SerializationContext.current().getUuidTranslation()) { - assert(src != null); - if(src.getValue() == null) - return context.serialize(null); - - IdentityDao identityDao = new IdentityDaoImpl(); - if(src.getTableName() != null) { - String uuid = identityDao.getIdentityUuid(src.getTableName(), String.valueOf(src.getValue())); - if(uuid == null) - return context.serialize(null); - - // Exceptions set the _idFieldName in the IdentityProxy structure. So if this field is not - // null, prepare a structure of uuid and idFieldName and return the json representation of that. - String idName = src.getidFieldName(); - if (idName != null) { - // Prepare a structure. - JsonObject jsonObj = new JsonObject(); - jsonObj.add("uuid", new JsonPrimitive(uuid)); - jsonObj.add("uuidProperty", new JsonPrimitive(idName)); - return jsonObj; - } - return new JsonPrimitive(uuid); - } else { - return new JsonPrimitive(String.valueOf(src.getValue())); - } - } else { - return new Gson().toJsonTree(src); - } - } - - @Override - public IdentityProxy deserialize(JsonElement src, Type srcType, - JsonDeserializationContext context) throws JsonParseException { - - IdentityProxy obj = new IdentityProxy(); - JsonObject json = src.getAsJsonObject(); - obj.setTableName(json.get("_tableName").getAsString()); - if(json.get("_value") != null) - obj.setValue(json.get("_value").getAsLong()); - return obj; - } -} diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index 470cc5f9587..11aee3d9390 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -37,7 +37,6 @@ import com.cloud.api.ApiResponseGsonHelper; import com.cloud.api.ApiServer; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ResponseObject; -import com.cloud.utils.IdentityProxy; import com.cloud.utils.encoding.URLEncoder; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.uuididentity.dao.IdentityDao; @@ -226,27 +225,17 @@ public class ApiResponseSerializer { subObj.setObjectName(serializedName.value()); } serializeResponseObjXML(sb, subObj); - } else if (value instanceof IdentityProxy) { - // Only exception reponses carry a list of IdentityProxy objects. - IdentityProxy idProxy = (IdentityProxy)value; - String id = (idProxy.getValue() != null ? String.valueOf(idProxy.getValue()) : ""); - if(!id.isEmpty()) { - IdentityDao identityDao = new IdentityDaoImpl(); - id = identityDao.getIdentityUuid(idProxy.getTableName(), id); - } - if(id != null && !id.isEmpty()) { - // If this is the first IdentityProxy field encountered, put in a uuidList tag. - if (!usedUuidList) { - sb.append("<").append(serializedName.value()).append(">"); - usedUuidList = true; - } - sb.append("").append(id).append(""); - } - // Append the new idFieldName property also. - String idFieldName = idProxy.getidFieldName(); - if (idFieldName != null) { - sb.append("").append(idFieldName).append(""); - } + } else { + // Only exception reponses carry a list of uuid + // strings. + // If this is the first IdentityProxy field + // encountered, put in a uuidList tag. + if (!usedUuidList) { + sb.append("<").append(serializedName.value()).append(">"); + usedUuidList = true; + } + sb.append("").append(value).append(""); + // We have removed uuid property field due to removal of IdentityProxy class. } } if (usedUuidList) { @@ -256,19 +245,6 @@ public class ApiResponseSerializer { } else if (fieldValue instanceof Date) { sb.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date) fieldValue)). append(""); - } else if (fieldValue instanceof IdentityProxy) { - IdentityProxy idProxy = (IdentityProxy)fieldValue; - String id = (idProxy.getValue() != null ? String.valueOf(idProxy.getValue()) : ""); - if(!id.isEmpty()) { - IdentityDao identityDao = new IdentityDaoImpl(); - if(idProxy.getTableName() != null) { - id = identityDao.getIdentityUuid(idProxy.getTableName(), id); - } else { - s_logger.warn("IdentityProxy sanity check issue, invalid IdentityProxy table name found in class: " + obj.getClass().getName()); - } - } - if(id != null && !id.isEmpty()) - sb.append("<").append(serializedName.value()).append(">").append(id).append(""); } else { String resultString = escapeSpecialXmlChars(fieldValue.toString()); if (!(obj instanceof ExceptionResponse)) { diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index af5989cf003..b25c63f6d7f 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -103,7 +103,6 @@ public class ConfigurationServerImpl implements ConfigurationServer { private final AccountDao _accountDao; private final ResourceCountDao _resourceCountDao; private final NetworkOfferingServiceMapDao _ntwkOfferingServiceMapDao; - private final IdentityDao _identityDao; public ConfigurationServerImpl() { ComponentLocator locator = ComponentLocator.getLocator(Name); @@ -120,7 +119,6 @@ public class ConfigurationServerImpl implements ConfigurationServer { _accountDao = locator.getDao(AccountDao.class); _resourceCountDao = locator.getDao(ResourceCountDao.class); _ntwkOfferingServiceMapDao = locator.getDao(NetworkOfferingServiceMapDao.class); - _identityDao = locator.getDao(IdentityDao.class); } @Override diff --git a/utils/src/com/cloud/utils/IdentityProxy.java b/utils/src/com/cloud/utils/IdentityProxy.java deleted file mode 100644 index 7e385fbf05a..00000000000 --- a/utils/src/com/cloud/utils/IdentityProxy.java +++ /dev/null @@ -1,60 +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 -// 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.utils; - -public class IdentityProxy { - private String _tableName; - private Long _value; - private String _idFieldName; - - public IdentityProxy() { - } - - public IdentityProxy(String tableName) { - _tableName = tableName; - } - - public IdentityProxy(String tableName, Long id, String fieldName) { - _tableName = tableName; - _value = id; - _idFieldName = fieldName; - } - - public String getTableName() { - return _tableName; - } - - public void setTableName(String tableName) { - _tableName = tableName; - } - - public Long getValue() { - return _value; - } - - public void setValue(Long value) { - _value = value; - } - - public void setidFieldName(String value) { - _idFieldName = value; - } - - public String getidFieldName() { - return _idFieldName; - } -} diff --git a/utils/src/com/cloud/utils/exception/RuntimeCloudException.java b/utils/src/com/cloud/utils/exception/RuntimeCloudException.java index 233469678df..52229800785 100644 --- a/utils/src/com/cloud/utils/exception/RuntimeCloudException.java +++ b/utils/src/com/cloud/utils/exception/RuntimeCloudException.java @@ -17,7 +17,6 @@ package com.cloud.utils.exception; import com.cloud.utils.AnnotationHelper; -import com.cloud.utils.IdentityProxy; import java.util.ArrayList; /** From cd7f7716155c3cd2d29b97d7ea302518d81fdfab Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Thu, 10 Jan 2013 14:53:29 +0530 Subject: [PATCH 06/92] CLOUDSTACK-721: Fixed network usage. Send network usage command for isolated guest nic of non VPC VR. Send network usage command for public nic in VPC VR. --- .../VirtualNetworkApplianceManagerImpl.java | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 1a6eb0982a9..1f74c7174e8 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -823,26 +823,29 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian String privateIP = router.getPrivateIpAddress(); if (privateIP != null) { + boolean forVpc = router.getVpcId() != null; List routerNics = _nicDao.listByVmId(router.getId()); for (Nic routerNic : routerNics) { Network network = _networkMgr.getNetwork(routerNic.getNetworkId()); - if (network.getTrafficType() == TrafficType.Public) { - boolean forVpc = router.getVpcId() != null; + //Send network usage command for public nic in VPC VR + //Send network usage command for isolated guest nic of non VPC VR + if ((forVpc && network.getTrafficType() == TrafficType.Public) || (!forVpc && network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Isolated)) { final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIp4Address()); - UserStatisticsVO previousStats = _statsDao.findBy(router.getAccountId(), - router.getDataCenterIdToDeployIn(), network.getId(), null, router.getId(), router.getType().toString()); + String routerType = router.getType().toString(); + UserStatisticsVO previousStats = _statsDao.findBy(router.getAccountId(), + router.getDataCenterIdToDeployIn(), network.getId(), (forVpc ? routerNic.getIp4Address() : null), router.getId(), routerType); NetworkUsageAnswer answer = null; try { answer = (NetworkUsageAnswer) _agentMgr.easySend(router.getHostId(), usageCmd); } catch (Exception e) { - s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId(), e); + s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e); continue; } if (answer != null) { if (!answer.getResult()) { - s_logger.warn("Error while collecting network stats from router: "+router.getInstanceName()+" from host: "+router.getHostId() + "; details: " + answer.getDetails()); + s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId() + "; details: " + answer.getDetails()); continue; } Transaction txn = Transaction.open(Transaction.CLOUD_DB); @@ -852,27 +855,27 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian continue; } txn.start(); - UserStatisticsVO stats = _statsDao.lock(router.getAccountId(), - router.getDataCenterIdToDeployIn(), network.getId(), routerNic.getIp4Address(), router.getId(), router.getType().toString()); + UserStatisticsVO stats = _statsDao.lock(router.getAccountId(), + router.getDataCenterIdToDeployIn(), network.getId(), (forVpc ? routerNic.getIp4Address() : null), router.getId(), routerType); if (stats == null) { s_logger.warn("unable to find stats for account: " + router.getAccountId()); continue; } - if(previousStats != null - && ((previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived()) - || (previousStats.getCurrentBytesSent() != stats.getCurrentBytesSent()))){ + if (previousStats != null + && ((previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived()) + || (previousStats.getCurrentBytesSent() != stats.getCurrentBytesSent()))) { s_logger.debug("Router stats changed from the time NetworkUsageCommand was sent. " + - "Ignoring current answer. Router: "+answer.getRouterName()+" Rcvd: " + - answer.getBytesReceived()+ "Sent: " +answer.getBytesSent()); + "Ignoring current answer. Router: " + answer.getRouterName() + " Rcvd: " + + answer.getBytesReceived() + "Sent: " + answer.getBytesSent()); continue; } if (stats.getCurrentBytesReceived() > answer.getBytesReceived()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Received # of bytes that's less than the last one. " + - "Assuming something went wrong and persisting it. Router: " + - answer.getRouterName()+" Reported: " + answer.getBytesReceived() + "Assuming something went wrong and persisting it. Router: " + + answer.getRouterName() + " Reported: " + answer.getBytesReceived() + " Stored: " + stats.getCurrentBytesReceived()); } stats.setNetBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived()); @@ -881,8 +884,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian if (stats.getCurrentBytesSent() > answer.getBytesSent()) { if (s_logger.isDebugEnabled()) { s_logger.debug("Received # of bytes that's less than the last one. " + - "Assuming something went wrong and persisting it. Router: " + - answer.getRouterName()+" Reported: " + answer.getBytesSent() + "Assuming something went wrong and persisting it. Router: " + + answer.getRouterName() + " Reported: " + answer.getBytesSent() + " Stored: " + stats.getCurrentBytesSent()); } stats.setNetBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent()); From 1b8e17255f24a3e6aaf2265b1c3f8e27377eca76 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 10 Jan 2013 20:29:12 +0530 Subject: [PATCH 07/92] integration test fix: test iso - obj reference within classmethod --- test/integration/smoke/test_iso.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index 22d424f86cc..8228a278cc9 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -219,14 +219,14 @@ class TestISO(cloudstackTestCase): # Finding the OsTypeId from Ostype ostypes = list_os_types( cls.api_client, - description=self.services["ostype"] + description=cls.services["ostype"] ) if not isinstance(ostypes, list): raise unittest.SkipTest("OSTypeId for given description not found") - self.services["iso_1"]["ostypeid"] = ostypes[0].id - self.services["iso_2"]["ostypeid"] = ostypes[0].id - self.services["ostypeid"] = ostypes[0].id + cls.services["iso_1"]["ostypeid"] = ostypes[0].id + cls.services["iso_2"]["ostypeid"] = ostypes[0].id + cls.services["ostypeid"] = ostypes[0].id cls.iso_1 = Iso.create( cls.api_client, From c6d9877d6445d36e2677c7b4ac7deec6a668a053 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 10:59:13 -0800 Subject: [PATCH 08/92] ApiDiscoveryService: Move refactor, interface should be in plugins and not in cloud-api Signed-off-by: Rohit Yadav --- .../src/org/apache/cloudstack/discovery/ApiDiscoveryService.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {api => plugins/api/discovery}/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java (100%) diff --git a/api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java similarity index 100% rename from api/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java rename to plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java From 62a42723f995279fcaa4a63d9b0be061d32c66ca Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 11:49:15 -0800 Subject: [PATCH 09/92] APIAccessChecker: Make it check based on role type and not user Signed-off-by: Rohit Yadav --- .../cloudstack/acl/APIAccessChecker.java | 7 +- .../acl/StaticRoleBasedAPIAccessChecker.java | 84 ++++++++----------- server/src/com/cloud/api/ApiServer.java | 33 +++++++- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java b/api/src/org/apache/cloudstack/acl/APIAccessChecker.java index 3194bd11d17..a5c656d731a 100644 --- a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIAccessChecker.java @@ -16,11 +16,8 @@ // under the License. package org.apache.cloudstack.acl; -import java.util.Properties; - +import org.apache.cloudstack.acl.RoleType; import com.cloud.exception.PermissionDeniedException; -import com.cloud.user.Account; -import com.cloud.user.User; import com.cloud.utils.component.Adapter; /** @@ -28,5 +25,5 @@ import com.cloud.utils.component.Adapter; */ public interface APIAccessChecker extends Adapter { // Interface for checking access to an API for an user - boolean canAccessAPI(User user, String apiCommandName) throws PermissionDeniedException; + boolean canAccessAPI(RoleType roleType, String apiCommandName) throws PermissionDeniedException; } diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index d39f87f1048..43ca403f890 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -27,80 +27,66 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.APIAccessChecker; +import org.apache.cloudstack.acl.RoleType; +import static org.apache.cloudstack.acl.RoleType.*; import org.apache.log4j.Logger; import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.User; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; -import com.cloud.utils.component.Inject; import com.cloud.utils.component.PluggableService; -/* - * This is the default API access checker that grab's the user's account - * based on the account type, access is granted referring to commands in all *.properties files. - */ - +// This is the default API access checker that grab's the user's account +// based on the account type, access is granted @Local(value=APIAccessChecker.class) public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIAccessChecker { protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); - public static final short ADMIN_COMMAND = 1; - public static final short DOMAIN_ADMIN_COMMAND = 4; - public static final short RESOURCE_DOMAIN_ADMIN_COMMAND = 2; - public static final short USER_COMMAND = 8; - private static List s_userCommands = null; - private static List s_resellerCommands = null; // AKA domain-admin - private static List s_adminCommands = null; - private static List s_resourceDomainAdminCommands = null; - private static List s_allCommands = null; - - protected @Inject AccountManager _accountMgr; + private static Set s_userCommands = null; + private static Set s_resellerCommands = null; // AKA domain-admin + private static Set s_adminCommands = null; + private static Set s_resourceDomainAdminCommands = null; + private static Set s_allCommands = null; protected StaticRoleBasedAPIAccessChecker() { super(); - s_allCommands = new ArrayList(); - s_userCommands = new ArrayList(); - s_resellerCommands = new ArrayList(); - s_adminCommands = new ArrayList(); - s_resourceDomainAdminCommands = new ArrayList(); + s_allCommands = new HashSet(); + s_userCommands = new HashSet(); + s_resellerCommands = new HashSet(); + s_adminCommands = new HashSet(); + s_resourceDomainAdminCommands = new HashSet(); } @Override - public boolean canAccessAPI(User user, String apiCommandName) + public boolean canAccessAPI(RoleType roleType, String apiCommandName) throws PermissionDeniedException{ boolean commandExists = s_allCommands.contains(apiCommandName); - if(commandExists && user != null){ - Long accountId = user.getAccountId(); - Account userAccount = _accountMgr.getAccount(accountId); - short accountType = userAccount.getType(); - return isCommandAvailableForAccount(accountType, apiCommandName); + if(commandExists) { + return isCommandAvailableForAccount(roleType, apiCommandName); } return commandExists; } - private static boolean isCommandAvailableForAccount(short accountType, String commandName) { + private static boolean isCommandAvailableForAccount(RoleType roleType, String commandName) { boolean isCommandAvailable = false; - switch (accountType) { - case Account.ACCOUNT_TYPE_ADMIN: - isCommandAvailable = s_adminCommands.contains(commandName); - break; - case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: - isCommandAvailable = s_resellerCommands.contains(commandName); - break; - case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: - isCommandAvailable = s_resourceDomainAdminCommands.contains(commandName); - break; - case Account.ACCOUNT_TYPE_NORMAL: - isCommandAvailable = s_userCommands.contains(commandName); - break; + switch (roleType) { + case Admin: + isCommandAvailable = s_adminCommands.contains(commandName); + break; + case DomainAdmin: + isCommandAvailable = s_resellerCommands.contains(commandName); + break; + case ResourceAdmin: + isCommandAvailable = s_resourceDomainAdminCommands.contains(commandName); + break; + case User: + isCommandAvailable = s_userCommands.contains(commandName); + break; } return isCommandAvailable; } @@ -157,16 +143,16 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA try { short cmdPermissions = Short.parseShort(mask); - if ((cmdPermissions & ADMIN_COMMAND) != 0) { + if ((cmdPermissions & Admin.getValue()) != 0) { s_adminCommands.add((String) key); } - if ((cmdPermissions & RESOURCE_DOMAIN_ADMIN_COMMAND) != 0) { + if ((cmdPermissions & ResourceAdmin.getValue()) != 0) { s_resourceDomainAdminCommands.add((String) key); } - if ((cmdPermissions & DOMAIN_ADMIN_COMMAND) != 0) { + if ((cmdPermissions & DomainAdmin.getValue()) != 0) { s_resellerCommands.add((String) key); } - if ((cmdPermissions & USER_COMMAND) != 0) { + if ((cmdPermissions & User.getValue()) != 0) { s_userCommands.add((String) key); } s_allCommands.addAll(s_adminCommands); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 17a2b29638b..1c1e8ca0e96 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -53,6 +53,7 @@ import javax.servlet.http.HttpSession; import com.cloud.utils.ReflectUtil; import org.apache.cloudstack.acl.APIAccessChecker; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; @@ -790,9 +791,39 @@ public class ApiServer implements HttpRequestHandler { } private boolean isCommandAvailable(User user, String commandName) { + if (user == null) { + return false; + } + + Account account = _accountMgr.getAccount(user.getAccountId()); + if (account == null) { + return false; + } + + RoleType roleType = RoleType.Unknown; + short accountType = account.getType(); + + // Account type to role type translation + switch (accountType) { + case Account.ACCOUNT_TYPE_ADMIN: + roleType = RoleType.Admin; + break; + case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: + roleType = RoleType.DomainAdmin; + break; + case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: + roleType = RoleType.ResourceAdmin; + break; + case Account.ACCOUNT_TYPE_NORMAL: + roleType = RoleType.User; + break; + default: + return false; + } + for (APIAccessChecker apiChecker : _apiAccessCheckers) { // Fail the checking if any checker fails to verify - if (!apiChecker.canAccessAPI(user, commandName)) + if (!apiChecker.canAccessAPI(roleType, commandName)) return false; } return true; From 1c59dae7087857858c91fc5497ee7a692833a2a2 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Thu, 10 Jan 2013 14:13:58 -0700 Subject: [PATCH 10/92] Summary: Add devcloud-kvm files Detail: Working on getting a KVM-based devcloud so that development that requires the KVM hypervisor can be simpler. This adds some setup devcloud files. Signed-off-by: Marcus Sorensen 1357852438 -0700 --- pom.xml | 2 + tools/devcloud-kvm/README.md | 21 +++++ tools/devcloud-kvm/devcloud-kvm.cfg | 97 +++++++++++++++++++ tools/devcloud-kvm/devcloud-kvm.sql | 40 ++++++++ tools/devcloud-kvm/pom.xml | 138 ++++++++++++++++++++++++++++ 5 files changed, 298 insertions(+) create mode 100644 tools/devcloud-kvm/README.md create mode 100644 tools/devcloud-kvm/devcloud-kvm.cfg create mode 100644 tools/devcloud-kvm/devcloud-kvm.sql create mode 100644 tools/devcloud-kvm/pom.xml diff --git a/pom.xml b/pom.xml index 1dcf36fe7ed..aad124b0baf 100644 --- a/pom.xml +++ b/pom.xml @@ -245,6 +245,7 @@ scripts/vm/systemvm/id_rsa.cloud tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf tools/devcloud/devcloud.cfg + tools/devcloud-kvm/devcloud-kvm.cfg ui/lib/flot/jquery.colorhelpers.js ui/lib/flot/jquery.flot.crosshair.js ui/lib/flot/jquery.flot.fillbetween.js @@ -371,6 +372,7 @@ developer tools/apidoc tools/devcloud + tools/devcloud-kvm tools/marvin tools/cli diff --git a/tools/devcloud-kvm/README.md b/tools/devcloud-kvm/README.md new file mode 100644 index 00000000000..3261fbe4b8e --- /dev/null +++ b/tools/devcloud-kvm/README.md @@ -0,0 +1,21 @@ +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. + +=========================================================== + +This directory hosts configs for setting up the devcloud-kvm +environment. diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg new file mode 100644 index 00000000000..47a128fea14 --- /dev/null +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -0,0 +1,97 @@ +{ + "zones": [ + { + "name": "DevCloudKVM0", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "test-network", + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "Pod", + "name": "SecurityGroupProvider" + } + ] + } + ], + "dns2": "4.4.4.4", + "dns1": "8.8.8.8", + "securitygroupenabled": "true", + "localstorageenabled": "true", + "networktype": "Basic", + "pods": [ + { + "endip": "192.168.100.250", + "name": "test00", + "startip": "192.168.100.200", + "guestIpRanges": [ + { + "startip": "192.168.100.100", + "endip": "192.168.100.199", + "netmask": "255.255.255.0", + "gateway": "192.168.100.1" + } + ], + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "test000", + "hypervisor": "KVM", + "hosts": [ + { + "username": "root", + "url": "http://192.168.100.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.100.1" + } + ], + "internaldns1": "192.168.100.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.100.10:/nfs/secondary" + } + ] + } + ], + "logger": [ + { + "name": "TestClient", + "file": "/tmp/testclient.log" + }, + { + "name": "TestCase", + "file": "/tmp/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ], + "dbSvr": + { + "dbSvr": "127.0.0.1", + "port": 3306, + "user": "cloud", + "passwd": "cloud", + "db": "cloud" + } +} diff --git a/tools/devcloud-kvm/devcloud-kvm.sql b/tools/devcloud-kvm/devcloud-kvm.sql new file mode 100644 index 00000000000..eeba64153a3 --- /dev/null +++ b/tools/devcloud-kvm/devcloud-kvm.sql @@ -0,0 +1,40 @@ +-- 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. + + +INSERT INTO `cloud`.`disk_offering` (id, name, uuid, display_text, created, use_local_storage, type, disk_size) VALUES (17, 'tinyOffering', UUID(), 'tinyOffering', NOW(), 1, 'Service', 0); +INSERT INTO `cloud`.`service_offering` (id, cpu, speed, ram_size) VALUES (17, 1, 100, 100); +INSERT INTO `cloud`.`disk_offering` (id, name, uuid, display_text, created, type, disk_size) VALUES (18, 'tinyDiskOffering', UUID(), 'tinyDiskOffering', NOW(), 'Disk', 1073741824); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','router.ram.size', '100'); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','router.cpu.mhz','100'); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','console.ram.size','100'); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','console.cpu.mhz', '100'); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','ssvm.ram.size','100'); +INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','ssvm.cpu.mhz','100'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'system.vm.use.local.storage', 'true'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'expunge.workers', '3'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'expunge.delay', '60'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'expunge.interval', '60'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'enable.ec2.api', 'true'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'enable.s3.api', 'true'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'host', '192.168.100.10'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'management.network.cidr', '192.168.100.0/24'); +INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'secstorage.allowed.internal.sites', '192.168.0.0/8'); +UPDATE `cloud`.`configuration` SET value='10' where name = 'storage.overprovisioning.factor'; +UPDATE `cloud`.`configuration` SET value='10' where name = 'cpu.overprovisioning.factor'; +UPDATE `cloud`.`configuration` SET value='10' where name = 'mem.overprovisioning.factor'; +UPDATE `cloud`.`vm_template` SET unique_name="tiny Linux",name="tiny Linux",url="https://dl.dropbox.com/u/678991/cloudstack-extras/ttylinux_pv.qcow2",checksum="81dcf4b4ca05a3b637a040e851568f29",display_text="tiny Linux",format='QCOW2',hypervisor_type='KVM' where id=5; diff --git a/tools/devcloud-kvm/pom.xml b/tools/devcloud-kvm/pom.xml new file mode 100644 index 00000000000..c9af192bee3 --- /dev/null +++ b/tools/devcloud-kvm/pom.xml @@ -0,0 +1,138 @@ + + + 4.0.0 + cloud-devcloud-kvm + Apache CloudStack Developer Tools + pom + + org.apache.cloudstack + cloudstack + 4.1.0-SNAPSHOT + ../../pom.xml + + + + mysql + mysql-connector-java + 5.1.21 + runtime + + + + + install + + + + deploydb + + + deploydb + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + initialize + + read-project-properties + + + + ${project.parent.basedir}/utils/conf/db.properties + ${project.parent.basedir}/utils/conf/db.properties.override + + true + + + + + + org.codehaus.mojo + sql-maven-plugin + 1.5 + + + + mysql + mysql-connector-java + ${cs.mysql.version} + + + + org.gjt.mm.mysql.Driver + jdbc:mysql://${db.cloud.host}:${db.cloud.port}/cloud + ${db.cloud.username} + ${db.cloud.password} + + ${maven.test.skip} + true + + + + create-schema + process-test-resources + + execute + + + + ${basedir}/devcloud-kvm.sql + + + + + + + + + + deploysvr + + + deploysvr + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + package + + exec + + + + + python + + ../marvin/marvin/deployDataCenter.py + -i + devcloud-kvm.cfg + + + + + + + + From ffcc6d781ebbe7985251b9641de959a07a4ae6c8 Mon Sep 17 00:00:00 2001 From: Joe Brockmeier Date: Thu, 10 Jan 2013 16:01:02 -0600 Subject: [PATCH 11/92] CLOUDSTACK-683: Fixed missing image in Accessing VM Section --- docs/en-US/accessing-vms.xml | 2 +- docs/en-US/images/view-console-button.png | Bin 0 -> 59996 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/en-US/images/view-console-button.png diff --git a/docs/en-US/accessing-vms.xml b/docs/en-US/accessing-vms.xml index d69d021471b..c77ad4eee52 100644 --- a/docs/en-US/accessing-vms.xml +++ b/docs/en-US/accessing-vms.xml @@ -29,7 +29,7 @@ Log in to the &PRODUCT; UI as a user or admin. Click Instances, then click the name of a running VM. - Click the View Console button . + Click the View Console button . To access a VM directly over the network: diff --git a/docs/en-US/images/view-console-button.png b/docs/en-US/images/view-console-button.png new file mode 100644 index 0000000000000000000000000000000000000000..b321ceadefee0eb00c7db1de14002c7df81b4b31 GIT binary patch literal 59996 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 Date: Thu, 10 Jan 2013 15:27:15 -0800 Subject: [PATCH 12/92] RoleType: public enum to get presently defined static role in CloudStack Signed-off-by: Rohit Yadav --- .../org/apache/cloudstack/acl/RoleType.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 api/src/org/apache/cloudstack/acl/RoleType.java diff --git a/api/src/org/apache/cloudstack/acl/RoleType.java b/api/src/org/apache/cloudstack/acl/RoleType.java new file mode 100644 index 00000000000..0d1c4460c1e --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/RoleType.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 org.apache.cloudstack.acl; + +// Enum for default roles in CloudStack +public enum RoleType { + + Admin(1), + ResourceAdmin(2), + DomainAdmin(4), + User(8), + Unknown(0); + + private int mask; + + private RoleType(int mask) { + this.mask = mask; + } + + public int getValue() { + return mask; + } +} From f2ae0ae5ae70fbb5f33c004e05e4a17327094651 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:29:01 -0800 Subject: [PATCH 13/92] PropertiesUtil: Refactor process config file method in utils, return map of key=value Signed-off-by: Rohit Yadav --- utils/src/com/cloud/utils/PropertiesUtil.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/utils/src/com/cloud/utils/PropertiesUtil.java b/utils/src/com/cloud/utils/PropertiesUtil.java index 3909ca876b6..90f8af8b33f 100755 --- a/utils/src/com/cloud/utils/PropertiesUtil.java +++ b/utils/src/com/cloud/utils/PropertiesUtil.java @@ -17,6 +17,8 @@ package com.cloud.utils; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -28,6 +30,7 @@ import java.util.Set; import org.apache.log4j.Logger; public class PropertiesUtil { + private static final Logger s_logger = Logger.getLogger(PropertiesUtil.class); /** * Searches the class path and local paths to find the config file. * @param path path to find. if it starts with / then it's absolute path. @@ -116,4 +119,41 @@ public class PropertiesUtil { } return null; } + + // Returns key=value pairs by parsing a commands.properties/config file + // with syntax; key=cmd;value (with this syntax cmd is stripped) and key=value + public static Map processConfigFile(String[] configFiles) { + Map configMap = new HashMap(); + Properties preProcessedCommands = new Properties(); + for (String configFile : configFiles) { + File commandsFile = findConfigFile(configFile); + if (commandsFile != null) { + try { + preProcessedCommands.load(new FileInputStream(commandsFile)); + } catch (FileNotFoundException fnfex) { + // in case of a file within a jar in classpath, try to open stream using url + InputStream stream = PropertiesUtil.openStreamFromURL(configFile); + if (stream != null) { + try { + preProcessedCommands.load(stream); + } catch (IOException e) { + s_logger.error("IO Exception, unable to find properties file:", fnfex); + } + } else { + s_logger.error("Unable to find properites file", fnfex); + } + } catch (IOException ioe) { + s_logger.error("IO Exception loading properties file", ioe); + } + } + } + + for (Object key : preProcessedCommands.keySet()) { + String preProcessedCommand = preProcessedCommands.getProperty((String) key); + int splitIndex = preProcessedCommand.lastIndexOf(";"); + String value = preProcessedCommand.substring(splitIndex+1); + configMap.put((String)key, value); + } + return configMap; + } } From 1425736c193c56a51ec59b23e35080bd74926baf Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:31:32 -0800 Subject: [PATCH 14/92] AccountManager: Add method to translate account type to role type Signed-off-by: Rohit Yadav --- api/src/com/cloud/user/AccountService.java | 3 +++ .../com/cloud/user/AccountManagerImpl.java | 26 +++++++++++++++++++ .../cloud/user/MockAccountManagerImpl.java | 6 +++++ 3 files changed, 35 insertions(+) diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index ce16f5ee063..9f5f4d225e0 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; @@ -193,6 +194,8 @@ public interface AccountService { UserAccount getUserByApiKey(String apiKey); + RoleType getRoleType(Account account); + void checkAccess(Account account, Domain domain) throws PermissionDeniedException; void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException; diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index c6a7d51f08d..b910a03f99b 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -37,6 +37,7 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; @@ -1542,6 +1543,31 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } + @Override + public RoleType getRoleType(Account account) { + RoleType roleType = RoleType.Unknown; + if (account == null) + return roleType; + short accountType = account.getType(); + + // Account type to role type translation + switch (accountType) { + case Account.ACCOUNT_TYPE_ADMIN: + roleType = RoleType.Admin; + break; + case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: + roleType = RoleType.DomainAdmin; + break; + case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: + roleType = RoleType.ResourceAdmin; + break; + case Account.ACCOUNT_TYPE_NORMAL: + roleType = RoleType.User; + break; + } + return roleType; + } + @Override public User getActiveUser(long userId) { return _userDao.findById(userId); diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index ae5d0e5de4b..550304adfff 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -23,6 +23,7 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.api.query.vo.ControlledViewEntity; @@ -344,4 +345,9 @@ public class MockAccountManagerImpl implements Manager, AccountManager, AccountS return null; } + @Override + public RoleType getRoleType(Account account) { + return null; + } + } From a56f355cebc4b409840a3f2c2deea5bd0f91ab49 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:33:52 -0800 Subject: [PATCH 15/92] ApiServer: get role type from account manager using account Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 29 +++---------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 1c1e8ca0e96..73871259504 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -790,37 +790,14 @@ public class ApiServer implements HttpRequestHandler { return true; } - private boolean isCommandAvailable(User user, String commandName) { + private boolean isCommandAvailable(User user, String commandName) + throws PermissionDeniedException { if (user == null) { return false; } Account account = _accountMgr.getAccount(user.getAccountId()); - if (account == null) { - return false; - } - - RoleType roleType = RoleType.Unknown; - short accountType = account.getType(); - - // Account type to role type translation - switch (accountType) { - case Account.ACCOUNT_TYPE_ADMIN: - roleType = RoleType.Admin; - break; - case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: - roleType = RoleType.DomainAdmin; - break; - case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: - roleType = RoleType.ResourceAdmin; - break; - case Account.ACCOUNT_TYPE_NORMAL: - roleType = RoleType.User; - break; - default: - return false; - } - + RoleType roleType = _accountMgr.getRoleType(account); for (APIAccessChecker apiChecker : _apiAccessCheckers) { // Fail the checking if any checker fails to verify if (!apiChecker.canAccessAPI(roleType, commandName)) From c4e890c55d4b106934ff3588adfbbf5a12f48d1e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:43:44 -0800 Subject: [PATCH 16/92] PluggableService: Refactor method to return map of key value pairs - Makes plugins self contained so they decide their properties file format - PluggableService creates the contract that implementing entity will return a properties map which is apiname:rolemask (both are strings) Signed-off-by: Rohit Yadav --- .../server/ManagementServerSimulatorImpl.java | 18 +++++++++--------- .../network/element/CiscoNexusVSMElement.java | 7 +++++-- .../element/F5ExternalLoadBalancerElement.java | 7 +++++-- .../JuniperSRXExternalFirewallElement.java | 7 +++++-- .../network/element/NetscalerElement.java | 6 ++++-- .../network/element/NiciraNvpElement.java | 6 ++++-- .../network/element/VirtualRouterElement.java | 6 ++++-- .../cloud/server/ManagementServerExtImpl.java | 6 ++++-- .../com/cloud/server/ManagementServerImpl.java | 5 +++-- .../utils/component/PluggableService.java | 4 +++- 10 files changed, 46 insertions(+), 26 deletions(-) diff --git a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java index ad42c23380e..44ab26a020a 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java @@ -17,16 +17,16 @@ package com.cloud.server; +import com.cloud.utils.PropertiesUtil; + +import java.util.Map; + public class ManagementServerSimulatorImpl extends ManagementServerExtImpl { @Override - public String[] getPropertiesFiles() { - String[] apis = super.getPropertiesFiles(); - String[] newapis = new String[apis.length + 1]; - for (int i = 0; i < apis.length; i++) { - newapis[i] = apis[i]; - } - - newapis[apis.length] = "commands-simulator.properties"; - return newapis; + public Map getProperties() { + Map apiNameRoleMaskMapping = super.getProperties(); + apiNameRoleMaskMapping.putAll(PropertiesUtil.processConfigFile(new String[] + {"commands-simulator.properties"})); + return apiNameRoleMaskMapping; } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java index 911078eac50..2cf87877859 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -17,6 +17,7 @@ package com.cloud.network.element; +import java.lang.String; import java.util.List; import java.util.Map; import java.util.ArrayList; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.commands.DeleteCiscoNexusVSMCmd; @@ -237,7 +239,8 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme } @Override - public String[] getPropertiesFiles() { - return new String[] { "cisconexusvsm_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "cisconexusvsm_commands.properties" }); } } diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 335dc6ecfec..438498ff38c 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -260,8 +262,9 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan } @Override - public String[] getPropertiesFiles() { - return new String[] { "f5bigip_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "f5bigip_commands.properties" }); } @Override diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index f491e66925a..55722ae23ab 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -24,6 +25,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -402,8 +404,9 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan } @Override - public String[] getPropertiesFiles() { - return new String[] { "junipersrx_commands.properties"}; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "junipersrx_commands.properties"}); } @Override diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index b1fe949632c..ac1619ef1f8 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -464,8 +465,9 @@ StaticNatServiceProvider { } @Override - public String[] getPropertiesFiles() { - return new String[] { "netscalerloadbalancer_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "netscalerloadbalancer_commands.properties" }); } @Override diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index cc53ee1afae..22fab500fdb 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -27,6 +27,7 @@ import java.util.UUID; import javax.ejb.Local; import javax.naming.ConfigurationException; +import com.cloud.utils.PropertiesUtil; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -540,8 +541,9 @@ public class NiciraNvpElement extends AdapterBase implements } @Override - public String[] getPropertiesFiles() { - return new String[] { "nicira-nvp_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "nicira-nvp_commands.properties" }); } @Override diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index b5b8b1a73cd..823b74f269b 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -24,6 +24,7 @@ import java.util.Set; import javax.ejb.Local; +import com.cloud.utils.PropertiesUtil; import org.apache.cloudstack.api.command.admin.router.ConfigureVirtualRouterElementCmd; import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; import org.apache.log4j.Logger; @@ -680,8 +681,9 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public String[] getPropertiesFiles() { - return new String[] { "virtualrouter_commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "virtualrouter_commands.properties" }); } @Override diff --git a/server/src/com/cloud/server/ManagementServerExtImpl.java b/server/src/com/cloud/server/ManagementServerExtImpl.java index b7320276341..8a59d2f9c1c 100644 --- a/server/src/com/cloud/server/ManagementServerExtImpl.java +++ b/server/src/com/cloud/server/ManagementServerExtImpl.java @@ -29,6 +29,7 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.projects.Project; +import com.cloud.utils.PropertiesUtil; import org.apache.cloudstack.api.response.UsageTypeResponse; import com.cloud.usage.UsageJobVO; import com.cloud.usage.UsageTypes; @@ -206,8 +207,9 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man } @Override - public String[] getPropertiesFiles() { - return new String[] { "commands.properties", "commands-ext.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "commands.properties", "commands-ext.properties" }); } private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index dcecaf40a57..3e0f6efae7c 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2297,8 +2297,9 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public String[] getPropertiesFiles() { - return new String[] { "commands.properties" }; + public Map getProperties() { + return PropertiesUtil.processConfigFile(new String[] + { "commands.properties" }); } protected class EventPurgeTask implements Runnable { diff --git a/utils/src/com/cloud/utils/component/PluggableService.java b/utils/src/com/cloud/utils/component/PluggableService.java index d2199394a69..f6f72a904d0 100644 --- a/utils/src/com/cloud/utils/component/PluggableService.java +++ b/utils/src/com/cloud/utils/component/PluggableService.java @@ -16,9 +16,11 @@ // under the License. package com.cloud.utils.component; +import java.util.Map; + // This interface defines methods for pluggable code within the Cloud Stack. public interface PluggableService { // The config command properties filenames that lists allowed API commands // and role masks supported by this pluggable service - String[] getPropertiesFiles(); + Map getProperties(); } From 0b1c2a5981fea3d4455acee6ac77e9fa84c9724b Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:47:59 -0800 Subject: [PATCH 17/92] ApiDiscovery: Fix listApis interface, fix getProperties In case of api discovery, it does not make sense to create a separate properties file If this plugin is enabled in components.xml, a user should be able to discover all the apis accessible to their role. listApis based on role type of caller user Signed-off-by: Rohit Yadav --- .../api/command/user/discovery/ListApisCmd.java | 7 ++++++- .../cloudstack/discovery/ApiDiscoveryService.java | 3 ++- .../cloudstack/discovery/ApiDiscoveryServiceImpl.java | 10 +++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index dcbaec1d160..feab20ac5cf 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,6 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; @@ -39,7 +42,9 @@ public class ListApisCmd extends BaseListCmd { @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - ListResponse response = (ListResponse) _apiDiscoveryService.listApis(); + Account caller = UserContext.current().getCaller(); + RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller()); + ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType); if (response == null) { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find and process any apis"); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index 96ea3ee4d34..a1d440e9ccf 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -17,9 +17,10 @@ package org.apache.cloudstack.discovery; import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; public interface ApiDiscoveryService extends PluggableService { - ListResponse listApis(); + ListResponse listApis(RoleType roleType); } 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 ea6b206fa44..2bc17bdbf4d 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -16,7 +16,9 @@ // under the License. package org.apache.cloudstack.discovery; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.ReflectUtil; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -108,12 +110,14 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } @Override - public ListResponse listApis() { + public ListResponse listApis(RoleType roleType) { return _discoveryResponse; } @Override - public String[] getPropertiesFiles() { - return new String[] { "api-discovery_commands.properties" }; + public Map getProperties() { + Map apiDiscoveryPropertyMap = new HashMap(); + apiDiscoveryPropertyMap.put("listApis", "15"); + return apiDiscoveryPropertyMap; } } From 8f26e171e64726a726fa146f9c02433e48c0ba60 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:51:46 -0800 Subject: [PATCH 18/92] ManagementServerImpl: Fix missing import of PropertiesUtil Signed-off-by: Rohit Yadav --- server/src/com/cloud/server/ManagementServerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 3e0f6efae7c..79ad759dd0b 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -223,6 +223,7 @@ import com.cloud.utils.EnumUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.Ternary; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; From 345c179e77dce7ba471f6846fac785bd34bda294 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 15:53:18 -0800 Subject: [PATCH 19/92] plugins: Check access based on roleType, remove unnecessary properties.in file - Fix StaticRoleBasedAPIAccessChecker to check api access based on roletype - Remove properties file which is not needed now for api discovery plugin Signed-off-by: Rohit Yadav --- .../api-discovery_commands.properties.in | 23 --- .../acl/StaticRoleBasedAPIAccessChecker.java | 136 +++++++----------- 2 files changed, 48 insertions(+), 111 deletions(-) delete mode 100644 client/tomcatconf/api-discovery_commands.properties.in diff --git a/client/tomcatconf/api-discovery_commands.properties.in b/client/tomcatconf/api-discovery_commands.properties.in deleted file mode 100644 index 49ddfde42d8..00000000000 --- a/client/tomcatconf/api-discovery_commands.properties.in +++ /dev/null @@ -1,23 +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. - -# bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = -# RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -# Please standardize naming conventions to camel-case (even for acronyms). - -# CloudStack API Discovery service command -listApis=15 diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 43ca403f890..689540aa291 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -16,28 +16,23 @@ // under the License. package org.apache.cloudstack.acl; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.APIAccessChecker; -import org.apache.cloudstack.acl.RoleType; -import static org.apache.cloudstack.acl.RoleType.*; -import org.apache.log4j.Logger; - import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; -import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.PluggableService; +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.cloudstack.acl.RoleType.*; +import org.apache.log4j.Logger; + // This is the default API access checker that grab's the user's account // based on the account type, access is granted @Local(value=APIAccessChecker.class) @@ -60,35 +55,29 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA } @Override - public boolean canAccessAPI(RoleType roleType, String apiCommandName) - throws PermissionDeniedException{ + public boolean canAccessAPI(RoleType roleType, String commandName) + throws PermissionDeniedException { - boolean commandExists = s_allCommands.contains(apiCommandName); + boolean commandExists = s_allCommands.contains(commandName); + boolean commandAccessible = false; - if(commandExists) { - return isCommandAvailableForAccount(roleType, apiCommandName); + if (commandExists) { + switch (roleType) { + case Admin: + commandAccessible = s_adminCommands.contains(commandName); + break; + case DomainAdmin: + commandAccessible = s_resellerCommands.contains(commandName); + break; + case ResourceAdmin: + commandAccessible = s_resourceDomainAdminCommands.contains(commandName); + break; + case User: + commandAccessible = s_userCommands.contains(commandName); + break; + } } - - return commandExists; - } - - private static boolean isCommandAvailableForAccount(RoleType roleType, String commandName) { - boolean isCommandAvailable = false; - switch (roleType) { - case Admin: - isCommandAvailable = s_adminCommands.contains(commandName); - break; - case DomainAdmin: - isCommandAvailable = s_resellerCommands.contains(commandName); - break; - case ResourceAdmin: - isCommandAvailable = s_resourceDomainAdminCommands.contains(commandName); - break; - case User: - isCommandAvailable = s_userCommands.contains(commandName); - break; - } - return isCommandAvailable; + return commandExists && commandAccessible; } @Override @@ -100,69 +89,40 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA List services = locator.getAllPluggableServices(); services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); - List configFiles = new ArrayList(); + Map configPropertiesMap = new HashMap(); for (PluggableService service : services) { - configFiles.addAll(Arrays.asList(service.getPropertiesFiles())); + configPropertiesMap.putAll(service.getProperties()); } - processConfigFiles(configFiles); + processConfigFiles(configPropertiesMap); return true; } - private void processConfigFiles(List configFiles) { - Properties preProcessedCommands = new Properties(); - - for (String configFile : configFiles) { - File commandsFile = PropertiesUtil.findConfigFile(configFile); - if (commandsFile != null) { - try { - preProcessedCommands.load(new FileInputStream(commandsFile)); - } catch (FileNotFoundException fnfex) { - // in case of a file within a jar in classpath, try to open stream using url - InputStream stream = PropertiesUtil.openStreamFromURL(configFile); - if (stream != null) { - try { - preProcessedCommands.load(stream); - } catch (IOException e) { - s_logger.error("IO Exception, unable to find properties file:", fnfex); - } - } else { - s_logger.error("Unable to find properites file", fnfex); - } - } catch (IOException ioe) { - s_logger.error("IO Exception loading properties file", ioe); - } - } - } - - for (Object key : preProcessedCommands.keySet()) { - String preProcessedCommand = preProcessedCommands.getProperty((String) key); - int splitIndex = preProcessedCommand.lastIndexOf(";"); - // Backward compatible to old style, apiname=pkg;mask - String mask = preProcessedCommand.substring(splitIndex+1); - + private void processConfigFiles(Map config) { + for (Map.Entry entry: config.entrySet()) { + String apiName = entry.getKey(); + String roleMask = entry.getValue(); try { - short cmdPermissions = Short.parseShort(mask); + short cmdPermissions = Short.parseShort(roleMask); if ((cmdPermissions & Admin.getValue()) != 0) { - s_adminCommands.add((String) key); + s_adminCommands.add(apiName); } if ((cmdPermissions & ResourceAdmin.getValue()) != 0) { - s_resourceDomainAdminCommands.add((String) key); + s_resourceDomainAdminCommands.add(apiName); } if ((cmdPermissions & DomainAdmin.getValue()) != 0) { - s_resellerCommands.add((String) key); + s_resellerCommands.add(apiName); } if ((cmdPermissions & User.getValue()) != 0) { - s_userCommands.add((String) key); + s_userCommands.add(apiName); } - s_allCommands.addAll(s_adminCommands); - s_allCommands.addAll(s_resourceDomainAdminCommands); - s_allCommands.addAll(s_userCommands); - s_allCommands.addAll(s_resellerCommands); } catch (NumberFormatException nfe) { - s_logger.info("Malformed command.properties permissions value, key = " + key + ", value = " + preProcessedCommand); + s_logger.info("Malformed commands.properties permissions value, for entry: " + entry.toString()); } } + s_allCommands.addAll(s_adminCommands); + s_allCommands.addAll(s_resourceDomainAdminCommands); + s_allCommands.addAll(s_userCommands); + s_allCommands.addAll(s_resellerCommands); } - } From e63e35250876a4f985a707ac52bdef34465a2470 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 16:08:16 -0800 Subject: [PATCH 20/92] ApiServer: Log a better message if api access fails and debug it Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 73871259504..be3c08716cc 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -552,14 +552,14 @@ public class ApiServer implements HttpRequestHandler { if (userId != null) { User user = ApiDBUtils.findUserById(userId); if (!isCommandAvailable(user, commandName)) { - s_logger.warn("The given command:" + commandName + " does not exist or it is not available for user"); + s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); } return true; } else { // check against every available command to see if the command exists or not if (!isCommandAvailable(null, commandName) && !commandName.equals("login") && !commandName.equals("logout")) { - s_logger.warn("The given command:" + commandName + " does not exist or it is not available for user"); + s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); } } @@ -653,8 +653,8 @@ public class ApiServer implements HttpRequestHandler { UserContext.updateContext(user.getId(), account, null); if (!isCommandAvailable(user, commandName)) { - s_logger.warn("The given command:" + commandName + " does not exist or it is not available for user"); - throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist or it is not available for user"); + s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user"); + throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); } // verify secret key exists From 18bdc58cebdceb4e078edbc8aa28f2a415729cae Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 17:21:58 -0800 Subject: [PATCH 21/92] APIAccessChecker: Refactor and simply plugin implementation using better data structures Signed-off-by: Rohit Yadav --- .../cloudstack/acl/APIAccessChecker.java | 3 +- .../acl/StaticRoleBasedAPIAccessChecker.java | 64 ++++--------------- 2 files changed, 14 insertions(+), 53 deletions(-) diff --git a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java b/api/src/org/apache/cloudstack/acl/APIAccessChecker.java index a5c656d731a..1645fa2c832 100644 --- a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIAccessChecker.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.acl; import org.apache.cloudstack.acl.RoleType; -import com.cloud.exception.PermissionDeniedException; import com.cloud.utils.component.Adapter; /** @@ -25,5 +24,5 @@ import com.cloud.utils.component.Adapter; */ public interface APIAccessChecker extends Adapter { // Interface for checking access to an API for an user - boolean canAccessAPI(RoleType roleType, String apiCommandName) throws PermissionDeniedException; + boolean canAccessAPI(RoleType roleType, String apiCommandName); } diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 689540aa291..d6bf3f63c74 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.acl; -import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; @@ -39,45 +38,20 @@ import org.apache.log4j.Logger; public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIAccessChecker { protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); - private static Set s_userCommands = null; - private static Set s_resellerCommands = null; // AKA domain-admin - private static Set s_adminCommands = null; - private static Set s_resourceDomainAdminCommands = null; - private static Set s_allCommands = null; + + private static Map> s_roleBasedApisMap = + new HashMap>(); protected StaticRoleBasedAPIAccessChecker() { super(); - s_allCommands = new HashSet(); - s_userCommands = new HashSet(); - s_resellerCommands = new HashSet(); - s_adminCommands = new HashSet(); - s_resourceDomainAdminCommands = new HashSet(); + for (RoleType roleType: RoleType.values()) { + s_roleBasedApisMap.put(roleType, new HashSet()); + } } @Override - public boolean canAccessAPI(RoleType roleType, String commandName) - throws PermissionDeniedException { - - boolean commandExists = s_allCommands.contains(commandName); - boolean commandAccessible = false; - - if (commandExists) { - switch (roleType) { - case Admin: - commandAccessible = s_adminCommands.contains(commandName); - break; - case DomainAdmin: - commandAccessible = s_resellerCommands.contains(commandName); - break; - case ResourceAdmin: - commandAccessible = s_resourceDomainAdminCommands.contains(commandName); - break; - case User: - commandAccessible = s_userCommands.contains(commandName); - break; - } - } - return commandExists && commandAccessible; + public boolean canAccessAPI(RoleType roleType, String commandName) { + return s_roleBasedApisMap.get(roleType).contains(commandName); } @Override @@ -98,31 +72,19 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA return true; } - private void processConfigFiles(Map config) { - for (Map.Entry entry: config.entrySet()) { + private void processConfigFiles(Map configMap) { + for (Map.Entry entry: configMap.entrySet()) { String apiName = entry.getKey(); String roleMask = entry.getValue(); try { short cmdPermissions = Short.parseShort(roleMask); - if ((cmdPermissions & Admin.getValue()) != 0) { - s_adminCommands.add(apiName); - } - if ((cmdPermissions & ResourceAdmin.getValue()) != 0) { - s_resourceDomainAdminCommands.add(apiName); - } - if ((cmdPermissions & DomainAdmin.getValue()) != 0) { - s_resellerCommands.add(apiName); - } - if ((cmdPermissions & User.getValue()) != 0) { - s_userCommands.add(apiName); + for (RoleType roleType: RoleType.values()) { + if ((cmdPermissions & roleType.getValue()) != 0) + s_roleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { s_logger.info("Malformed commands.properties permissions value, for entry: " + entry.toString()); } } - s_allCommands.addAll(s_adminCommands); - s_allCommands.addAll(s_resourceDomainAdminCommands); - s_allCommands.addAll(s_userCommands); - s_allCommands.addAll(s_resellerCommands); } } From 74bb043c37d28bad586ff8a42d8aa6533cef4aa8 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 18:49:18 -0800 Subject: [PATCH 22/92] APIChecker: Rename refactor and add interface checkExistence Signed-off-by: Rohit Yadav --- ...{APIAccessChecker.java => APIChecker.java} | 12 ++++----- client/tomcatconf/components.xml.in | 2 +- .../acl/StaticRoleBasedAPIAccessChecker.java | 16 +++++++++--- server/src/com/cloud/api/ApiServer.java | 25 ++++++++++++------- 4 files changed, 35 insertions(+), 20 deletions(-) rename api/src/org/apache/cloudstack/acl/{APIAccessChecker.java => APIChecker.java} (72%) diff --git a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java b/api/src/org/apache/cloudstack/acl/APIChecker.java similarity index 72% rename from api/src/org/apache/cloudstack/acl/APIAccessChecker.java rename to api/src/org/apache/cloudstack/acl/APIChecker.java index 1645fa2c832..61dd7de75cb 100644 --- a/api/src/org/apache/cloudstack/acl/APIAccessChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIChecker.java @@ -19,10 +19,10 @@ package org.apache.cloudstack.acl; import org.apache.cloudstack.acl.RoleType; import com.cloud.utils.component.Adapter; -/** - * APIAccessChecker checks the ownership and access control to API requests - */ -public interface APIAccessChecker extends Adapter { - // Interface for checking access to an API for an user - boolean canAccessAPI(RoleType roleType, String apiCommandName); +// APIChecker checks the ownership and access control to API requests +public interface APIChecker extends Adapter { + // Interface for checking access for a role using apiname + boolean checkAccess(RoleType roleType, String apiCommandName); + // Interface for checking existence of an api by name + boolean checkExistence(String apiCommandName); } diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index b779c860cc2..bb39839c820 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -53,7 +53,7 @@ under the License. true - + diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index d6bf3f63c74..740fbbc6456 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -29,13 +29,12 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static org.apache.cloudstack.acl.RoleType.*; import org.apache.log4j.Logger; // This is the default API access checker that grab's the user's account // based on the account type, access is granted -@Local(value=APIAccessChecker.class) -public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIAccessChecker { +@Local(value=APIChecker.class) +public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker { protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); @@ -50,10 +49,19 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIA } @Override - public boolean canAccessAPI(RoleType roleType, String commandName) { + public boolean checkAccess(RoleType roleType, String commandName) { return s_roleBasedApisMap.get(roleType).contains(commandName); } + @Override + public boolean checkExistence(String apiName) { + for (RoleType roleType: RoleType.values()) { + if (s_roleBasedApisMap.get(roleType).contains(apiName)) + return true; + } + return false; + } + @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index be3c08716cc..7663e8e724a 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -51,8 +51,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.cloud.utils.ReflectUtil; -import org.apache.cloudstack.acl.APIAccessChecker; -import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; @@ -146,8 +145,8 @@ public class ApiServer implements HttpRequestHandler { @Inject private DomainManager _domainMgr = null; @Inject private AsyncJobManager _asyncMgr = null; - @Inject(adapter = APIAccessChecker.class) - protected Adapters _apiAccessCheckers; + @Inject(adapter = APIChecker.class) + protected Adapters _apiAccessCheckers; private Account _systemAccount = null; private User _systemUser = null; @@ -558,7 +557,7 @@ public class ApiServer implements HttpRequestHandler { return true; } else { // check against every available command to see if the command exists or not - if (!isCommandAvailable(null, commandName) && !commandName.equals("login") && !commandName.equals("logout")) { + if (!doesCommandExist(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); } @@ -790,17 +789,25 @@ public class ApiServer implements HttpRequestHandler { return true; } - private boolean isCommandAvailable(User user, String commandName) - throws PermissionDeniedException { + private boolean doesCommandExist(String apiName) { + for (APIChecker apiChecker : _apiAccessCheckers) { + // If any checker has api info on the command, return true + if (apiChecker.checkExistence(apiName)) + return true; + } + return false; + } + + private boolean isCommandAvailable(User user, String commandName) { if (user == null) { return false; } Account account = _accountMgr.getAccount(user.getAccountId()); RoleType roleType = _accountMgr.getRoleType(account); - for (APIAccessChecker apiChecker : _apiAccessCheckers) { + for (APIChecker apiChecker : _apiAccessCheckers) { // Fail the checking if any checker fails to verify - if (!apiChecker.canAccessAPI(roleType, commandName)) + if (!apiChecker.checkAccess(roleType, commandName)) return false; } return true; From 3df026bd51da5f82aa4a4b99fd231ebaa31c6bba Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 18:50:57 -0800 Subject: [PATCH 23/92] ApiDiscoveryServiceImpl: Implement listApis to return response based on role Signed-off-by: Rohit Yadav --- .../discovery/ApiDiscoveryServiceImpl.java | 75 ++++++++++++++----- 1 file changed, 57 insertions(+), 18 deletions(-) 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 2bc17bdbf4d..9f4031c4769 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -16,8 +16,13 @@ // under the License. package org.apache.cloudstack.discovery; -import com.cloud.utils.PropertiesUtil; +import com.cloud.server.ManagementServer; import com.cloud.utils.ReflectUtil; +import com.cloud.utils.component.Adapters; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; +import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -42,30 +47,50 @@ import java.util.Set; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - private ListResponse _discoveryResponse = new ListResponse(); + private static Map _apiNameDiscoveryResponseMap = + new HashMap(); - private Map> _apiNameCmdClassMap = new HashMap>(); + private static Map> _roleTypeDiscoveryResponseListMap = + new HashMap>(); + + private static Map> _apiNameRoleTypeListMap = null; protected ApiDiscoveryServiceImpl() { super(); - generateApiNameCmdClassMap(); + for (RoleType roleType: RoleType.values()) + _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList()); cacheListApiResponse(); } - private void generateApiNameCmdClassMap() { - Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, - new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); - - for(Class cmdClass: cmdClasses) - _apiNameCmdClassMap.put(cmdClass.getAnnotation(APICommand.class).name(), cmdClass); + private Map> getApiNameRoleTypeListMap() { + Map> apiNameRoleTypeMap = new HashMap>(); + ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); + List services = locator.getAllPluggableServices(); + services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); + for (PluggableService service : services) { + for (Map.Entry entry: service.getProperties().entrySet()) { + String apiName = entry.getKey(); + String roleMask = entry.getValue(); + try { + short cmdPermissions = Short.parseShort(roleMask); + if (!apiNameRoleTypeMap.containsKey(apiName)) + apiNameRoleTypeMap.put(apiName, new ArrayList()); + for (RoleType roleType: RoleType.values()) { + if ((cmdPermissions & roleType.getValue()) != 0) + apiNameRoleTypeMap.get(apiName).add(roleType); + } + } catch (NumberFormatException nfe) { + } + } + } + return apiNameRoleTypeMap; } private void cacheListApiResponse() { + Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, + new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); - List apiDiscoveryResponses = new ArrayList(); - - for(String key: _apiNameCmdClassMap.keySet()) { - Class cmdClass = _apiNameCmdClassMap.get(key); + for(Class cmdClass: cmdClasses) { APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class); if (apiCmdAnnotation == null) apiCmdAnnotation = cmdClass.getSuperclass().getAnnotation(APICommand.class); @@ -74,8 +99,9 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { || apiCmdAnnotation.name().isEmpty()) continue; + String apiName = apiCmdAnnotation.name(); ApiDiscoveryResponse response = new ApiDiscoveryResponse(); - response.setName(apiCmdAnnotation.name()); + response.setName(apiName); response.setDescription(apiCmdAnnotation.description()); response.setSince(apiCmdAnnotation.since()); @@ -104,14 +130,27 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } } response.setObjectName("apis"); - apiDiscoveryResponses.add(response); + _apiNameDiscoveryResponseMap.put(apiName, response); } - _discoveryResponse.setResponses(apiDiscoveryResponses); } @Override public ListResponse listApis(RoleType roleType) { - return _discoveryResponse; + // Creates roles based response list cache the first time listApis is called + // Due to how adapters work, this cannot be done when mgmt loads + if (_apiNameRoleTypeListMap == null) { + _apiNameRoleTypeListMap = getApiNameRoleTypeListMap(); + for (Map.Entry> entry: _apiNameRoleTypeListMap.entrySet()) { + String apiName = entry.getKey(); + for (RoleType roleTypeInList: entry.getValue()) { + _roleTypeDiscoveryResponseListMap.get(roleTypeInList).add( + _apiNameDiscoveryResponseMap.get(apiName)); + } + } + } + ListResponse response = new ListResponse(); + response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType)); + return response; } @Override From f1700755586f427702391672e4d487b94813521c Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 22:48:56 -0800 Subject: [PATCH 24/92] ApiDiscovery: Fix response add response class that will hold api response Signed-off-by: Rohit Yadav --- .../api/response/ApiDiscoveryResponse.java | 26 +++++++++-- .../api/response/ApiParameterResponse.java | 11 +++++ .../api/response/ApiResponseResponse.java | 45 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiResponseResponse.java diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java index dd1298bfec5..de6a9f93965 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java @@ -16,18 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.user.Account; import org.apache.cloudstack.api.ApiConstants; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; -import org.apache.cloudstack.api.EntityReference; import java.util.HashSet; import java.util.Set; @SuppressWarnings("unused") -@EntityReference(value = Account.class) public class ApiDiscoveryResponse extends BaseResponse { @SerializedName(ApiConstants.NAME) @Param(description="the name of the api command") private String name; @@ -41,11 +38,18 @@ public class ApiDiscoveryResponse extends BaseResponse { @SerializedName(ApiConstants.IS_ASYNC) @Param(description="true if api is asynchronous") private Boolean isAsync; + @SerializedName("related") @Param(description="comma separated related apis") + private String related; + @SerializedName(ApiConstants.PARAMS) @Param(description="the list params the api accepts", responseObject = ApiParameterResponse.class) private Set params; + @SerializedName(ApiConstants.RESPONSE) @Param(description="api response fields", responseObject = ApiResponseResponse.class) + private Set apiResponse; + public ApiDiscoveryResponse(){ params = new HashSet(); + apiResponse = new HashSet(); isAsync = false; } @@ -65,6 +69,18 @@ public class ApiDiscoveryResponse extends BaseResponse { this.isAsync = isAsync; } + public String getRelated() { + return related; + } + + public void setRelated(String related) { + this.related = related; + } + + public Set getParams() { + return params; + } + public void setParams(Set params) { this.params = params; } @@ -72,4 +88,8 @@ public class ApiDiscoveryResponse extends BaseResponse { public void addParam(ApiParameterResponse param) { this.params.add(param); } + + public void addApiResponse(ApiResponseResponse apiResponse) { + this.apiResponse.add(apiResponse); + } } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiParameterResponse.java b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiParameterResponse.java index 9138288e102..fa6dc1752d2 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiParameterResponse.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiParameterResponse.java @@ -40,6 +40,9 @@ public class ApiParameterResponse extends BaseResponse { @SerializedName(ApiConstants.SINCE) @Param(description="version of CloudStack the api was introduced in") private String since; + @SerializedName("related") @Param(description="comma separated related apis to get the parameter") + private String related; + public ApiParameterResponse(){ } @@ -67,4 +70,12 @@ public class ApiParameterResponse extends BaseResponse { this.since = since; } + public String getRelated() { + return related; + } + + public void setRelated(String related) { + this.related = related; + } + } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiResponseResponse.java b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiResponseResponse.java new file mode 100644 index 00000000000..b96295e1290 --- /dev/null +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/response/ApiResponseResponse.java @@ -0,0 +1,45 @@ +// 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.response; + +import org.apache.cloudstack.api.ApiConstants; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponse; + +public class ApiResponseResponse extends BaseResponse { + @SerializedName(ApiConstants.NAME) @Param(description="the name of the api response field") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) @Param(description="description of the api response field") + private String description; + + @SerializedName(ApiConstants.TYPE) @Param(description="response field type") + private String type; + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setType(String type) { + this.type = type; + } +} From 86a77e29dc26fee1bb2169a9a1424bdd4e52f65e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 10 Jan 2013 22:52:10 -0800 Subject: [PATCH 25/92] ApiDiscovery: Fix listApis to return api response, related apis etc. - Fix method to return listApis per api name basis - Return api response, api related cmd etc. as part of response - Caching and processing all cmd, response classes when plugin starts, made class list, maps static so they are shared by multiple instances in case, takes about 1306ms to do the processsing but only on load time - Cache for first listApi() and return precached data thereon, takes 2.2ms for first call, during runtime and 0ms thereon Signed-off-by: Rohit Yadav --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../command/user/discovery/ListApisCmd.java | 22 ++-- .../discovery/ApiDiscoveryService.java | 2 +- .../discovery/ApiDiscoveryServiceImpl.java | 102 +++++++++++++++--- 4 files changed, 103 insertions(+), 24 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index b4ce24c2bc9..d3bfcd66afc 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -158,6 +158,7 @@ public class ApiConstants { public static final String RECEIVED_BYTES = "receivedbytes"; public static final String REQUIRES_HVM = "requireshvm"; public static final String RESOURCE_TYPE = "resourcetype"; + public static final String RESPONSE = "response"; public static final String QUERY_FILTER = "queryfilter"; public static final String SCHEDULE = "schedule"; public static final String SCOPE = "scope"; diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index feab20ac5cf..ed3e1751027 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,12 +16,12 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; -import com.cloud.user.Account; import com.cloud.user.UserContext; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.PlugService; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ListResponse; @@ -30,8 +30,8 @@ import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.log4j.Logger; -@APICommand(name = "listApis", responseObject = ApiDiscoveryResponse.class, description = "lists all available apis on the server, provided by Api Discovery plugin", since = "4.1.0") -public class ListApisCmd extends BaseListCmd { +@APICommand(name = "listApis", responseObject = ApiDiscoveryResponse.class, description = "lists all available apis on the server, provided by the Api Discovery plugin", since = "4.1.0") +public class ListApisCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(ListApisCmd.class.getName()); private static final String s_name = "listapisresponse"; @@ -39,14 +39,16 @@ public class ListApisCmd extends BaseListCmd { @PlugService ApiDiscoveryService _apiDiscoveryService; + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="API name") + private String name; + @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - Account caller = UserContext.current().getCaller(); RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller()); - ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType); + ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType, name); if (response == null) { - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find and process any apis"); + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find an api by that name or process any apis"); } response.setResponseName(getCommandName()); this.setResponseObject(response); @@ -57,4 +59,10 @@ public class ListApisCmd extends BaseListCmd { public String getCommandName() { return s_name; } + + @Override + public long getEntityOwnerId() { + // no owner is needed for list command + return 0; + } } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index a1d440e9ccf..611493bfc08 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -22,5 +22,5 @@ import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; public interface ApiDiscoveryService extends PluggableService { - ListResponse listApis(RoleType roleType); + ListResponse listApis(RoleType roleType, String apiName); } 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 9f4031c4769..5f84486ae49 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -16,13 +16,13 @@ // under the License. package org.apache.cloudstack.discovery; +import com.cloud.serializer.Param; import com.cloud.server.ManagementServer; import com.cloud.utils.ReflectUtil; -import com.cloud.utils.component.Adapters; +import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentLocator; -import com.cloud.utils.component.Inject; import com.cloud.utils.component.PluggableService; -import org.apache.cloudstack.acl.APIChecker; +import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -32,6 +32,7 @@ import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.cloudstack.api.response.ApiParameterResponse; +import org.apache.cloudstack.api.response.ApiResponseResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.log4j.Logger; @@ -39,6 +40,7 @@ import javax.ejb.Local; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,19 +49,24 @@ import java.util.Set; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); + private static Map> _roleTypeDiscoveryResponseListMap; + private static Map _apiNameDiscoveryResponseMap = new HashMap(); - private static Map> _roleTypeDiscoveryResponseListMap = - new HashMap>(); - private static Map> _apiNameRoleTypeListMap = null; protected ApiDiscoveryServiceImpl() { super(); - for (RoleType roleType: RoleType.values()) - _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList()); - cacheListApiResponse(); + if (_roleTypeDiscoveryResponseListMap == null) { + long startTime = System.nanoTime(); + _roleTypeDiscoveryResponseListMap = new HashMap>(); + for (RoleType roleType: RoleType.values()) + _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList()); + cacheResponseMap(); + long endTime = System.nanoTime(); + s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms"); + } } private Map> getApiNameRoleTypeListMap() { @@ -86,10 +93,12 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { return apiNameRoleTypeMap; } - private void cacheListApiResponse() { + private void cacheResponseMap() { Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + Map> responseApiNameListMap = new HashMap>(); + for(Class cmdClass: cmdClasses) { APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class); if (apiCmdAnnotation == null) @@ -100,10 +109,32 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { continue; String apiName = apiCmdAnnotation.name(); + String responseName = apiCmdAnnotation.responseObject().getName(); + if (!responseName.contains("SuccessResponse")) { + if (!responseApiNameListMap.containsKey(responseName)) + responseApiNameListMap.put(responseName, new ArrayList()); + responseApiNameListMap.get(responseName).add(apiName); + } ApiDiscoveryResponse response = new ApiDiscoveryResponse(); response.setName(apiName); response.setDescription(apiCmdAnnotation.description()); - response.setSince(apiCmdAnnotation.since()); + if (!apiCmdAnnotation.since().isEmpty()) + response.setSince(apiCmdAnnotation.since()); + response.setRelated(responseName); + + Field[] responseFields = apiCmdAnnotation.responseObject().getDeclaredFields(); + for(Field responseField: responseFields) { + SerializedName serializedName = responseField.getAnnotation(SerializedName.class); + if(serializedName != null) { + ApiResponseResponse responseResponse = new ApiResponseResponse(); + responseResponse.setName(serializedName.value()); + Param param = responseField.getAnnotation(Param.class); + if (param != null) + responseResponse.setDescription(param.description()); + responseResponse.setType(responseField.getType().getSimpleName().toLowerCase()); + response.addApiResponse(responseResponse); + } + } Field[] fields = ReflectUtil.getAllFieldsForClass(cmdClass, new Class[] {BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); @@ -122,23 +153,50 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { ApiParameterResponse paramResponse = new ApiParameterResponse(); paramResponse.setName(parameterAnnotation.name()); paramResponse.setDescription(parameterAnnotation.description()); - paramResponse.setType(parameterAnnotation.type().toString()); + paramResponse.setType(parameterAnnotation.type().toString().toLowerCase()); paramResponse.setLength(parameterAnnotation.length()); paramResponse.setRequired(parameterAnnotation.required()); - paramResponse.setSince(parameterAnnotation.since()); + if (!parameterAnnotation.since().isEmpty()) + paramResponse.setSince(parameterAnnotation.since()); + paramResponse.setRelated(parameterAnnotation.entityType()[0].getName()); response.addParam(paramResponse); } } - response.setObjectName("apis"); + response.setObjectName("api"); + _apiNameDiscoveryResponseMap.put(apiName, response); + } + + for (String apiName: _apiNameDiscoveryResponseMap.keySet()) { + ApiDiscoveryResponse response = _apiNameDiscoveryResponseMap.get(apiName); + Set processedParams = new HashSet(); + for (ApiParameterResponse param: response.getParams()) { + if (responseApiNameListMap.containsKey(param.getRelated())) { + List relatedApis = responseApiNameListMap.get(param.getRelated()); + param.setRelated(StringUtils.join(relatedApis, ",")); + } else { + param.setRelated(null); + } + processedParams.add(param); + } + response.setParams(processedParams); + + if (responseApiNameListMap.containsKey(response.getRelated())) { + List relatedApis = responseApiNameListMap.get(response.getRelated()); + relatedApis.remove(apiName); + response.setRelated(StringUtils.join(relatedApis, ",")); + } else { + response.setRelated(null); + } _apiNameDiscoveryResponseMap.put(apiName, response); } } @Override - public ListResponse listApis(RoleType roleType) { + public ListResponse listApis(RoleType roleType, String name) { // Creates roles based response list cache the first time listApis is called // Due to how adapters work, this cannot be done when mgmt loads if (_apiNameRoleTypeListMap == null) { + long startTime = System.nanoTime(); _apiNameRoleTypeListMap = getApiNameRoleTypeListMap(); for (Map.Entry> entry: _apiNameRoleTypeListMap.entrySet()) { String apiName = entry.getKey(); @@ -147,9 +205,21 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { _apiNameDiscoveryResponseMap.get(apiName)); } } + long endTime = System.nanoTime(); + s_logger.info("Api Discovery Service: List apis cached in " + (endTime - startTime) / 1000000.0 + " ms"); } ListResponse response = new ListResponse(); - response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType)); + if (name != null) { + if (!_apiNameDiscoveryResponseMap.containsKey(name)) + return null; + + List singleResponse = new ArrayList(); + singleResponse.add(_apiNameDiscoveryResponseMap.get(name)); + response.setResponses(singleResponse); + + } else { + response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType)); + } return response; } From 2bc3b5cc6f3815be29649741ac62b4c8f6cd7016 Mon Sep 17 00:00:00 2001 From: Jessica Tomechak Date: Fri, 11 Jan 2013 00:50:23 -0800 Subject: [PATCH 26/92] Docs. CLOUDSTACK-959. A sub-heading was inadvertently left out of the System Service Offerings section of documentation. Adding the section "Creating a New System Service Offering". --- docs/en-US/system-service-offerings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en-US/system-service-offerings.xml b/docs/en-US/system-service-offerings.xml index c41aa2e293b..84d5f7ae7b5 100644 --- a/docs/en-US/system-service-offerings.xml +++ b/docs/en-US/system-service-offerings.xml @@ -26,4 +26,5 @@ System Service Offerings System service offerings provide a choice of CPU speed, number of CPUs, tags, and RAM size, just as other service offerings do. But rather than being used for virtual machine instances and exposed to users, system service offerings are used to change the default properties of virtual routers, console proxies, and other system VMs. System service offerings are visible only to the &PRODUCT; root administrator. &PRODUCT; provides default system service offerings. The &PRODUCT; root administrator can create additional custom system service offerings. When &PRODUCT; creates a virtual router for a guest network, it uses default settings which are defined in the system service offering associated with the network offering. You can upgrade the capabilities of the virtual router by applying a new network offering that contains a different system service offering. All virtual routers in that network will begin using the settings from the new service offering. + From 5f19c45e0401bd380e15af26d5c9d1e03d77795d Mon Sep 17 00:00:00 2001 From: Sebastien Goasguen Date: Fri, 11 Jan 2013 10:55:37 +0100 Subject: [PATCH 27/92] Added Marvin building docs in developer guide --- docs/en-US/building-marvin.xml | 46 ++++++++++++++++++++++++++++++++++ docs/en-US/marvin.xml | 1 + 2 files changed, 47 insertions(+) create mode 100644 docs/en-US/building-marvin.xml diff --git a/docs/en-US/building-marvin.xml b/docs/en-US/building-marvin.xml new file mode 100644 index 00000000000..3dac9d65d60 --- /dev/null +++ b/docs/en-US/building-marvin.xml @@ -0,0 +1,46 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Building and Installing Marvin + Marvin is built with Maven and is dependent on APIdoc. To build it do the following in the root tree of &PRODUCT;: + mvn -P developer -l :cloud-apidoc + mvn -P developer -l :cloud-marvin + If successfull the build will have created the cloudstackAPI Python package under tools/marvin/marvin/cloudstackAPI as well as a gziped Marvin package under tools/marvin dist. To install the Python Marvin module do the following in tools/marvin: + sudo python ./setup.py install + The dependencies will be downloaded the Python module installed and you should be able to use Marvin in Python. Check that you can import the module before starting to use it. + $ python +Python 2.7.3 (default, Nov 17 2012, 19:54:34) +[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> import marvin +>>> from marvin.cloudstackAPI import * +>>> + + You could also install it using pip or easy_install using the local distribution package in tools/marvin/dist : + pip install tools/marvin/dist/Marvin-0.1.0.tar.gz + Or: + easy_install tools/marvin/dist/Marvin-0.1.0.tar.gz + +
diff --git a/docs/en-US/marvin.xml b/docs/en-US/marvin.xml index 062616ac888..8fd2c96fe3f 100644 --- a/docs/en-US/marvin.xml +++ b/docs/en-US/marvin.xml @@ -29,4 +29,5 @@ Marvin's complete documenation is on the wiki at https://cwiki.apache.org/CLOUDSTACK/testing-with-python.html The source code is located at tools/marvin + From 5dd14f322c7332ebb5b9aee22f84209763e891e8 Mon Sep 17 00:00:00 2001 From: Author Name Date: Fri, 11 Jan 2013 15:45:18 +0530 Subject: [PATCH 28/92] --- .../external-guest-firewall-integration.xml | 53 +++--- docs/en-US/external-guest-lb-integration.xml | 4 +- docs/en-US/hardware-firewall.xml | 9 +- docs/en-US/images/add-netscaler.png | Bin 0 -> 22777 bytes docs/en-US/images/parallel-inline-mode.png | Bin 0 -> 145392 bytes docs/en-US/inline-config-lb-fw.xml | 173 ++++++++++++++++++ docs/en-US/lb-services.xml | 25 +++ docs/en-US/management-server-lb.xml | 12 +- docs/en-US/network-setup.xml | 12 +- 9 files changed, 240 insertions(+), 48 deletions(-) create mode 100644 docs/en-US/images/add-netscaler.png create mode 100644 docs/en-US/images/parallel-inline-mode.png create mode 100644 docs/en-US/inline-config-lb-fw.xml create mode 100644 docs/en-US/lb-services.xml diff --git a/docs/en-US/external-guest-firewall-integration.xml b/docs/en-US/external-guest-firewall-integration.xml index 0b34dca1065..bd9ac604970 100644 --- a/docs/en-US/external-guest-firewall-integration.xml +++ b/docs/en-US/external-guest-firewall-integration.xml @@ -21,23 +21,16 @@
External Guest Firewall Integration for Juniper SRX (Optional) - Available only for guests using advanced networking. + Available only for guests using advanced networking, both shared and isolated. &PRODUCT; provides for direct management of the Juniper SRX series of firewalls. This - enables &PRODUCT; to establish static NAT mappings from public IPs to guest VMs, and to use - the Juniper device in place of the virtual router for firewall services. You can have one or - more Juniper SRX per zone. This feature is optional. If Juniper integration is not provisioned, - &PRODUCT; will use the virtual router for these services. + enables &PRODUCT; to establish staticNAT mappings from public IPs to guest VMs, and to use the + Juniper device in place of the virtual router for firewall services. You can have only one + Juniper SRX device per zone. This feature is optional. If Juniper integration is not + provisioned, &PRODUCT; will use the virtual router for these services. The Juniper SRX can optionally be used in conjunction with an external load balancer. - External Network elements can be deployed in a side-by-side or inline configuration. - - - - - - parallel-mode.png: adding a firewall and load balancer in parallel mode. - - + External Network elements can be deployed in a side-by-side or inline configuration. For more + information, see . &PRODUCT; requires the Juniper to be configured as follows: Supported SRX software version is 10.3 or higher. @@ -58,22 +51,22 @@ Record the public and private interface names. If you used a VLAN for the public interface, add a ".[VLAN TAG]" after the interface name. For example, if you are using ge-0/0/3 for your public interface and VLAN tag 301, your public interface name would be - "ge-0/0/3.301". Your private interface name should always be untagged because the - &PRODUCT; software automatically creates tagged logical interfaces. + "ge-0/0/3.301". Your private interface name should always be untagged because the &PRODUCT; + software automatically creates tagged logical interfaces. - Create a public security zone and a private security zone. By default, these will - already exist and will be called "untrust" and "trust". Add the public interface to the - public zone and the private interface to the private zone. Note down the security zone - names. + Create a public security zone and a private security zone. By default, these already + exist and are called "untrust" and "trust" zones. Add the public interface to the public + zone. &PRODUCT;automatically adds the private interface to private zone (trusted zone). Note + down the security zone names. Make sure there is a security policy from the private zone to the public zone that allows all traffic. - Note the username and password of the account you want the &PRODUCT; software to log - in to when it is programming rules. + Note the username and password of the account you want the &PRODUCT; software to log in + to when it is programming rules. Make sure the "ssh" and "xnm-clear-text" system services are enabled. @@ -124,13 +117,13 @@ filter untrust { In the left navigation bar, click Infrastructure. - In Zones, click View More. + In Zones, click View All. Choose the zone you want to work with. - Click the Network tab. + Click the Physical Network tab. In the Network Service Providers node of the diagram, click Configure. (You might have @@ -159,10 +152,6 @@ filter untrust { Private Interface: The name of the private interface on the SRX. For example, ge-0/0/1. - - Usage Interface: (Optional) Typically, the public interface is used to meter - traffic. If you want to use a different interface, specify its name here - Number of Retries: The number of times to attempt a command on the SRX before failing. The default value is 2. @@ -180,12 +169,12 @@ filter untrust { untrust. - Capacity: The number of networks the device can handle + Capacity: The number of networks the device can handle. Dedicated: When marked as dedicated, this device will be dedicated to a single account. When Dedicated is checked, the value in the Capacity field has no significance - implicitly, its value is 1 + implicitly, its value is 1. @@ -194,8 +183,8 @@ filter untrust { Click Global Settings. Set the parameter external.network.stats.interval to indicate how - often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you - are not using the SRX to gather network usage statistics, set to 0. + often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you are + not using the SRX to gather network usage statistics, set to 0.
diff --git a/docs/en-US/external-guest-lb-integration.xml b/docs/en-US/external-guest-lb-integration.xml index 5760f9559e6..acbb514207c 100644 --- a/docs/en-US/external-guest-lb-integration.xml +++ b/docs/en-US/external-guest-lb-integration.xml @@ -20,10 +20,12 @@ -->
External Guest Load Balancer Integration (Optional) + + External load balancer devices are not supported in shared networks. + &PRODUCT; can optionally use a Citrix NetScaler or BigIP F5 load balancer to provide load balancing services to guests. If this is not enabled, &PRODUCT; will use the software load balancer in the virtual router. - To install and enable an external load balancer for &PRODUCT; management: Set up the appliance according to the vendor's directions. diff --git a/docs/en-US/hardware-firewall.xml b/docs/en-US/hardware-firewall.xml index df0568aa2c2..28269cccf31 100644 --- a/docs/en-US/hardware-firewall.xml +++ b/docs/en-US/hardware-firewall.xml @@ -22,8 +22,11 @@ Hardware Firewall All deployments should have a firewall protecting the management server; see Generic Firewall Provisions. Optionally, some deployments may also have a Juniper SRX firewall that will - be the default gateway for the guest networks; see . + be the default gateway for the guest networks; see . - - + + +
diff --git a/docs/en-US/images/add-netscaler.png b/docs/en-US/images/add-netscaler.png new file mode 100644 index 0000000000000000000000000000000000000000..53c1344b9ddd49bebc276af347206ba97948b428 GIT binary patch literal 22777 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 W{~Om+ralt@KQ$%IyX6WNf&T^X{FKQ6 literal 0 HcmV?d00001 diff --git a/docs/en-US/images/parallel-inline-mode.png b/docs/en-US/images/parallel-inline-mode.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c1555365ec7fad20412bbe8d605ea2739c12e0 GIT binary patch literal 145392 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 + +%BOOK_ENTITIES; +]> + +
+ Configuring Network Devices in Inline and Side by Side Modes + The external network elements, such as load balancer and firewall devices, supported in + &PRODUCT; can be deployed in either of the following modes: Side by Side and Inline. Inline mode + was originally supported in &PRODUCT; 2.2.x versions, and is now added back in the 3.0.6 + release. + In Inline mode, one firewall device is placed in front of a load balancing device. The + firewall acts as the gateway for all incoming traffic, then redirect the load balancing traffic + to the load balancer behind it. The load balancer in this case will not have the direct access + to the public network. Deploying network devices in Inline mode ensures that the resources are + protected. + + + + + + parallel-inline-mode.png: external networks in different deployment modes + + + In Side by Side mode, a firewall device is deployed in parallel with the load balancer + device. So the traffic to the load balancer public IP is not routed through the firewall, and + therefore, is exposed to the public network. + + + + + + parallel-mode.png: adding a firewall and load balancer in side by side mode + + + The following table gives you an overview of the supported services and devices for inline + and side by side mode. + + + + + + + + + Mode + Firewall + Load Balancer + Supported + + + + + Side by Side + Virtual Router + F5 + Yes + + + Side by Side + Virtual Router + Virtual Router + Yes + + + Side by Side + Virtual Router + NetScaler + Yes + + + Side by Side + Juniper SRX + F5 + Yes + + + Side by Side + Juniper SRX + NetScaler + Yes + + + Inline + Virtual Router + F5 + No + + + Inline + Virtual Router + NetScaler + No + + + Inline + Juniper SRX + F5 + Yes + + + Inline + Juniper SRX + NetScaler + No + + + Inline + Juniper SRX + Virtual Router + No + + + + + To configure SRX and F5 in Inline mode: + + + Configure F5 Big IP and Juniper SRX. + See the respective product documentation for more information. + + + Add SRX and F5 to the same zone in &PRODUCT;. + + Ensure that you select per zone sourceNAT when creating the network offering. When + adding F5 BigIP, do not make it a dedicated device. + + + + Enable both the devices. + + + Create a network offering: + Use SRX as provider for Firewall, Port Forwarding, SourceNAT, and StaticNat. Select F5 + BigIP as the service provider for Load Balancing. Use Virtual Router as the service provider + for DNS, DHCP, user data. + + + Select Inline mode. + For more information, see . + Creating Network Offerings in the Administration Guide. + + + + Start a new VM with this new network offering. + + + Add firewall and load balancing rules. For more information, see + Adding a Load Balancer Rule and . + IP Forwarding and Firewalling in the Administration + Guide. + + + +
diff --git a/docs/en-US/lb-services.xml b/docs/en-US/lb-services.xml new file mode 100644 index 00000000000..3bb79dbd335 --- /dev/null +++ b/docs/en-US/lb-services.xml @@ -0,0 +1,25 @@ + + +%BOOK_ENTITIES; +]> + +
+ Load Balancing Services + + +
diff --git a/docs/en-US/management-server-lb.xml b/docs/en-US/management-server-lb.xml index 85a86221c80..f4275786be7 100644 --- a/docs/en-US/management-server-lb.xml +++ b/docs/en-US/management-server-lb.xml @@ -19,12 +19,12 @@ under the License. -->
- Setting Zone VLAN and Running VM Maximums - &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management - Servers. The administrator is responsible for creating the load balancer rules for the - Management Servers. The application requires persistence or stickiness across multiple sessions. - The following chart lists the ports that should be load balanced and whether or not persistence - is required. + Management Server Load Balancing + &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management Servers. + The administrator is responsible for creating the load balancer rules for the Management + Servers. The application requires persistence or stickiness across multiple sessions. The + following chart lists the ports that should be load balanced and whether or not persistence is + required. Even if persistence is not required, enabling it is permitted. diff --git a/docs/en-US/network-setup.xml b/docs/en-US/network-setup.xml index ceee190d4ca..192c8e23d2f 100644 --- a/docs/en-US/network-setup.xml +++ b/docs/en-US/network-setup.xml @@ -20,16 +20,16 @@ --> Network Setup - Achieving the correct networking setup is crucial to a successful &PRODUCT; - installation. This section contains information to help you make decisions and follow the right - procedures to get your network set up correctly. + Achieving the correct networking setup is crucial to a successful &PRODUCT; installation. + This section contains information to help you make decisions and follow the right procedures to + get your network set up correctly. - - + - + From bb59c1e38529ac704eedc0b9ebd759313e60532d Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Fri, 11 Jan 2013 15:51:28 +0530 Subject: [PATCH 29/92] Revert "" This reverts commit 5dd14f322c7332ebb5b9aee22f84209763e891e8. --- .../external-guest-firewall-integration.xml | 53 +++--- docs/en-US/external-guest-lb-integration.xml | 4 +- docs/en-US/hardware-firewall.xml | 9 +- docs/en-US/images/add-netscaler.png | Bin 22777 -> 0 bytes docs/en-US/images/parallel-inline-mode.png | Bin 145392 -> 0 bytes docs/en-US/inline-config-lb-fw.xml | 173 ------------------ docs/en-US/lb-services.xml | 25 --- docs/en-US/management-server-lb.xml | 12 +- docs/en-US/network-setup.xml | 12 +- 9 files changed, 48 insertions(+), 240 deletions(-) delete mode 100644 docs/en-US/images/add-netscaler.png delete mode 100644 docs/en-US/images/parallel-inline-mode.png delete mode 100644 docs/en-US/inline-config-lb-fw.xml delete mode 100644 docs/en-US/lb-services.xml diff --git a/docs/en-US/external-guest-firewall-integration.xml b/docs/en-US/external-guest-firewall-integration.xml index bd9ac604970..0b34dca1065 100644 --- a/docs/en-US/external-guest-firewall-integration.xml +++ b/docs/en-US/external-guest-firewall-integration.xml @@ -21,16 +21,23 @@
External Guest Firewall Integration for Juniper SRX (Optional) - Available only for guests using advanced networking, both shared and isolated. + Available only for guests using advanced networking. &PRODUCT; provides for direct management of the Juniper SRX series of firewalls. This - enables &PRODUCT; to establish staticNAT mappings from public IPs to guest VMs, and to use the - Juniper device in place of the virtual router for firewall services. You can have only one - Juniper SRX device per zone. This feature is optional. If Juniper integration is not - provisioned, &PRODUCT; will use the virtual router for these services. + enables &PRODUCT; to establish static NAT mappings from public IPs to guest VMs, and to use + the Juniper device in place of the virtual router for firewall services. You can have one or + more Juniper SRX per zone. This feature is optional. If Juniper integration is not provisioned, + &PRODUCT; will use the virtual router for these services. The Juniper SRX can optionally be used in conjunction with an external load balancer. - External Network elements can be deployed in a side-by-side or inline configuration. For more - information, see . + External Network elements can be deployed in a side-by-side or inline configuration. + + + + + + parallel-mode.png: adding a firewall and load balancer in parallel mode. + + &PRODUCT; requires the Juniper to be configured as follows: Supported SRX software version is 10.3 or higher. @@ -51,22 +58,22 @@ Record the public and private interface names. If you used a VLAN for the public interface, add a ".[VLAN TAG]" after the interface name. For example, if you are using ge-0/0/3 for your public interface and VLAN tag 301, your public interface name would be - "ge-0/0/3.301". Your private interface name should always be untagged because the &PRODUCT; - software automatically creates tagged logical interfaces. + "ge-0/0/3.301". Your private interface name should always be untagged because the + &PRODUCT; software automatically creates tagged logical interfaces. - Create a public security zone and a private security zone. By default, these already - exist and are called "untrust" and "trust" zones. Add the public interface to the public - zone. &PRODUCT;automatically adds the private interface to private zone (trusted zone). Note - down the security zone names. + Create a public security zone and a private security zone. By default, these will + already exist and will be called "untrust" and "trust". Add the public interface to the + public zone and the private interface to the private zone. Note down the security zone + names. Make sure there is a security policy from the private zone to the public zone that allows all traffic. - Note the username and password of the account you want the &PRODUCT; software to log in - to when it is programming rules. + Note the username and password of the account you want the &PRODUCT; software to log + in to when it is programming rules. Make sure the "ssh" and "xnm-clear-text" system services are enabled. @@ -117,13 +124,13 @@ filter untrust { In the left navigation bar, click Infrastructure. - In Zones, click View All. + In Zones, click View More. Choose the zone you want to work with. - Click the Physical Network tab. + Click the Network tab. In the Network Service Providers node of the diagram, click Configure. (You might have @@ -152,6 +159,10 @@ filter untrust { Private Interface: The name of the private interface on the SRX. For example, ge-0/0/1. + + Usage Interface: (Optional) Typically, the public interface is used to meter + traffic. If you want to use a different interface, specify its name here + Number of Retries: The number of times to attempt a command on the SRX before failing. The default value is 2. @@ -169,12 +180,12 @@ filter untrust { untrust. - Capacity: The number of networks the device can handle. + Capacity: The number of networks the device can handle Dedicated: When marked as dedicated, this device will be dedicated to a single account. When Dedicated is checked, the value in the Capacity field has no significance - implicitly, its value is 1. + implicitly, its value is 1 @@ -183,8 +194,8 @@ filter untrust { Click Global Settings. Set the parameter external.network.stats.interval to indicate how - often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you are - not using the SRX to gather network usage statistics, set to 0. + often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you + are not using the SRX to gather network usage statistics, set to 0.
diff --git a/docs/en-US/external-guest-lb-integration.xml b/docs/en-US/external-guest-lb-integration.xml index acbb514207c..5760f9559e6 100644 --- a/docs/en-US/external-guest-lb-integration.xml +++ b/docs/en-US/external-guest-lb-integration.xml @@ -20,12 +20,10 @@ -->
External Guest Load Balancer Integration (Optional) - - External load balancer devices are not supported in shared networks. - &PRODUCT; can optionally use a Citrix NetScaler or BigIP F5 load balancer to provide load balancing services to guests. If this is not enabled, &PRODUCT; will use the software load balancer in the virtual router. + To install and enable an external load balancer for &PRODUCT; management: Set up the appliance according to the vendor's directions. diff --git a/docs/en-US/hardware-firewall.xml b/docs/en-US/hardware-firewall.xml index 28269cccf31..df0568aa2c2 100644 --- a/docs/en-US/hardware-firewall.xml +++ b/docs/en-US/hardware-firewall.xml @@ -22,11 +22,8 @@ Hardware Firewall All deployments should have a firewall protecting the management server; see Generic Firewall Provisions. Optionally, some deployments may also have a Juniper SRX firewall that will - be the default gateway for the guest networks; see . + be the default gateway for the guest networks; see . - - - + +
diff --git a/docs/en-US/images/add-netscaler.png b/docs/en-US/images/add-netscaler.png deleted file mode 100644 index 53c1344b9ddd49bebc276af347206ba97948b428..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22777 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 W{~Om+ralt@KQ$%IyX6WNf&T^X{FKQ6 diff --git a/docs/en-US/images/parallel-inline-mode.png b/docs/en-US/images/parallel-inline-mode.png deleted file mode 100644 index c0c1555365ec7fad20412bbe8d605ea2739c12e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145392 zcmV(}K+wO5P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T4T38z``G z6KvU|pu4Il+BS}Wuq8RjmKCh<^zzL)=N!&Cx96ODe(U$`@3;2vTruiDbnZLv{KDRA zuQkIrzd6_1YfruIb+5ZOH8oZI2Y=&@{mjqL<7Iqz@7}$!_x`#6;#fasdV0F|-oIb8 zXwg`E{`uV8TpaJ`p?&m&uU9WjFSJh>1Fnxg;oAP!uZKRP-$U2)>!a`9cB_xxrhkrW zai8!S$Dj@W>z_f!I8OV4V}|sB;}_Bsw~I0PU+x3+#(m`1+()#5e(`(O8RX8_hwNMS zrPpTtuv}R#K6ch8^vkw{*K7xBPtYyfDcZ$%YU@M#Vq0L}fE}p5{dkNC*J6FZM|iBP zbBu-c314Vk3*WIVz$RG^Y@a+1#tOEYRR)k(3wKz5YMc5U+Yyhsb)M>& zWi=!>K1ci9vZ0op>vhy-`Fple)w#;B)&G{BfCsF9$f{*)Y+tZn#R0_vzpmRd+geK& z?7Oge_1F8sPsNN$IN6fhknFe}*0=VFeWn!`I1XUUL*v!HKptv)IG^o@^}^qCpH!cW z(-=of&+7jiSI`H1rhU_Es*cqcS=RpD^o9)^J{m8KKyWZZ!>m*VEewACo`LUF7mQnN z@Ok*2ft){MV^(MI>uEseYqB7ap8OR8`clx#MfXl+|mK}kL|N%tLoc4cEvB&K?}RlSGG&WF8-d!-O>m5i+!^d zAK1^;PS8)531iLu;#@1HwB)IH+Oi+kFUHR2VGQh>>MuO5A$*3cSdVHCiv280|BkVY z{eH)*8(53598vt)u`3rSY`~2 z9BdhYhX8L#rrb^|n6T0FbyyGe7z^A%oRdU4XK8_rf&o`&T6U?XO`(APMoI~jVjMA-^1~&PbG0JJ!$63b`6rxm1V`)R-0-!EL+GFZF9ee zhRp}~pb@-u<&CPdZ#D#vCMEj(D3Hdl@wBHz8 z&S>hmS!dc$fExdeN}5aqs{FYM(bBsgk3;}%x32Bqam5qY(E!{c_^okiUov|06Z#xIlVrF zk$#N-Fpep?VtitI)G_-t*oJV;A^+j?$MDR8BV!eG-pZ~yaJJ;ol7R**55~A2W1-p_ z%idojCbe(_cE7q0NAo^Tzuf$)DMm5HU$i^ic=98Q^x z;UKJ>meN`Pr{FzinCZwZLsW1b0?VO5u7<`61;{d}YS3r_<&f})WW(b{|62~g-|1`Z zH_NI8kSvd(OcVwJIkaSj&saw28-qMM9+R%AMIDeMs0>{LeQ5!n>XzFG@H2<5&Xr*3 z$H1}SRIO~Q<*@D~>}V{XRzR85Kj@z22VFvr?5He9wH361akPjDfSLUkV}y)!%seLb zH^l?hAKSbh%fJdbXppP^WlD6i$Fjt+8q~Q`!`Ov$XJ==7?Lb~kuv*71WTWUS_owB1 zI8Kwop4>BwtmCDisXoVgZ?%b_2)XF=KlIzO^)Y>CKiF23Ttem=IN@_Gn_%B#yN0i^ z>@l7eMlzNT`2h%#x6`UZY20G_2VM=~bL;wygBmXwV_We}aTPLzJXm)crx-W*rcSJZZOBnLP_VqwZ}eeO(B*6Kb;k5Z3%D8F>v6Ug$N`G05b9_E8D6KtI$^NG z*s4CgeaiBgo$L5uzv}dQ9Ig!=dEeQNv_C`gWJgo`N3~IPtU6T?W$q`HH-^b73nf=A%wfD_8MP7}mhX_wu}`55u1JUN2x0T@ zmEiVt*q@27YaKa=!#-HPm{#%QIDu)&f#s<|m~Fac4?}T_uhWVrExdt@*>5;53=xx- zZUSE^iEH@+ND%36}Q;t@LFx5MVhofrJHgpw%Q=Dx-?gj}jVSVqu4oVtQXW3G}NssbNMqULxY zpggXY>{Ng1HBZ1NzGu4gef|VNwG-W#DOnh{{>* z3p#4q0PM#51e;SJLHk1>-22?umQfiWz8wHc>vYtv*k9u~tT-lxb8@7_tL0xkJTP6m z9GP%wFk+19*<&V1t#k1i`Uaa&fL0q*JwiS_)v2UIg9dDceKq7pL0-@4$sjK_MvSED z!}im{6%Ahep8Li)0RLl~;PF5nJtF2hq`O^N=ju1`)ryg6mx>?U24pjad6bZ;JUMA@ z*|*2WUOa1bp!L1lS_@a%FV&vLzs9l&tV@JS8IG27lSS9itP=7 z1O35wJa)!{9!B^)wEaWyU~uFrn77qRYB-oEe^I~XwtGayzF=TO|8UnCV^@e>5}()?7#IC>mJg2|!3W1E2Jl^;E#gu2E&|4Qk)VKtGN!Q1H7N0M zu$8dmBplrDUi@%+8PAoV*hO> z_>>_k4zX_F?;6`$)dsa0wHw9*)fa3=b;^BXa>MqFzD-Yc>twheipx3^qPEiVJK#>$ zi`gev>CrE?BfakQ#*G_4$_lFikQSY>kO5WtiEQJ{c~%0|i1hHg*~i zjxmR$xog%Fsz$B;GVw9`&?7o6M+{vhQ?BK2*$ZeWbE-PeegZf{ZYf{3LtKm7iy)H0 zlQTB8Uj;4bS?!nKv;8QrslBRRIh#g1Euafvk@Yov%X7`_NJbb7`w9C40|5gW##RYx z>WvAF%A@D=3oJl|e)OD>4P{eGI*`Dyz29%2phw85*S4?araJ&NFju0IRSOPwtWWL> zNW!GVNpTdo2tQ|Ato@@qHG4sNVET%2N-=|N0mlvX*U#-$52A?E-J!`C%`#Bk#5K}r z{o1YIi_d}2L00UapBwn-l{cF{pBnYUeFqgsjKpYh#10ReiclWWg$5TQN!#8uX3h1^T3{3OT=*e@%o)q&2c$2V)M#2|wg3=!=q;ZPw$Fx(Ck zApd-9&4wM|^PAddTnon|D@5BpfbdwEeU9@8NZ5cGT&tmzaC`kGOT9PMl@a3_X@JqM z1SV88)Y#cjFrEOy%xZe8#(7Fhy(Hha^crLGxpojukcK38EEl$go*^daw95Y6?+S*b zGqw?Q8@g#ZnaU`Rp{!XmQa-){Xztkp`L>SHv1(=$-*c%x$$D$e4%@YlkwG@bjA>8? z&M?E#ZGn&tXMHTMArOk|O?NBw(Pw0vL%zTO%>8BAD!BFZoB-4dWJ&y6_QZN%n}@xy zt#RL&EGaNXJES1?8+8vH+Y0(@8|*(kezq%aTm21fp=yKvqdKJRj0M)TTlEvjM6*-I zF0O`il}7!O2^@c?I?z7AR@rCO?)e0)eQpN`Lor0RDX?^XVY4eWnGUWS~f0;lX_!c1r^sAM$)oddJ0hUb_q zSy9iBQ{bptRDjE}5`zQ>J9d~LEXh<^ma=Cw7_UCUj!}LK%P64+YgQuH2lDL9sV(H&)hl5=->KkWy_J1Z&ma1B`e&D2&Xi zEEU{xe;fuhc5FDSIv|Ui4HZPpWsKGI^K<<@co@`p8b!gb*N@ETpl=S4oc&iYH(Bub zaXjzU)6-?nZ8Pv;el)TL0fcI}soNNbEGUcsmeVavY|?JCPs-%L$Ze1@k6xlulEB*45&DnjVB27DslZ87rL6xLe-cUs zQgQXV*A2^*iA42l0-P$>lo|Uc+g+8xz#1$7arIwXxXIw=l_iY77mO49IVi$Dv`;L* zp8Zpm&d&vA_+R*7%Wrs`N;okt;7YUaDNpDf*H-yyzugwq?-}S}t2I~?M&UT?#4=^(aU}wOTNwD*GI_nG<0LzA{!s`h+9UeldK{3fl3;gT#a=HW=HvZz; zJT4|1Ose8_?r9SJ@_%&uBlmTPaMkNk2@&!b8!J^nSVr}=mYEw>g*cYRj()SVghAy$ z$ToJ{6i4A~pR-GqVZCO`D6WO6hDIN?tzO?KRS7M5Y>RxNZ8#U~ zfOW;=2EYNdI8dn0Tk_&QRNxjuU2QZ!Z;=K+hS!*|t-u#Bjlsa7eL~w~{i5k1j8)|T zS+vHX?G24Vfpg5~^P+KFl0F1B_E|rSgL}(vAqQN;kM9MCJX^?>PfBIj`}A>!Nz zR3pcx$0^fok*j)bY8!Iqere?mz6f7tduF{=88|d&g2v+<)3IYiR%GET977`T5*cTE zQrsRRK6Ej*gNogZdz9g$ACUK;UkmB(CApFWF&0(glm5qg;%npjI5+Gmr^IUfMI1?7 z)V5fsATdD-vhVo5;*!gR>=fj&Cj*fEOnO?$ear8$Y=fttYM-dEz;@1<9O_Ix_2Oyr zgi2Uty1&}rh5DNgb$V*iek)k2c z>p4lT^%!I4G-g)58aqH9*Jnp!`2fU+oCSv6Q)p%;W4Dqs2}EX{{Z-j2AgD|<@G<~t zpFl8RXuMUpwyOr-yAH3f(F^8#fIti6$DBt{*R6hWJtvaZj2Zqs= zeKX5Yrwn^<^nI|c^vy{mX3V!};dIM3hKL9389}-NYPQFpSADo2Bg-Yg1yMp9iYH72 z(8nHG5d4`WpNd69hS?99m@G)HT9n;GHp!F~5mT6LgR3)~XHJ`lM?Bqj8?b6U3w1ZyGPg zsQpG?5FdME7NT0^4lu_?2DKf^x7KX8YxvwBcaSkUoSs-Zn)EHj0 zbb)Ctirq|*dUBykGTTbUdh0};Ss-0b>Ko!}Z<9JGv{!CKU_lm>WxXmeQWDBUSd_{g zz(T6(WE4=;fc-qQ<=@5kl3C#MFv>xuCQ``#jj71zh~Q0hsHD!fCjn)G3m9>a?4I~*4ncLDpl9J_ zy^rvH{p*U&wE-b>JjjzWH4YRkCksUIG&XGTPwVS@C^L zP<^iH3asBc%Zn&IK_IXeq&W7AE)1G3Hf^)s3h>z z7RvyyyC`J;(0@tZ;V-xz5@75N)3e)v3xN3e4KlUQ@<3qd(#PPZ^R#;}UdpD3EUOwv zC|PDZt4Rp(GslUsBe`W?@&seNN#n_jl02>%tmn7z0E;5}_ zm8K<9ng$5WM(LEw$}k=V3I;m0*$A4lYhbhi21q4hI02KL-gTUWNotRPPz@{l9PcwY zK_ep zum|N_{{fxAC|%3|@-YK#IJX*V1#b$}wLdgPRQV-Jkfh&1FiXJiIZ%h1ovI~JDWR#l zqKu}V<883N2;s+ZRhDeW1K9`LCfjo*4t~kBTdi^o*%>|`n;J&{`EQ55&7ZOBlFe~n zVIOFRZ4$a3x+RqDCjvN6%ciWkD%kUXki^cJYvpTbFR5;*l&w~y7=2zb1bS{{p}im} zM3phH;sq0OBD>xnUgr?*N>frjduV8=McQiRB#Afc1nmR=YCvY0B>q;6r^*Yu06W*d zYE`ISPszN-3?WF+C0D{bC>yO2t2URPbKI(SoBmnxE7zs8)~&QXpl=rl(7^pLyPVoV z|LR{E6Waw>3E>}1qHt_W&fHHXc5K%?e)k<-Gu5lqWMhh@un(1aeQyft>6*sc;|7df zoSYM$sobM4k3IHSXLboVJ~%9TY8kx}j}{Su^H%_|w)sh`P|A=Yz?d1_F<1z{wjse; zgN{0Sb*yy6vA!TEwt_y%2nNB1!^Tv{=F;_NU#4@Tl*h7R<$HfZ;S>NB^lRH7iUS$p zm@Fn_G=nntIoL*(qa|0^3p;&J#{%>%*^gDfKqwI4lY9bDYrpBZxF*Ibq^=h*ll_5e-{wnqq47dQk!plxv=U?*2X!^F+MV}iloDZ$h4s=YVJ82Zm+j7-q7(3-tF znQ8N6^7Jpx2z zL2-%kQ!$OJTRPs_U-IK2ykb4p>y5yyZpYB79&4Y*Y?^F$2+#HUJwM7|4`R@{-zX92 zO-B)~#&KCSV;!g-wZC<(NRkvM2|at2#E5N^{gbDl^Z~oQgb3tA2xH4Gdwzg^aH7?) z-H{qiYIA0@yv0F&*&{Wmc4ShoIv>Ma!a&^3)btzC4fKQdTIYoR5+CsW*pzVE!jLa; ze_Qs~;sJpxRd5JUnJw4M90ulHB%|QhtT0}@Q$No(VW_oi&J~Uh$?H!I*rIqYx5dGn z4WbH=t@Mo6j>DZUaICn7W|J6y0$v3i^n(n6mC55~Wq5X{iw`9 zFskjQ(bv*#_E}4~sz)xl)?l9Y)dQRyO1;Bq%osX>C`g42AUFIadqHWx5|@;>>IIG; zT|>o%^`4*mcizX|8XV6rsj6B1*hvb1NBzh3Scko;i(ilIwH}ADk&WTn@t16fr~V*2 zt(syke=MjF$-udlNTduIm+CPbtU!=+`ULjIw&<_freHsHOq~Qfmqhl5X<6tVzJb3& zl56EHN@JaNpkw&7$~SPrj_pmEr_TX9*+n~(rl(kw|5UpNR*)_A+DaS&exOfdHctVw zwVp-^2HPN$wh*6G7xA7GLdc741Ul^DH|a?A1x#f;L0{@M(-w4k9TnN|59@QSe8HDV z9<^Ud#GoViEpV=Buj!xBFaMVnMd%OufS+j$u2=^-q^;E|3fUiUtLJxw@ng8rWAA+& zWRek6UQ`K=? z0wI942GGFv;YY)B&|?5+r{-V?XXE)!225tjErR8r#jUw{OIf`oE#%tY5R9F-PKSsR z@wVsSZUiYKHqyAZ%_XCcaJ(=eX2fZ{elCMoID+eeNLH0ClM4!-m0c46YtUu@Q{bt` zdYeRQd;K6M8S5`0?3e*&FsNXWWKp-6#<;yN(Z2VCgBt}@Tn>vw*|A{P-Ujpzom4VF zYfyT?s>Bxd60FY1aBdEzL6~nxMquOs$+E}z>RJXSaJYWNKe}C-^gd>T0-*eT%cq$1 z0_-{P!Y9KF$rdWOA^`yDPcY^ZGzZ+Czb6^uK5`(awl6_?fMbr<#(@9|(XO_{88LT` z0$~eB>P`*tN58XGe3-GQ2Gdr;L(>SroYvi7)#r$Wbn$2e<`wMomU1Qo(FgyR!Geiv zwTEo41{@;LY^xm<8J^uUJnI^cwyWLbXAmi4DeQ>-t0!Zz1@);2?jVwKHxmc7>PHBs z2%MP+#TXh%xDqNH1MFd9%QDnQa6n%83qlH0WD=yYZ;UvmoiWLUY*jw6wYv9~?jVf# zLcY<80X<)BtjFx#BgG8%zA5J5XO%IAd{;^BZ0ODPk+5`l4I;{pnXHA}&~JA}Crw1cz)~w< z`SEh=c8{P4n2$|Spfu<7Sv`F4yYsxp24XYeYIh91)aZhx(U; zOs^7={ncs?kCVv_WE$iZdxj(!cJT~@>$E@CAM&g4L12a3@^q)z-ZgUnrD}djzT?54 zxrY#B6z39&;d90UtozU?1L{2hP>%&sK;L?JlUs>YJkOxc0lAV?j5j-m#EWA^FJYzZ zIN}EpTDD`xW%gsPGN@lLmen{w{>1ngvc{e%&}rJBk`&0Ok`qdCN0^?;&#AmTjQxa?cOmz;Mi7}@wLQb(;ICqE*fP=6uY-4c6+;>m;Nj4Bft040Q zIy@FM1mtQNDFbznRAe9oh=Fm(++}72%z~?Nc;J+062U21Q7t2f(ehZ4Vd~~)Fc!3l z@*@BrtUHW|0So~ifRTo#GQ|7u|Jl7|-@bii-`;&?@7}$=-#vTwl%M;7PVu$UF|LfU zX_4;O?=L@R?RuNP{bSFKfHQ>9&t6;}-}kTgl)ZcG`oHy&@>~*K|7`!h{r1_1%QKmw z*KtePHFW0Ap24J7MQM=@o+?OZuSOpJ-Z?28i31ut19ZxjMHW%df$};^G+{q_7ZKV< zrqL5UkzHMkiM}!+t>BYHw1SwA(NYjD<)gw_g9nH=2S9X2$Y4i<dX!1^;DUVoCnc%7Gx@teT{~)21 zI3RfNHMC+I`pthVJ0=~9JvG1+9<)db69M!gY$Z$dAlvo2nXXp(TfY#@Kqw*a&|N;_ z#E<#@f8F7W;|gPq|fDi&mky%@8}d`mTSx zI`c@WRc}dRL5Rizi`ap`ea}zqG4k>BSaMiN6-XoRK;H0i*tNQLh zat8VFH9;;brjm~QIKJ(^>P5&^tq2pL;keFgTzj!l2w08Zi3ycpQM>U~-nQ>`wbLD-T&AY<2RO$DVS0#$^h*Se0%?|8tp6p5ow z6^O(0v?l`|>wT|DvFih zrA(3eGXR5B@!F0aV5N;zJ*WN@7b@UpbpigPWQ1)D_5|N%(#gpP#>%DxpN2g!DOHM03KPc{_K z&@up8In41u>YRVWr7k> zsaFom3j{!95NGg+4gvIO)%aNHJB^eU5#%7tpv%=H21XbmkEs_d5B_}l zJ|hZF7M^(GiTL|{KYuWr*j*lbdNdUj<=GEE-8p{f;MwwHpV(ja@AoO5ZrVqGUjKJK z5oOspX76tmtL~1n+{RiLZ}$hXyu1Gsf5)znKog1{O-W(OE2gG$O$~@M>;bZ>&fqpn zrC|=XXan+6J$8dm8&>;H+pLblRjHH}0J&xxIptRYBJT=PqJ$v8P78ZMsX4&YraPjG zAjr^>`$m4&^QjSXjF)fIK-KYaiux><_yMLIbZ}k^RDJxhjtBr|{RJti`biMwtSr8B z5Jb>Q9Ed}yiUJ>HqQUZuzHwCnbNfUz{Se4{Oop6@2t@XeZT!hkC(BC87kpj&mzJ?XJxJ6#4_xt441p_-9zK%Yg$%-&*`xLB%=(<>Ipl z7Re6lXW=QdKrWfEvO_T0nr%_Ffakb*V60RGo2sZZz#3c_Msqib)rbT=JUl=2|+53zb?5Mw^-E<>+kd$UBp3BlN*Dw)ey3)yNbnNaA{!00k z5AG(>>@FYtmA&O>vz*ff9{l9pL9QqItQz*yA1=SO_b1DHM9_YXeLwg8HTa?OpiW<} zB0&lIReRQTBVl%K12n!dzybKdZZWmu({(v0CmFn`y#`VOGB_s(w$2N?QQ*4O_cD;f zSD1M5bQ(Sf=&&ube0UuX&H*7{;>*Dd*RJYGpsCl)#G|$cd15*Y*=CLra*1moLrov{ zK1ARB8oApwuN&f^4S8|D__NR{Csm0e#rlT zPv}c8U`S;XghK7D2EVL^U@Wi;#+i6cxLJdAD0URIA#d(i4S@Dx_r`5c?z6%* zlEEmGueda+5}XfG9U(-%N;xXl{Mv`cvF2kR$V!CZ8VB^Q)zK5Ar=I(<@`?TbXdG)k z^ebg=f*00CK~61uU_J26!ITFsn@E{^rO1wB=y3i7RepQJ|+x^ zG3wJy069j5EoTD9@?bK@{ln+5>sn=|F{es;?o+F>Vh~IqndAW*fZG)_LZJGDVkz%% zhZ$I_GjP_DnHLlrf2o|+V_OUu1b!jJR8~&`jey1TX^;hzr=jXdm0JceD1ZYAf_u%f zaec}NaXbsVH})JCz>p1xjn`jS;7fVxnuiKvQZa~jc7Le+T2w_c1F>vlL^uwXJzwq3 z?Tma2a___Q*t<`CxXZ8}ee}cSllkp?e)4C__xt$`;OdzE$T~Yif42OcpZZV zdmpzl?_-aZ4}S^`{zzBRksl_sytax#UV{dRMV)$URFjlkFt{rjhJMgBoeSo^aQB%c z1R$hcGvQzxhdtplwrPLOfWhF&wxl-3w#|Lh^YuNjA^M&2(_<+iLSO}+GUnCu;ODzP zSbhaKlhxP};W$|KzAO$*GL11-;bRAGPMu0|tZ`g;{PB;J3Jr!eAE4QQu8CZ)#cN(N z`M!7Wnevf;`oYASt}6ZLV~>`P)CT`b`LI=^bt448jdFfutu8H&QBbGBDseJ%ytr2ht({ z!K{p;;>fR%@#QDItDTvhft;n5YZ-E6C=vJ~rOn1!Syuy|;RJJ_I zxMXmRx1aj(hsrMx9EO0+L__6MKKbGDq5psY_RHmmD%;py9)G4ow9)z9E8kIh^poE{ z``?xKW>WR3e`V`nl285e#~o2VRX+0gx0j!^#W8SP9y9c*HpT|e{caHxc4BoD4$du6 zg{|kE4}31N*Z4k@0KPWgRfEidowM3$qbk7uQNb&1!Uc|}x>g4#A7I(_2v06hVnBh7 zF##NsJ%E;F1iRHX(MFup&DHhpBtcs}@b<^G(wYSX-d<2q|CCA=Crn736c5-Ixc{|M zgQ=JtC}hahEcHqBRg;|_K)VcRp(5XU@3sW8!E$E(fY@*#1r~9#13c$GHf>%K5A_k& zQ44p~S3dQTA1=Q_)kn7Vaj0x$J)bhHF|g|V?U%}j2x}gDD)*O>i#EsD!~2gqW-MwW!V2({?o#Po`2=?2G|!9gX%j;U}{_<8$(+v zr|R#d2E-@C>z@7{=Tk0G^`Qa-CzyJjW~Gp@3dC9EP{)#EtAx&V8B<%t1}pm(5Nu^+ zP&BWL@#FY`YXIMB00~~9Onc1(uF8^fvpPow!u&#=EgY1*go7SlS1<`Y9W9os&Yk^) zk>W206F4%DzX!0=zp9udWxYFOP$JCWI5*olDT6BaVG=Rx%j;nI*!MmfU@-P$00U#_ zGUL&Yvf+aVUh9>l%WM0~!8m+(dF09dTqIi2HXA*tV=TXH)tKFXx%^^gi9Gg}{@KWp zy;OS?607Gk81ZW!GY4VT`OvwTALg;wF;InoZIyir0g0V+DCnT%3ZjH@bHGG9aDMn@ ze4dq2mLY%&eNvLv3+`!`IA8B3Y>|SNk1Foe_cZlU{gHeL*a5xZyq53b7zI6+3+tE3 z?+{7j4G5d~B?gE7jU@!+-ykP&LI!PauIiN*-1GFl_s6e;zdVh``o{HII1>FOayTT{ zaeq#%`K8fjko6cmC^8BD=v>*)%f2{xU~ha~ZIH0$(I>l(jj*bF-^GN{Pq(&l^d52u z9T?U;`sjzsFY$D}9g2jyWvlGhTH$440()iKZV}lb9AUjwLYn&M?NcQ_i0h(V>|v$J z1nV+WrT!;G@PnG7N&Q9i^ z_cp5&1Hr{u8QcK|RyKA99A#H5Bse0Ut3-;yL2prJrBP%_J{+?yZa%}0bH&#s7<+={lk-p~& z%Mc*->}X)k1@zPM1$NdUn;bfi_h`^#V7t{9vjolZWdHHkn(;wbELVQ5{=tcY27dKx z_9w=KDl6JJ41MnTAW!=YRApP&P^?kA(|&_cux@xP2q3*cA-)D5=fCRbDjyu%!jmAY zmH_qctjY#)o|5O@^|FFEWYfSJpGF4WJo@Ojm7laq27VYL9BV2Dbp^QkbGO-jtEPo ziUD6$UxdH1U)S+u!j5xUhU~|De9LF`n!Rzl*t4%a+@@I;e6Pv<7?ybDg$KgybBu+N zmLbsSfCF;cEH3QlGV9}OsIkELRj@4sWFu)Qf-wr=%s|0@0Q*uLOi*w*cHGQuIp8eDh!4ga_D+xvby zu%=~O=ugj&WXibWR=CLcmJF)HYX6A`ECao`6H^?EIon*_fLDdbDu%SM-{DN(p z?Ua3s{gB7oJ0|T%i8J@BCmXq`LNO=E3p>Y})JNHeh|t zfW%o0gvj%Y>|8@-+LmAevfSsG+s+30E(N|fT>*!|7Y5Ei#bDGk5}HEuHhAidOKh!d zNlU2gSZows-(D;GyZIhl-}^Vq4>*>Z4xj$WPnFREf3B)zFW>Wz%E#>BuDu^9ANxn| z?Y=npiSipSjDWcNkfz~yF4d=|Uigjj3A%nP_O+j9{=088fZAO?^lSU;b$IT7oP>=6 zRjV?nwm6ivLI)g3h6s@oi;#sSlvudSnHGXC+W_oZ-`@oPtvCR3pif5`5m3wp( z^ZFuRK2`%?>%9gKw9TJ8wm^>D2FAd;QJfyLRnr%e7qo?AAk(O3=f;?Ej1ZDu(no6= z;#kQ`T6Q+FiPy>j`1%k1typa9KhOQ0pC+uyDIae7y&cwcvig8wP2QJy@RQ{?#%?;u zX{4AA9sNXKU;ND;)_fqx`s{bTw_?rDe_(Vzbi?G0?P$m*u;x<(E9+{^57Nfs^OS!j zSDD0eRhR9~U#r|THp7>=&uS~|V{CUVpJpFo{L(gCvg5vSzu7*yefD+84Zf{1ja#KL zkVy*Q6a6($>8PM#2nqyX{CYeF!sMjI&RT+X<*QS-fWD41&77SS${yPd7+DhSq{-PQ zuB*EXtFbD{L0{D9)JX9j*HIvf^96hu+!g4}qs!g{=-qqDKeD@%4jed8e&dI_+y*~g zVCy5*d;U>(?0&oTFsV!VzqMAb;@#R>8c7UGu?%Cq8#G}K8MkAN@7dy5gDn+4`7i%LEV}LgbXd_R-$D*GNnL^KC~F!kddeYxlJ`b7;(!`xSeY3MhcLP+sn8IJAlORA+qc9?mxsrJ*3^pa0T_9w~oYu;x=A{$9eG(Rxet-?8Sq8H@~Te(t+% zU#VZBUCPD(TXGFuz4#O5y^oBxc3`a8{hohV6R(zB@mUKG6nC+f3$juY#QkHt;CA5e zY4gILY6$&#T=lE)0z&>|kJeP%(w=9=JA&JEJ?wS~}>B#};U9FvWUkAq-U7;4PiXLVQr92^?!P0%)u=XEID zo`N&lQ-`Q>^2{wWPsk9#r3K0wIMsMGm}-Ai4;WV~$nbXnZ3L(&Z`1w~43>ILcEpyB z_*|9&K4+rIePZ1yz(R(Q4-*CeHp^lm`yB(Q2@8f=;IFcTOc2aCD5CEQIBc6Z24o4} zVQiE1!N>CPOmetgZA&vJ_Kl&y$NFHKW!>_4As=k+*zyg=5CvSWT7b}~pQ0a3WcfOr z$T0@ubGBvnRrX(e&SPUew){@pZ}qz+L)MvMsrHF+b&{R2-!KVh8&KbayeIi!E5-oJ zS+9)mYLhHGwLz74OCEd<%Upe(?LhUczQKBF*%G(S*VJ*U?eSP!Hq*ib^$*2m){pug zW9v|iMSE&@Y#Vwm-g4&hpj)5L+wt%$-#0(T_XDzwuI9c}WOhaJRvKf|x>Qcdxop;bS?2AdZ z2)(p`w*@%0E#I(B7QaD83Oqx8A7GL5@$ftKTlJHczp381-zQI?6~ zCdSX#n1nanXHA|K!W6wWAJ6!qx@6r?!lxDnu^lRw4e6U@$9-fBVj|8v-l9##EA)-~ z@5iV;DDL2U?Gx(=cG!wFE!@>UunnMHmJNRoAJy-N;`a2qb?ZKg!9$oFNLm?U3$$8J zF$7);7TjreY8L7csA8aaZjlPBbuBeS6}WZwOAj|fuvWaWOf4GIawFajPHImrJ?k-=jbbb@(1b>doH|5fqF?{TSzHU>UMe^+~QYscbODR#i;f;p+{_p|uAWYykS!AUfoS zY@?XgX!VKhi2KDh&DYlJ@%z?y96PuIq_)SpW&PuPtt?F%cgv4jV{gR<#o$)3@A-E= zNENbEY~gXTe7S1IePcWI<69Lqm5<6|s7ln50k@_8#_hCt2K;@L57-&Cn zZmT>x2@F|AY5@2S&Wg4b>?e(%9Rk3jz@uO}DX{Rk71Y&vTh5HOhe(6USqTFJ+$4}^ zfan28POEY|>WD*N31DY(&Hl!E(KcH4&L9lkG6CSRbKv0XYu{CO3~Jm5mj6NlbrM<7 zHd`2@pP}-@_N}(W{_fwkDiM4Rj$cTxEgAT^>RYT!^%oqgI@aS_cBSL=_nKI+u3I+F z$8$j8w$yeMGZdTe2di8DJ!D@k-3;~5KVSBSzfo^Cx&76j=>=j9(kxd5_7=vruuA1M zgi#n5?5TC0+O^6Yv6TDBui4jCKSO@S@tl2Kk5|2@ELytYHuUw7eW-Hm{hp$j)pip%%4Oloug9Xb<<%B@6kbL+&1yy#`NwOUR2m}`ff+6QnAi5tXS?C;m z-;yT+0Wtt!K%c)X5D*3d4OHBxRsd20HIyZ)%v;xK18>j!;Z0$-QFf7=pZT&a%- z;ED%IqR66k|071in@Ypqk26o=MZvUu*kcKmO|y___rC+mQfQwWl6> z=%MDC7oMYa(RhZm^3DI_e>+n8`bfVnfv-#8zghwpfAde5`LkcB4{gK3RBw={?0n4} zlB1#Z0Njbzx{Ldn*48Pqp@HcX>(?rPN$U`_t@~LsqGN~rCdq`qn>1CA<63=g$yu*` zziTeAg??)d#U%N*`oK1_`rCe?o__Tce>q-Hn(F59au962)_%3@;(p{dX?&Axjn{v) zrgs;zd0dzE&-%L`+Z&p~{#t$F|BT}ygT;#%*P9HccJ10#*Sugr`qwY+-~*u1dH9wR z{%b%$&snIA`#FB7Z$2h9ilMa%er(H87Bb8hI1GWPI?$vw6>6C3wEX>~akhX_fvUSaFotc>l;==nTwQS2l7{3bzjQf#WOa7|gp<^b=_I|MDesr%s=k0R; z778jH)YLccM?MSr-PbyXg=D!9M&6IzwQSEnTl<~ASew86pZ;{bo@0_920fS_={hR24p<~#m>_3f4a{AYSLHDs_HBo^wI0{bLKTd1u`!FVAV z+;2Y?3N%CQv}Dx+;jhJpzE%fc2yiFa*Uld~RZl)h6uTfuS?c=LDqdLf&? zpP<0DJ&EWj4zy&tkerA7ZU}$4y-CSg3pZPKvHs8eQSHKofB%mAP9%l`^+NJjyW!(o zWBXce5^34){bKCbs;40g{#wUBq{D^!GvouXNyZ!Koo^PX4>9&>qn5$9oEOBUb&(-K zPZAW)X$507hW{FXZ7GADz+ba)CI!Jsj-qYek33cJlYoq!d6I!m0w5(5>@2OjL52XN z1=d4yZW-aEK)8@yshk(eq}aah=iG&y%G=xep<`8)XMX;{p2@(Tv|kI^_x*szkPYbP z>Qk-rTK0-S$9>g1_gcra{M(OXn`+(uslgNd);p;fbI>>cJ9O8bp5F@68VE5iK9>7G zB;z5U^3MUb>gNb(tzhiuakkI>YWaND}xuJWj<7z57-1PveKm%D-n@(!2eD8G0ul{Avh0 zT6os7Q?&{99mZQH1bCvgAA|E+{nfteHE z6zu0CBmI?%RS zZ7d|OR?q;*Z292PD%!KZ@KEmw#Ck0b>6JlWowya;8Q9pqSf_lR1|jsj zMaDQN@Nqg8wPl>A`k4gU+DFEmg#glz9aXB*aZ12UaCyd zzV?BMPs4WV~aZ>Gz?UsX`22AyD_QN5+n`HBfQD~2C7}({q*z`Xfs?DAMH@gQP zFs%O0^5!w9y|rQp;ux>tQmj>5*BHSz&vBt8KW>X{nn@4z$Nk`IupbXy18uOZwV!Mk zY->vJl%TU6vrdQnU?^^|KZPCWfO!!34u;PcW)St)oM|Y)s=zR3#m)euz_qkJ{=C&5 z1Dp1<)plzvJWdAsXnWD((Ql3y?do4`2Qu~Jv@bed9tVzXeFm9xKhb_`ywIigfq@d& z@%0M)qp|{U^0+6B3xI>&T)q8T`lGo_Zv)5h_uOX=94sFOD98qFsqFwHhx)8C9JDV`lv0Yfh3| z>o~|tuj`*{Keewc!;wvcz|)SKy;2`rMX(rw{H#+c;nCcZjsGthj&Np4w7N|M-mc1FUHI z0^4oNKhYlapgzbpmv+(xR44|5;1k&p8Mycy?hM*cFvPhEB12%NhNgn%elu7rP~kfT z)RrN)0zn){j>2GzYYp|4WuVT$#@3R7%1^J=I^U0h0kJb``)Z6VKW4;iFf5zuu(oqD zj%VX%nYWyRuc6@1cEwJFHo33-x;4gDK!S`qwRR;^yvFso|C4~5+i3X=02#-%f=CNw zbllJ->q9|P?LqAYebMprwbYJVKHTby9*6gO?2w-q^JWfkm%9$zLFY7I3Of z42_k2uO&y;bIacuXW6b8^jW7ZA7;6$-)Wy(_Sy>Ae0?6f%5zA*O#WJZ;3PwRAASfD zulUUEwO-@ANx_%niej8%1p7+M|Iik$%l^v!Qv$^J06+D%hGLdqn{Bm)D?ApC2^uT8 zk2tPnzZje1CED{o;HmM7%PK4N;rp>AwY^1PbWm=~c%iUX2EvM;1gtH9WM{?eA!CEn zGD+ghhn-pl$IOtOqXqVpjC05kAv2W^gGWogOybzN6f9a!g7LPTk~0>Jm#@$5D=h;(r)c*ARmh)?SDjR&?@(U)8eq2k=xF$P4 z_XA+ivf2CXTPyIey+WtjUdxBPAMSH4K%Er07^u|e7a9kuLu`BMSCfFR)qW8GTd{%Vr9RQJ z!IqB=>7*5u{d|6)sNy@z4*Ej?#<7eQkd0PpI7Y%x_*#=})W2gg)A9+(l(C?d^i7f} z`)}RKFi02dbD!?P{MGd?2eKgViyp-1++M-M z%67@}ZjDFfzyRL@8V*n_4-JHT?)})30$@wl+*b}-N)9=JfzK+rMN+1==Hut!q~lPW z8wv(|9_z3bfQN`ZVd58ZDBymzxg=T8?MPdg5%W(C*dzAhT1P~Tm4Am1NzU&oa)-&b22|w?LW$1heS-DNAa=U|?n?>UdT8EvHccXELW`0R3ozBRhgRfS;%1WFo0@ACe#X z-?AGH9%?sib2?t`8;)Bj;KRu^P%#*{f(p0GW6<#^z@X1~78vxeWE=njIkoIr!9~Z6 z?^TBSphvdn7O=NKjDbP>*a`&f(>xaLn+Bpu0kLHlY7edPPqGU>UNJ@68X5!J1^aUg z{}_-VAJ{?5j@XwtaPa4?%u{vR^68=eDQ>DAD&DqyMdgZdx1LlzL|R%lrsEpIo*@is zoj)|bA$uFbPi|YQ9EvR*#}tQn+$|kxJYhdu$d_>}x556wvS`^mAIrF`q-IE_t^N)9 z6+YM5m4$GC<%#$Zn6F<98G{C5D8!F%0hS7F{@#2oovX2EX2sWPId}_P{5TFWEv0F@ z-Y0y9@u0K@V^l-b_d{ey<;4cs3YrSqEMJ_vkdqA=YABi>00~*?@vZY&H$%YN>KBtP z)nUt)AlH_Yuxwh+@8{?(p+g`zseP7t%kK1Cj1hf;9JC!iPGvkdKUas>vY8f0vd^_- z%Ymjf-j=?`{M8l+a?l%+JFf4(#MgyBSr*y`kB#+@&l&WG^u~aTHhg?+?+WJZ^9%Vm ze?R13zzVj5*i|;SV!-#j5MBvIOTLP$DqjFOUw0_jwPe4LkG6uD_5trF^>xU0fNN^^ zz$eC=q3h~+wa+aZ8p4K_EvPSHENoL81BNh~F~6lFwn>&3Y-dQXjP0#)4PBRQQ(voX zs(rWGsU0XT49Tlb8?~IYWpo;3*n!wk#*8YRnFXUDHDsVHEOwGsTdlIU z8YPsqXsTPNJZYQ@$$$-pD=R|)%*L;dp@E3U$Jxw~k%G~-$mFEz417Dz;vQ&b=hK_ObwN+LN=~HcmL244{r~?jN2koO>*dVvfeTGl9z@cRa zEGyQD1_*7Bk7a$SP3krA-p66PCXI=RflAwg4YfYk{tjV7D`;Xmqy^9|pF=+w3otH_ zOCC1^F_Sj7#o4*pDvR2dtru#It0iMxL;s>tBxLCK zu6V26`gpz`I?iX@}gCsN-6k;I(2B>toE;?Op-J_944v8Sph3 z6B)m7Jo`vXZYmF!S4;Q$8TY@1V`v|8Q@ysXfno>bsrvVGV!^H|ft`4WQLzKFa+u7h zqcRX{02>MtLxhN(M6bzCqiD*(7;S3?jqy(kKza?9$54M-PBLUn3YI)xT_jbFG^<-f z1de6Qa)|RK@U%bx@>2QmxY*cO_Cud5(6;1?&srsFe8*EZY|}hWc5JnaAwXv!QF~w+ z4LPumo9#KiYh>tZ^E!qWK(NoYzSpUY)_A$E>L-c=Eq@In*4?-@_QUq9Z4XVe;2Id) zB%f#jpxUL5`F{M{$HeWhABNBSKe}5Dw#PoWkUU_QJYMxb?(0zCW;wO6284%grPY@9 zSC476&A!D+9AgF_qkg4+!E0%Nr<44b^`h5dxhQ#18&F?^kGfq~n-`x|`NVts&yQCu zQXRYf=yHIb{L`NhUm&MuKk3fNmd^OvLwGmobJaWEYdmUIlNm3xAIuY4GKT&jPrSG5 zj+|2+gc%(RZPLYIIP821B1&q8oI9?WL6zH6160FBdo94mxoWh`sB!-N^plSr0@+r3 zJO%}2t>CmAQ{@XFW#el(6*Kl8KvHI*{n0V{_pK@u_p_B5G^3h*2-^a zML#49@@s(P07P1Pxn_TJ@|to79(~V^vP@ zbNw9p=ke44+_?L!XJ>Zcm|WbHu$Eu8Xx@kWP`%l!mh z#-|qM==JrOA-iMSRNaro6JL^G|5T4dZ77zYJtsFBSBC6eD=^$9Y@YwJEkJLMr;P0^ z8`S~6996xzUN z=qLgW2QG9vIy~P+RREB)I&a_4kMHwZ9Oznr&tvKdiGxS7<){)Sp!#_#8wDd)Dqh2Z zR3Y5%5csIUD**9WdIp>QX1Ocis2nt~uyg6_7KnyTqzoCP)G^d%G-&X9$h+nEJ!0Z^ z;hC|d`+gqIb$dbEY^yEDZB4teeAEtF_B{#UTueN+A)jl>y(N1E0c{UH;o@OHhy8{R z5m@mQ2(Jgz>r{KES)wWn^Veu6GgX|+J_CDZyKV&>4yLWZ$>7HF(PP;^TL7u;;C+lK z@uzi+1_TWrL%xsm)E6NSeBVj{)Ni;gmN8=>u$6sKF@7jub31AW+Mepr!r<7(fT~lr z#a5r<`^1+PMrfaK3}XjhQ{xY0jCRrv|k*oS_aAn-g2&L3{+{raaC!O4NocoGhj_33b?NJ zPaR<>a18+u2L}Wx4H#_9EdZJ%GaftlwSt6@2X@L9;B#PTIfl2(C1W-CR{yy=r}on# zQ7Ur|8r)|k<|-!*BrQk9+%4NXJ8H{D6@0WGe4Sn&q)J&UBOv8=VvnHYqFk&I3jfYU zrk*`1==pnO(s+&QR~b$ja616fbW01E<2w0ol5KM$G}Iq%pOYZ&+d|11+Tb7*_(kNr z6|{zQfzNRcV<`ty$PqY#>vKO;e%#keQ0+qo{XrYaJ%?KIU}DWg2yhqy$84tMBQ3vd z1wszK9GF;6Y7d;8AaQMBmW~-?fQ(w?4%cE^;dVG-AHpK;i^c%OBVZNFQ8ANs!vq%n z8oORjE%CKA&Z?hkTP^Z{_^sd7>!kl8Y2~p_!tL6BSt8f-FB=ob0kyA4P+No0QhYCH zb=0H+8w^?lBs&5w+$#ICp(IvRAFd~p<;j_`SKnsdx zM-ExgGzP$r1K5~x(^NtW5uxUGeQlY#;}?NBg><1#}Z0szk7TjPlHTpu)t z%V5Z|XFK4vI5j|KfK`LmpsxW#<n60{ z?CjiU1wB-Da6HHe_t$;5N4V{MZ{s=956eu!Nx?GYMeVl$y4o?V8wlA@wU*`HvP}(A z@OS@QF{U0%l_0hw&9v1&7fp{Ud$4_$I|DoSTZ3WCX4nU-oTbVDo7M!%Kj#V~#>wMR z;?6{8()5vziL2Xso(58W&w+o^aViKu?1cxHtJZTue6qIs82y&dJ2s>lM#y_0&Z50G9<8L7G@#Q zc`10tdG2Gr0A8jfRptT0v~IArB?%s6&ubWXoculeu?E|o{fOMX4etvoX^L+k9_;rV z)Yz`r*MZ5yu1Q_HH4A*|`) z0pT#mTl8;8$Iwyl!HmJ|a?VSY%MDh*b8yMsL;Wv+jE$C^vd7xVfN?w&072uL3^M2! zl&OYO6=6o=g(bADfrbH!$HU`igH~m*JbJGQ>>&Ks?XWG!;M+|@o_Y5W93FDWUtuS?o&?05kHxsE z59YcZf6qE<1&)@DwD1hqQ!o!=<%&we!}f^RI?fnF-nr@D&E4y6i^kY$8#2!iKL2(}}nS^ut6FGO0l=31F{Zo;-MROxN`` z+*fgXxhI|))cLxakg~1xNX|f2o5@@FNM0YLNimagLa#Nc;?1^#Hd#jMGpzI8ac*1o z4}GoQQ3|?6C19?=y z&lBtC^u7kbEcrRGhAf0>>q zPlDJriBfi|2C^Qr9Q9bqo`NOI5@P|mt$G%pLa>D#6|f>W4^+E)wnHUk^tiTZgNNKE zO$F-lM?PH>$zePVIc6O+L_x^CMM_$ zCr7={B*B2LLIzlqB_><_#zRdX+7uxJ`xz#sOB`#q`gCPW_K#Fq^sK+u$5AMWpp=bsjURBRd(=&4CB?(G(tS)1oMkB%z3bKC;T2-;x zPB?)XC;|;EEY9()R=^8Ed3vf_j9Ceo9qT#{nesW2B4x>5`iA2)SoH#8qr5xvg8HgD zFYBIV&TJg7HGAmUV+M{Y2bVMVzjLv;F3Yq6l=s`e=Sq;vVQ#dGtO8hlPi=c&nasdW z;3G`V0bo2n&X&EOai?9{ixPYG-8$7sSw5;L_iRBe?1gpL1mGlIu-CXo+A))N$Qia8 z{+K}#(?dM{3IAtc3t3U1Vgg(NGo(4%xt48MU-Ra271-G)#IIR?8jxWl9KdQn(pGBK zO6>-DPgWax#6E*p4Je6sz_uP6)+J_3h&c;+N9^~LrISt+iv4RYUL8;XC7AgDO>u1_S8#|VtC2?b62sU0z9^Ywsp zE+f5TmMaj9G4YxJR>xc8LMHVf4ovtuu{Lb=22~Trn07~n>kkjI7aTmp&58>?ufUh((dd^C7y;SaO{FU^LSP}p z6d>B=zddJ3poIeUJ9a)cICTIu<|v0{DZZ6G@cG&|j91w_&S80i-NrTSpA#DB10d<| zkp-|JqY}an0>`XDgMv7&UkL-Tb0*KB`{1ld2Z`{dT&ly{F+&-c+A4qsL9p|D%69U4 z&{^1U-bDp~g^j5E!wz#iEa&R%HWZhMzn@t&(_Px_*GuCxwO8$ki+tn@dR;hvy(TZD zBNBk`L4+}GOe+AqFb0tOAXr{0N?_N@2jf7?CY7K8cwi^~H~dhhQCj2VOq9Rp1O_09 zcG)j$P;m1~+(30tE3N=}5Je8K9irqvu8!dL@U*K+w#hC)*x;iWdsLo5+%nLs3|My1 zJ8Z}GsU#SE=INe_d3Jm((3bs?6vvnZFj1`!Q_LytCbprXKouCY&jg&wApAo0*2Gt4 zWhpFF%am+@-~nfVcX4gH4PGl9EuzHz<%$gZ0@@F~(3A`868Pvc)hYYXZ3b=3NMNc5 zvB}$ktl`>b58{GRXj?3kIyhe5pqgKXNGn6c`k0~LIk&O+8 z?ft;rL2&R&P%>zg@inV;+fAKu^`(~iGH6zi^7fn!bD%|qB0pnbK|efWZ;p@HKXmQKF#!UJ zsAF(P@KQ9BSu8T93>AHb-FeA5R<)z=07VCTX1lNfC#|%YIr;}yZ+DNd!=dlcX9Xy^ zR!i@kF-P2dtt&Eq!8yMDXO~4Yk{Bv zIO`^1kOdLGu`J&KhSo1}z{PdhKLAFp1O>7V-_EJjSic5<%<2={Wymr6$wU)vFd?pF zhN)tHv;u*`aa-Z4g|yx~vqQ|<8yRefUk-rISwY*we38(%7gF^aXPNmNP6OX zzjH2=oSwYx_!hP}=DM6~!GRKcKc9;abywZAuSkY739Jb~#w^%j_(4uza#5r9EyvM| z2Qn__W7e(?hcddC zZe^IsXrphk!Bo%ia!P~8$x6quEhqDHoKf;N$V?KzHd!9bfU8p_V8PHikVOE=MOqbj z($N6u06PxG72s*gCV(k3X%2Ed0!5%30F-M*5FlcFnN0w^S`G&muTBZ4g-#F@YDttF z1Az~1;cvaAH!CzXGsvKffa*@iBsBDe%?&#$7DM2SwSI<-5&)1OtW_rHmhBL2R%b;9 znt`JNW;!^_5A9)k2RetX!S5I(qfcbCwK_rpgEKkE5q<}?aX8DM)jbFzk-NHOO#Qeo%&HpJMy<*S#tUHn((e1Zj6^aoL(do^(|! zZ`oJ)g9iQh9Kp-l#(C&tC3xHyB4AZFbY~=FfNNDd_9+3slPI@#00#6h#(fwSxQ^z; zzltN!C(D>BcJMn*_<&2%r|c^SNqo=5ie*uK#C2h7_bMJG2?ZY3X(~!2V|*yY(%2N2 zAtxULuFbdzvdkD;D^#?A*)NCj2WiVnaP?KH-d7Bh^+V8!#*j+(D2d?yu-!m!@E72L zl6~}*<-v9W`9WVjf6KA-63$$6qWBi)XR@z}38sZOp#hHdh^_k=rf#KT$V4b`GL`PH z5hD~YW7?=@>)B&o3C@{^pB&CZl>`R95DYsAvUAEXK!zBkqk^D|V%=H6vhsY~0tiKQ zYp`=2f(w?&N@P16{Mk{`$*X{}eFkDS{1!Q*rn^|4rQ^CNv$M7?xVWP7gj)W>qAdbI z91{V;|7F>cvpRMz1Pd&{g(FnJPw=f}L;~*$D3k$)!(dtum5RLE27v_n4IPkvs|{sf z=3vYKTY(59f&)A!%p12{*itZsCvXC{kIY+uO3^HqZNP}bcwK5 za@5F9y4iS%tqt?Ls?t9=K?$s7B9gMM80a=;L<=#c z2LFsP)s7PHG`V3?g6lFV1jcjUE9PYI1{Ty~GLgc2*kJX8j2Sg46F)@)iZSARZYPM3 zRl0i>zO;MBM7?$-+qk(QV;}H<`2zd^w!wZL`i;U-fA?Lsl^#j+1DQBfz78W#fQ3;Z z+eM(QESiqPcV0TGLEB1J5qNX)jw^@e%n)YatJx#!g@lkdW z?@5{nY?y+9VX#nhFTd(o7zd^`>icx$;426q>5pNE8O&;*B}?Kl`|-FggD}Q}vU6k_ zxv&=gnVrY=l8l9o@#1>2DO?9Z75(#m!{)=| zB$@N?yiLE2w+EbD?v_aE=Q#FpG6!3Sjr9B_eHh~nn@y|$vGLEmZXUaat zm@HlANn|RLi3wv4 z>;?LU968~Do%b-%`cl_DVeLx#T~97_9NSdbA`|`ma?ICJiS&S-!JqA{@()ZiXJBVs zf}M5IFiEy+1<4>PZJ9s;Gn8;3*@#=#k!)pw02t@j3aq5-_|QCoRst6om3RbsRP13A z9k9{;!x(yT+dp?dr1i3)*X=vD2Q&v0LU|K&*C_xv02Ch`$!Ub%+;=zPV9*G>eq1m) zu8LGGXXcirA(Z^!*vwRs8TZ(04z>y;-y?W=A8c}G)E5VY6eefV;V1~88K{`ad;8ly zbiDTZ^v52c5sZQ*oQBB}GMq5NWR;baH2Mz!i(`-(V9{{`t+$DwGUl|IQE|Bu@=$|| zYk3(x%a~);g{)=;80Ov!Yy6uS`0n_ z8|bJd@2U$odI!c3XZMc-VmO6YOOo|+o7I`JpKgQOf9OQj{i%=btgoX@w=MFW_%Z{E z%2tCY2vg5_0T5J1R~th~6*2`lf`G6cFsN7AXXcMgz7oe=i_{BlNzSWp*x1~+kuk9y z^mLN;P=k49{7l54ljwJ5(zL!Zh`@`nVZRvy!aeat zf&`Br?bp9Kww}$RN|SyIeNCJEZrwIwH+QcrU9zNXShuq5dSFv|;?Zs8xhHm(ryk!~ zc0atOY}vZLl$n`w_2RX1?9|1w@6egDXWz;4>b?`@;Gxsy#HsV;@|A1l&Rtt3U@D%T zaiZ=H)%g&THTJ2kA39e3@8r+z7)|#i)^M_@xT7+FJbYYrT~1a4IGKVS05cKffoCjx zmMioW_K|^@ZH1F+BquH69^cXWuh6#<#xdNfk{P{#U!V_BvB^ZQVs839blmP`p8U~FuBxTb#wfgsZhg`u3E zgaQE#fLNpjL-_D=W`Twotn{~63X^zQ5ej#5jpAdM-@ z=pTIsHTU#_K$z`whE{FK^~<)GjNSXr_E=>{b{*GDyI?XBHe;VNd2zt(kwoa&$p(TX z^#eqp+KF2_#!Ta?y5%)nM6g{SzIf9EIRZS$5VEPNV<&3~4lFBx4HLy6S|oq9weTkk zx)m=FC ztppInCP6e{BS|m<50j{|K#Xgvx7RmdT2r6!C19(Iu^r7T(O%-6o3FV`;LF!FM->^*p@?0xM>+4J(gvhTpj za^l?8a_P#=a{JDmIM-J!IH?I6u=m@3Xgr}*9RO2XL;_=je&BZ?y+~@{%Qa>Z_M?5^ zd$?NaAg<|S&d=)mfS6I0fn#GYIZT}gUQklRZ2L|)iv0GO3AXRzmrMlaJ$um?dxwhS`FW3A*P zi4xXcVc{H{EUrye!m9hc`^t~=&qCk6Az#WDI^)3C%XmYLuRj)VU`gSL#||kz#`B=FFduVq&{?!7+0&@MA~aL3^9xS@W?6Hf$*W>tFt+^3)q1DN~!*m9lnqu@a24jE<}rdAW!Ek^FrG zVXMT)l!8|g{DushrtrU0v5An8o!N5Z=Dl*_+P$*x_{H+tYe&nTJ;%!a11HMy6KBe$ zOIORy+qcV#=l)Vzw&l69bn`Ri?5})BCG(+QsixM-3#RJR*K49KF`*`FNj{LgRGiIq zI3Z6YJZWfJy+knQc*1zdl}pAA#{L+S$2g83?ki~roPbyTWq*KUOseWkh$e16oJPnM z%>4PgYRm*AHHct7H^B%mO}s6osF zbxw_hptx#~PT$M8z4DUd^|96a_4zswJ_2nT36HgsKrmt2z9pi-SV zniA52=``w3=*5rAtQ39Vj1#s40O5sk(U%MY+$=z2%nmpxIB9Y{dPM{kGT0WCN26W% zK~C8X+7MN(Dwy~PG37?=gwKPz|$BE7K!tg}Crw7P#enYGltCQ-0%xU0S8O_A5`fE6K_pY}FF$ovrB3Gm;u%~Q#)hblJ zI;ZFYKzBm?u-{b-g$&bov2L+u#r8dtCnqmE)~_!={-jk~mf1Q8tEQ~5X`|&^)|KVk zHj7{lBq>5cw2;f>$Z`UyWQ1%S;69^R*|u4&64G1%3e<` zHuB?DmZesqF|uPuSZ-K_=H#gh<-oxc<&{^Dmc4rpmwo$=mE*_Hl#7?H*rMRuF|)xGR8tiJ0P>~73nc*+X6oNXgWR`P{DBS=cMFZ6+OZ<1FA zJm_o351*{v@XCujaorCk2~$ixP*n?Lj_tMDXc9TrjZTHdu{G{wxw%0`bnTYg30KXK zXw>#YwWFY1`$x9WtIYZF8Ps?UTlE1VKx_{+b3>LzcS^x8Kv-}?04GIENEv&Wl(URb znW|-U0Y)Y@O4{SQ1Wo8L0)G-IE`wu?NIGhzB*zJxLO?)!ac5LkchJTdc2aVLYh%3V zkNR9q9x`df*m&JS=)y5HNj3Xq3_URm)tHcFRvCJP%s!hlJ#JmQzWn`Xx0hWj7YBqa zHouy&S57&W*qf!xmz1SzR+QzBJy@2%>*;d+tdWe_MPIA|#A=71uMlt+LBF1UdEoV#ia$yCgY*v7M^qd;!~Ho%>KY+i{?Pt$A}yPFyc~{j~31 z7C~8A_zT$|6BxfPFWh$W!efeSIXJkZW~R>-pdqrSQv#twvzeI7c0X_%LRE_@77QRD z%@85aqldb3v1iRR#dMMqAx5DWU=+LtlS|xuf#>{jmO+0me~*jK#vGfk`mX&x*E4p*ksEOa%?!B z$y&8VCm3Y&;o?~puSAImIPg9El`Cl^boCn@3*!LfH9I?3wys-W{_jt2D-RiYalOn~ z-xgctV~LZ68T++<&dlB|%Qvqr8$bA+<;9P`P(J;!KPc~c+Q`f!TgviBx7*)sWyy|B zW$}i!Wons`8OKY&*d|9a57SMJ=jH8dyAl|zS) zm)BlBY!#XVW$(Vj<>-+U<-AQf-MDQPpRnCIyDQ9m%lgUV4SgX%0_P#C#9k&Nun#64 zilM-PiU+_jsyNnmkU--*#;o+^zfStMh24iEyR445`EkyQTtDdRv8rKt>HFgA+`kI#*43*$fwy8jeY>TE-dd8mF zG3KH;(}=!c4lO&zbAn++V0Hw|AUzx$d*G*2J4sk7L6Oow19D}XaCnr!BzxzeqLr7C zE%$G|?y+_rcb)))P#^~|VZ0T;GdPc}B_J?V#j@it391H62GR@8?y$6W2vv)*>_gVd zggkxzovSwh9b~dz-37*K!?FO$ajkieL)+PB03cdLmTU1Y|kZp&GZ{^SBv60ciM4 zzaxShU%8AdyRDfu_cO#iZpQ#|O!Wm$DtgH^Fp$!7=#VE*WXl96ge8Px0d$p*Q?Fc!4ZNOj#w z7C|ED?D#7*U0~BjXakBH%G#JHjm<@p!E^t{rj2rNm{&yx8OBDdznikgbQRj5D#OtE zz4>*NKB*#s^0+ebcpsTj2i`Ea-ZWhrN!<^HSiN@0u48FVJaCB40hd4P38B&SCpmajsLPOz0>e zjmeYzLFECvpJY$-p{ODS{83y8x@%) z4{k3@AKX!9wr?woY=Q8im3FS*$>e@z)gNE$8?tmFJZ+?9%BPh~SagpMLf6dOb&sVG~W#zUqw|GlAb#rk!bmUms`|AGk>Z^OpzP8L>O{GwVtuAmzd{t5wOV5Q=G4BOOn{Cj(hr32gCa$JGHt;NdQ+3F-={k zA~|u#I-#rp`FYrcupS>GmxL$#(EB{GCHx5iHB{BzeafUn@h$RGUbh7TQ) zUR9Qqh4*YCh2-ZddFh;GR03`V8GNQjSb-O;o=Uz|9tl*z@^ijYgLfUb0Cul0RFUF} zS~w3FEVAY#HVRZ+ePF@^q5+wKTyga%+Cs?^04=xuabIHmlu6e%+gfIJ?ldxEd%JAeS{AL@&@J{gvNC=5 zW+_+BmihB1jJRAedo^aW)X2`-t);B9eVJBmu}Y3rb8Pdx?#C776`Fj1?|M09d(Ip_ z?CWQY(7d*}KcbyTWYRw4I>1DlI^r0F*b<-7 zxZFsv0Jyg8Q+ueq#D$%8`-f&sVXPtuR?Zl^rzszF)Co=ON1?$g$Hi#p6SuM70Fq zhViJa0Bm9G=*JN7*5i}pRm=fs6G7_$aTLgV%p|EyfA^WVn~vgr~le_HpxrK){7=aUi{YyjB|@=`|Izgta<}NGrh?7 z8M3u1ar{h~S+lZCuisD>KfJ3f-m<3LJbAjzEn8DoKmL?4t6j!RHd^D$!gB82v$ZZx z6mh|vYO;XWd5-^$s*SIo$)EWvrJQ=D{QLj?-<7}hPku3o6enAdqsF*O0C{?rl8ewq zCcuI7NO+XQkX@?Hv3*t&K-be)IT{qWUB_-PPgr%NU;9 zp38tX!sB3oE%N>PKAq-&s}JTFyFVj)X55Q$_#(_qtU@o@N5$#tU_L%f6HsQ|vj+~k zJ?!qB^Y-mI+f43OxnbM<-?e>RX3fWE?YO&^k=y3G_B(H{yLrHvc4__C*K>F5yxVs3 z>>aZy+m~+6{?7S(+vINE+MTmU3e4TJwJ6ie%KT#cU9`B&-ndil9ywZOUwhHEiMd){ zdErF)ji35NIq>g(yBz<;|5Psi-tU&1`(G&YSI%|voLOOHXr=ucL5cNNKFw{nW-qcz z(A3g$@8;z)f8>j0?hF4%nf)*Su+07H|Fe`A{*SWe_L(y8k9W5WSiGz%#z$rhbzP97oX1E#>@^_r0I1}gEKlrvD)5BIj7S$AB zf5tDqK3Ce|zrdN0iuh@*P9=Ub(eL#&$A&&muUxtEqYw}d)XWLr!#VhP%#&;ID^!9X5+hHkR2fPm5>hz2SJ>1-j7F3R^Ez&_wr^S!_&6|!DAQk=QBkUYPO^;sa# z_ImYOM|N=Si~qC&0fHhsI|C8cc~u*P469Y;3-uH9BT=8_+45WU0R%ul7NE&QrUqgH zHTIX@YtEvy-}xSPU4v#LlVra{`)E!pn(V7=+hhG^FqK3~t5MO8|K~C#@~pl!hFPhL zT184bWCBqMv=1oOCR1YKNku*yqa{9&-_UUqSdbnhbUlnpeN^A>9Hds1W88u{?8BAl z(?W8-GZGl*azbKLr?j#nxy0`D*}isF*|}+rEquLRE?vB78_dlHf$^kl+WpVkUusi6 z+u!lJa^~>)a_Dmh%0s>gSAV?knP_w>tRR+R@WAV`q5LKmz1wwc4b75W+sdf}7s~Ok z94c#XT`1RHeXU&k(ih9M&wZ}k_~Xx(J1;$7=8hjO<@)80NG`WU!+vMnxnpH+@8`NTrB%7GTIxwH$x=y9Bhz|fh&ap#m#_Sh-` zA6VPi^ae3@R)7L+U`AF97>w9Rl%xU7dh>wkJIM5yyj=U@|J?N$z>t7}Kv&tg+YA;x z0WdRI_xx7aa?9|CKpfzRO|a_NP$kL6U}(L}fU|oc09cn%`_c%iY!|JdQ$e2lKv}Bl zCqzy}0Y+YlUOEQbQplRvd`ssTL+x)m6J*7G*8rxZNJ%UcuSw$>10(^lYPTNjl1OmB zVAC2X*(U>#lSFg&)jP(`mIy@+PynNpzh1A(F2P!{fPF6d@4=V!0^LHF9S7|ki2a3$ zX{$=pxn%+;WpL^<{JxG?vVN8`gFgr|dt-r(DO-39?-`+&Irs@ zB?QJ00qNPNe9q&keNKB~EFP0h609CZyR5QG74pdU)!tJFx9zs$B|A5jzyHtvVtM?X zkC%3+zyK?<*IdkrMIeY$wJ+tU`S-fg_dF(w;m$OD*4jXydo#cgvP`eddp5!H+ zm;h{n)83iLXF48W7;AfjtX@%;?y?2A2hNw1`_7e3>sQ*wcZ+Qns3S@9H*S`@r%#sK zdtNDbzVi8U_X~em=AQq2xwrT8W%i37H}dkua_`b9TLA1E>G_sRHtBx6;;kuQy zrO)tG6Dt$ss}~qRVqmmgRpj1y#qGM$LwSX}DgXNqKY7 z3(|pS*uatG8r3e6C_)cm<9QB`NeN{y(C0cM=&ITSWeY=k^mdtOvn{i}`4|RyCRprz z%`x!CR@68X6LnOy$)He=XY@*+V|&wJ#8Z7u*;0EfOZW$Lqy!BB*dl&Ce@;RSz>e?o zvoSwxWO@);jDspAoimQ6m35quDf_wFTg$hB0m#^T;K~b+6aT7A$#=q@6Et!6njaT^ zN$~Xk^~igz9#GYevftWQ4}jPcBSetXg)|LO0bK?Ny|BHZAA#jr4TetHUO2GD_%QYA zKAzL}96+Lt#A^5#WUzesvU2Y1<#O%i{blQ><>k%a`=;_efA>$7|KXqgh4O>{;LntA z{7c_bHoxhSa?ST*@wLUa*TYk$TQiVDVdD5i{TDrw%9s`#%@ zE8VltegBvFyEcvF$M|3S#jW?=*Ljow9iOVQsir&jd)Kae*VkXpEGx72MC-e@i|-xV z?f2%fBW3o;{xW6LQd9PwuXl+XuI&B2JNC3}n+A*LGWp-!vkP)Sg^2Mc0=5%ZNl<$+ zBF6}sLccAWhdA6uFpU^;&kgN*{+bCH`s06@{A0-i$68Jll-#!L3u6Pu!_In`pN69e zCYvwE4*fjNYg9uukqeplv=N942M8=EtoG#D6gfOQfHJ2R@M|X(d?$V15-g5)rLvNF z4BSV)UTf+Aj?cshnTNL@8F$Rd*@MKs@>4Y-fb3XK@mj#UE(CV4Xc%{ol;kn&80sW2 zP9B%a5N)!N*Pw`nSMXLYSpTkHtGd; zd(Whx0*Mcp%KlIc0|0}DDz|3I1dMPz9E-Mi|A($T*copNm^pjqshd^_EE-9Q&*d*D zpr>@dt{ari-L8JiU$L)l+V!uO>#zL0ZzX9f;;}JO*E?q8+*g#=IQt(8Fu4Bx9Lsvs z*RApJHS3&uUa$gnl7nhw^t~FA1_tyUj-chgo*m^{5+<8`J{*Gsqw2r*2PN*bk0$5~ z8PjS_OCR`*ZLvjOyk7{~EE9YN-GDUr7PMubaV^y&lir?u^E`|L*H!Ys_RKnlE|8&X z+gPvB(@AT}6EZht^LW{x6$D!(7CJ*4)u$75S*~h_EHfO3K*87Y*R_uTSr2ZUlqETU zt+o2v!w7m)`$5%gmV*L%B?tuI@LR=HZb$VP-%)T&E zw?19o^o_48kG}2Uvi{Lcm%YLhPSdZ5@4B;eC zWS`U53yoKOq!)Wqu84~~z0C1I`>pS%SFi5Yynxv?$q7XvE-|uGu(NZ=nIQB?29;Ws zI1L3w|6GGvXUikD$k$fjsn;t5@tg;6% zq_eSWI(XXmykPgr7ye1DqOojLzUWIFL)ozQgU`eDTiH)fXH*p!w5tK#MLRiFpkRaG z(6UcGmdA%aXkwtGjBUCn2bT~{Bi04eS+$zfAN_6!w0p-%AmYWnp)b0d4ddoY8|-n& z&ls;-{-Xr9XDjJjL$>SJMElKPNSzwHc4CWuj#D(#XMIH<%*>v>SZ*IZVRr=`w`rOaW&V`i`D1&stg?qVZhdlxt(AGKyz$+Sm&cvV zJie*SZCGB;ScUt@joVh4F*0L!6y32qV4cMHV+Ur;-@E*?%k-UmEw)>xSH5mrIkER_ zIriGwvU-I*$0#s8*T+PcJvw&;sLN%h%1Xm--%Gb{FrNgYk{EmM`_;U9`g-}zmrvPs zN4vPTd|rKH=orSGDqBjz;xnD5r5i(V4iX{0u>f|#2|){Idl=&wu|T{Di8~QXzkpBk z7!?bK`~tDu&sAPfuOWpJ9Yb&02!m-d9yob2Sqy}YTFcNpSSAu27+L_s$MW~e{_q`E zId27A>G%52bIv;jxaHu?H!pB;zK z$F;cfa^(yEI7GBifM+LXpTO%O8*i10VN2=@>{DtG-VRr2T7Jo6@Z%LgG&pkK_}o^2 zMxTd>SkDf~o&jtD#Sg>2l|AM`rGwxlpEV-!3ccj-)M*Z!M3# zc~^OZ5t*mowYzM3a%-92xT2i1yG;&XyQ}RicrM?lK^=IjNtGqn9 zy__`ia^%%BWu;+ucV|*=u4u>j`?}KC-`nqMOH6H9Z&!Iq;u5BlzrOe5Vym$4vxUdM z{_>faHd4FkVRj0g{SkUn`HlfMDj#U0mX}=Mxfq`+gK=1rNVL_8;fz0u6Fe5KKx*G~ zjGTn2%@6qnVg%aazP5aVF-WiP*9h`5)-hr{Z1{RH?Q~0t>OehVNlBx^esu7=j?ZBgb(S{Bb7{ zmG?AIk2yxz`RExmkP8QP)~6Z{_m#n`<;WmNss}x8_a^`-w01e~T=|P;wWT!=x z)K~R-3k7Y)1&pgjh|mrQSPN8ZTbYTge)${_Go5aOJk*|<)V6$zZBNI9ez1+T^xU#% z_Ge9e7$ek&V8<+f)_?1B?H}9T5GKUfymDa=QheX0)n$W`msueI-MZ2)f$Of}FN0mi zZ%nh>Q=jK9Unz5^&y~B!Pum_VCt`YOk?q`j*D5aCA6!=+dHciVxpzHUp8SS~$|ie` z(!KS|%UL_-(8XKjpjAXpp1od{ZCX{fz2%{D!m2KZUp?KCm$+(I&cJK%1Mrh|hV5Qi ziO;>iPGIae77`nl`}&((cI)?N4_+ysI(pF-?%K*>KMV_-$tXCPVmY^}Vng~-T?I~O z@1vcp+%iGe7^rQljkNq3dWLPW-Z4b=4UGw{gqHDq5i`)12mAtTHwgy{E zrCDF&QZJlT0m0w%ae59q*UO-ZI1L3q6(SFu4J87YS3V%8c3n`oqGeSK0G5%u$xwD*BoAbG9q$i^lk$FY~L-oYorYS#5^D+DME& zlx${+o$FIfsK(fJ{F)##-jC_1()jZ+x`kj^OQGOZnQNn}5(-2WES2Wx$2qh%hz+ad zJZz90h!k8~*}{-s&?bX6>v$+YFElmM0pB?B8gd5oPmO(unDFPC{c;fTymDy#{%fowlvxQBY#}>aiN&6ns>ElStYSfU&(Q*i3rQ1fW$FfxKGyp<}MLpo;Hr;7wk;dNXG1}NfgZ08x7xl+9>kTyw$m@3gl<_>%JUH%u0x3oD-Rt`nAOE#w|-04O1W9 zS^neC|3NwP>6gmp+tul^ll=|WXk*tb?-6#HOHejJm*mVYRIg>!+^%d&Z8KbtXQ zp0=us6Ou(M?OdNmGG^|#r`@)BTHL0_z~;|~u^p>zJ+BG$n(YQ@8N;mYb8ydgo}Bkv z?rcGs|BYMl{As$Lq1f-7-=ddnf7ZVDs*LV6!`D&yvY{g2zz|pmL&1pKV*rF+(LNil z9;bTZbNPH2?ht`RUz7+dn6`qDI+ymJTd~78^Svg|A zZ0SzP5blcO@v;qZ8!ege7+dma$-qDJjp(**+*p44k?rMi!^~U$tR3HBKc>umrpVU; z8V(zN#`B9jhQt(mk_tZtpE)M`n!&l*vhtM(b@uI$QX=bmN+`$kxr+s$09A*(xH2p_k8HE3bX|csaKJd^vOMa=B?c|9U}u zr6s7VSK9QyJtJv}KQ%hySt(C%UtZSR=gy&S88)A~c)RSg#kq&i-7HsTE#cg}rCi&z zrTpiwe7T&uWKW;IaU(?3BObX{#XsZ6i$DjkoA95s+acn@_Rn^}akGWzL%N@2^X#9R zV6-ry<%+T1`Z=a;2EpSm`^T5=xT41aJ zgn<=<^=DfI5iw(o0oon{US$bK@z1>W=MG`k8zjaT;Tl1)9j3blw?jGzG%Y0oWoUN*W2B;S4Vmo1bVn(mQQrq!Fb}qIici`+m#{m=aZ06;!N1fXT_Eux3>;ppmDdQMBO=nDryCaCJ4YzuYnoyZ^eT|t@k!+~70 zQj8;xZ!8?F0bbU!pdBV~Y{wYC_DlP$`UVCLk*T5cL8e;d0XE0J%esJ{s?PX4^ow-@ zxw74{JWw%XT?`RK_Tx!Ot@m}#ez$JeSpNQwE#(=XayLAkv8uLXvSVzl`wLRy_}fjX z2R4Jq7>Nm@6SGK3bPQvcKmJfz@$NU2U-_q>C@YSgE^mBnUEE6DZKm6mcHBgQ%&c5) zWM)~7gC;~;!SiLmPpI)^U|^^g17A|EX~Z(*_83hb1zntizC|7?4HtX6vQ zef2FTFUsT?)Yzf)WC-8?4hf8d1UnhpZ3S2iT#cXyenvu^Xe_d+pZRXaBorWEC+6f8QW7 z^;ScRn=`hF(xRL8$#rYP$;?fw$|QN2GiUOOjCp6R%G~o{Yh#IxmvRo)pEsq>!a&A= zsAN#}2E&;Y2(`k7_J>GBOP{c-7EwXp*@0UD9DV1Y%ys}9=}6Y7Z0!$OTd{0O*|KR} zd2IK#vcxKA2M?bvCr@20SFhhNT^e~bW;0`e8`sS#ItC0lGwj>Hd+@KFsXpf9g?)#C zNOfN%ktsADF(Ct*za430TVRVCkHO>zsiR(9_Mg> z*|%BF-p7shP{iG~QQiBDG_1QdThQ3Okk(wknzJ77WFnz{u zo1U>p7A&#ptg_agHtli1F!#clt3hH8@3CEY4_~&Y1l%agtiQ9?m*wl$luZxqD64ku zEVFCYmz$P=F1c~JY`by3ths!;{Nx`WDjz>|w%opXJzSaP$+pS*SDRD+hF@uNr@CT- zu6Dw0vcI*kNE4J^JoSBhJo(QXMqo$m=WI7xCE>~qx1spWV`aIiOe@Id3-+6u$UAvy z88aWOL4}3R7tt(8nLc;C6?j`-KKj2TEI5{lOawa%jQFhz z^xYSY$V^*BX3D0R?p?P^j7>2)f$?fgJb)~AbF}kwipeWAeq*3lWn#L?#)xM-u#s?o zG=OM;Wl&=yXZZsVTUnqI3Dzq+$U@-B*H#-Fa>Q!54u!i=BRg0%*%DOcx%7Z&L zmd761TAqDkXL;sz57_H%W#@K#vaH#~h4a_S(c|aKo&%@LYx_==SNEPMhmV{or|fQr ztJgY06YB}%85(W}qv=$PnJX_x{@P{4mn^8fH)YkBja_;Um$B##qOsML+x>2 zH2}lk87MhOYBfp6&DT_5ZUx&(z{OyyRUO4FmIs1yi$Jx;tA5eKCY2dqqlK9)2W?OL zsy4v=QP5W(Z4n$LBifgtpu(9m?2SL0F-9@7Y(@EB{-+--I}BI%{NbK*`n6N#?%6A4 zl~-mgQQW$Ane7K-RT8Vp#QNR9XHPJ@Jyv3h$*bdDt+DO-S3bF`taP+EsIc#Q6DWBbtvb=(-(-jkHXAH9adbz86ffX(un?Ts?QUoH%f) zoV5kNn>TMLE7q`nj@~Fg^80%Yzi)Oi zKq`Q$AI3o(&w5cmfDc1Yt>lsAj_ZL~stt4d(6y4JA)jaB0-s0woKz@jRy*WA;WhrY z2pji@2{roybCs#hn>WYgL@S^{=nM*a0S%N2!m7AQ0L$ME1T7r**6&l+Rd>wOM% zdAB2@696OGW%;7Aaj zfdP@J(?@n}kSw3u%)cF(NkWtBi?B{+$!&AU8+QCnBQ7?*G;13)If02OB_}gUVxl@@ zxXL!H~Hjo9)SC_dVKo{@fCKZ^ZEY zg=^)=vGe6M1IazF9W8rbJx~rFI%TEeYvqdV02(_@`@+8{b(ga9uN*Vb?4Fl`H81xg z2L^;8fKu6T=GICu?&rFbWXb2NAGg3)eVKg;<7<)KRzF*|q(p|Xq=g$wNZunqUQvSm~{6KlbpL~O(P`P{YhCN^CWI6c!k#h9KW97=x3uVd8+hvmxm~Cs9 zmW^wcl;v>)g}J8Rg^5bJuaB9%TUI}_tE~O@HwSrHyyrxD{e!D*d;if|nphg3BqpYx zXbLL!=kdEclhAlV;*}YT1yd`Gz${x?<`%Ckw{9;kmrht*cj)L%Vvx%}v74%qg<9eIHqhA>k74tB`;nURNgc488bd6%Dm8;$w{xG!c#-2 zve;*L%(=V@0|Eom!sMkREBVYNB1itr4Un3yDwFGEtV7e5jx4bSVvBE?=U7E%{)S!0 z%CKEk#z~AnD&80W8gU8o(k=Q0k%?-ISDq}ZXt8$H8Q!B*sNm@G_wU$ICy@;;k#Zkg z9=#ottUsJ?_YUudFCyTm9lxA&2`&+_l&bwLmcNT{yY+w zQ`~vr3?vpo#hneYb|ZA`W6WREZLzx@&R?A^M=sBm*N$8$ue^G=?B93XrkqZdGX`)s zXLeXA`mwTj)6?bp7yohY`Z-$fgp8pDHjpJ(k94fP%)Z(1GA6&=XN+0TRpLBEQdu61PiT+Ni$3H-5nFv2y5=MzHH2Y)eYIik6O$(XoU!(P zf(rZJkPNvUmKOp9`zE)c$Le=%M;rqxc31$}VryRh?%Q{k?|NjlRXA3bnQfcwL5Gt5HSd0H z7`Nv2yUP0ScuV=!fA+~T^YZcX+)g7eUQMZsfxERcsJe9PWtiM_i3SJ`lbY_1Am4h% z_wrg?UV8O){$M!M2S%x~I*8Gr1v2kd!AH+y$JvhTHs zyZUp>o?FCx$iCIaCgF_Y0_>rM<1JgzxZlF2A=~19DZx>@0`9K`t=%`J0m6NzNo-G#qdUc2%O%8pqVN3!tb*P1c4IG0P_O`&b6)e>ThWg0PH)mseXv^mE6Hjg` z+hZ@DrDes&)n&!D4Q2U`&1LEKO-3-*mqlw<#gk?4+1&`S*w2aQEn9TwM8&6t9HD0H z`z5yiX~_zkj`TTltE@zoCW(;kMRE4rm2%XknD*Fq=P$o}xa`|^tQ^IN*oX@M5#-A^!^1fDIM@#8^qxL>VliXj_CyNoq# zGmKHVUW=4NPKqrp0A`?M;s_j2EW027;$WbJgNZx7193vzJpPtU8B<%tXedaw@E_x2 zV&|W+>>LYy!S26%|D)xx^-If*xZ%Kltuj8daz$Be3B}B|&1J?G^p*{4qXK&O^38JM z;Mub8D@V(*S5KB}CoYy{R=U}|a;EIqXm|cBohqB&`bb&(ogI0Ze&JYoX8Y!ia8 zNlX=WYiGKr?~OWT#4=_%X-vGI06!^Uvo5qEs@T%v0k?iAb>>;0Sn*MIJa)<pQol>}C3U^V(9aiDcxnpp*aHIE3jg}4=sAJ4jrc(Vf&;f7(YD0F! zZSpxvc!vlu_W{Q1#Bq)7?)fLStu1S8U6WU0X0P8WcTQa>xAq?^w_Z6=Zojmz%^2UwoeC?=v>fD`j`?lS^6c0rld8sFqeoar3 zJl)-EH(LDeiA#nJ-6nNo@`;L0#*D;Ie?Q33sGcjd-sNRNf06wS350Q(Z zxXyTk*X$?Wp8A&hxXNx4wy8|HtspN$0K<;g0u&y&0ur~$9nfiQj$jn&TbK0M+lpF8)27KKeR^6@PzD^_XB(}vK@9B_^ z^vIs5E_!b5)K}h+PP+_(4G1r`Qw1x zJ#l)m`A*c%ql#^Rb7Q>jSwu--lAQ2nd3nkR2J@Ix=j>4fb}N(L#pDhd)$y#7$IQGJ zXYJ(uSMQeJKXutK`%+VP-8lG$z;16!{r5eC-{+E@D=@_n^0wpI0G#h{iC zunnpmX!VoF-NN-2UugNMk~YSO*kP9qbRobTawrA@B_fl6bqM?*Oq{!B&6@JS0}qs^ zpSCBGzU58j$>*LfJ05<(ZgE>#F5J6PF5J9q5AE`m?VHM#n^!~8X#3XP+vTF&_U1(9 zs_oY3e8j6V{_CU#(?7mOX6cNPf}C1%BEy@~b?v2xWWZ5YfQ`38rnvt$&g$3$uf3_n zB}t8v9Y4Psk)7{-xqI(!xixK1U0rTR+r;s-@9^uleOmyYi3drJ9#?<|d--~p*c{LM zMC5}Fm>omQoP3<>O9MdbSOsUc2ks9CRD3@4y|=O2DlhL`zcR>6H$2F=ljKylF@)`e zyrQgn(_`iA{xjvZPrh8Xp1xeJy>Osh`P?hz${)R0u6^;)B*ildJ1z0xLtVNoeNmJo~qD&FZrA!3WFh-}t8To^Si+@&kY7yUL&X zz;~DT{>g7GZ+*iP<>7TxW!=;rv%481rc>pPO<~PubqB<_6;y`+OOI7wR$24+Ex#NB zs1`;nYwdJGQKh_I~*sA3#%Xe(?XB+tryNQiSC~&i$uREKvyF8aY^+-8=@O(M` z`MqV=%$;)mpb-RD*V_JcGuBuTTeKGcHfW` zJ5+R)7q7`2xOTVv;hD?k^WF4t&#w}vzZP6$xwmBBBCA6ryyeqsBa_Z$y(-~Wdv7IK z7)vW5;&{Nm*Rpf&M+^VQtQ!SaZU%z|FcKN+~*|xH_ z-&y;eGsl~=1;8F`Rllr zbhAQ;S3&HS^ckB@wA(#n2hSb0@bJNHWvT7^u-F$MZrWr!F57v&9wv#4t!TE6IFNND z$)}y{{>*Me3dlbYS_E}p9eBRdC*d7sHy_;HF&Xg_X(AAl;ci(~X>dSk| zo;~}@VJoknJ$trXw|!{tn!WimxcttFxZ6o8G%UMTaBKOW`YFf)x2-^^I#T=L>#)8V z8q)$+pCzdA*f+c{LPK$td_B4)7rA(PrtXk@Vk4; zSO3@FE8q4;dwO)losL~Nk?@D&&e$T~C7aim#aq^wCH8CO@^JPWXRnr{w%GUJODD=v z+jQ=_?b))-@NA3utKY%2!4~~4_boHLsF}am6ff{RH^Hk5d+q(S_3tZtua&DeY*%03 zR>KRovGZ>C+ZA4|!fFZO@14C-{_%@P>}DfNeuccW^ipM%cb6)e9wHNy@VTW=j+;Zi zI}~eiZp(Mzqk*;ZFivexNit(LUjt*t>`RMl42_>Z$LlGOmlm+yR}hsT1pz9tX*nT; z;&%tFUAwl}qY8qo_^*=}kQF~})}{dbukXEa=iY3&K7XrRyLT(d%d5BT7T1f1f`q*O zfv4=rqbJM|bE&utf~y;G`?4>G}p@A^Y%!3 z%T{LXNvx>8w2Zt(L|cZ(fIi77h8&uWP=gqcvGpD7C5+$6%f=1muRXNc$csIM%|OQ& z+68%W65~&s^^FScz%@J8mq&i+{pGb!?(Vvb^Q9i7}#ypb_0#h+$d-4;dBQN9w~c`$h`9M zYqltOe>rsYc)5J}vTcrawOqT|ztiD<{B!7-p(KTaslRS5eAOVUBm#C1vN{xO*$(*} z^cf&GL@WTTt*JL91w*#1^1*rVhlPN@MTF3%`ap{WpnVQzN+uyEY(39G0M}}f5ItUl zu8yrmt{BgGT-66Hf%vJ{?I=%L1-K(G-JUJouI3$ynKHavx@B$I^ymL%dExi=l;{8L z@0RyGyTQmy9*4Vy0$eSsJw@4O+ROQXB%g7 z4808bvD)AytQfL!|GahMjQUb*oZQ!zf42Nx@qqi>BsyOUd0|J>5@eWN&WTLQJp4G% zsO-8?S=q5;N063v>(&)pe-jLO))#xl4yfHUKxJBHgI*rA8c2|rtG0>IWt%&F<<60E z@Z!;!26}qOzhlYCOaOUQTRJA{ zB}OI9%4k^ILOq_r{#27a~+HhOMbgCW{vvZ99U`ax+Pt{IZT$5`(|%j1?K3mIbz52d&@NjzK2zo|p0RW6A#oeFma@ivS8lSqnAX@< z>9((gPdWMBUpY5lt2MFzklzjA_Uik`bbH9ekL@{e=HLslHTnPaFMrAOI+|~9$$iW| zVqMLs#I1o+gH_80!k+1QL(u0!z|6Wg~9kODK#;S3oz%DAS1 zr6n^4S{|#CI3;)fyixyE0d1V;CSkX&Y6ttb+92D;{qzUp8A@u|e};UiWsfc2Z}qJe zd(`*q-9}wigVqet;*237GLUh@t&*`mKash#OaJ=y2bIxMjjlD(X)x z$m-J<5DKqYIC=4@CnqGnHpZuw&R#uVj$Jwx(@1`YlCP18K4ee`0PU)bwA#QM~ikA3-+?Ie7~_NBRc%N*P)L%v@OO&hhY z(_-0dZ1-dIFvOP8E2%|$d|iI6q^W0bMg&%y-MrpzkzVF&hTKM61Npyh(X}riwE6K> z%gffcKT*yfJzoymUJVZ#5cYoJSSHHdg56x@k}v$(SiYvn&NcEK8{b{KQs$2zDT}Pq zvUtm~@{-*h@rD0#psZf9(x!dvI9orpXsO*HW>bt*24U}XeOx!a=pSSYwo#2=c zUOQXv9e<(B@BN)J_3FpVsv9qsi>FSNU;LxP)+f_pR`Vcd9tVOAe+OXk^WZ<+Mys73 zc}@bvV2Ep?ZPvM;%bUUBx-HvL+v005NoWOC{*2eRvCXu=9G@{s(Dqe6usi?DYr`-m z4P1! zrO^|Mc))C~E%A!4FNk0LmdDGPBj?MBFC8im*{-|pLb0U-{4Za3%L=;~;A~>b*PJ=A zyI~dN3zy1Wt5D9KI#=e-U$Uv$yJfjO0$}Uoo6D1L*iqi}jt9$wuiH`<**d^eHeJ5w z3TVH#cOD3;XO_-#;YecY>k2wfaP|c-<9M<=E#NP<=jK3@)f?m&4+$x8^siB5;MNrNgrRNOX$izk*tcU?)wGQu@w$-~>ru|4O?{@;7C ztU7g|T>kv$%hf;nOu7Dr&zD;-zfk5*9kshFu6KTAcW6w_7-3&zgvF*I=g%B2^Lsv1 z=Dz%&%IsJEQ<>lYN9Epy!?t+%Mi7CQk6bCg@yADeg>dMXNyrdT3=sqNGbI)ZNPMj7 zhHaSxI$yUHWZCW(0(%Bpyk=6vM3-#~uho9JBFNWfAHcXYU@$(aZMVkB{(!a?BIYU^ zz9#oE@PXDL`1LvY)c)YTCJAag_#S^XfVG0CuMPQQ+kfh_wgtf%!x-D$p=@*_;}u1F z9gk}MEX&^Z4Q2Mp=d6Ni(_L3imX}|9t=zEv zXzKIrDA{2@QW>e=R8SdsF+@i7aK-_)wH96~#>4jcS}osiVX*o~i;(d#+)vnd%kGBc z#(!G^u-%;^-u^hDvCo3EbjMoguv_SI!K$qzSiQ*Z zAhNqS{MugDbRSx7q{gc#i;YlW!7dicx^wtvPE>r|ixZgBSI$|**}u zh{=kc?=7vcz_{#+?Kxr#b!TthiAN{+v;{jFbjd*8GDbF1zP8 z2B6w!6XIRVn3g}drTpmM`+>4)_vYAC?(#L?Q0}^I`+w6OU++ZEjdApDVY&@P}pg`7e}vNA{Na6EBy$pZ)bR`^EoK<_txQ^x*5BG z-8JWPSAL(vjHQaN+3udd{zWG*qdOhcFI7jXQgW}^XJ$pt{LmaHQ&?%(Rodc*lx zdx7_=Q`iVTZ&f$=9Bqe*)DZYHh%&e;plaLrp2@Zn36}jBhGx|QpKBn&*tLHxKWxch zsDG3C3m;z3iXC#k3HF1;_>?$n>Qy_TN0B;um^rcrbwGK-I8jnESA;qkQ+pm&!NawL79LYxy19bB6bM zfgG?li**T^xn7xQvK=U9s!y}6sQt8Tj`5uBnr%VxSbY!eYCqY|G=^ZT7$^HzYZ{j2 zrQ`WQ?cKdJcw}C7d!4QPT?EW{W0h?1d z+c<4of7^Pz^2YZ)SI*c|VPE_7-m+tvk>%Jg!YBN?>NY94?o|=j&N>X{k-GkL!0Ed6 z+dyaRfso4{-dau>aXIno8CzFqk8^W`b(ZZ_MBjJD?CG9?rr%mUZx4Q(J-oL}pFi9^ z=*=hfo$SQA7cXaLr|fT#m*ZE;uYK7nH+i=k10(xoEAT?*?5nIR&A1pq0TM%1H3iTi z4B<5#N}O6`L)+0Y!v6UBJaz_gZNF9h&_K^JYk_;q)|s>@fk8jHVy5Jz62fd;eP|M4 zLw|7{ZQGM6RMLlhv&z^hGu`a4kiM!ddR5z|+i%^uQ;rzEfA0Ft@@Y#XUNRzc)qXeF zbLO_c{|)7aO&cAxsoR~g@my!;^_J=+ENuVbM_%z9n^H;=Y-MdE)&3vi8#PvdHdiU19O!v~6Vfo0go+S@O#IWK2^s$oAPH`HZgSf03A(pbwqff9$_zx!(@IM_B6A|SJ>PM5Xs?}H6C;Lf9 zUJNj?pGgZ4w6l5)gULo)#OR9f%8FmmfeRh=y=vpfdyw*}09KYenD1uld%O6ZMZQYhr*M|oEhAQk2@>P4oW87?UQyO8T4}Fs zF{QD6&jjZdbrln@$oSNflNbMc@%rVs)%wJx({bmL-*t4uNDPw>7H$L^>zd2&#_e0> z@{OxOW}JlhqTf~4?mAoWsp%dK&m9L>s)-wkH9xof6X2=ZMTE^A@$k)`@Eih)nz`NoaQ%G)oUDYJVH+isrc;@0T3J2#Y_Z`oa*G9vSaZ+Wsj`1Fpl(&oi)UAj>Y z+Lq*pEJHkL8R8WKG?#NM@^vB%GLwKB4wwWc`k4Pii95>IzNTjN^0M5XUVU=kxpMr~ z(`B8JmkPE~Wpf2Zy4XF0&Y!>J3&SlNosMTQ<@W*Roqo`Oll0e4T`j-y{P7?!DhDQa z(31wz78&5_Uj-pRj#W0 z(1mXsVO4M6nfjWMnEgg#K6Cwc`Teuk%DzMA$~oIBW%|VB@`NR-zImok^9E-@)g?E% zBT-gg;@xxW6q8@nriA>-(Mun)?FU{sS#F=ZS{~kE6@M=_n~%?3u_wmcW|epCch2^c zx$CQNEzwZuo&a9=715gkJ}wi^M>6z zB?vu0#?S}fsR!9FR8e4=LXUcmk`gAQEqqr$tFbJF%yufLVf8YYR z2K%3moAIDU{QUT7Ta(h8Hd4oAgB=1Vb}GM%$Oq*_#5>@`!z(SPY|-J*{LIgkpZv+6 zEN^}5TZ@w%Cpbrs9*ru^nKNgCz??gGE?!@{)KzJG&5UnQx7GsHs#R9a@CA^*U^0I^ zkOX<@YA^A6@svF_z>L#q&4|nxsaZa?)aGKB+e5*O7!?Z~wns+G3%Q|IItf7P~+C#>K1Uu926U2aa?b&h0;1 z=Fi$z<5tvIy>)G5Z%%67_-)UWUACj=3d_K*En8HM+uZpf+iCZtf$UWSI>*kA%-G!r zzK07G9c7jnT&-BgTdTY*He$5mv2FIOmNVtJ-Sx26Zq)=JceHX;`tBBWM|a|RDo&2N zyO6rJvp!zS=Ej{V@BLQ_1kc+g~Ux)k-{;U2LR-0>SS~_Gb;=bY7?yu=9cBHmVLT&G&FTZ%S ze0JaIa?ou0kgZX1ySJy0Sz_7kn(J#|P>t!Phn&bK*j8ds@6%;`6V4eUFUxG|_MnlM zo2Rdohqo-Zig)^+Pc3qu^`3Y8 z3c++P@B6>Ja_M&YEqglloF$q{4%MerHmw-S_SNz?))(uOi9P#|VkFyGy!Ik+KC~Ct zL&b*mi#B--I$rJ%6A(U^{SxiFHoOlyb{wmiRnJRbhppo8v{g1fssn8WEC>@BH9Hs! zTFHx7QQQFhHs~My(I2%f(|5;RM&J3J-&y{`U-%2<+rRzW%Oj6G64j7n$Bvc#`)zNF zLx;-Y!-wPds1X|{G+vQ$BIBFYIq|`*)s@J&)5dcsx{Ayq+o@>ANlj$bL2J6-AT_qw z*8acB)`hILsioCMXqL>+*aL;HN9E;)Ioon875Y?tONd%ScTQ`Zdce#r`y$?SElRbE!zT4MX6S;fT`qS>CYF zEZ2pvF@o{()1w)P@LB_;W&*9_*r;J2>|ku%I3GaHfX=qaeRG-l;{m?iwkF?Tw=UbP zclT%j2Ohs`&9be#wvg}k!DHpN5t-Q&r)?3eJzvFG!dlz+<$>2fRGxmfZAtzo9xD&O z@qx0^cJsVu8(p2SjPY=g8C%=r+xa^=G2rv9$=#Ovj&6E0;9P8T<}07rR!;0WYvkpu z^~=diM3D-#TKNPb%fx@0l&l1jwGu+u$?K+_<4R#Oli2xsFd#CVXmBmr}jlb zSV@P1atp}W)?1*@vf}C%x5eXZkpQiVK~C`3Rwf?jn8~p3aQ`q?m6P|k-W}$_CD$|ZT1224kr>MM*B+Llg5Di)w$dR;uu2iIl!ym*lG z#j`hUgRMXHr~XuI@$av_%Ho~&+o!+r8^5vq`9J^X%lCcX_eE7^_3G6@SoZDPR}LDH zdHLm+%WJQ`T3)ji-(ID;W{V)b0^>x+?_TnCHhxEwlbdk5$Yc#5%|4y5_}T^!-cDwM z(Aak!ndyklQmfRgu&T`3=~d=DR(_nbYEi6rxf)L7YgghSjtRJ);qZ>S43hd98H@|w z+i{0DZ;OC$TGb^M_8NituOTcj4rZ~jaM-4&HZHc^EbrOVlx?Tod$y{+*xfky{MWa$ zPtbSyIf?OKpPIvNraaxlZ6iQ1AR=HfxN<`{_R`1@BWM;M;G9q;1lHZ|VMANRb*xHTftoRg=XMO9elK15H za&qt4a^$r$Wu@&qgRCw5B!7FwGW&4#QYX?*UOI$DwinrRW}1tA+Q@eI{PmYk#bUwm zO|zv~P9Nl`zn6;!SAMV4F$!?p9$s_BVhj+yXq0=vw5kPcOWZaGSOsUcFSfan-aFs( zDPI18tpea+=ZsB5AdJu1UJ;mBzUUhh0hTYfA4DtdoyVws_BNHY<6N|d>#Cn=y9jC; z1a-QIgC6VDWy-kH>wi=X`wRXx=&&3?w77lrcixhVc}qs`#6sWO<;yp0eT*dwUornW z=Zo;o_BWZ2t?-ITR%4>56j@&Oo=A+ZY4n|WS3GLu~1FC)+$cwen4bU zLG?<{*^6HJcHZLt!D;x(I^qjBNsCMc7SuR+Y6k>=xWB zMvDA)KqD<)d5K59j{LY+y7TIo6Bw*9a>9u|0nGe8+Wzk~qHE&?M z$_Uh&XLdy8<%sS0xxy+qD1SR3#`UZCyZ7F&wZ03eKRh!)Ia9>=(^X)W`nWw!M|OGzHgBZ6?YsM7K-3JK?Nx(3j%8aI3Z$$f#swyy5g6oFU+xqEV~TM#_~zCPL&Qx1o`VznGRq5}vyb5Vo+$F(II1hv z4TE?kb-DkDl7%6Ew?t!u5I0p_V4t^ZgydV&IwdH;9dtYSwUUl*HD>XZ@hHjeS?%RLZ z7U0^VUMst=T(zb=_Sj?Pz3+W*OfP-U_k2%GH+g%0my(kougo}s`O=rZ6u*1+?6I{n zm!bl*efy5GYuCeN=gtSBLK6#rEl9^UNvS2lDj8TkEW3*ZiF0H+U8|`%tf1Tjf#u)!3oUJ z50e!?rjnJ#Ys&T|8_TwP>&r$XE9;D`EWKvqx@sAX?O8B)-7<8qxJ1>(uI#r-$Mfpj zKWyXB)hs(z9SZ~lS*ixdUU0}js(=nK*NP8pgKeze`$h3!#`oJ(r8k-$ zx`)Dzkgco2c&EFwMh+3~-Ib1`Oq_G!W`A>5nQ?M6{lK>J2mk($%e9w|l+A1G?lB`s zJD%BIo_zbm<@NTv>$&Y^#f~-Qis^mdnVYr)=hE`nJ9d?$2Aq4pdeY=(q&YIV?pi^r z>NcC17jy(ZCcyoSR1C+DvA-Uup-ex1r$25CFW2L$Iks@ouU64AXxsIjPN<^Goeram&B0A z1=;&&AYdGb`B<#GP~F6}oF({;6h>nF#)pHpsQ!;^huc3e((tMgnVVKUU1!ru8_XU& zC5^?nxwzLilUcH%BQHK}bnV!s@__BE>(fT4yhMT!za2SollSwFowvJ({5fR)J{-|V zQhe7{UA*${1=a)CX5+z(zUGBx%6jkVkfufzHz5=CG00zuKH6p5Wcz@;Rjw@}+tWuj zj9CQzuD7-{@e4cOGX|(VYJb&U7$3Cn%rQ7N_;Ii`$TOymz@(Uc)od#ntAdLBci%C4EX*YX zcFSt*c@;}+!#UrH_w8?gd--#J?$4D!`)B`bdFMOd8IKn5zWe?$2M->MX{9fJ`OD>V zpZi?-;upUd1jnm9Yi$!TCovD%Hts&nxw|gIJXZ)}2 z9W&!(X3p+}nqOL$+tkwHd0!Ij5ApJCIXsKjiVW7TbPlu9#^Ge;%FS-UE@TE}V`Dme z=fud@$*fzl+A1q{2hH?`vgz)cvhJ2`%y!iP<+70!D`(EzUIp`ZJL0@oT5j95Zrk6x zcES3KS}VKP@M{nZw}B=0RAncee)rdMdopaSVajNWsYQ0Au>cxi(GlQqO0R_FbO(9> zf?UCrN()MA;0WEc(aQ3Ed)|oy8W!h;Sn->H)FUw&fI6Pj4Wz>?-_g!W#Ov0SnTNKO z&;G|3%FUM!m5uf+lWY4=+H})d+tKr?>D!)_w0X7d9kH#v?rpou8{fIBY`4X~ORf5I z$Eq@C?arXf_8gQe_B^TE`8bA-h`F7_=)0`W{G#1OK8&!C@ty$HSjUj~@!S83k>e%J?e#xg~p>R8RT_%*5s9Ei}K z>wp6tx6gfQ?HdM6z(UT74Zd#8NX%8My1!=Cm_M|gZ~xHzYM&7qCl(vbcGsETJO17^ zKU-``%qsIqpEkO7*vN}LYsm^SSwiWiVUxRb_>jEj;8}YFfRUeNzBNZogE~p;{L>R4 zzZ=Sv+rx&je{lLzEI?Krw2+kbHROLhrNYycs*9cs)BpXNN`}=&*f-c-xW70D1&Wpp z4Yf1$IpP<$#e`qw1$lCzL2NuB);905 zlKD!zJ7kG%M&x%MJ@d@7<^At}f2^bVmT&o%^7!MA$2u6Vyqq|3B8ZExmGLR2Kl-E3 zmal&GtMR$}vsYpsc;G?%-DzZMvymv9Vlv_p;lqhcEcoqScO=Hw&)8p^dcyCFkr{uA z^NRT;Mr3U77+dh`$9m@OdvjoFX{11(Hd+}D~S*kHg79GIqOHniUA!yY=Tq_p+ zon@W8tTDZPr>&3LV(XExTPKPy(WhSJrAxxF9eLM&f>^$ZZOqr(gW&9G(tAFCs4TVY zZ`%gDYr*b}@CCqk&Ri_Fj-4&Hj-D=ePn<9JE?u`rM%dm#w&9jHwtmOD@`iUkTpoSK zCh)ecj%lh(MqyGT1D;F%Qd+FHK@&~V8C|@+fa&q4G zgn9UpviR-qE~j_Du6+K*=gX~YzK>8>*{jZ;q>zJ^S4UWe8c6&*ej<8+p#2LHL!^>{ z(2to^`i`KKM#lI6km3GufA}@G50Vj|WyOyBhVv8AV? zO-I4cwIa;E-m;sxE+sA8pU_1TuaK7z@7RIeDvo!J$Xql6|B_W>e&2}9XRRW0)G#m> z`r7Z7o%YNlTX=uyE4BgZ!Hcnv3<@t@@?vchY4MAC_2zpH1a;m&yN#f_ujw&y(Ax->SNj;8*4X7S^y3T_kQzi&wIExK(+=rvz-N`tP?NsfL zzeAt-JlKDH=h?Z~-%#8Bd8|95*&0niI3a~>{Fu63ix&`b@ig~a?Phw#a@*&{OX$Sf zAxv$6l~A(>XXuetc8f8c7$?yfd{=IKh=XVY*vrWV9 z*{#f9Jvn0=8u?Rwt-@i?thqb0q8z$3RX)4ta{1Jkj+M`R`A|7@_(a*Z-lj>GOj{;; zH`?E2JNmxk9q%aL`@P>=zT-Q-qrB-&Z;F2SHNDCMGUMxIyei|rPHg-;uM9bX*|~G4 zt+}zPj1i-yc2|xAdMx~P{G?xB>}wAkHZtW8{j=Bp*X(}DtWCEV0b6Om%dIjKR47Yb zF%@I`$t<^Dzdibz-9qgo#$~qL)~sw?w$3(A+gu))v9%Uuqg7W{mz6iIvSVcBo{<%Q zsG?5+b&GGUPrio52+AV+*a?dN^IpueJ z-LmOF|GjNs63>q^T{7sa)4}+l~dFU**I`{QOk zz}q^P*{e2PWMt;{ak~@l#JO_UZq>eLd&jt+ueKd_cRabZJZamLKWn#gKk(>=veceT zecg0+%C;syV`S#4WpZ~7J->ADa`~f!SIeopR^i(9VA=B4Hb-^tgu^#7fUH_IPe zVsP4UZ}ZMI<+|-gJ$LAG*=aH5PD~}k$C0dzwk7bY$_ZN=7|E(Nf5ZIxhCdWINR%yK zuxa7*R@M2n)7Q!;ZP)H=wy^k)O&hTu0jW$fVCPIGTRwoXwf@#|Q*72YRPF(Lp3vlt zCEPc($NRape30z}x>NfL|Mx07B~t7UAi^$t*!dXdI}C9J-e)hm@<9htQbpvrQvKMb zP-1mpudEMrqYL<;y)u9d3rs1T$ti4J{EcsVV`SsLSBrx!I(XLt-?!QV+`sqt{$5N& z_~3nmIuCvx6c=0B?&9qwc3bE@TSqWg4xPPI&Rw=rx!qbfV^P@`KHjl?I4)kgTK@WX zJW&4P`+NgATV?L+Sh9@de|aAmUmNqn3on$(fg9m;%3cJeI)Lb1b)CpMLU+ z(4&t&W<=P z-pV(3W{kK^-!0dtY{%RgBLMeob2{5F?yeoT!uDR-Id4x$y=_Xf251EWy9>hgjwvL|R=5{iK0)=CDxtrCS8)NBMb?q5Jcb@(JIrQ-42a z*BiBKk20{&{ehKgh$s;U_@*<#S@brW+Z+!uN7-j{phBcefGvZDnv>K<~ucF&F5I zt2EpmbTQFvvLc`X5y6W0_F+(B(9=N0w&Cq!{fj>`!|^9(%p+Lt~30xO{8Q7U1 zGl5d@?EE4tUTK>E<@iRb6-=mb9Lt%B83zy$u#hKVFanZ}h2LvHWs>D>h0G`rdcS!6 zLJhP@j5Po z=|kpo&zZBo&vx8>$QHyewc7~;UJZ-GXPr~~)8>7lytVUXTUX{qYF{`XcO03n{SL%) zwoSqptitm}ukc*4SpwTheb%OJgL^xY)oAVrycD)B`8#dDv)C75u4&~WuK>?Uo66E7y! zd@a~-oZ~hC^3npSDnJ4YzaTE;`;veyK?r`=k8djHIvjqK)Z50ohb>shO4T)JV#cyX%iIWu4OowmII&f7w+o3{6c-6isWdDp7) z-+%kVR_^N-iRmwd>Fx4@VPD|;d3#{qXFl_p^2#f(#CjXwB+t+H1*+ax@4xret2w?W z4W4@KLD~t7lNn!(e8Y&$Ei-1{r^PcvCol6xTAau@fpOyE)W$!%XRqhYVeZ(jzW40C zS8Qw@aD4AmK~pzI#N?i35MJqVV&WB)`5-X-x0^cfAT>@<`ta60^s)PgCH*nVk_KmCxX3{fbrfNgnGph=9QH*pbv}8MMIib)|mG(bue8 zZBG(kTz>Q4{8f7h+au-N%g4&0uO2Cfp0~Y$Y%{F+i`UBrTT`;bsvaBdcjYp-6&r<< znIJOVB2*_O)25$$HlMxv>4(djZ!_}pPd`x>?=|wWYfZUpI*Y1{9~-|(dO%_V_&Tt1 zTaVMrH%=kAxz0b&tRd*6R6+l9tnc230UIBqY3n0?LtJ!C;yv{!0 z<1L*j_%JD{fw*I%eL@lM`3o>NiZ}k!K0)a(b(dyC&tGbR=-K2gUw=Nkbf7#XuzHj5Evc%TrZM3BH zIZJNdVTr_>&Hr}V+Q~)cwwPpSBclwDetgP3wd?K4a_SoUX5{Kt~R3Jw?RMs z%roWnuYY~qN#wUWJBjdp0PfoKim!!nrhEPNR5^KNs#s!OzI^a@`Ie^^mv4NXt)rRk zGBf{01%}`IYXnyR-m5YpOzWFZB|ZQA^W}Gb=Xc8Q|NifnS8X2|pUU#%y)xu?+4#B+ zCo@i9yszFrU+nA0_&A)*_^%V0*l^B*pEKJaG9WSTEJj|uD&xc@D1cWlTuLrqtE4RQ z1@B&Ui6!(PE?HUWR*uzb2on}mNcw@S1E7A@g~>{;qEE8oq^zr|bmV13R+98I;tXf0 zShS05J8Z~BT0tXpa8cdRPoL}o5lT-&ed zZ_Tq0mv!%db5vet?7Zh5G=k)PLe|zIF$so2gg|0qZA+3F*K>Zp$o8aJWVd6_+k-q$ zoViyn`o>o`uGua6z7LS?A7cxoXY4$G+=ct!O1s`~SSkER|8QTqYmc6Axw*eq`H{~8 zG((mN?67ypkb^X23s6B;Rc^AYhd+`@T$$N4zdTY_mydGWbJgkP`=h7RjkH$`gl(U-c6qq#V2v ztTA4dH|x-k<>Q#RaRo@-(T{_k8?IVE8uHoJIqdr}p41%^u&}8G3c^eXaUGuO#F#G| z4*Sm)59{9V=h|BWwCVQ&&J60|&uQwvI)haU1&#xOEf8Mq{@I}Aw<1g8! zd7r&{yBxfBz1%d?;_GbqhsUJY#z8try!(Du>8gDO%yhDdW0*jQt+5}Vau(#)r)0gl zMboz2KI92qDR~e4bRyyF46_>7i{+wB5EV~oTEwSCvd{$ZDEgOUkJ#k5R9kyN29uD~ zL@92Z0914`3XE{*NHP`v?RWS_<;8v=e1KyZh5hsO+;A8_CK$i{!=gV9Qe2WoV0FXw zN{qjEGT@aEpC$s4@xbYyImz)#j8|pe@P;?UZPGq{h z7?_xFl_mPwsK|iK_}|#C#eV(ANsF(6`Shnh9Yn_ORPrj33)K7ULdo9j6I8cAgQ7=OxkR8;cUb<&lNy`3;XPL#th9xoT|!EG~E#oJ`r*iPHbYSUUWWW0IhpY?d{%CvB4eM29CA7de=Di+?R2wx z<2N^a<@rlCH92o&*+`3hu*ANP#ol?0%V3qg|Btqq_alGgm6vOyMVUkpv6cvnZrLXR zV%}D-q~8Ebp4#ZFq5B82)B{^m5D2B~1wg2v4frcrIXzOqBUGz>}}rxy~pOa}}cANs~a_o6?ag29Ld;l#D9gJO;mH$T5=z$PoJT z?|ZTk0tk}Jz8d2oQqdwlN|d=0)FXmvXIR7u!V-yz$DP!Hk{$n!?}TF=^0Dq)UM&WB zS!=N-@F=SXe%`b{8_yreYd0J0vge7t#fZ$i?IDd%tz1&RY}3up+f?(H?M}h{SFhW8 zK3f`KJMY$DDv5pc-+dzka)>HlgQSOS8U+C+rA*pur7;(U!@jxF147#Ro!X%UA4O$1Y<@|Z#4B5F)Izumji%1z&(*X!8c&DQx=3R zmX21dt1+W9E#Qhu3$EbCPL&$8!z9Mra-!mdz{!BW_Kx4MwI$cBD&q@5eLswKwp*@O zI-Y&@+47dRyv6P;dL{^ilZaW%j-B}UVqH`WKw`WKf@v$i7MDbo%jS`qZaB6>DYukp+IswLiwd_p0%8{q}6H-gsYpy2*)*6B=*F2|+AwHPUt0iGt17 zJ6(z2ybo{A34{ML!s3rL@V!`^S#mW6)syb;h_rO1BiE()8i1&nbc6`Up^}2NDzSFO zr;&p2bfl;ALJkij(ld#$ROii8Yt*4X8W@Zl5KIP-Gu(lr9 zvaS5Wdv=#+?BR^Qly%DIwS#b5z_q*5X4bAM(_1!{#XGl^McX&~!-V28myNs}HX?KI zg`?%v-ZQq?_Ig=s&qv(0Vo`bOy-$?~{`5P_ul~{n6EQd0m*@Ikga3O_M#tH$(>(9b{v2a1b`>NJ%Fl` z43+=TagZUv8|1Qrb5^*aJNO+)pUWjSFr$U=OhQ0twEw*Toa5HdV*H6$yhg$gXOgQ` zBFLEKh@is+Ym%Me+Hp*)@|!_Bf^SacfV`|*x36c)JQlC44&l zN_HJ`@pdhHp0%YI9V&}l+=oyJqCP3fU~=JY+>g#Vky2f^5(xIGCMFRERNq{)c8&3c zQNYoTdncR?bs2pZd~rNyBdl;Z8_offXD9bIe3Q53%evccL1a*s@x`)tY%#Ad%JjWi zo_zAj^5!?cIVv+wB7FMB+wnL7p!R_SgQslNi5c+^4|&z4y__ zb=RkroMhyJ*zR%f{q-wDL3)?NJ?F^l0*pr3umo1GLWtM_tp7nUKAOdm$Y_T<>lx8#4aN*_QYr> zEFcd?0=ll)XGR=nHm)lx-v7`limKj*jDhxmOu^&G5v!oj5&W+VZ5T!Rao*j7YE0J zU`!d&-)Xz{SNB}8M_tTWMrgOe+jsHnV{jsr(=03P!{0uAqkQxW2W%gitD~tjfEXnW z?1MoRqn+*m^YQKgi=*?!Z-CJJu?hU2v5m`pcN@RRNkltKWNI%is#Kfj+4o zTS*6G#WsU6BiK~kc(o}jK=E1HdacUPnvrT#jTi+z#@<<1y1QG~tXZAJf3)bo6`SI+ zUVXO*G2XR1m>?sU^Vs-g$|J^=!4w3F?G?eE<0ji&wf(d+UL#YdX_MfGOoY5wawpY3 zo=zSbGmlNHXGktNu|Z$M_p@5YK8E(Tce*Tld`0$A-oO#6Vy__-eNu@?-8gOd@TQu5oOy(;62 zYMog8!Y}+nR74Qmy-MS^KR@-5k21*^W(Rdh7aPPvW%s!<*&C zr5k0%`sL+wzy8(oxsShW6XSR6nO9R~`>Lg7^Qt9fmETR|i+jBS)NRw;?cD+rlha8- zVz7`m?r!R;MzPp8zx(RmYj*qPY^-&`I+t!qjb}(5X05PuKV^4B{J*|*u-v|JWt4Sg zpx59S^2&d`wJ{kXS^!Z$%j#I@;Q!Cwe?Z-KU1g%+zEM|_l_gu2tSs3|P9(!CD7&x; zg>6-J11@^>drhjQXrN3m4dp;RH#Sg%!UP+}AQ`I0=zf5CqmToI!BK@NFu~c9tt>f7 zvXymn>iNw*zj?kj&)Vml{{~%!|G)b6pRo4|bItk9Z_X7qfe~_z6gUAm@gnLWQ0dq* zqN77fCq-gV2$h#Xbq!}WNo1I^553eygmsE50h$g#96{=|S3M(Ll{gXS)BzFi7}4T> z>U{!w0Jn}u0`Vx|oUWe>2qjagk!~dkY-=6YT=+}72~tQ$QJtIGH`i3q_NtC)|B`$e zW>v?f{ia^3Y;(FIh{@bog)V0wV|u}59|RWVR`R0Hz0!!j`YXknB-Sv{(EoJOLAHFX zC8Oh5C&5|GYVulU&@(%TOm5(y>JN3QAx|+a#dRNO6Z@YTjL075G%BMhY1_IKp`mxF`g40FHhun6dpODFGS4 zFV>czqgX(T#kE+of@}#sL&gTLaSsUsKF4#Ce*DLOJR>#;6W6e8kQa~;&I4+OhUDfq zfAcqon{K+vpU;H9*m;CCFDM(?mXl91Cuz(dZNzsVFd#B`Yyoy(!D->%(@q<=Vvo~5 zTrArX6(=J29+@Tl;z4GytsH~}zkaVz8yyw$;MVpJh{!E2Z^@X zt*-x0>PCBDMu<~PzPrh;`Pj`yUUu5F5w>pnbkTSZ$qQtK1-t*lo~86lAHRLrZKwUx zRx{#@^gbP-+muWVxy%aj%Rqx<1-4qIPZY#-3>1WD%e{2CI$16VMSqy_aVN^HmqEmc zFT7VHGJ>|^4qt0_sRmx&MmX*X@RC=#J8Cx{>3PmveOmP8uYqF&$98?sXpnxri1*6(VT0``W$jnkn`W+h~z z}>@8yU7RAQxi?_+5hir4dEP01*U$uyPS!1?QJ7&{e8n}*Km z1w=G4mzQfJ7*?X80QyKbd7Z&DF~x$+i!Xw;ojvHtR@={yOa@2>2nt@qi8E`0dN5U^ z53&M*K^6vEqcPp{bzk>&Nq+Dh3=W6o{kQ-2-v%6FhX*@)8d-MWjMFa%eC-RiNn>#_ zuEV+U@)&ujL@6$pEe zMd27}(;!kw!^pA>7(ceeO16&%;-6{KC?aF7mlz$irHE~;zs-&XKi#Gu$D_bu(dc_5 zo$%MTns2oE?GvuLc(~_|dxyI|cKdMQSvJ>=%DnAXmMz}h`;`ZV-FMz?j{&%Q*mv&( zb|~QP;dtAfaOR~?8!r3W3y0^u;DX_TE6*M_TUO?7JFn%Yd$td^+V5BFIZ{|-ji*d+ zMYawlM)OB-piYmU>(7_&wUedsNQa10Mn^lg-NgbK+3(GE*2Lf0>7M)S%p(O;{=l2Q3*E9q$}} z{hqJm!gNfr^NM9=*{%*_pfoCIfMO7}lv9+;zIlIybZcZxdD4++q&!v;8G%?wza4wNAr>4De9mk^j*-7;b+cwSyw8+X^fTXc zx-Il5i8S?#V`qJ7);zH<_+IfK-n%bgkQ-CSnKjVto0a=&!$kc25_XhETNP_4OYL*Y zoLQ-ktd;0{1w!=oSx+tt5~@%+Cv*5LrsMeD$2$m!j|a}ihY4CU`Z7)1KC5uv4n2Uj^w83IgPNtw35z;WRULX|C9U3afb}3c- zSjq(s$%8O?xamojuAv1#O@Ey){dEpCR=){Bf;98XV+Sk5z zc*i^5;fsW^ZU!WQ1coFBnG|GsFa?Bc49h>!4oW-o{H?>o5A7VjeD}R>pg2?Jy6dj< zr(uI=VVw@v;NUOT=HQGO5Hlwu$fCr&Eyxk-c*Kr_-)?8x?63z0;+Zx+EreY~zGh~$ z4j=p=D$9t8I+w5!tOiNZ_t`C}ViL5*c zLh4m$wqiizfKaR8f4wi;AsCSajlKeHw6-+lg^N`Kmni!rjnu(74MH=EX^f$34N(nJ zOT0@mKz)dtl{BavEX80mW}5o;d4IQ zhihSw`8nR6NA!XBUFYYjK~!f} zB7tP&vCU#jmk*py1Pol0L|aw|uFj35XvB|EpBmi|@E}N%#Q1eVstJ7Qm?FX>$j;zn zw%aH52eOZBj*;=n58@Uc6iACsrViDFK1@Tsr=8l70QUWpBSjsAN zH64gJ7}sHSI6*XsY5YE;YzmXp_cE^TD4{3PrgXG)#v(|*k)l3O_Y=!F2BCX?fMVcHI{nZUm4E6k$q3eBD{&znf*f(BevGBs zkiKpRJ260fDfK-wW}-LDI5ijo+h!&_#+l1M+_of{LDTc=8AzK9>-25vdEikdK-iWM zcqTZ}Pwvxs{B_%telMqED7$$L1{*>$~o{ zYk05f&?c;zK|Lr7vN+RD8h*BAeXv@7pJiFlSAS@wWLB1CSNJ`R zZc&D%MrbMLHNMbkqcjwbGr@)isrpiM#&rNdBq{qOA*$@5gDCpslTNWM(nbvI9@|qk zoD@4W;;5Wac18|x{>#ZeKfpKY3vp5Q+&igAUl8^r+w z$o=+sioN&TJM6pbE5m_%AG8C9_6*0_^wJsUpFUh_&ocVzuRnjd;8|x4$J;ZJzHIAR zZu-(A!;N3uKHT+yZJo#CEUYN3alsVR=kMQR2QZp`S>+Gd)X=?ls^=s2tgPXwPaift z_xZz~uldH|3ul}&eBxvOIP9>~clX7S26SZHe#y0JX;a?X(MdGpTtGu@l|-irMBq>a z&>ZXnted)MtBMoM>dctR9Ij|x>WG`qLrygZif#24Y$2 z1hY5@FbWCGaiV^(Zt6GX6*!w~U96Ja#RY~au8%^)eEPPivw7F^COIxg~=tsp4& zSA&U>gT#0Q(ZM+S+L~C<%-Na@NTeS6jg$=sF8bZ@1Hpq$<~(2TvX_)AUpFh9MG^CQ zjx|9sB1j5^z*ketO$5eHM5j~XLaDt&P_h7rY+C?pGB+r`DFF{)Lso`F2AK^S1+yg} z2ABr=%fI|fd+PMx`qQVes21fT6N5D?$jTry!YmG_tl+S*c=tW;d5`Zr!kIAVpMRd+ zbE=;dj4j>x9AzL=gF2u4ysK^ff=w;iln~m6^)vpQB_lA~j67i>FV?%XX03W%+K2O`#@goK&n%|{<7gqH{Ubd z1@dA~fp#D4bFPjENn+~sP6SAyKd{n3T&#n7#IiD9zR%Xx?6>n|P9Hx1i7ySiZO78n zFFj*8|Ei}C&;43kO#Ga)hcljT#MO-dR@*i7na@8m-1+5Q_Mk<3&XHwi@cgcwcDnL$ zmZ>}Q%FBk+zV@qzjaNNq*nj$2!W#=LBRGzoC4fb*P8dk?doW2oYP}WKVB?y#iaNiU^V%Tr^%3GZz_#A*7(EDy4w5 zqjD{oX_8-doYxZo=u^4EIgdmH zM{v`~Nbnla(J^Z@j~SDS%NU*2(OF=>akkd+lJUo%XcXFW3Uxf3)%XYunoV zDRcDOZK3YTrc9^X?+GWLFr4sBR}6RAIWKp8w<{19$SE)`D($QryR7sb`8nPe~L%IXy(YLO+!EOHt{F45AJ}<;bbtb z<0X1D4oVf=_!+T|Qyxvd4xwIX^Q#V>WjE__qP`3ws9&KUN^Y7g67>Xil6+PYA>>5c z%FNV#xobikL`=WOn?CAb%HrXgspP2%+7IB`FfYJbk z8c3wW*zim{YwwGqJ09p9AnRj#mP#T5ZU)LanA?S8P^diqHzG8=rXnMIf+-tpwZ`XM z-@<4U*MYbogMtI;a8?Y?i~*?tX~Df9H^|mtmlDVevNy=opiE?S-uQ-J7*2hv?TFfE z&(GNZ6u%dl7mybms(0s|Sj=l#0gJk^g9!u$Kpl7PS;JGl;mYBC|KEQa9=hRk!%M#Q4BOUjQJEc^yXk~& zcFv4FUHY_>?8M&_ZFbSNb?>qVj~aQ|i393P#~!lAJZRHVo9_SeaLV@khEopgGV*1a z9b3zDwoQ5c#TOnKe)t2Qu_sPH*hFI-hU&DdY$lbhES z>x;5~BvPzf``GJm$4Yf9xX72&>FF4XOcq7`tb*x$%}{uGH4?9FVqGyNB(Z9PN%R6F z6t{>OHBi;eo$FN5wPs4Q<7iPaG42IoW=@*!+UcfVSr}VYwvSz(1eEFJ$r1*0T~oz zQ}7)!ARrcK4#)#CBjbYG&-gQsFeQY=yvUv)JA>Uzd=3*%^!@s;|N7xs&w7?;X+Ub8 zdD#`iwljARU*7$h;q+}6Sw>~6eK&6N#*?jg+7{hywv88r2iX?11MNW{L0b3_OUjv~ zWeyNJz;{R=iA+IQaNfxH9E{NsjJrN&=}cx@IMx~^G-D}^(a$qFV)PYJjYc!6N1`VZTio**WF5AbaER;1}*5c3PHi>s@yaCv1Oku(Pb~L6LU$jJ0udEMC3! z;XT7&+dH?jsz+Pyk!j$gE4 zj>z(RO_hhvK7PoQe+{w{*gXX!x)5dcY;Uf9Voix=D**SL z$lN*!H~z75W?)i3{ljruNC|9poRkskZ=8(kJLR>2Ts6T2F+SSCcHtTZlS`)yrGH+1 z2~a(l4C2b>^&IWoR_VA{2~4gLit$f#DC0CXW5fmOc~6ycF*xx<>P%uU&Nc~%26I}s ze%>Pr{EYVqk<);MB;WfXNr5ETykEvXA2ZQwgOU^!szE>wib$xoo!Cm^fS62atE1ujWYKOTGf9!9(y=6SrV|oF&vdXfk_xS5D$C^h78+f{ zKtsVZP37J+jN3Zu4>p8BBRYsWnZk5Kpo4}Wusp*AN}|B6%eajv{&I~B7T`j--}Fu2 z=k+I!lMyNL0G5;HPJ~Z6&i93hwU%Y$RxOdmMrVEeZ z2w|dnv}d!8!}SmB9{%cc_ZfM?6P&_XNmi=rK+S68E}+nn2GGJWEON?RFvsy%C)~AR z%8qytHrh*NE9myflV&`c`wP|(s5M|}7JtW3P*!tiZV1Lr;i1Yo13CgML7(J|gf4Ww znPwLPr`V?UmHjEW+XQogd$c*~Mr-1Md61W;;Gyb;pw3O*^>8E{Q)0ecQ^{C2fDvb% zTYYO=sJ?)0x*XH>B{iEsolRaL5PrEciD z*g_gze%_3+AoR+GhD~8?KFJn{+M-U|m4vJehzah&`7J1y86oawVmr84 zw}&Bz^jVjzj7R$`5v9WGV$RI61kq8w&~1SPj>!nhttaq>yHuhxIwmAKsy}H^a0uR) z0N_$iwn2o1GjjItA0O)ZB^%q1?AkMY$aV^S%CaC2+Z4@HtT3Dxvke3ogw~yrWEO?k z_%o^eNL?dHwzdY-LC0V8w2{1g>A~SVJ4eP3@WuVn-=Jrld-IIUU0>Q^#bE6aLK$Cq zJCYm}Z-4h&BVg+{KD1|e-{(j2;x=Fxc;+Cs_*MeY04+w=`cw%FMbmTC33wbA+#eBK zbDsnbYU^Gm$5?`hxrj|1VGfnc48}Xt6V<8eL=+S=1EKW`VM{ECT_zQu6p!X2ZpFoD zTLoyAM~w3Kft@U`SsQ?IWXf$$Zz&&%IOoPqZAq}UuJNc-i;XjJQHQej#>91!8a&$F z$j!!a#=UcEN-97FHtWZgxUt;a`Bli4V!78Fi;^Kz?l$^G%bpXfYM+$Ma_k)Am`UJz z5U#xo+hLn4!B8D(`XXzcaE&_p96wHd3W4mBy||$vs9}#Pk2xY5q$NKu3!-V`ELVw? zS6TdfL)Jwu+2)dsA=y#6ni4qOj)llG%(R zR2pwju$(f`X&t7!8fHrXjrl^9rHeydIf#^D$T=NR8k)p~gp7tyb{fLb`gPY5$izSV z!#@t6`qZaK^XHhyk zPn5JYz}t~kwoT;P7(zIJ1Ox7r&~cD?;l>#$z-syK=UV5gATS5gaQwD_d!H@z-EJi2 zcKiK%o4)%SBQiG{k=bKp*VE& z4-Ds>jzjQ90H99KrlUqDfpYJ;4~xI~wAm=s9R;>-W80%eZub5bn>PA@WsN{yGz*dh zA;3iSwnmNoE{SQ7Aj&vFHEej!k<&4T)0%Vc-tO6H+Np;GL6Q;Nk1a<+Hn_I+byyW@`BTMK~C_f1II4w*Q(@YuIoWk*zR$K`}nLJ9E^tb zE2Hvb3TTYPb&Qk@a{8#sAR~VBx;kao12^8Q4y5Po=JZ4WjpNUVj>fB?%*cxbOm$EV zMeA0hz&7;*HU_)w5eyI6NyayU#BAR^{H<-hz75Cr8<3r8gzwbY@!?ZJoHFu301-0s za@vW*iI<%{+-~G$`{#|k*t3@Q+qJ$OJEob&t2vbfkTmjQC+vd6j6bl0kpMV(vCnO}t7*W$FY9QEbLTqRi-0 zt{WhLy5p6(@9e#hkx>S-NT076xa2fp(PJeEse1<08F5Et6&SgOVlHS>eI#LxG`R+Q znOzA-&USFRx(8LYE`MK1KXgVS^V}*-jgfnL_T@T9IjTdaQ?;>h{fPHd(~GplO2`_= zOId}}tmL=KKp)D;@0zxTE$Dq{-#EQtftF<}iEH@$HGDjPWnS2Cwzm>kEmOa%gs*9{ z_#l$qo_w3}iiAMwvzFo55ETjB9qsmVCo0+w3XE2k?|?9AtNbPf1;S?X|vZiO*g_xjdsrGcP^hBm2yLLsl?ok`#IE zi)!r0uN7vD_kKMi+u{f){{${Z3^A5$m+J_sD5O`xSpkwH1j9~3)PPJFxPr>qfic6< z10s!<8)GiOU1ix28B8nLG~S+_JM6reUBjog?;8HcBewn8h|FD{=phRX) z90QEJY_;vsCqCz|1l)V=F*f?)=Iw>(O}rs3&PW8G)0C z$IJ^B6XUzvw(lGM`YzKIYhUwIWUiS@%2ahi!MT@3tz?p8RqaySFlT#WFSK=ymh#@n zUNm|XZ?w!DBe}je#<;Ztuo41(-?b-Kukqg^2Uc~mlI336wY;ger^Axyxz`pQ3)1S)iW1di|UVi<8}Z*Et3u+ksyrE1T>gsvGU8 z?i=kSYrM9|Y+T!DM)FhGbYa*3Cwu-~ElaZ;U0DgKs5ano5EA0=gM3#XM3R#7l`IZr z$RjU^zk2N)=1nPUeBRh|;QS(;%<`EHjd7Z)H|-bp5#`gD=Yn@;TSG>*$x}9?zKCUc z7E!W2iwG|2@ddjIAeA-s8Z*b@q;on*xVJhSFRw%x>>!+qoueQ5aWzy53ALj9F5f5lEz#aS_@`8pY_ znfa4H`I7+;XvFz3JYg3Lgn5Px>&APw&q+x9Ql@p9hrX;j6wRinGpl{)R_8jt1U>44 zf*;4Y0&R69Dl?KDEhpJ|IFRQ4a9q_`dt+4fRdu76nVGxZJ~)7fUgET7Tf6inJ45Cp zj~J1$shf`(k$J!lXF178-x)Tog!M7|ZQ<``+Y0@ZD~!B+>Py2TcN%$l3NkOjT{zVQ zwFlXesi!-Pyllq-b%-LZEUdMGUORa~=EZ&uu7^AA+?v0>%N|i+Q(f#cqaOu_3ZB$` z%8g@R$7U*HrLs|-;{6J48olQ@aSEj{+h*Kky%O7zYZb&66Gw`pQO8PPt$NYS*LO&I z&tawA1wQySrS6ocv&I>~Ck{oXHt`Gh%YsG4E7aEz31-3=oikga!AN9YdhM^DF=MS* zSA!X}fsTazpL1+7Emrlz?}=yB=rn}NKg%t0XzGJb7-0cH*B|YX-{$A zV9(jue7vn|*=C>FlixvVaP9Zmn!-Ky`YpDTbCl!gXI#dif7&e)PJ0H-iBr!wdjq7vu2~agVLtxxkK2P7Kj70$cvvGI8Sv+S{^vfe#OE+! zn>2oTh#ty7JN9AKCzK;Eyw5T*J1iq}$BtdYhaWZ~^U&_$ zh8;HDwC~_>s$F)@Gfo}0e)W07oge+;@ZhcY4d>X|ESNSLGa-?>_tXkIj5-h63A=c- z#Q}SmqfKAgg~-gImw1i)u+wOZ{eH|A?EceN9!l~;C$0LcdO^A4GnK7=PTBTsPG#AU zr3ECPa#Uci_CrAR_WMc2WBc@ZC4Nmg3qt$R!x2s+sXkU+>V2o}tJtOA|7ycMEU3gqZAS48*Hx_0x>_t8@tX%Ys-0?3RI#ICloI|qoxltx*F1*JRC{UU zYilm-pins{0t&^)kIT`=yoQCH1Dz<{egK-ejsg^y_y6XV(yIxz-2JATEV+XKU*Rw7b?Ze2By}|Zu zwCAq7@5-aq>p)YcJ%_|L*YC9d>eO((&n45j76jHY(lS)uGz2f#|C<%2P78!>iXb|e z0SF~Jrk?nHcut1t7^m!-I)R4~r7m(rRTmkJHDDBFDY&_AJ3t>C{?u0EzVpPBhHIa4 z(r~_k<^OWgnZy6(d%kMeZs)x0_|TohSD$5%1F*;3AM``*%pd`#IQR}58|?Kad%fRY zfBZ{3jpSe|?4S{$eZJ-e&pbNOqRkTwh`(UdRqy-C_Ti)U2!VU<{mSsLt<6z=tqxfM zT0unhq0vd}3yv0;1Ca^fP{6nqmQiG%Zufxwe^ltkEv(sQAhET2^m7s#D-N)}W%|DelwHs6SeV+JN@6 z%2F|-VztVU<3c&A>^=SfS%E15a_lb-mQ2E71jawZ^pJgysUbh?ajRurwrudM%cc{y z*jW~KvptPeh|>A7fO)W#%hB; zCIQ>p59(0$1Gokxmk;OlI*>iKe^Y+9=hKV3Y1aZV^BBHCZEAyU)jg<#qToo-n{wz{ zsS6^UmI|lmFsmW59tx=fZwew9ZUtN&_&IREV9IlmNGxz2A1X+&$@oGAQd*pjE?AqgU`iwguz`(?i>B3-4AVF_=ce)DphKA$a^zuu$Mpux0yuGG7FU zUPs8*7sZM5s9?u_=Nc!8MswUT^&@MY*at>)wJkb+4bWAshKfm4KBe?1-w$1iC^FkD z(I3ZDjfr}wKK*mDnaAt zUZ3d(a6z%B)>jD(+pqYiI#usiTOgTj$Y2CbJ;z>cvWKa}Apw9< zonswa)?58T&++tZSuxA&i)kQ|6`vBqbWp5k@wF>B#TpN|HCq5#*=XNyveU7Vf!Tb* z)?v#@wwA?SAG9pYzRh7z2q<ei!2z3!1$n_=J8;Ps<=gp6 z_IICsw$Yf8zc*dMgA4r;Kd}jcn8Ef}dH3{JF+=aG7~PDw_%Xo|&Y+gZ_%` z(C=oB!d^wTcSta*S^vRst=*A@iW??_M_T^;*i>@+Mtt{ zUgfIL3K$%$DN>@1P^Lyj!2OlgRU^^+c>SCoi);~%n30qMDhEaXs zRj1nE3ATM>tx#l))!u59$?;N0rFxmz1oACJeu|LPKB{ahkgJT8;MMV|a+#Aih+3TU zqjp{u_py5`)<#mp@NvoRF#yUvp@Jw!C1?otT_(a&&v3f5U>nY z@@j~xH`K0K zwtRm3j$x;fmOZx4hBik~>dCu;l#W~Pddf)q*K^Dj6F5da0@2vc0w7f2uTd_?BlWFh zKPd|hbh6#C_>+CAx;sY(f~Zxeq(p$P>)2L3uR2o~8>=4bYmO=9s^h};D_K{a_x{8h zlioIP-j6ct*svUA@_6PG$D)$r9tKo-_|&LnOz?{nt-bunv~V#k2n^Pz__M=|py1a@ z3|`x!Tx3?Zo^+f&{r$LMtNm`W?8*jnPN?6fiX)>B^0MDoytiw)#%snDFy*>&kA1eo zvMvwXaRj#5e!nfY$74D0d(fUc1|qZ1PTB^E*WdOJm4_NwB^b4zwM>pf1yYWoIz0uj3dGt59Usb_t|bZ`BBTVeAK3hK4QRn$HR{dJGMXUJDk!` z%?WUdRQ0?9wMH%aoyv?3k8}OBX$4D;nU<&Z);2Wu9E(M#$nF%#_Qqd{EJBak7U&>MRxoa=4Dc zSG5b(5$py+X2f>|#d$jJcp|gn~tS6yQ;25U!j|^bNsv0O&Upb|d6^k;v6`igG1ntu)TGe~Xu-aSAK(cKW zM_5;Fs}gL*?rKLcrU}wxLE& z`h7!^CQ_Q!2z7i^=@n!Z_$w$@qpAu|-O=kA)Y0`6k)OJs%_T#Rd=XgB#C-|C3tGvYAbVX5k2?10%Nsb+P+GbRG0ah3odc3 z60d4&bkK>-SfgbG96NuuSXObPP3`y;ET*$83&ZK4jYdi^4Ybv=j>nw>vSL$0HkG=~ zGL!5dGbiIZxv^#v8O5JHb~3hK8^IU*-MqIOT=#;+@OqT%2Xq=&*|5i68<9C+Bxawj zE5m|ckQmR%V66;DOiVE$0|O%CpV>lvYz236gU`cW6J6S=PmG?T= z1C}WuWjS?SM0M=Fj@8emoL5z_dLP@S;HS!@ibwLo=>q*ucfjbNPPJXzrPr`b1sbiV zDmRT~6&X3+b=EH^Fj4lbe<^@Q#i~23r#k*>G}>3*!_Sy<)bUABBf_oFX|{h#S9{-2 zMa?w>2R&G%t8@rz@RW%iZ9Qzk!#HgVHnv7I$tM<#m!RLN-7H3j2pLseIL<@frgZS7@G*w^ZSD0jalyY`_0v!A=@&Tp z{dUOhR+}n4(at|YW(HZ7Eyvjo%6NvF>SRkiMnaH!ktAij14LxcKCA&7-*Z!dlArOI z0ZunXd6CWWXO{WtkukkwtLC@h0q;AlY@1qgB4bA&U~0+9i;x-5&R|L@rj>jFuuV0A z-0&P3b4m{Q69tN;Y74LDMwnfXS z`q#r8)d`lh%(rd8R_UH{R{*ODt(9qG8l#s*hP4hgYAtKZ$xs;8sVev=aMb!LQ1tr8 zI%*qOmXa3*#btHXfni$~^|i{^jkmKPkps=|ra->7VbOb)O_iJ8S7p#+$y3I_I@BQ9 z_Fmf*TnRop-nE`yz16wZHYlKQOjVxLS$LDKtcn|rpQ4xtCOYQJmMca^E0aWYko_P6RlC7890o{dh) zNU=rjV~UW}K%_d!srx9q8tp6LN>TxRw4Fa&Z2EJ{X~z%So@ylJ;**BGo9ra&gU1c0 zpLv>Ze+Ie0BTBZ|_GSFlm_uVIU(*s_l91Hw3T3#@$OqQGa4ifoE17NK^pO&nATOwb zL<4F2L^N@QUMWMu3wb}jjP zAu>J3pL!rih$v1?*)7MNe|u-};NC?+#3D?X(h;p!%U%R=`>dIa)?`7AYUcP1~*gtxB%OS6O;br=|!m z@73>B&uX8laaMg@H2yly)IpM$6XJoIYUGQYL(k}^*#IiROh=^$K9J=>FIZ` zO=-ii4VyB;qGi5T(xC){_fCOfb?9|0*iV+TN<>#}jQ3WOFqLKDIP@aVWwx|zTok;Q zU0eIExII-)wUI@-s&cA*_3^Z00JfaG%`+}1oOAN9>9UiDyLa6;oO1k0!#7^`wd1qe zY?|kh-8<}eyC1l@*)ok=jmYEyg|Tp235!k}xvs>K3z}uw?+19=`W5>-n-&_gEzG>2 zZ*4{<7XEfV2Z14(@tsSXHV<2ETi~YMw$OOH5f$6HgpAByTc76BOE^cyvNKLzV%xQ6 zW}MWFi+!;S7~8yvRA^lUdw$jf`BjaeUZ+Y#*)38UDx3DN2l%Tfp0_2^+&yBWj$x6JRcBa% zypolwTfKf)y{gWPga?1C9#q@uITi(pDywSX)Yl{im}8Im^`6{xOsU5`AVj&V09_@+ ztBmckYbf)c9H?7*4v@-!S@uuY$f)dUo0MEEvilyOs?JqhRJ`PCb@=u5BI2%Xu4B!1 zX?auQJcSRc`#kQU%C|>SwNBjUr`_5Pq0OfrH$3GTrwtn~Imvd)-8Gzj%2S7DKJB96 z?uWiIobi;?hEq>Cc{twId4X)~*t64rK^8z{HgB|@cX66Hr*pVqm)V#~UeI5X7TkkO z%$PwL*SU|nxc&&Dt-W1l;jk+hSJ%_{b|ifvW$y6hejqiT=D8Gc{O(R!Bo4P4tJ$WuC7$%(c> z+nH?udC|hCq!h3M*(w6jfl=e&y%j*T?jE2_byOWvb@HpUlh;f|SUtAOg_?}G2~<;x zpnZ0uDyPRzwX=?aj)e|rRU|5lf}_f25reOC?vWmj59_H;W2!%^I78Ko>il~Kw1^D! zfV)?Iue~aV>crUZ9kwF~Kf2p!nL$>4tH#)CUv=szgJWAk0Xn1Ej%9tT?d_4ZWp-4{ zn98td-&Hp?isOQIl&N}ECmwf#H*L3_U$ooSuYfRYwqvNhE*pDfYd}a812nsWc96W_a}XHZrv%2| zH{@g_|6CBPQ%C%qq-Ji6f)Js7AX_#8Hf#|hvwyo~W9%#$Undg><2jj$?92gtZcnIp zLW68US#wx@$TIBfeP4aGj(x?#9tqIvt9>oHehO!+3>RIeI;Q?bb)CL`P9NKtQ#vO)iAo}-rVCV|s-v#J zqO$49g5OV-(~F8!SrmYK@}pBQh?<6Rl}}Ez_HabR4=Lg zTAn&cd_F}WIriGF9-+YfBrkQ^sFpn?e+8^+PkN8)tb=i6UwZb{YwMI9_CT~JQ`L)F z7RR`!-__BnF7x^taZUmI)aT1Up6#2`<3+l#2>e$e1ylO0ZSIXFb)g6L6*p9edTpB0 zy*h4-##Qalf?R*F>^bM0<9|;%>om{2Y~QeZcyPn^;Zr+q8E(7(3&Ybb^K!{kFBraX z|6P`~ur1VaP728c2*3$jj}Ibqysd??6LXD#fVAKYmrZd3G(OwC&oUe~-NdcYlxva| zl9!nFX?Ga4yN+sBrXet~%Sq3R>B=;S48B7@HrcV+Tla3Xtc)!Kc-W?~WWg`akU3za zW*^9n{T{F#P4!G3*Z?*rRLrS(j`w=HZpE}Iovi+E3d0xa^df&vGEsF|aj?f1)JIo4 zUgWcIZL_s|YQe4wP=%{bZ^{ua0u0`RzuGYxRWB1#jh>xXBc~u06qTqXNr^>Ue7^`N zrpOD|yi}0l^~^X;DFypI<(#L0YDz|Rz}4yTbC9B@ZPt zJ*DnBiJtTCm80N4^P{k8sbFzE&Jzz1oL5zCF8D{ZV-= zsuyj=_qq+bVgcK(V|0o=`r_=f&mPV__gw!y^UO2-nQYuuxqa`>;gS72hldVqA0FDc zbGUxjZBAa!J@xG2qO;CR@=`I*aX;3kU=c4eF(+@cr?PK5(Vnip)w3~}V)C6yu|0jS zy~pQ!?R4EdvoBQdkjRw1aY1J{CpZLwps zw;r(Rv>iq?>`a+G_wO8b-@jwn`@pVYuN^*#sU|;0-|3f`&+I+i`6 z(F64A}=e&bediOwAGqRfav_)NyC~*}o}rKIH&q_&G(adpgd~D%P+b z)C;om^rt_4IPbjk{4dCg1-AJZ6xb>5=kM-=dk1?mmy?$VH|(&?3&_johVxE8XSm>u zbBE7c<^>C16?b$8QRmgI-5j)iJNvt3Oq};%oKUN|N;2DVwi#SG(`oV#U!#I$M2JEnnM9 zf05)xJHD2IQ?_0m=Q4v=huIsfWsXO|Xv#1vVB`se6OW?PyXunmcS`TIY}E_At|yTz@m;33 zl$Sf>1=E8)d{E57y_6wsqn3xYQD>ZShLe^X&ilVOoO9~aeCi0(MqBM6rCluSe2DA`?mP3O(>((N0szv2 z&mY?PNZH~%W?OJ*9WpXF`-Ka4i813knK@f0cmMq>)Im=X0zb~_l4G0w5b^6wm zh7<3w11-Psz_9zi9Zp_ws;^>a&j!_BRZQSG_w-7~xEG)(DIw-54(k1SEkCdAs(L|t zS!TCAyQ=ov!=0Y&H`r5+J(pF%RROsNdTMM{FnF&~U~RC1syb*DpgKB&j}Dr)51$iA zDrl+$@j=6!YCPDif}HlFmwF?4Io=+;R~M`HoQs0C%9l#mb3#4mtxBfRDPOCsrvQ_6 zO_eoeNY#K;N!4jB8{;W`ss>rx+0#uOw<%pxovlu(H?}<;?zIKwa?J}fa7uQn@%G5q zRD`9v3UJLWrQyufS*mUkj8v9tGgS|1XHzzlz#Tgzru10bTk)e}2D5Bx@4QEyY_-XX zGd+Dl*}beywdV@3su#VeumWb!De#)!*z^FmH!f4x)z5ptuk9udDvnY&kXgClf(wRc zJ?mM+S!bQ)Pp;o)IL3SS&9O zYuLBxfM;I5^2mKL)ni+V$5OhBRXLs@8&5m=OkeDa>7X6EclsI_OeuZh^EWt=!8U9V z8*g(g?nNeM&wflb*}55^7Vef;xhJ$#@b^NH#(+;Z7>tP$^#r8mMy)3U1f@)J!L`3VK z!eQz!ajga}>R%KSrtGVy(@h^^fpaervH=Trso-pUZMZr_DtmQy8nITeQ!uReu}-!@ z8(y7`-mAi>gQ1{R0kS%&Dd5n-VVgAKR)tU{bES&8T6Jm~k=McD{pwU%j>=BuQHfk7 z2Nl3rXDx%usB)_MpnaN>SJe?6S9MrS`Rg-iRN?E>!S!D4qsm;zs`g{*y&7S4;=QtY zJ^qrsfW+z)hPF>h%v4*ePN^;(3qID3fz z7vu#;oa`UA+nN^;m>maq4ZDrZ?6)Ty-nI9BBQp;VTkRP}Am1PrSa`d0FBae0qSeTR z_M9uOf9lC+45uD{vM=b}w&gg_sQk@M|LDZT&tS1^&Iz{l`XnPY$8Q7_i+I2vt zcA3;Rs^iu==oos+(dA%*TM2^#Wp(y-3~IS}&$(HWiz??zyeLPur#f&| z&f2%?5PFKQimvkRk+7ORpSr#}N!`As}iG1(rbANI8{#B&v^D%PX;rmIyzC6TP?fFyXv;SuX0r2@9CtH&H6p% zQgyYCV;w8KPvxlgqxw{xeszXdUU}tk?lYb-eBtw-AMUy59w#Yi!;T$0d@DWPbIJ%i zhmeKAbP>1NlgP0Csq71~8oLkJx|ajHhds9b1(}%L2lv=InBBIJcefE6duG=G%Q)D> zgbvyR3poXZsUECn;VHSyE`kg^{nV#grsbsJ;a!h-)`rtg_dIlOvv!7=5NyE)fjP+* z`(g(Z>Hx{vZdn`D;ajogRPwr@w?0Z>Bqk$4@h#Y~i)q}BJ$t&f;$zxKKFVMuKBsR! zX*lJJn}A;VkRrH3;A8IB6hBpQNgJ zAXRCmjF^L}N>a;H$I1G8(YHDQ$VeAzD!5cYQhBOu6u2vh_dvCdOOGIE-8xomdv!on zi8UQp*=_}BmF+SIs02x0>ljvD>&Z&n+XIb7L`-#{%CgrE)st#``o6Axst&S_Gsi`N zqUwFm30Km^a;uZ=IlXG|HF~NbSpjs}Sl8^xlpf-9uA|_1;BO_b9FGc$b(|_N_jF5f zN$b)+*81w$_W+moRDz=KDYvSZQyHl`?rN{KAL>A=t+V~lfBy4_J$vja<#*iS_>7DT zh>PL;aNm9RIZ3gl0{#oq0wRO0&)8Xn*C*NoLpK@;KwaY^T~2k3(>^3KIQw>=`3Dde zKeGSezG0VYgmOZ&>!6VtBQXyfnb~DT1`{`%?7@w2@LYI{H7g(zI3won zhra9t=FF2$^9&EBpFn0va;iS~E+e}ThshyRgN)3H#~trmnX#bvkzG4{;V-f>c+cr8 z+=DvDol4_jcRaNh*WokN&qc;{>~-;R#U+xL)9%_jJp4JEK9kIgmeaH2N+v3n^e}Ld zzAMh~USj^D3}+=pYAvezV@}YCm%n*xMcvzKsLX&5Dj(r zra)9awVwK(j!|W=eX0siIci&b3Q^0g3Q}dYNWQiF9;v8Gtz+CHXQ;2I^z2`)W2%gv znlX~IWs5yj(Z|VK=+6S$V3{&(b>?{|cmsmmd6bdY{-YHygRkwJzAnVH@8dKdo2R&1=H@r;aQQc};$XARzs`vWNI*|%q0u&X%B>vasN2dYawAGc~bs#p42ZGpO|Sk?1K6=$ehb(W%%CdC`=EAOxV z1?^N@?!C?hyY=EJN6{0$0!t5kD#NVTG>T{jpmo8bx!2!~vBxVZ6wY*+rukEeIu}s!_ zea~oVNE~~Bf-d-5)Zd=I==Hs^>3v3>t-6iRRS$rwB=*!rl8`9}sNm$|&D6G)#@SFLAC@2V4ETXcN5 z3(*f%iv`k3E>^X_h}~?>xJThNi?q;T#o=#?cX<8mXFuByKD+bIJDs#3rfCsE0=#_%>!_EbK3`82E?3AR~J%D`Pnv{~oXLZr6c5wpM1h zO)c58k8JJC-i-&1ByI8qx?62gE}n-3VuUQp$L_p7w@b6XXiKaopIb-b;}&aGU=x^r z0*S$T8cbW=_La~1Uu0xJVrDuwBScz8V?Xhx2HL70(DSploi?2R@M*(=`*#lqA2Dgz z0d~6|vBx7AS;TnYw@%S5!l}fpN;2i zLAT=HB45&wmsOn(8?(r`v{7?lORZa_Lc4}LFV+HL)rl5&1px2GE%OV+!{D3o~AEMo%{g}m@S)tlPSo}EmQMU|QAhxUQ;Ual?U73z%fepQ{B zvh!8%XZw4B#3Ff3=_uQdaio1&yzhi;88%c|Rzjm0R*u0`nR@RcoS7QqMK)M*bFyFY zWa3)ZbD#U%hP;4u_@Y^JmhX7SJBF|S`mfJhu&DP_pZe7BKmN!67(V#H4-Oys$VY}R zed$Zk5L@JX(s0(9XAMt32ivKiFd)^UsVy|V1Ab*k>$d33_{T+!lgJ{(ew6PcL_V8knzt%v}?X1kSEYjH? z&MT&?Jux8Qu>z}LNv)gxb@H-G0ljO`kX4^=qYbEKRaUpCJ@wjU0M6s7r>ZYK`7H`S7J>URU7Y$} zabuBeHG+TM^PV@Cc|n#0Q$m0Gr++$p`?r6)J4|F-w%GJHvMQ9>?YG}P{KG%|!|?w1 zzi;^Kzy8p0(~URzP99)97x`Xz;f2F9pZQGx1*yT#CCCMi7*kc4f&!UAb_Na_`VX?= z+lrBm0f7OTK{mz-jAdkk#Q1CbhjlX#VV#U+Wp>z_8k>D`o8Y<>WOGyx7TH8PaVs0A z`JR5_seT3xhzl0vVhV{1fEDM~N>)%0c0z62eB5xnO^uy-;N)TJ{nqCPY^vxHTW(;_ zH^Rdk)m9mVfVev^%52y>P2Iv*Dd*!iRmEH!zSs6u&?eznCGENh09R>)+hIJRcU8TpWJAZj>LvTo5Fe0vpD&nY zTBfGbDgjctXo!|cL;UzD5 ziIWN}=zYXK!}Zusjddg2wjG~c0NMG(Cq6NJ=tCbG-uJ%uc~%CW;b-%f&BOWUo$qJH zTyn`J`4{VLu$u{v`2PFv_XWZaKKOu zo_f+rgIBx48oF(pjvG$gylpt~;I`p}16%D`N4Cajw=D$5vyJR|M#Bzk+YXQy>uo$9 zpoeQ}yC9n&FwDweyrzDtzD)U+ifcW>w@kOz;$L{}GXJ50Iz&!6EFw*8yJud=@@Txh zNO@5-i2D&SYUdSH=rCxs-Z2F6h|c2>nqK)+1EGtyHrZ1?-PxhIC`$pUH~%&TMit<6 z4M8O@y>e@m-BUP~(IRDG`KzpX(0UNxcq%=9+~7ja)v$ZAS7qv5pR!(%R#eB+Q)1SE zwvKQ!E(UiUC~Go$GF1IkBg}Gf+NtemaOYa)hD`bN&OzNFVz$~BLlU$VPWF$S;oXm^%{ zzngl#cY+H&9nSq;czIpiDzx`V$GJo@-zZq`7<97f4sZX`-&329q{vs;_LUZ}$ zm-}mEWiWORKm5?}m9N}uZMfGnGsx2HwnqT$v!K$mF+QbaukdUCoVfV<7+W)gol8z+ z>@}vB?El+0*y96?(Cpr5c4GSIyM>Gxjf-u^Ggvqd>;yi;G!)K{x%1vH4iD~p$iKop zQ@)LM$TC1ya7f;X8;r1QJYhI~pOKY)ws3imskKv*lq1W z)@6ld0p4y|#17&DG6*6Axq;MB57&|vQLJA@mzI&BDSJAc&(~6?U(2o1Imlel8AO1e zQ&2s|maI1pXX8B>1mB4xV6N$~DbT3`P*&}WObf&2U@T*K4luIbhNP;JwqCm`d8x`k z@KUhqIq_8nmrh5WPfeF=eT*EC;eZj-aQXS7tdq(EuTvIFrmQGS9~-C2N>FH}7UxLAuQ7afu=>f~otd0U_1=FStBI_wz zV*l3CpDI(X6Itd^d-kX8QmjzjQext|6bs$e&eU#tdS1(}L~l`m;Q9`d#4}^4lM4uO zV`E&LFYC|LCKzy0AEw4M@hHk$X7kHHJLMGE6pKly^+kAM8*!%a8c@t580oLE_*|Xc) za(|MUhaa|l$}U?tYtvKytRfTgxJD+{#u$0oYeWE3OW1ntYi5wC*Je4|#42TaF6Z?Z35!8;0d$ITz0rNJ)7Xx5Y!&iU@sU{> z{k*$icPh%$hRuPfWKsws$uw7prWLffn1_SGsRz98I)}(M=zuLETk7Z zh`TMFhaX+ATb-*aP>)R2)MF(UbO4%-Smdx40pFtURv~)JK$jqj>(=TJDW|I7OoR5a z4{T3Wetlm-Jsqk{HK;sSAp>-XZ1dFGrzxXUr@G9xRDXK%uY|Za#(s@qnP%X6ps03G zzn^MnwK4X2PL8smbjs1zwrk&(>E|+sul?x-Q6tiiS+2x2tfi7{m+N&2$XIW!e_4Bw z1$6%(sd3i1Y?=sJ1$SV0tO@Y1kd|6+kGyQPQ+MyT%*+4&`qvLHe({Tax(HJfAQQ-h zY_hT1cG8){|L5&@4Lc5O9`^3EH5ay!^^`4phfB`fGCc2+(}w3g^Qpt77d&k^<+PJc zC^#x&%mTuR-g@h;zE&~wDVzaKXx5a#w07pTh{5M;e_F&joXIf_iq_C?={)) zv5byoR`&0;OpPtP1z7=c@xS|mz+j9?TA)^VkKYwDF0BoAZbH!RNrf>RiHz9YciolQ zm>ymbdoEd!UiGAEKGy*^-kJR4Oq&q-bs28Obt1_3oEDiYWLCGTCeQ_= zpZdNTupoiUNC}lg@6`ycvTI()zUesTctymyibL-yqsl-*U-f~qbYl`ZPxZGtYt6h= zMej|=c!nm{&@9S8^^B&GZ4g_ub50K?c7CMIkX#3fE!@r2$$05lEh9g@?|b(zA{5^4 zvf!G1;W%Y>qd51eF?Dpw^L4w1TkhUDY_x30W}A|M4(ztI8+$D?a-2=qoO|+y;mT*6Fue4e zo;h58$+_nAv0-EL0CL3kBdddK45pa={_p?Zvocu!g0^5i4BCUKsu`KN%wC`8hw0%O zvT6Tb}q9mB(?(H~bm<>mui>*OQIcj5=uHp-C@Q^bq@qSxjmFElnU9Ebiy+IKbK zk5{qNo{f;7EE^z!T_UlzfsqeS;MCL?9U;qF2HF$^+u$H1E4I~XCJ+}#q1X2oLghkD zU*I-NqmsERyJa1jNr?G(g4bl^R)IFi49lxvS^>?$Sf_s^)!d9pT@L^Q!FmS!VY;6( zpG)1dFXFgr#z@=M8#|6`(;s!1F*d48sb6K>C`%fN8eh-(EYl^(pqIh%H5(?+9R{fQ zIqtaeA#pnH)Vti)*vUZjh??5YoNko3Qq0N4QEMh`z??;P}}x8T9&3OwjiA zrZcJYy`ZGx$s}p*WEiN|6=$aOwAwiVS9hu%O15VuLIdoH#l?zA6&tJFEW+DmV}`Q7 z;Tyie9o*e_-|g8I;vUvc;Jcsy`JeYSDz3+t^}sdw&Q9>RO)=Ys8}B(d+1P|klU%W=P1;6+~h6m@! zfW-XW-~HY2$xnXL56DBEd{hC5&zWbQ=?{&>bC<9s8&gi>6w|m%3SFx zVUw6`mu$*xDrlSr@?Q`btkVH;0inTXc!U6!Ms)ZGWK29B$8}K(X14ARR7P4F_|4|)lOMaw;=mVYRjX27B|Db+77 z(s#DI;RSNT24lk}<8iG67sX|ULY!btCxNf49_27yi6!~5AD zbsSnY9gs%3l~GpGp=`0H%CMFM2Q=ZQp7XNIIeS}}CX0oKjP_J^%4W6wT)3BDEaTD} zeD9b2qZ6Tn?TwQ=TVdq>I!FX$fQXc-_1+<9kU9QwF(${1C)mk?c@i(Q*T+3{p{^m(dzp2pHqgtQ z^c=O4B$n$s6ziy{PnE>#*f)U}^jSz+j&(Q^$2k%@&+^Zn7@TsaP9s|MV0v-he~MI4 zp3I8$bie6y8H--II>sDNl_9bk_{E`gxE9kkm|nmd7i2|15U`yZ85&IC;MqplZG^QG z`|QxRjUWNm-3NDW96tZRhT$eBGkb^6f5jsF?RE~!j$On5a>=IQHLtkTsKQ8G;GF6& z>Lx*PTQmoZ=_E`mVS4GKAN{Bkna_OYGp=V?D}!GUE41nS^Urr8gNI3?KPV4dut8=( zWFCIxVJB7~GR($+xQt7HBMW2ijp7UkF^rq64V&$~5i!JQ_}yz+nvJ%YcJmHvpsh{G zwJIbgv6jU%De@V~if47>cM8|WL;Pk_le6m(K-drT68cs$D^6H!-0&A9W+W?q!&pSj zj9@1%vQyOE>f`7~G*e2SNQ|BfcEbk~k9t|!xu8RW>}vZ{0m_ujc)w;T_1eT!?l#J3 zI}A6;Mu2%GD|C<)8VlzN{EWUr*tv!y-ur{PY+w>hqVo>AF+K!%b*MFRai$62wtw12 zzE)@IpXuV^0Ow}#kOC~bbLbSYSPDNNFQeYg7Pzwi+J@>(U6Bfj(Ww?Xob1ntoHM5s zN~O^*0j@ejZJRQ0ZBs)E!%_ORkYz;smGu&k)hSLXA!S6l=XEjG8UfSDT%TkYi2^v= zn}8qkad`;|OMs88M@>1Z!*w~y!qVP2j#vSJ85Of0R;b2FS*QHNL6S^T2j<#T&UMf} zu-+szq3b;YLPzUUu1KnPGN@_05-6xWlUP$%lC=85$Cli2jMb^C&FS~-J9M5?!fMYw zU8}mqvbAkV)FRWQa_NDr>rn)288DQoVkLjHN7ZK~taY7CUMG%5`_bSU^gUAOsuRRK z6rsV3+CYOBMq-_KM@AUf3PR!2LPoMt9?xIFYmgcc11zY;sk~QRef4mG5r&gaI?1oy zYeeQ?Y$M*ecf)Yc!yATMzB~*cxqZ)Y@mU*(@BEsrmU%&aGvWfWQb~+vWzY^>gC7u( z8*jYP&Xf6TJ6GoYPHOJ5^&1#3WL-e0@E2qTnHjVdzubZEG`*@jrk?x0vp+zdr5b8JCe*fFz)8_#KJF z{NHhmM~u+#$InNyqGkBAqwE*t5+ubB`6E&BX{R7P6ImVBgY`x9Sw1xxx?F8?iiCLU zB7>}U#d4I4@UPS6Gepxizjk*7yjvGzwDnvym2X*7?R5{O7%iCUG-Xl7+Q zZcII>QdP$s6^-K?&Ton#v(5zKvC=tWM1xVMli83M8*M*d>likXIGi@-<74rqI>wzX#yqb>gXLDY)qZpbHD;LC~qarOuuH^!-?Tq+7HLP zF)n^jLWU_|lLZ~10vbUgbun~^?a9oKeW3lXB#J~$?M{iYl1ns1`ef z_S<1@=4p+vfBMFGMgo8kZ&pW%D1SJAA>`0z{AHP+`pOUR1i8D2w9O-9j+ z7>`y+vLE=Q_NN&|=&|eP2+++D5Y;!UZE4n;`mDi3Lzu!AbrHH^uj(*;t`p6e0Z^Rt zHt7kwD3se!X_)C40lx8u(TX}S8X&LfMHd7oKZ_(5uQgLO%u47YKv^?TqicdM$xPVnxo9WJ%W)P#a2`*|7o86k!5xz9j7j7W=Dyrwx<_BaZDXUG=SkQD7B>!KCPFwrp=ZN_8cI=^oC!OevXs^2R%HgZN>Z?36gRBRpbq?6{xt}+J zL+4`QD9Q(cKo*1xa=DI?#8$}+Gc?S~;62(x-N2L=4#-1R29GYlTA8nW!xf$TA^w1iA9m+C8>&3F~8gOSENUJo^z@4ZH)1@uhw-ZA2o1cK3)1 zNCspyPV-<5%53V$?;Qrhyu#UC0V;PybfJqL>Z>%HU`YM~bge zyH=Zb{|#BhGwGdKziHMOLvQyO>!lEEyMIIxU# z5;2f`&&&$j;(8}LQ`m1`V}R#_!~!@(+%Bh>FRx%t;j`T840{fUZP9)v`wV9^1`RWU zl?ogYAel7RsZgE-HP&&h zvH9$88cxWC?MXur!kYv_7EiK$eti(5N+w;EWr|TrrDouGzmoN8e9RE^h)DJ+2sNE= zIRBUW3?C?$wvZ%Tt^s$-k>7JYVkV3$m6)upV^hdRZ?X+G)$i7v`ay$Bs0 z#Tr?tSexatWrieD&I(+ruSp7uE>^wO$P;DjG&RbAb5ohJJ|`n_PK?V~&d*2(A|yVu zMDZENlVk0hA0qRmSy<|z;;h1FeVyxDBqg5#$|$^9l#M>b+8$=A=!|n5P3Fhh)0{zK zKscB+VFrU!OxPiWsT!Qwg0(WwfBy45D+98CI()IOWm53yf&cnn|EsT00olQt8XQ>1 zX)9(JrZO^`l>rd~nZXaT3YcC3iMip18@#Z2w0kHzfLPiD| zCr+8+IuIFTJ$wy|>5mf(y!PLbpfU^M1jUI8vnz$Dc=l!_BlzXC4+)(<=gG%_r%_K3 z6~%$Xb$d~XOz%4ej3kOmim68o9(tJC*e!gFPp8fBFWZ2iQG%kxppvcZ5p?(U%sR`F z0ZL-juPAQiHF01i+U8G7$Fz|fx-^Q>c#~oZuwWXL#!fQg8H{kQ3UmtO>eLCGX@GLj z8Chv%a9%F54v1uHbekz6G5ZiI2SNdX07Zw++esp_KN970t;5!>TQX~s$`KJW-V@v# zav*6z_RAwgSk1N( z@{jS*1(rz|>;^`ys!NRyML$Wr*w*ZRq|O~w>>rhSj^&rNO4MnMCbEoJ55l@wcO@6@ zz_~U8R^lmO+nyK;w@)x2Z6XLELYmQ{Y)Oz%uV>1{0rPs27bmfi&G1aX7}Jf8Kb*Z1 zeCo3X07^1^8By5HOtoU2ggnVQ?Nz2*NI-O4N0l1KL$fFiScdH+xfGpFyNhygP1+tm z3wub6LH{KyOHxA{AR$m2q8$CZh%9+sMta1yIM`78kU&i5qivJ+G{iiniZ#Jcc z(V2_T(I#^V{1Dx(#J}p2`bNhtVlj3O8~!^vm-Q}c3)=3c{emxbDvMkMf8AEaN2-7G zX(MG;kT;!60&swc0uCCb5m9|mUIIX53JBm}Oia!B>u4B3d#=HeCgl_h0bM&mqLD|5 z%iz)3j-xf|Q$tMRS~YlrWhGvWxItdLop8?4KLu!)3#W15c$iL)`EN2u4lJF5=y)`D zwv%PFgF;?}SaB?TOe?D0mWCvqtB!xPdY2F}T84y5s0>n}$7!^tu!5w@o zR8}3E8nYzU)XgYMNgy4jMuDSwj^v%=mpT?0p=A?%)1G<1-#(6$mk%*Twu0C~ysIRd z-|MtXf~QO^)oCrt+I3b45HXFq%==g`Wve>iyHl`E5RY4t;6}+Qv5>fuq^Cs7B=DX& zj4{(_7k(}IPwkQ1)MYfb|(D}ldw zT)?Ye{c7J5%{3Z2eMDkJTZC+s;DC5w%k}U7{_lIn1rLF|<(6AKn!oC*tA?-r+OPHT z#yS}I6>hP{HQ3PvG6NEZa~9_8GSyk84l%;|v#nUecI#@vI6C%rjzwKJQ7w zf-UB_ZzL>ZHV4Wlsg=OKRf!7yf&L|qs^gz}?e-iq98KmT$VSCR?|&>$$V_1g4r*XR zouXgWtc_x{+OxNpemCs23GAhPil6F#iGS+9ecH&uKa8C$4xgo>hd|h18d64wI1ZUn zIh}`(qZK02dOEat!TWVE(pib4roc1;W5?*wb#bOTc_n5IkqMBagUXaHGe}Yy4NBL% zY{bC`Bv$dvmLv?3#iBz(9WFCDgM)y_@5ZC7$3f1BP#k~`K0%#Iu8xn_v0PVBPH#mP zK{G?@Ts4BF5#-oJ+P_Br%ZP%PW51k&pbjYUBj{7k>Rdc}jm!f-PX`>?w@RuTMGrm1 zc+m;#{d64ZjKiU);|bkQf@I@E^0GCe#dM^j#m+6bQzx0%hRrG9ppJ$}MO#=m9Vv;k zP6yUC)3E2;j7-VLcAprpa5y&wKr^m&! zKAu5%Kthly`NnVjM$eo$`N0#XBdEi*nD#-|6~!SVx1MP49j0d;K#$*9rYX9X|Er=c$0G z*jX|lE4Ek}nO2aNefYKS7<~I~ps)`mDCxxM14Bs5NDO7U3Q^H9N|*L4)EZASRxM9389iFLvkI0g0Pl zuN9GOq!AK8MOy55PW>>uB7o!$$s9%#i5A1+AnSSw+{ftAonAywbb=08SiBZW9N?tOmq%2BGl%k!hCmeM~-CUqu^w{5qJT(d(KOTkI z*n-LY=RyzOXrN4I$04unV0AQ5CzU+I1vS9F!mt(el8}ZT)8HF&FKR}e&Gl(DI_iKU zr`(t+LEm6=AS@^!Te9&PGC6nNd8bb~ecji6T}~0<8W5vD{^LI$e((2w&&z(n3tr%5 zr+lTWq8VITZfbEQ3hYU?JNG!N0fsFzc}p|r}ZLRgY3`M zwj~_j;Q^ESutQ`|a9XXCA*%<|P}qXa9ZbGn#`-(1kC|F;V*m%>$L8Lo58gt2X zTUH|CHW5M~sYTz3In;yHS&UWaLMZEu#6};JGzQUQxs82V`(aaX{>Yw;nThe2L<9FB z`-1k9;E>E<3I>PMfynS_)X1P@Ee!&m6+rIr_f36ayldxL}ZH3%?x(nN~ zZ70@l%e3I&H;@@jE9rvXRY-|m-yj>RciH@k*@FFwL*xyd4(FOeZ-*RQiT9iAgV(1aXepxw zj=CPkPUfG$9Bea5jDTS}))*jVRxDEolOTZ47_oMs7Xl- zNh)exsW8&U%wU8PDO)D6B@nXBlp`A#ZPW!+4y4#o0YH!Gv(%RWO(h@%es%5|iK^_= zSw)8$P*BHdc^w1PP!W>yntg^!q7av18&IAHS005_Z)cCyn4SHV8Tb_?577hY0OT0}ixD zb+HCbB-|-WX40)5osL&5CVBNO$vCp#96ksKGc%kP!aaOk0H=?za|ma;Tz~!bzSSAz z24~BB@ArQ1@X!DGKhI1VZI=WFWrCFWc6uW-IM@zrTuwgaWYZrbd>b~~BHmNIJP<1E zQo>ZxUOSxT^5eO3bAgw6L_RpT(kBh?Q}WBR?WmRc+1R7BS?w*SUFj}MiCkLhLa?q)Xq@= zX;7MOg%Alwqr@|URL7tMM1|f&g)EDWR;OR0Gy-Z4Y7ii{-GMHcB#oV!7myb^XpPKV z9zLrxMr8Mgr|nMh2a+!V0rq)B9=<1E+fBJm&=2${i0nIQvNF1v%$ zK}QxMBi@i7^_oOAvy7Buu}8Lr_S|I61j7`JRkl@Mlk|x^8&VhYa6OJ}sFVHJ$wA!1 z_uPF(j8NQ60uz{~L|kow*&?T=S_IBz}&V&;+BR-{b`NUb8FI=L{@}%NiiYYk#&;F6@bgw_30|GFKq%qG75@ zrVr8~swdQuiH@by#CLQgvduN4I~XnMi|vgH1PP)FbO8unY()GySP*cjU&&BI7y`ib z#6e~Ta-n8ym99}36$owiA9Xk)7oDDBd)@g*L{H+QjvzB9?57aMblOm4$t+O(z6cu& zR`FdSEzRP}a7uJu)sg6MR??`?Hp+}eb*NA}ImywTW2|Xn|9Bn;oqigQGJh$T%FelF zW#}2bhciz{5Mz^|4XIH6Dpv>qL#fWsUgtS4$8F0Kk$ueKtcYBj;J40F_LNJ?C)%MT zSKG|UI-NAh4f`(+RP`gBI30iJMA}vW4oNhw_fva0&4GoKJX0a`joAVDPvB?IX6blHAW0OPzHu;u?9;|s9vyy_HD!o?I+2qM zv-edF>8rjV^?-U&`k>>Y?Eq=PbP-R={0@;L0d7Eg!ig*wACcW)Yr~mwSy!6+Gj(sK6D&>T{6(q zzbSiabXNknnqAevpz)o=76FF(eN(s9;r>r{7%5)mwGx2#e1O{z&v~H}b)6J)qDD+o z-~*^+AV87^H)3+TZUp7fsVB3G!*DWk6@Y0RrIe+BN#o2YAjph5u!cZD(3~0y$62R9 zD2H??=u0>@tT@LHo+gZ+#!)iWs(mLplc;583GqrnGJu_Oqzo%jphL_ti?PrH`YMQc znIsEQbuxBlP2hkm{mSQ4>Gx`^e!H~0M+6&V4MkMogYq^z#5&Qhf^L#mDm7&qx zkxA-3NEIUWcpO3{0?nd(=yU`q-o#4yku}mtEBczZyi$KyH~~215J$- zc`Z+Lbx^ByInYODP%|d@ES~?wz=Px_`0iXLNI$RG!tdB-Cqi5>pXOfH1Jag6mKvz# z7?5Cy{woeR$>8`DLWe4PYjPSK;dqsHB+yCQ#9Uk6&_ptH63HH#*t#D}C&tk64+qIb@K61K-TL$n z^-Hkd@lkf(lI*H{T*YO*iUukgAhSM_8~T_UBxOS7xNY`qBgtSSP@=*xm^5sj#4CcK zlc+}DfFzx`M11ZHI}WIJIspM~VTOiere+F!aOb0W1ydDF!}y}VO1cQtJ@V2s>U6d; z4W^%Igss4b*GdQ*AW{c`3_hRL6^vI?_oGC|H4E|9ZH_E2w+#`O`;UW=LaN3R*7Zz$P{&0vn^hH7-}6G zewVf(k-!{z5m4atUDfT(0I2RJD#nY*s8F}ureqyf0u0aUPy(r7CBRgHSDhI3TAglF zr)2Rena}rZb9(hyFBG<_84Gn}K2{MidOP$GHgUd{s5j#j`q7Ij394zsAS$snSL=q2 zIH?ln?*s_{db$xh!!rDu=&QCP`zl$&N*tM4Q!MfEQi7hUF)N6+lvq`=L>zOqFP&mb zA}4yQ7?~f}=r=k=0>eJ`vO$WYnKfd72iOT;0DZ(G3$|Gn6C?tJhHF-sO+|Y!UG(A? zzj*kWpZOVoVm21r;@lTZ5#a=2F6hORs8DJGB=)P;87FQ$zYvo!Nk#5YIm>-Q_YCs`Q*Xe2IB z2?>r>x2UHYOg67+BcWGfrX!&jo0udC)($_#H#R3wN8N`-U|;o%_R$1DEtAdZcnu84 zZcC6<5&)T~z;#=;Zo!QB7)kTS$h@eqHM_y0O1ZnBJCtTWpw@Xh@{k^ zk?GZy$c=L?QEJbir&yu_IH#^q*WTC~$ivA}p@aZT0LTYV|5S)j z#9roU9K=~PpWv;#jpBY+Ui(+U2<^$X1~8Hk=mB1h&PX;cvlT&5^9%}!dexb$KG857 z*n^m)1M5VTI#w!EwzrqPspZW%0f{noJS&OSb6zO-QT(GlH4dMo#lFwJOK_0)layKi z=|p)>1Brl_ZHH;4y~edEJDDa@$HMD<_yY_ZCnKQYpL6#>j9cBYMLCkFRg9n>s-0v& z#JWmgqjIDys}5_hm1nUC(X0K#`#kF+h)FLZRcBARxE^V6f$^m+VfqNss7!@YCMwso zW3|fynB)rmW%hlde{SQP@`e7V&=e~gWyyPV> z@$J+&)fYdQN8Rlih3EtWP@G2@A*z*60AU zklo>e-DZ4fKjp)wFZG56?-kZkcjNjRi0K&7KGd$MJLxaUc@=vjX)tGt7$?|=1{1}u zynT{%(DSqS-6B$*K>^1;2v8%tPVl03#d>UvHocw#A^1>WD!9493x!Q^>_ve(6%b0@ zELt0-KmKS20I%cu2RShI8B>)69%YTZpT^Dhx=`XI(o_uAsdYzNG*Z(({?ZZ>`Q=WW}cWrBmj!+H6`b3FnS;v3ZpE%$r@?LLq_eK8a-*-5k2sIH z@2LxDd#rn?_Tcx}bzHF9>^jS|t_*nSLjt=52+g=lV>k}Yx(d}-+CkJu$J#go>5IyZ zw#0GB;DBXSBNx5OYyh*TF;2}>(0j74W%7OKU=jv^BswE@PkB!PvXgIh(2+gieXjp9 zHBDgFD3*3NYt|^d2K(9}o#BZX2(oxx6Cgz+6`x5|ye^h2 zhE32{7|^o4{m}=%27#1J4K};Ef`F6Id2{F#h43h@=vYv$x+8`}G##Fmhn-6x4VbN<;blveRn^k@m`AfaO4!N5d0}civ z#AvxOcYDQWiS>bNNm%GhWd2p`L^E7fh5*Z3$QMZ7PYPwWj} z*2qJ2S3hrpA@(tNhfibK!X#*Yk_TVhseAp!@u=f%8W)PIM%6?JqU3293XH`lD*$)| z9^2Wv_e=W`kv8+pF_4wisDaHf#VC)@QE~@iZOAn*@z5}So^y_=At6uu!)c0i_$)gZ zZH>^#h8tt4vQlMjMtfFoFIufcF$rHRH1!i2@lO{d(h-Wqc^f;~xio+nZ-SK)3srj6 zA%efIi%~#U9UU#Mg%cg$)ZvcYc%Nn@s?4c>N=jK9%4P;`i!B1wY#E7}5=PIE2oUu$ zAza&{Ykw_k?L-C;&V-fLqc zCD`sHM!=hT3;&uV&OVlfwShMcl5R z$jIo~O^SCQKXIf1<=0H*;a;1XaLf!{OIx&iIi+;YIp_Fv(O22pmS@oK`4KmTzs;XWAqq z9X(b$no+Zhx=#R$mfaAG4u~>pOv4d{q?}QnE+TH^FLS2Nf^0EF8jdSVY(r%QMAsinYVf7-7`h&(T!%2!f9sKM)azY2cQrRGj`?mfR^OR^;-x?u0!&V zW132dX%PP;WnrI53L*-kPP#sz-6Xbx3naXiyrqLwz*Rh{BvlAqLj=OHE0$3|YMmry z4Y)>~%v3O=Gq=+#1gtXfsv}!b7sjTqD!8DSG-vzN{f-={>$?6gu}G%9?XbEx|lA)R1?;z zU<>wFzH;yIfB#>w@Q0vbcs zie<3po@rB*FhK-BjNk!L1_6Z*LS-O>TY*Hu(UsZ;SLH0^J&Amd566&cd^#Z^iH&Td z9SvXz*s@$YAZPh%C^EJRM9i4cF}my{i$*6J^zoS?Xeo!x6rWj zUwyw}Gis6}Uu1_cqiSIsowF?@5p%)J*9-9NI9C!w!%JorcM_;Cx07O@4ibj5{1;~_ z@6_tJ+_vgV;Ls3Q>zE@v>B(d&G!>!vaxt`NIN0CQ+I0Nr7})uzWyR?10A9b4;|&f7 z%OCc*I3=%*(H)R)?<%$Mn*h#m4wPMAWZz<_su#kf(BiOVCS%OlS?@NK#VzSwYf zyATnJ56eDU9<4Ro!9Uy0o#AyNx3`vDvWF>S=%-SjGO?3C92baTQq2Xii$)?>2z~x{ zB6aAOR%$SHR|FO$9$|wR=fXVRMw*;GXXXN>+}c41{Ar--g2HC%6U5xz`ob&IvaPwvFCsndkLa|^3KJ35VSmQr8?>5J= z-%3(U>^ADylrVN?709(Hl03+BtxC)*`u3)IMoJ+;MBb|f6G%EUR>A&D-vy2~ zwwAEPRh+e;x%YBYzGc~i@XUL@-zC4WW%$KXUBHEXz$h>ZwaqZ4+awS5@^|yx6#du4 zu+Q|mcma0j1bj0mJ%#p0R<~Gn+^Bl6y2;LEa-oN;wfQVkwfs_>9ZDXx&y1%5DNl!w zseKHJThF^)$=>CKJNA3Aa5i@L{P4QdOLE=Fx<{tj6#6u5I8&R26yvF%V+Q$+T`Jv3 z^G(zh*BK^OS^)9i3Sp4OtON$i{VKL(@rb`?%qg6j^PPLw<5BxD)q*$0jW$)~Dsv#w zsJ)Gfv#P=Z45|K1=+c%BeJhtM8hH<>(q~aZ`mY%#3W&zM1POC~KACxX0bdC}JHwme~8I4P*e{Z-6vfU5Pu`Nh6d{7vG3+*QsLOrCu( zMo48X@Aq6Tc4XJ#e=d~!xnb5hY0mibi2Tp%WS3^qGHk=N2lBF=ydBfgv6r7FX}n7z z=8}d;i0p(oxUR}QV_QZ;f@UU#4^wo$Vv>j3`_7V{T3#$J@o>nvcg;=HEN57uMUW&# z`G7>*{L{KyT3_sHpaPhxs< z-u%j*#Sppiu%jY5_DP+4=LVX#`4?57B@vC8dl z;O(u=8W+nBnmd*w97LPmdH22%v|#)v25U`gHBLKm9d`N{d`m+J6h6yFUUIHi`ZV4-Gq!4!1qmnV?D*{2+RCXgl zNVpn@@635z3;j%aQVVgm?V>F;ubjdc_^h9IWOLy3vjf2~-B5|RJCZTPxv43|^FS)o z5+k1;vGdPVs!vROpNr8h)O|SRVrDdW`Q9pv^||nbz!z(!-piV9H%3oBg<*3n)pU@TXX_=M3MDrT>VO2yA)`j^;m&Q$nAAAx%)|Gja;_4E zPEn{mASyHIqMTM(pG2RV$sV)=wvzs6@Wh zq|&7jwTEufy=Gav8Zgm_)2*aes z=#J!x^Ltv`)G+?sSjL=vU8Dqz#NA(OC6m?|=p9_{79FBrFVg4iLlzj!7JL1>l?r5k zp+?;c7W@#*gr#%&fu?jnd<$%3_xj+l;*-3^U-kXNk*yHaHrF#*yxs$8YJ*1a-j(f_G_1FbutgAFolGJCE5h7I)%!p^sP&i~~K`7MD+ayO2`%lZM&c z`3%+e7nY$ukB3uF&L*X}pJU`NysQ(@z_-g_z|<}7*yaRD17p>S4dWe#ozZJWz(rVA z4=xvp)ol$MVv5Y7v2xUC#&J)>!?e&bmIz0U6n-gA39XlYua&0>1_!vk#Vg3cIvH>+ z_amD{Cc`Z4BQVprfj8$IoXuhP;onH(84!mAJw-G+=AcWvW6yE^^5whH8wd15vP7>8sYgu{FMbIZUy5S><-cg)B=fnoF`00!9dUF~N$C21sCcwsfhk zL{KLKV}VUQUZ9&!vVe44Q75!FYL9C__anZ1(TmB13Ch-UO4%dul<5F&G)fISb7}|a z038a+M&kx*`0B<|bTiTHj21LBg*4&bh=n3u8UgYM28s?vC%n41(&CI5s!t1-8)#Gf z-qLVAbVUVMQXGoM-zR-armcdpAE{&teV|TlB=Ss7q@Y?eicg%xJkmfQ;Un;GPP%)3 zCgWK3A2aYzcZ^5$YV4gQrX@tSD=#g6yA>LZ4k8|G0wkBKI>oEImt@N-P@B_ZOz~j0 zyZD?hx( zDzia3u8;-B3+a^W`Yk(n8D%;%hxluS@AfzdQox6m5sxubE}@xVVBM}mHqT1HftYn1 z#E@vc^60D4-rZ|Oxf*l|ck#`8gh$J8Dp2|!qnaW?=R=l zQyrW4#TBwkZXQcZ8_&4Ab_n8bnUUT5D(@$ec55=B;J_-#_4?2cibU$%W^*Oo-)0-L z*lg6G?>hPSESxkvcHc6$ZYWV2cf2w0bvUpuD6AM-8;y%(6XXm>R}P7?K)$RKAg4VNFZo$GWtlh!AQ{zjpr<88@_BKp0_u4{ z#PEn@!MO)TP;6--s`0Ripec5DDi278L%ECB%a15Qmd4fJ107-?p@AQP5*GW$bG%7TOCTM7y5{U3uJ)4-EW< zFk94Pt7AG9A1WQ5?u&V$J*)wq_G2UlM$AnN&FVn>^4V?Rfv1}Es43H^M;qg2#k*Ce z*t?+wRF1h6%C7x9;-h=@HE?YZGtE3@C<-4Yr3^{IBC`pR5gD;{QkStwF?Yn0nBr{;^W?W=k9f)ehkCIGy8O_4%^<);uA-N%uc8bH<>J=~|EsipM7-P-Tj9z>ju zMCW2Kzfbf`%<8952!6Y_a1Lt7gXxN_w zo9#wDvMV&@FEj^IlZ#u@-%wHSQPi^ zp*OaH?HFNC(zyygp;*0$>7#?XL~vn~g8(T-Jh|)SpGwZY#H^=S&y{Ox(Z5=xZ7h&! z%=GVntusg!Aiew8 zOtFEIdl1t*3sWhi5S=2A##2c!wEm=>PRp4nL3g>HG7ZCVC>m~re;U`!C;KO1j+8{M zHXLn}UDp$6J;jl>AFWKmfuf<5h42$LS2j1OfcIax!}v|``OzJR$8Q~+q4ez(20Qm^ z-7b#p#3bpx06U#;;AbLNB(lB$DhXH_7>`4t!^c+7O1A%m|4rbj7h&g|LNd^&h zo*#&m=H{4W`+nh_4e@=!6p57hd2!77^O#E9&$JC_!*f9AzHUjsn$?b3tR*{=`-fHx zZB!((!Sowfg)3Z`ibjMgsVg2`BmzWM zl%$mt{cf4_iYy!mcC8Gdp!fiM|Bgw-^6m@wzdwIVK`-l_|&+hZSG@wSF6gDMxet zgnkR(m8kPAkuohhbbCyGghdC0pea33&&PL9=}23edTc@5m2i{IBkH;NOV%~mcHwdS z8aXsKm_(BQj>)0yv|)vONU90~Z4EHEy_qF~X165|QjeujqM*@qv?Z zGdLM5j1XR1NXs?pCc|2};k@I!;z%MK&jxAcHw%gpxdy_+Ybezq3ve!Ad%?Oj7O?R` zAy%-5I*RF0k#GM}p?va=8+2F@5cU?A|uul-`hSsFjK5m@073 z0wVHxZhb27u!Y7%jD>>-M4h-QdPBvx{&=R;mAo@2eBfU&Qa02yUg_kMa!v?{kKGM} zUK7&<;zofeNcp5~;l_UD9_P-(wsXU?LKWQ2?le(De@M7%E)!13+~Nf%^=W2Ru{#+R zT~sPnxtx-MYoKbCYE`G5KNR>bM_!=-YAceIYUCYd`hZ{c=w!s?;wln-3%c z5#`Itm;Kp*MK`%=)|1t*y!0BE4>qAyLJ4k0K1~;}#Kb1MAP=x1QCgJ-rE!wixQ?SO z+A#e6%_u1;^Ia}4#wID8Cy$53rTVPU;7u&@#@+n_dva0%n87VS)+j^B4>3Js;T`37NS`j@UHa8>eVluFHR+PrdCFH2R=YZj zIn;;!TVs>zQ-FF74UY!#u_^3m*F+D5Ytmf-Ir8kDZo$F`55{;WHV=bkb`t5T+Kyfp3(d=qW6(l}5Qx2ao03^vx(VMPr z;mq;~rf2w8MY-cgYC+^r%?s1TBC6msmU$v5@GLv5#7QKY8AEVD9j$dNuB6Ce$OM&g zk$fBh86AyrYrXse{;nxh@Z+f^J0_k59$B=s1-Z}+>NDr*mt`zaE(8i-Ooa)*Ok%zi zX49J?ZzgRXYm1V)3&IiA^!Vy~9FTs8SwYWfnF`_S8?0*xvi(xHeOjN4wooB`tI#;; z@(>tq!2j*%y;_h=t(!q;JCCj$CG1qTinR@S?HAfpcWd16Y2(2k;*gVW^Eey&Zu*8H zBL>d`$WRT1?JvCK-xNL-ZfN4+vjq;dL3X$1i#qtKO+4c6?Q2mgh$4+m6o1?o-TKXr z%iEOK*G*h@kgmgHYZ%SF9+MeMYj{B?|130|JlrcENd6+|SHw1>K6;J|e&!?S%noOC z58mH>#&mSn$Jdwd1`r-E8lfKmB`SZ{Z}kb~h(myNa|r-dN;1zjawcDGG}nAS z3C1b2EdIKfA5Pp=;}F}4H;56qIm7i;Fhzmc&w{vQJy2IUdWd8YIoi56E^VDfUlww#qr;b1h`(aX74$*2bsm;2tAR_DN zsy>H0j?>uA-BTVg7w%41c}@A9_(%Ba>ZMo9r{3IeihP+A5vkg>m3ko4*^=He>wr3>vS)5pi=!; z&7d1S`#LK6uGuul{gXwI0NN8Ldl?CT~-+95SAGzHbaROLg=RS7~k1yqi<7iLj> zZe-Lvbsq^PxP|Fx0H!!u4Sm|#rd59eN_pYMA|9W+C1RelAPX6@RveA#tK zu8#Wa_)HM@>kPu#Ud34U)v9&v2TCN@X@LE!hXeNw&7-!fq;BOo5)>RpoMuW|Q3^_O z!B8br7c=Vyp-Gm*w+BSg&ud9?p0=yB;YiL8|P={l7r%&RvgDgLo(fH zBvH5QOVk}vwU)wuW>Nelxpd;G6^-WmjmO;JX`4on+vd4M%U9WejAJ7gs>4_;sPr>k z)x9B)iTI0IsIRUUVo`gfybCBm zs_rAj9PWy0-w|O>;EU1(D-)LDOpEq+w{6}7r%`daekaP>&j_oro8j;37#BnZxhu+0F(|Tq3nXTJq%*mO#`G5w!zrAf&1zo> zzF37D)X}6QF?uVRCpDK+O&wjSdQK=8g4REhSbkJj44CbCQC!v2CW|o*yCj2)(X&2? zOygIxA@=VTku3BV^rgvH9Rg@Rxo{V(lNDJtiDIFjUa%H)^?G4^JZfbwae6yy)zbYz!==I17W%_WRHzEJ#un%5#YcW2)77#Qbsaj}^QX_e^f-^S;AbRHs~M zP~|(a-B_m@kB2UWfY|U$A$m+4 zUz5!e*$9(0Bk>Qd04Imc*42L1Px2lc#v3AL?2ZMeLF+XZI*aLZrRRQ_y0n~Wxld}r zWBI(GPnn|P+xF^^lt*XUr^=vcj!?oOEI?$NajS-PJ(l`nJee$BycpyeuLk46(Zc;y z9H3SpeG(coQ&y<*hh5CT$PYZg$Ef1Ty72CTuH#6QMG{zwBFM9mbnDQf!*mW5_XhVYd8ISU9i zA=iYF+5ti!J=17ck%r;KEl0gdEZmb&Ir8Zhnfz z-;3~W(ZF~|Wl5ons#xXQ)r^t6WJ6NO0E@1eCn@a%P1D`Io|RB{{JVU0e`#r#UuRUL zg?wT@q+|+<-UZ9VIggi+OHQ4*4#2k1+JINin4mkWK|*P4V_nVfoIK5#Q?GxY0LKf> z>t1qNZe^d^zA(*f)!?6|K10aEqZrEQxY+vpab%C?OJuHhO@OMP#ZI9*V>XtmYZfOq zXK_W~DLC06c~+bScszXHT-QWNtsbKcH_A*o@4$K&2LiippaR#d*6orT$BrLYVU`=b zh0?Lg6|z0$UtWpk&d${z;nPBrIcRYz=tB`to1%(nun1-BTDcJYB1qT3l!Y|vb}Mo! z*FGtvsG$+1wwT({K6jI{fiTR`QgXt&7#u>55>Wz{r3Z|oRO_k2Iv;TwQ_@X&Gs!%( zfl}WB-#o`S6Yjd$hU^VT4cuImC3XLJqbh9og4D4R{fOWeqF#Z-iWk_=$gg|$bX6+D zO6F8tc(bRtqJ)dM7rr%2%)c}J>{U}8SnM2t0}wS8p32Ad-i`(&m_-HMr3tCh6CF|D zJ34h(wAJdkKVYZb(6nr|alktf`;aXo!q+iV9f%l7wx&5*^P@)FY+vmUOf#tjMVdNP93zLR7DKgste&Xr7t zXH`>ZFJ_TZ%7CT(FoQK4Wnubzm--oysvxd{Z@yVX)ci}XcH7Oh4)PWh%(^pD`L3xV zXT_KGf}=kDbD9n%N{$JY+`G`>qlrj)P=vZ zEA3Ji`F|29nX-*y?+=-ZIOIx3MUViFi1=tu~=`b#T|{B61_iz&!j zQ+>y670Q;*^(hUJAB%Uj=w1BB_`d#6+RH31V2j?9Vjk~;ZB+LHBsJULgANEI6IB`a z+9AOKXyzMiV>qA3$+ygi>KkqLa?8p&&?+4D zA4r(=i5I3B3%IbDBcx7R;WlXPWCw0H2kts!1T<80FEZ2JPM_=X%9eBTF$`W2<2om z)ys&&nZ_*l*VxH4kHr&4v)7wJ7{Q8z^olrSY$UiT}}Mv;G~gWK$xZ%xam=e3Rv2I|s>`T29fE5p}H0s?}md9qw|E-#+ zH~RfN;Ig|7f5831w2;K)wp2o=FKta;EZ?9O9WyBc5x;6kx6LpTx&*I?8mKAnxo?;D z(C!zSr%uv*mzO_1i?3M^RVw;meR@gWaX;7cXs@sj3Gi8#X$)wIXK<4?0*K`t;qa)n z>!lJ$z1bff%JERu(F>qn&_pGjoO+<7Gpc|@YekYGrl7IMw0^UHe`OidshvbRoS~As zQe6A2LkT8{B5PN~D$1wY`$uE%9>rOc63z%UEhd34{Yfnys;$<*+)%odAWcx5l|!>Y zHKr{{u8S&W+6CR2l;5Z<$@PuKC&Iy^;GFYA%KFB>20%MmUG~pVi*@p*fg!+jh#Q`6 zvFJnF!j0~A>U}_2Tj&!H`%++Qo9>v73{F@gE5l?x2Ro&YiRAX8Vx*o@&Ch$(hDxS_ z*z+#OerGBn*56U=>~h3OBQ_LEDKm@S8l#!!b*^XSZV3!LSqC}Zrp~y4 z7Ne8}CdNMRe!}3;0@O34mtAhz+u@{_B2+C#uJd|cKvqYQ6Fa+sNvfUtiHU@W%<=qv z7*3_JOe2M)sgkFbQQn?&lFWT!t$z0W;CT#YuMzQQ6B^qI4!z*N>NHLGlI5Q&qckB; z9Tr(6Prmjwa$R_)=o5wq57#|dd%Dqf#YDFAQHx`;ayro%TGqmoA)SM9zoWwVHb+du z3+LAqPHp+x^OI_ExY4F@7|xm~1tm>e8Cxt0^b#wl8sgW2#7a|DR^tdgja3nrIv&?c~z;=Ezo&<;eUFcu&KMe>Lu z3*Tmd0X(y3V67p9?{B3DZQqd`rExsW2r;Mvg~#wW`1hQwhth|Lx?T4QUZB>(*t9$M z8SX_nR5nCBS0$O(C0I_)cckcBg%b^u=WVpo@*$&=s~lu$7RN+gIVS0|FNf4o@j!my z6rnd%@flf&MwBrI=20B^zG@TYeLfuJ3-!tJX}8Wy;T?KB%P?yi`|We?J~HXCLO?O8 z7I^O(y}Jy>BTy0-F8y6uMLSv*8A?9Md z1@-fUx80+L&(aCAP4Nc-mizLf%DY`qdW>pt0;pIW?{xEY`JRmZc3r?yq7o5hw&xgU zdYcV+=_Kik+RgyT+5Y*4L~~?oY8H;r^l7P|ZK)+1b#{i1cyx!$!AFi9=vKyA3eT0pATs8Y zH@}~G<}2f$K1z^UVQKY;cnX!oNQ%s;l@)QPxfAZ>`lC%S>Hd{MXp zHlEa(qF-}g$ytNhvov~V2BS%7j9V~KQcUR`RdpPzy(Hd+k}iCIwp_tH=6n{bSV)A7 znAWnD$Pp20IDMm7&$Y$NymvWlR9EO?hyP$Xljsy7c+)t~SQ&hqO;qC5h0$`Zu+Mm< z5TiH>ZWLSp00ofN_oBuFULtBzXeQmr$tBR3u`x6~5kK~(NDdQ&)LFvR zoFsO3B1ucF6lZrY=fVIZn4xKqq245}XKxr-V^Rdl8iAJn=KEHQ>ZX~18@9laRz$#L zTL95Ot8m=zwp|D|{>M=3o=0ne6IsR~Kj7!bV~i}bu5v8zg$$+q6R*40a;1+Yg>TXm zQ4!978%otjLDBU7_Iq2d1%w5#Ng%rI}+zd`z0C6v;JUorX}n%TyS zsH+X{HV*f{L8t~9kNtObE3{YPiBRXZb#H-dfiv-B0sa5-EqnEczKKwR{K7%kKsUOT zao=joVV*ufnTlvFveA_X{lrfPs6Pq4G4^*JKtf7OsP!qztlmX zuNA@`i1gtte0hCe04cEwi)*D0?dcSa^xP?Ze(mX@#oxWQ4i?R<9T*0`T8JF*(DBky zZBa;bi}v3!x>4$)>o)KP+L%~eH7O%0Ts1%9zTr2CsPC5!cF9<4&p#y6jzS;StWU24 zS`x@kzRiEF2u%KLk+`Y5ux_zU5hM)NY*FvqXmgr3dtpQ_8+tT0ncDa6#WlThorN^rwaOuKi!Nd3SDvwU8>(`0d&En5dhn@?DcY(6ktai$ZUbWer=Ow)O7Lq;4 zRjEB1p7IColBYWBQETvuFhyhrG&t zrS*w%ZRpxGH+=X43|b)T#`G)=Z!NN4>)4muy@dWYBETB-x_>N!6ImfSgUsZvk!|ZE zSJ`K)$*=sAy3Y4~(L*>$PiLec^j2@Zu^b{%6Lj-~nhy}U-r6!&`up_=@9M5}0+o_~ zvGsnMF`J4)7%?I5(_#UIwb4W2MU4=!O^cFrpxt--!2f$%l|ezRl-rT~sJoa1C;MrQ zqizSRV|{(HQ}yg`&`NJPKl4&Y#6LkRwhK7OBnhXs1TbhMlf>eU(3EocrkJ1A&nN9%HY*Dnz=B>C0tysI2oJRs%|^NB4v# z&x6(;Q1jTL_7`FGd_KA{(yO)e3|#KXNX&^ENc!uO{|bhNEq&BNXZj@OQtSK~D5SB` zU;eQeVrkwHu0UqD(j7>;F}Q;x%TqQcuUTCpZh+}RR(b8dwhWUlyku4Lt`btc5~=yz zGQq7V;-QkEh@Q5zZC_)*d&i8~-Lkym&~Smq+Ge*`#ptZ3XKndHH6uYZNV@=$-@tw| zxa;H&ksvJU0D;WgmpylUUwI<6?x!0QQ?ynVBS%+rSeYOm@K=Thv+n1o1Ug&+u0jF&<&@sS0!CcmHU=_yH(e z7SR5_lJJWk*52|xcG_wTMEPYx@ZWsMqUX}{%6fi+sJOJ>W-B>&C*q6r#3E4$axA z5-DPI{#2p+bGuqE0Dn`y#|fPGS9S46c7+9|cJ*5H_MoE@DOH)G$R{U|+!dB4ARL!S5iL9H<}2373y{WaeEKm*-|)cZzw%V|=E zw(@_-uf_}Bx|2uasA}%^ndV0FUyYpH?ULheWu!1NF~pwbW!Hd*2XE>#2ATG1Nwj@E zewnJ9e0O=E#F7Apc%5kWVIh0M2ifb<&8vZ3{!o^!LrT3(0UPH}N@f+pUem8K23Um+ z#{~D%JlLXbKwUN(uPoVW4Xd(5OJ7yk&<-kJ8oP0Rav^YUbC8^Z(rB-Ilj3Vv90$OU6^e&I_C)8u5N$e4EzHa_B-%8Scd8GJPF|J8Uc)Mhdb2^{A8KO z#?k*+NdKrU3;IC!>Nxurt&FM@YiA8)EsR}oz4jBzUM z!ayj^$54fu0QyRkyRbi-0_R%-Z!eHP#tCqG(1he9`}!Gw60UR*1A@&!LIB^gS6+8q~Kf$+ZV6@p3##8g9=%^;IkCaw=A|T zy7A(N)l~F(F6AAlU9`i>Xf1hYiUsk450_Hf{hkvQ^{I?|Gs>*ou-pNQ)nP=@rNYw2 zc&9p;K++ffIA+uVzr&Jz!hy4gzDrH#(lQCR2itTVr@qWZ^_;xh=%3u3?gXG7nU&wS z9#U@x@UZDMOW75Yk&?DW+UI`xGCvM$xp_@Rl0VmB{V%Pj0n9PXC;lu44c*{f*CG-Y^NToBGm9bS3JfbuAAm=HrFNA(n~jeI~DTqDPXFZ9Vv0tSJlQiYYervw_RuuF}EiqsAEUM z{G|s{1iCVa8`}%nR}@L#f-7s~jh{d>&MYrJXOnGcANpy3aO;SKyU+J%x5@47p4qE} z_S)*kRkOJdVSg9W+II$toh78Q)}y4ixxVDhLxaCv?xa%ZoCge>GVvTYcT`fC|1rKA`LxN4w%QZWxK^ilc?y zTI%HwCy0@}TYV>`#0WIjOg2+cwy!^)eEM@Dh#RZdGV(PW zX1xCV%KLB^U%UIxUT2xv;tPKSJUXV%DX7P<9BZsv938V;^qfA{+A3fkl1bAv*yTVD zJnT=mO|{NFNaHyKh%9SoS5mi<%7erRt01b$P#^5+jhbWojZO~}Iwb*B7Qq=yTQC2d zpEbDpBGumaPxFfoMpcoWAh&NLZgQ7@Ok{>!qsOYtzgyDb(==62l6=77NC5d ztv0OQy8MEy&*nQDEy0}oX&0%qK2wz8#++{GCybbCWEUh+z zB>1!HHZo)wb$BDDq(3n?9vuzV5&d8r10bi)DAuvpf~CGeW<_h{F7dU>;1G*x^Qmuj zE_t8bXdL%t(mlc>?q_59H3mA(;!~H3Xqz-oeH5&Md!6D5ck*AgNhfh@&n8^HzG!L0 zu33VMrnq^{?ueIp95p5s3-B-vd!9!}(|W%8PwGMZv^aiQ9+LceF!vlDmwf7Y8d0v% zxQ#TvV;%_Tyv>5W;Z=_LhKsk! zjVKW^Ls;Qgjg23-mE^FW#ByeHwlqK7#Ef|}_`#RzpeErX*U?1X>+O zn3efmhc?SiBg1|6qz{_4#)sKpO**jI6j=!;fELL&HT%9?z4rPl{}pz>M}1YR1d>a zS>X{67PqzhoI2&gg_a)WExuaEhHq=xS)LDz>7VjW*f#59IJ|0g$FU?vV(~IpICM%r zB_soDJvLW--v*q@4H!~z@9tEAGwW48IP32=$`=YKyHWQZLa++_b>aN>D^qEIbPh>M z(okbj6Qr}MnoXaY;U_{b9`thlwRioSOTLTT=82Ox{y2$F-ho|lbSqQ-FIROw zrGpqhoSc5o7RNOKst(&mQ@lpMt=(Vt!~$ZEak|f|vuc|zlaiw0kBknBxDo7Cri+jh znXz;84amY8#3J*RgDK9}iL*f|geDb8nmA33sF}bSj&OA^r&M8~KCdP<0f? z=0ZQJa*LY9d9&pKWm6^lKfZIkVS8fi-_EsozRG$91P|<@trxLzZP4B_H{2Y~yJXCD zxfM7yAJwdktP>CuZz{};UruIYXuurT{8_7IR$;9p*Vejwj;%-oh-Bm4&2p}4_@uDjHiyg0BMr=>g2?H`rl z#@io7$2i)CByE+oHNIQ(!XgN4d`FLs3K(R{pn&R;2bXNRiUg3YF8N@fG+>Qlo4+k`cFGQ}*RY!4wT_#fX*GmVYf0Voed zHYW7*dX6{O3<*v-mb?*@&~AQ{o;Dv&BrM-ECxD}PbX-J5HU6frgx>8)T>bQ+$-5j*4v1J!#I zw0%y9Xj$d-@CtWdXx|Lgi~Z3o+Dh*gL&iDzYjDFM?mh|P2#XYY8Ig*V-M*3T-`W$Y>lKWUP74yp;D0T{ojI6%Has^ghl` zU_buZ+tVz7Bp=PL;n(Pg7wv&uosv<+x<_pQ-5<1tT&-9S_Pq>nY^gJL1nP9oK4KQT zOD_A6i1$RgO;&adktGBOkaSdUcd>@F$e0AI+kBeW>-98*IRols^mW25|L5If7a(ckSgZNC4R37-aXHFktV+U9e>$HfhhZ^*?%z>jC+I{Xy>Wu(Tci%jY_2TfqeKi#z`k%mKSnH)t=8h z>g0D+llnm8ei}pFM&tXR35@93&MH4J`@cn>0lgdLc3gQXZ3s|IQx{Qf@#ulW8m zpieGf)3@n=Z7BuhGN*0s1lQhsmAbjGmGj^tx*P z2M$fzmcXt5XAnt!o%=#0C!{w$#5}cS_5fY)gk9p5@kw)U=j9waVEJPc1blYd@Zb4S zgoGiIkypEXlq;cxRj``=J^Bd_u;6uE|19`HicYS?w;OJ{(duY#zx%wTEQlQJP2y4G zw-^;=q+8C-4#@J%>&iY{-zY9@NT)MU}uf)&!o_rfb<}{*L+83j)AXoJ1U{2MM_4~ z0)M)9n-`S)UgbP`4nMXrS1jHY7gSpXn67>1rdks!&luJSPYt|w@oIQ~=1=ETjwMCFrnw3d@ z1>{_}X@2IkdXP_uD|u)rdF)A{$M0_M^OfIY+Kut_Gg8X+ci=PV1Ljb${>I3#05 zROcTLk>lQDiB{Btrs=N*of(MjVc>p`&a&Dr228Mf;4;UM$-IrSho@Xb>G;I?shMWk`Uqbf$= z^sPx7kWuG5xqsa`Y0Uphc!1X%bU(4=_dfuLKzF}8>dEZh`PZgHE|bT&EE_$qZG9Bm z9wcg&tjN(;we_j#qb=d}^4BFWA%SBUOlgajl9xpTxJs%QAalfjy-|kfN2BaRD09}F zMSYFUTHfp{sFm|9BQF2P_YD__5?=6q|Htra##&dZb1C}Fbm(wo zxl&t>psZ_Kk7nB&5eA8xA`XW{Y91p%xKvd@aTzqNa`92WW<6*+sv=$wnu>TONOBx_ z6oaOTfj%tqQbFudkA@ycz;{#)?GOq#_kRd?J-WAC{%!xliOY5W@%h8^pKrhaxBoKS zVeen~;+LuR?*Mp|6ejl@->4=k;6^X-Il@;w=c2D+Yh3vsFynOiekA8Ic zX#W1XeKKFi@bX`mYsTxZ{qf7^+R|P(mQ@FJ5@>i~Q`e!jr;aD=|cnR!{1^6h?ilmho7nZ4O?&2N~a{Q2R9jr?9X{QO6+9e(19 z8Mfpf}hQIuP<%ce~Xt+!U=(3B(eqV5re0uq}4gbPE z1{uT8n#OM}I;YpJNGcW;pG2#3Q7)uifDeZyjSqnK^%e7k9visJ9rZ)In z51Qtuy4QoI>FNI-{#4vZ^0J6DtV$@RqOoO$zV`3Ot{t?+#MAfMoZJtNgyg!Pd+zYu z=Z?SM^M{ytFo*b`Y@w^C8ZRHd6&}Rg5@dsyE0 z41Z|U=!Nc=7Ocat?+zRYG{3+u{=@H?Z_f|2p4Hle^2QSFugl@`;oDZ|$Lu~AOlb$E zWNJHR{eAv_yv}9!FTV9zR_7?Yo{UG?nT(@PS*P~>nqM2PUpRh{+1rO#dRa#B{>aw8 zpuH>HH`58o2juXh!^b}MvGV&H!^#XIgW z-FxASXZ2oskxA)};r;Kveq}wJY-{SllJ!77Zma(uDo0vIe)#={jYc={+sWiqvanKH zjsQ7Zsh$NFEhD(Rbyc!Df8CQfXbR!2Dr3KVJ!m@iLDS(H6+E5cmi`?2nwJhptV(i@ zKtGljamBX{-|U>^=Z06lV|Muszkbc|bMAw`dHA*~@c9kHuU`W)^2%Yn?3&@tAOHC9 z@jw3lW})bC#l^#g_U#>i__M>W-@x+h-k%*w&cYv+`5k{a{OqiNA=~r9msrhfXwO`Q zHw?eFNGBWog<8-D%wjlRiG$WQxw;O(z;vU3gFpVxd(BV+5-@UtL^*(a8J-SGR; z_hn+c=FOdPSa#D9{l2t!)&AZvPH(;NCF6*Wx??2e{rL34;bPZ2)3ld>(Y$~7OV=mS zL$|F7Jv?-aJ))ACDvTIVr;aAc38sF7P%WEon!*>&%B+Q$t^L}u*N@4dX(D)fG=ip8 zg1^HFnw~oX_82rpzt@5|tJ5?4wZ-~v3 z>F7n--BsFk)UP>KLDRBn{1P;M<~RP;7{npKa4)c85H}~l74B>Nhy_hQF^eWw37Up? z9HpRXLS}~(G$D(4_&>)eX!3?n1WkwEsWp|baGE&AZR4Vd$mb=n_AXMo&9z+f5QCNA zWS=huz25k)I_7B4n#8c|;%kPt{K+iKa^36b z$>JYgZ$+p21zj_I3mp3&{><=ek>z^FzyCJ_k~tTA|DOzRdCRvr!MyH0l2Ti-Ma!lq zmVLiUHPHWefW26D@7pcQa@oa3R-Owyot_ z?Gx`KslXwX1mrcBxy+$P#l(v_+*p*|T>t_{lEgJ-NqeX37%ysqrU(d*RM3R-4<2UF zg!8*HXnN*R4w@pf=7K>$U<7<7zb97EbYQ%7;d`Nb-?@koZ45sm;S!}J=WF>hKnw{#xpD+TIj=Hyw6IojLbF2 z#@H3_VIS5!e$w|&TPORu#Aft9y!Q8D<8xUO9Xxpr+jr8l0t2qs zLt759w`;!bXar4bZp0C|p*wbvx5(TxF9ZO0F_CS_`qM+kCjlz_-lMWIh$v5^sYxK6 zA}qZr82K!Ydt2(F=>3f8cFndH(N;;V0ku#sS5xI&FmZyz?io$hKeclfOLt z04n<6dxvYo$(Ej4Hv8^xq zxBu3N*zLnDH;#*UufN5#$TBkj7KHVK?-|E@#c{vf3EzUYW?3wA8M#~jeMo!!Gm%vV zQPCe}Y8GW+YjBf+6VvXYGblq(`S!A{I)0XQ1hC=zI>yuEPQ_dncu-EGop*yK!7^Oc z4VqqTES5T0$?7|z4h@=sF`b}kw1)_qRHwUmI$FV@1Wk@{HHgbVWE_LZpy^o=fVfNH zzfpeOz`?~jeutmQpb34vX$&Nn1x?<*QQ}L2oVY6cs@E?FnpECR9bpaC9t-w_Hnr{R zwRbH+VhNf)=*uQLK@;>1|6(m?6TG9Hb=)&p7THY5mRK-9&dbMP#KM_fHoy|tN510Z z#T6#LPz7pkq@<->zc-??W}S;ven=^$2~v}W?+ts=@C%>%)bOd!@4J4=$iab64{!S2 z4~|#Vo>hve%hU-S!7)-MDh86_|Z^xEM^UnAvx(#rhg z+lC*o==p=Ve?EvgaP9D0f8auG#_m&}vT{va zx8LpqX5;^^;irr=EzYLQKygtvqLF2?ExT8;L$ zxqdTf^06vG3O?%vO-`00XzI14V9{tuQ$bS@Xvj_5p~Wmf&3pPmQ-fsozz$0rAl!P!V!|jY53@;|4Fu%S6T?l0DX}j6_nz=Ujz_in`=A(D~=y26{ z|AFuPnEe=0xay_Do37_4*AH)c*=u|{V)kR?=DV*NoU2&o#ZTrypWa@}v$9_LTf?o( z+M(ay`dh;K~Yqwan1ug3B9pK;v_+J5VJyi5E{kDrTydZ@SbWVaxd zy(kkhC$uOBSryN$5F_F*FhSSD)cfmna&O&CkEnP#BrWlx5;WGu2+XIsqg~v&#CtgH zwI~W?c}t14U$`V_NB2(`nnn`)XKM#g;8wY`H&df6Txz6GP)CaFIc> zAT*NK`je-b4M4#t@8Ae1mtA(5U&rWd8KFTr+7=aHrkdj#8mzY?*jO(e&F?BGdfCz5 z@ntaK08p;|aajmBQeN3MxlgCe>UG-Q92~7b2<=V<4G}o?g~|=6lFp2x@P97s?A$CvXZ z+u|PAMe3p2PbsGfc5ols!FF;iLhgPoomvN*ruxoc>(Wav9fwz@ujlTOa+m29%evyH z-ZlKGXG;4&xBtO+4=-g@bmgmtKmXGo$hBLZUA^i@g~Xzae>MEpr+?At5Pv|=uDPbIdkmT);PrM5v$5=ydF8AA-1Ox3 z&Ulv!H(2}LHIwD_!<3BTzB!%h1e3Uw*M0D{rW@Dt=5gFEw7$FoYx6X-+R;P1=H?&y zl;~k?+mg1{t}e30&N$q7B*?HoO3Esb=e4!WFrM00c0z?XMO3Dov-Yt%q+WZv zq$G$`I*g8k?Ahd;eAS69Abyl(b-r`5j!Jvvbh59~(AqwJHK`ZH32S?_&Aqy(uAM2W zE7#~?OZ1;(9>idd$dU*YLfh>R>nMgj<#elTQ_loIb)540AQ~j^w1wIx)f?Um@`4}5 z1tqHd+`CKLQL+sp0+}E<3SyY=LsqDZ!4Qc$Z5w~NIF}fua-ghqoDne9u}n-zLk?VH z954|$OcB&M9gF@|yJ+lYf{1w^CWv1p{a&7syQ(V{pK3eVJ}=k56j4PxdK)%)eJ`+_ zlWoC*RmpcRP+1g|s{YRT3dNSNV+}kgN9yfT+!8EEnTk%QZG|07*=ohnuDwRv)sLjw zmPPQ5PpSTJfxfA&>+7{(b;XP3-Uax#imY$G`Q{9YG*P1Zy~%!Fk1w0u0aWP7HcWLC z1u=Tk=!{^8zo(scn%~}Yeya3!p!_{RH^5I7b)nKOV%4zK5@l*xJ!Po_+iORDrbwX1 z6KSyuGz86)2~OWY1Zo;fBM_HWkCsDMpsFNWT0| zuhr}Gd-NonVI7NF&s2SjKG!l7#Jj*6&bq6+uDY{@>ngW}Is{#jv1)9m=vUSYoiCZ1 z1XHiLwct9nqQJ}7l*9cG+@CuTai5bFA8(GJK2WF(!T9K%2vdk}>F zkOT!$WW70E#kDUal7Ta)pMH9*Q9kMCluf(U(6&afz@Fn0? zLMZw$!>3txNbAsyQ3YDsCZo2OoHFHnkd=BHAHkjlW4;!U*Sr6$U~iTC%IC zcd%CyeXQxlvb-QNxwAOm9nse`sV#sxMP`bt-XH7KV-XKBCh#QA78=cvDfKpLUIhQ&1p0aoA?R82b##Lm{ zlv_yMoB?*qo-)i;>z?aEAyB<8rr3i3cMZ2hH94)(A+F2FWStV}iXDtT98r%DF0G@Z zH#Mu)%d+*z^^~q?ntn>hntPXx#e_aglCQ{!+;`u7WA%{{aCzx#d<6%tQ$?fkyZxtp znMvU^QUp8hW9*liU&R^}!%PqBWqUbB*s;{y!+>iF z^QzMX6M9?Q=XG>2b`b_F!oN9(9}zbfOEa6NI;msU)AKA-b(183>-uVtrX*#V z&P!*f2nFSq&N-ZCUN2d{$>34jQDzEyW2(f00fd_j*L>+sbqp7k-?MSCH`V8<@yM!I z@E=q9oqdT5DzTihIh}2I;DHC`F5@Nvs=y{Q{?~hCgL&uJQka7zf^skpCYbZnfyRwu z#6VK1L0;UkO6De86~M*DbOAt=XCcsZggpnSK4LM2(o>XqP3u;<)VWO<)!cmxqCc+~ zYTLY5#6Ng!f35_NVwU!!%r3~m^uaUBaYyowQyMLLxovfsRUvtty&u@_i)z;w!~ zjd;^Bfn>#+k*=z80Il>n|XGtl!*@>#7bbpv$?R(5^F)L6?%gS_YiTXhNvmjO36 z8GCs>*OoYt#G!L_H<6bs5tk}Ucl&&_nHFT5B&e9lSP)M|?L9H{Oi$(XEb@iI>65j9(hp2Z3fC zAS+IqIF;2o0lYfSQ%*T$gsUD%i@eowRgoqh^*~%MR^pwwrVdQn(2P;Xfu=lrK}Jvi zIyyJmZ@~+1^BBdAKNSb7lOl1_X-g$n#d)WARJVJirruX-|On5WH;`-$fznXmAe-Bry5=IB8RzAA!Vy zOj3;iC6?Eumlp`S)=zmYBRv(6)4 za^e)`#1nm3B!fx}tMi$=w>Z5yfRjcnlf9BBmjMYv$b7DCb`53fQMQZ`m6_w0>vkf_ zr`|Ps(jmo_oT)>t-%&SNrnYx(twsP1fv`8OqX-rgb!|`fxq!dw=_1|ZP$@|1mUilb z_K#zPz9aLZ*Jz)aH9;NzIv6TI6>`d`URlVw>(7=ghg*GjZ{buFr2anC!f4q_Fd&8}g49(?FQ z|Ip=69~Z$6ZDX7^>N!Vtyb6He8&cw#Bf7XI9kpG1^2wHY>HKsT22C*4mC|o6vzgR- zjIzrzc^}zhZ@`ITtEAhcuWXMlcpJxd#!{E{%}HKFrE^L#!Ct4-B>}O>YEgi}_Rh(! zjMW&+Ek~H_PZ&;*kn){$v?(r_7XKHTS3k zw~G&KFx|s>LoxnU&ue{ifmR25divNae@Y+uIma=v4C5+xGH3ggX^>F{yQ3P7eVhv- zLRUyGHE^lp*R-qHYa_QXoP}exC^*!@=%g3T5{Um`n|pQBj!D)h@qq20=wl7kNE#QF z2cNBhLsrE^{;~0y>Ux|C|L2(gAe7|QYj;HkH7#wpF1Psw9*lz@^`#w z{Nd-kHjaI+&o?1^&XWb@RK>|-+RJg~d0HQi8#kf)d#uaBKYPD_|NhyjlEJX|AK0Js z;&|=%**#R2-cjLX=Ik4zD&DJ+S-rpQ%T>eAzUSuQ=J)*Ua1|MUw3Q0t*@TD$G%Bcd zv5%QukYnoov(6(Fv|R0jwqN_2*GL^3JW6|v z;;R0-&c%Z!InLT1jv)=-zYCeOZLXuSo`cuTwT-|MGV^=vUn9e?Rn;vz3I)^NIQQD_ z@&&jDV7SAK({+gnB(BVqsUu6`P3)kf2t2`9=s7OxuoRoT?PcpU%ho9;%9`7)Rrja* z+_NQKOYG3`t+<2!a{M^1={&^N8(fKXL5-eZtE-G{ZEw{()#I++%EM3DF4|_(zre>y z`9#pR@O#)r=x~;;wy*dvk88j^#B9G$Pj403(HGD*d<^1v{chiBPZRRjHcs6?_qnvK z=hrF*HTEtzM>}Ic(&$Bzq1rL)bXgF$)W5_S^z??l&}|BO);!K&^y{kE%Y4a{E=)a& zqw0p2A3iOyT>WCf3)f$rqBs25SfeIS^(xEjqzN6!_&`Q{AHR&m(r|^TR)Ae(2nskZ z?3ni=$genMx9ME>eo-JKkq3xdC9i z2&7;Y`7OO>328|JRd+lDkxbPH!zB63MU@dnvR_o}Q9ow=>Va}P^N9AV{^Xd9G@y}( z>tPs&8h-{}L&uR>9ulDjmm-?yIEOlQiRF|HK!!?ysc%Xq z8~YD}lI>Ne7`UQ3m-Uu$QIcBqovye&9X?0#~PlyCsF zB7&e(=6%_oy#ABJe|pI!!^JQ8rQwss@hyt(<{Y8kyPrru%Ca%QWe!WT8k8d=yPhFS zMt};!sCxW6BOPN}z9k{4c)e(+0g0e5QQwr&L{YR7mppfXT8Fz6^%lgrEXq`-)+H%w9Xv-=D#z&YDPxO=hB_YXr zB0EFpNqcdS2XK#|Ft=8%fl|p$rn}>u7@PN|`ivQ(vM9M{DGWM*hItE~77pBa9Uf3puue9AIi$-uG7jOF%ls`?%A3u*gk^Ci6F^-1h!g4_AHX z?+>@#X0PM-{ja`y2Ij0&6nz-JYxsS;_WiHEYB>0vzc<`^t3C15-rs)P2ZmQad+ez? zm4l^xTe-|6k1_4W6yC*c&dfZ2`7)Dv7F&#PZEydQn|4;B+j+wk7UL;DN)$~ccx zDf8|4&X996)>iiIw?P(Y^Y0JenU1=Uq*~sscC8v+q(Eo#Zb_%Nxsc)nFv^aRV%SIO zoyZNJHPMfNL5)&bUtX^|Yxgl)Q@crWNS%iHGxJ7r5Z`IK*PS)NKky}Hi}`z9Gt(n1l_WG|c7pgVBavMouUIkR_@*NI$+in7 zC#IIN6E~LyPMOX9^xH~*psTlisiKy`DGJm+LUZ{oWAiCOvD{))ex-s%Lq zEMKu7-@_>Vewpm(!|JTdgpE-q^x@1*Ca19SnAvr{!SkVj6HE&uf@v1t z#6ez6*Ajf16E2ySLIf4_;7#qFZ!W(4sZR=Xqzy8 zDs^6b$xjaN|Id2wMZ*uh!$`+fGljnjWTcdj`@Ie@hcFB;^Wq;F-uy!sjm6*gp5Yyz z90uHfTT{pQ^+iAQF2BFFsp*>-BmL5AU!HHAsv zf5}fY{lDmk-aNeKJ6|(=K>G{%8YyG6v*Ej}9ko2FY92DS-^{Rg#qb zq0L5?hCzwT zBXRN7v*69;f3*crV=#9$1Ck8pO8H*a7{DR0@Zc>12Fg;$l0L(~yZY6``>ow$;5Q2z z-}kfj9_`k;5%|nGgS)mTjyETlIELJlvA#@TM&XKC{ z>cFL7z}#fMH624l%5(PS5yQ9$GJhl@@PP?p!glzy667L32l1H}{=T0c&cERN;erb; z7+(6jxA~PX{+Hi1bLgzD)OFE|Up!o7_u@X>|1!VV2+U8Kv-Sw~>fzJ%Vdf(^sg#B`hUw$k8(Tzr{6pF{a1d-`{19w?03AM!^M~RyuAbD zkIdTPeX-w^+gn~^ONOx}{=0^sbP{))6?LJPb>W3C8-CZQ*NcPOjrQ>D;Wg4PT<6!i zd}AC!*Hz~jtT(MT@YhceDWvf$C{5OQ1F}m4eRug3zcQv#$J1$bXIC zM*ljJxDkuS#ix44i)Le~K&qQ~OLqo&$c_5zFlXhzvjj^Blq~+3m2UyV zZMXgBxj+a32m?1?cq&0++7q$V0zVCMJn;E03w*S0^wlH0_(7o33BY~@fr>8-8g<}G z1dIy;pB(Rr@(|E5@KMZjT?rqU*~J*Ulwo8ee7vi#vWtA07V9EI2buBoF@l?yOp5AB z+Kc!gB~^UQ_BPq0&@Hr4+tdpn>KZ5NRMr(q5uWYhxS;kO35appC{nc~7tM4;ATn>x z)Nc?GpL2#ma%H(V$^<4cj9d^|07UO^08NMsLBJP#5lAHZ;%5zz!_{^cU1{pQS?xZe zaPy;t3t!YsOSY@&yE^#y4zK#bKgn`G{foafzzyf+F<7Y_+JM`BcX;Xd|4BOjPrUJk z!>e%fi@)8bEwG^M6T>gO5YGJvhChWNZ+OM<2Y1{t-2Sc~GS})tinTKA)cc0teB;Nx zeHT42p#?_Ve&B6mBR2k@?;hoL+wTlN_KTkw zKl{`>hrb%Rpc$nZ?Nu)yUV@Il_f^C9|LJU(+9!S?V5X5!^J4-cmMtH z#!rmb?LYAG;SE0)WQcOR`sD+--EBsee&A0>2{?U2zd$5y90dC2ra+qreIorjwmqDS z+FJkIqJ;iwsgAP@ZB@6p{$qx7 z;PX2*@UbvyS>Tgdld|K>g8OADEyM;(Ns4ENrxaGdlG02CHT?jp_L}HGZbjWh* zD&;NyQiB@mzxsA3R?@d@cj!D9Nqg|8=c5JQZP+v-1p1v@r8DizgXh$NgWSY}8k=p6 zaZMgp7lNg8cVZI;rT~x(&v7Z9GZU{htD-=_NXJ3m{?+ZNj5u&lLoQUX5dlH?Bw_wK zgu%#!O2am1h9y|88&0eoXB%ClWAe&>yuGoYez@(H;WGzD>5s~E!*I*3{%*|Jgc9gL z#>c~O%V&pAu+aGXnOk7&7Y~<>nbu)=_G^a^8ezG^e(#){E)fvMwYS|od`9~VrMddG z!*zFlZn*P~JG=LLr(#Qd)Cf)#eI0>n!xfh}S-R-o{rPa`omP&O^*NMjumAkt;TyCU zj&pXOKb9ie;)MyY9|*^B+s!wK+@khdZX7#K>o(3TF6BKNMaPHKD~%z-ewu7eeAa+y zDa%zxiHs0IB`AtJm4Hl@Px%lBHS?9_h0<``YF0;aQkp&zKm3HzX)rnJ>kL@hO!0e% zpZ-CM7y_3*$zUtwK#cW1@t>1_bsE@un{l@_!Cg)KjOFwGPg(h(7A|L0di6CCFuc?P zhR`7t{fS@5KwW}m3qq9w2)u5aDnAx0KCf}pilpp&N1co}Q-&e9jeDgkqJ}4ed z+8OI82UtRPi36T-wSUAU*C_8il_BQ10Y)CBMYIK$OJf@CVdjjfI0O{FSCH`Um<}Te zi0Kw|GQnE}muyot6Lm-Aq;v7?2L(&Eml>83Y5hkBJ^>+Q;APL;a@I_cPDPP+>io8U zoCA@XY<=G+yOw4~o^{cgg-m8377=-rIs2T*WSN#f|94}S#qG|rDCeDLzpomz6sgcN zAv#cj0sHp4@Ams)jNSX$F3KzEZ#FlP_*nv{90k%8k% zWp}H!v4!Ir`|U&`bY&#FvcPsH-pP6~eCC)G#5VO&%A%}i`~}Q6 zbo$m?h8sMl3R^|6b(;&yZTC5^y>2A&5u||3fAF=oi$G0=#D-(xm=kX-nDg>+jc2TG z7;cvGhYT1j5RxEB1EFU=dyKx>w?=M(;0%1magXL%;A6}D;@(e;fe+rs_@jmIeRrgK zqkNS8w!etL2Z|Q$yVU|8;)}QAlkXVb%8G26PPO@K*yL^)1yOD1oOQ>P!K3 zkzZ1|s)5uT@!_~w`JPb? zeN${w)b*{>?l@#>g%?n$kU?`4I8MV1l2bvQ!sgnSF4GDfW)!Ci0EgPFv<@cd0B3WY z4&Jr}Oe4ve;~9ZXNmmLe9Ck8Vl*cr<5HSjDZjXPoL%|e-i0fRqqwmb0v7S+p@w0Km zxF9-Z$}8=Ak{^ON%1bQ0_*uhq1Yi$XDso(-a?5a|rDXP9HBNuL_f_W&=RV`y;rsr0 zoQm21>@hlE{ri2}-1wgI_OW{QGspXX>KRUYaKFpoIpgP}vmZgr?|00wdNnN!g}?r0 zk2>D-Q|EX)P!|54d#?TB?=!w>c*DmVbaTK^{h(~pSwz1ZM-y$LgB!n_$(`KjCExxE z|Io_{{rxxJ@shmo;0?Ab%-&sm8CJl|i1@*Smk$>^6AaQA*HJ#tc*ZCv@85an4$nC6 zpIh`bBTAHQIz!0I8kpxNpW8zRIz{9Y5M%t%LOOEVFUf}M5&wmw_x40v^1g7| zItFe#;~>u>oFE_B*2YWCt|JMW5y}vEIK?KD5;FID5cS5C%xolSH}O~iu>sbTi-QGE zI90{|dY$1+l+1Dr{{Nkw&GUR&k=6@-4RrGwyaXCJZXg^rVrb?M=wQ`E$n1G>!7w{8 z+$h_j#~xgFI|~fiAsQ;U(uJV1VuD#ivoXeqVM8~%8zk5WjqT06`DA_0Q+ew9h5kbP zs_Nc*PQE<(Wac@yZV4lu1cTtKAa0`9mR=Pn=_?c{Z0hJ2`J>R(SodP6WdsjPE^(Rc zlK6n_*rDe<@F`b?IHx!=3w<>q$(stKD{;lS5$ihCt2gE-)%+*NTseacNYV&m_4cOb z^K9F3a!3>d+&4O~oyk5S<=q;KG8QAjmEW9$(t~%iO8E?|>Ty?-A!l=V3 z$I;ZH@Lb}yt|DJ_A$nD|`6aQ3Ez!ne=AzRlYU)p6&q2sNW!!5#R_thA%EDqK$3dKE z+}D5odRhJCdNz}76y>BUinx%{YL+p{RrzfrE(!D5E+iop8tw&lUo2=?^)vZs94~5? zbIRCDMH;BLB5DC)gHeh0bXF(oB6AUYJJW!p&sAt7+@q_kZK5tda+=$ReaSvCP8JLT zAf5(%{aoldi^Ih+T4nw47cO6Y;bS>h{P+7`{+E|8WVP|_OY{d?L3sX?pK36^>GGM& zH@^MFv-tSP?`H9H0{IG7`BtEO{trIg_PSg?efhdpV?O-5mycF5ETo_FV2dn2kL{MD z8u-M^-@m-@(XxH|@!87@fBxF#wO7A!j9T;SU#+}#adh2AYn)XuUIQh)zN`??=9gEF zrQoPao`31`^-o_D@$Vho;!9Dx{P@3L{__tHzr6C7XYq1ubAA0&>b#%5eEEAXT|NOj zy>X29-Q&dPU;gvUAO9X71ohF&3*UR~^6F2%e)&}4EF}XwFNp*Nx6adXzVF~Z@UkTP zvIEa;thQ%Y@=94EY~tH=C`g#NZ)7P*icrY`Ip6W;-%M;@MPa6!>8inrW8w$}L*A=$ z{6GFZO5Gw*0&*@f;JYC@fMNZ&jGKZ!w>mtI$Pbud7sNRguLD>X(zlj^>Q` zI$po>&p&=)5g$B(U;U-vy$A#bgEo&d}L2k+&7VXN0)?*cnkWKLIB6Y!U3W1)sY z&BFEHk6*rW#4w9e7L;9Jfjh1%Yu7~H=T*TapFjV}Pha`IlIB1BgJOm7%l|kVwGaQ@ zkL4xTg5mF7KB6V;&_<2V(O8DP^8bJP+Wh>^?|l4d=v4NUX_UwCuQvnCi_(jjAU1_x zEB?S44*yy2>&^?0$2S3xX0J0Uff9bd7#90~TdSC0bVwbw4+{$f@x zmw)=X|8RNzAb?;0;6GKeemRf7`s%C4|6lF|oc_@b&cz(@zKgdXD%roB*Z$-uKgsK_ zYZOsY#}*Tp)z@vJbIJ8bm#=*FyAjftFMj8zCC96mpZ@eamk{~KUwi5DtxOKLy_*yM zi4zre*KdA--%}Ia#Myis#n2l+C^@2#`f2I&>g79Ww;x~r)j$5z%Ma6s-@5$amqOks zOkOS9ef#o-%XhO_iC{VX^~1}bLa*?{Y2$B~UN5I!iUWT>LlU)alFS5g`#68;PZC** zAguz`JWTTUu>H`nsiR|pce$2kX2ToKBT063uL=tW@r8Io+e^z=tyj9~cPjLA>{!i2 ziyNyr@`dB-hAhL)uqoqy+U9e6Z-s4AmgBGQT}*48ZA}y@R|cEpt`(K?L~=6j{ks-9*Og3S`s&X3 zsfVkdc=LbiUkyk!3|~GvuPaVJdimq;{p5)0uU|e}+nk=K@_iG+x*eEOl|7WiwZ)uv zQseW9moMM=%vFbvcHhbEU z|N8P--SBOB#j!d*lgSz-;hugcMj7vln=WotSW6DA4g(P$D=H{BhZZn|?=HlvF%ZVN z10s3#Z`LHZMT&)2ic>Mwr#NXWga894$kA0bc+}R%yxQZo;F*HX3FZp$+k#;Vgo%(8 z>?)*asNaOp1%|jrHy=+Om&T{;PF5t8<2M=l)JgxPSp2K6UY@HYn-~4~YnM-c=npUd zF?^6o;V2rO`_hqe`QMK(U;E^TE_vC9KXUo|%Q19z3I11pe48?V^YfPvee!F4 z)0)nUt)%C^@=7O)bt(Buh*NTyd@k@d79mh>Z+`2K206Za`O=4;J3Ae%V%*4kob%kv z$A;YbU;FS8da>iBPeqan%$o#fMR63QG1j?tc;1^t((p#&Av|l|PI6U9UAx7T>7AH} zX%+}iJ$Y(zzhZi^7i<^T^6SK@&ypf1G_9X8LFtIL;n*GKc4_^dR+6TFgQFhz?#H9vqqP24^VZc&xi~E1Z`b zcB`?FeU}CYH{udUnTVDxiEHVTg$){>|5x8I>3D`c+uN1k-gx8Sq-q$x@Lzs{rc4b( zHA3O<@~LcdCe5CuvCYOO&WSX=YLfr}H`GZ)K~(LG6FcdRYS6BY&+{)ugL3}=Y#0wt zJsO`MWU;n3KHbcq@j2~u)q@S)weflB@=e1PF%$L;Ib*Dh!TM^r=OF$x03%0*+|=aj zGc8^$O;s5%i`*)Br!lU+JPStgRi4XL!}6;*g7KXGDjSgNd@ELSDX!BV&ph)?x{nqA zL?`T;ygP6rXl{aUeHJU*1FkN2H=&wQ+ zDRppT+{cbb8`2qa<~rABF8}6#{fo;dzWb%i-~8Oazv;$j4%X=jT$Qk`DGpsV8OIVLkC|kw~@VE&I6tAHvaSmsnO;VyWV+`3~EPZYL!--nV#mz`uX_lkXoZ zqnD#0dhRR7isZAGfA$yuwcr1!W9ixRyubR=hu8kNI9{K|gkR;TZoP9pnG4KRO;MQUAU1>$7Nt4iWM{#k6dD9qv!^ zx}$^3rs@3evzKrD^jMKT_%w9Tf1m!wPcMJ=kyHPc=VRyf*Bzi}d_I47&U_PCY-YhO#_z5Cto?xCs3Ju-jDh<=>o%5m!O z?j^OI&bvhCGXFM(m?x6GjX!(&xBvUkGT8pc=l)&q53_5f-FM)3@cMitQR@8|+xR(- z58_D2GI81c8+sqMiIs=;;Q{i#>%1m=C>~Pp*(*l{t>N#vGjPJ?v5HCHbN1ecCJ6G7SO#PTSep{^HE0Pw>AGVCu z*Qv>z;`=c%zi?X>Yd`xxKRdTKt8o%{$xn%^$*3eK?Mdt61+!5?W$% zf+Il*K>Sy7$Voh=Ia+?(Z2xnj+VR9 zbyJ^hJJ3(EEt3j~iT0pulil?h<#oNLB0${$gK9TM-W+IMK9>@GzVu!BnDWs-yvAQ^ zTOsVjAn`!C`s8|Ffs>o`qYY$VFKGDF^9#0Xx%)AAa@=|n*e&xiZis~mvtHOTHWlB_ zACgNqe-S%3d}>=@I(Ovl`tSz7;=rga{3dh+a6WNc1g1iRL_h-wh$J5=6`y%R z(lG+ojS%nitI@U>tcYv*lHJ?ey;$M-Ki(ZhryuFok%>ndGW?%5XTfijs>>?Wh2RJz8)8aiR{gUaGGbm zk(yYXubWak zsLzzty*Onuo@`28oI`o-z2ah;ld#Q0}=L&S5Fa%c0Nm6rrPP$3=$@U=+b)gNMWG5Niw;o&!Y8~T>%x+A# z4|OJ1D0|0KEe-GdDVy(bNdnV3)ArUq+>`eZ1 zJ4hb)6|u^s5#zt>UGG}H3N23C#nQwh{+Z^GeDW*xAsJ6wgC1ud=WbsXDojwqq-4@D zB|*tXy{S8WBz+j`>$0jzunZe+rvCM>d-L>Ab>t)EKmx^l%JvY@P2bx|2PH(N3Oq zeO~LVQ=dr} zk_XR~(S3`8vM_mjp!!&p$pOQ_chHf%+3J|RSv&Z5BuaTa$v#Hzi3oQ(%BH?zLcMp1ne#j( zmnTNqPDRY*TbJ4Gyz2%TKMb47voD|zgCGGNS1ww?-4#)xn-;g#1CPrPR5H!mJ1?!7ms$AK3gE)V0~Ih**Q zjhqYVuXyb%DYS=t=JBa9U0;}8!M$2iZ&oH~!XN>7gW5Z`MY#{u(6lN)LZ76zdc*8~73Le9CHpR!K#O@)VK^`P`~x#F`UEKg25 z0-$UU>7sKzn0*YAOT1Qx9|xsao^LJ#k^FIUjp`<`tO9$cq zUea}}^*nKp8@eQq;kb@lZ*iQ2K>uhC-DBjks+f@P?-jj%t;S|iKo0Wc$XIM2N3$*jwe4x`6gK>J36)tJ@wLf9+Y%2Uq1vUCqx30&T~Jx zZG9e%<0Qf{2{H$W1KF$SU9$C+wu$hkAc@bo|1S9_@^JEfNOsOg-%!^0+;Omza|&kJ zlJf5C>zI#g)NQFT&}SZh@wp%Kua%S7Cmm=%x36T@@~smj{qC{IM6dio*b{#f#b0dA=f^}uH?eUoIfQ&&QF=Af?%>Yu|IL8#`p8?amRE_zVJDAd4)OA zuTi1=7@qSyw6poH*>W6s9B6#c&%gZTFSqx{3cF8^{oyQL^j|0>;uMh+#3U70EY1_D zDL8e{iz}gX=~Oz}jkK(|-1+KbI?W0f28BD7?;WtxfdPL*x>hJnm8TP+2Pti~lQr#8 zk6D*3-2M|mk_@Gf1BK5Ln26God)gqL5^P^Zk83?yO!|wU_TG{4G>=wZ+;+aSPJ8U^?A$0B<#)#W4*OHWVbQirBJK;}k#=Exc@wDf z>9ffOJ}$4DlIFyV?g#S76gSgxp67Apxbvj_kPRmtg?nP~h8u(Hs-elR<{z9VT^;kx zX`D~IJz>n{_GG?`qa8M!110;EtNEGu#^upG6VC7DA7b8pMb7s465hB9!?B2i+%|HO zm`IL9=R`6EhZLjIyTlluPaOgi6rIXs!w!%jZS zn3$;t!JabkhpF&H)AolI3=^R{DJ;72hf9t@8+>>U0?ClJRWPz}@}+n$LenxD6+NI^i(cJ12Nziub(nk^JO|)%A&MqhVsa>Kso}ia+s8 zzJGFlO`AHpE$O2v2A!Oh>}eC)a^heA%*U8GZJKA2PkQrwk4yQ~lNs?xd(ww)FZxXL zP(R_A1s%sGCrRc-*Uf|K99PV1dM)l)c-iiyA{Hp)#1)j4@tqGBJ^n{~W&>C}JjDck zOq*)kZ{iQ`MD00zHUoi zJ7H1!I0?zmOyF-(%U8eB`Ax4@`Az z%*Q4EBsYt5Cww*n9Q$lba~F=LhOcpDcP+L#SBK@rn<9Uiw(C<+Heqd6d^C&%~cSs8Jl_ z^LR6$<37L6BTnyOp2w#1^chz@;xpbOMgKGY9ZPQSv^g4m7H$*vG$-SXaglsPf?LP} z)#nmC*1gMV8b<_15^J#FNt+4esyrQxI$zFFk|8;!Ou9i4PbST4hi@Th4iW?jfDf{Y zb68iAi=N;WGfHEhIezix`t^#EXc7bB8_n+=_|JXn*2Rb94X|9%N_XS;>{Q^WRB| zW1fUbRKyU8k3`lw7fy9d`1arX@Ytcv+|Mk+^aFoP67pjgm_{Nxmvbu4rexp+pT~wL zD81)(Nj&wacE+V%Qx;uMy~zV?ZiFeu5^X1pJJ~y?iG7Vl5|u8B3H>-@a{zuqg-Ncl zQpJwuA&wpA{QxsGR`i)L&AB~ps4tTYlcM5HGD&ZJyGpk8SY|?19H)QlXA_(&H4pKy zE8b*t#~9;S_@~bpdy>g9K9ZBN*WapgsC#Ekq-8xddRS=IoJsdv8fop0zDTKz%> zYzle&<&Tcx_dJ{&{MTqj{4yYeAg?|Cr)OyBw`M%xoxBjoKeXx*k5o2x(9e)w~yvL4M zB0+nc62pnDx*s84>p3s7DKVykW76CC?q1AHT%)mxDR$A>AjKkOthOC`>wFeq@)_f7 zvilUI2 zb)2@Me4bZ4w|MS~t## z$;qc{Gael?@~QOD4ZGCcWByH1yd;<+5!9oAo$z7+b#8oIeG_37A^gQtDaPM8Ib-O$ zTrJ~F0!|L|?w&zSK+z#f(mLMIXe1UIW=YVv&tx|TWgUx>O27_mkwH4xR%V>MeD1Bj zW#e3Zvfs*ad-c*CeyKKPEG)QxH0I*>D?{G+cJf1>E*a}ukvj3?`Xz4SC*eyew~zeF zBEW-q7pT+cvVj)_JIs-!ov`v){Dp1pehT7~I!Gpt<#Q`8Z%C&KkIDW{!eg;kH}J_o!Q^}n&7Z>ih zr2T^V9Y>znl(d;V$O$_PITv~{NaCOHx?s#~LEhs$vK?`#0>XJ=7mKYYzSQ9Q-f&WF ztxWu;@tB`_?g4KaqvNl5Zo%ozL@RGHURd1tWz&0}Kly0!i<+_8vUaSv&bva}@ydp0 zx+czNF}R!qY`OT$J@GwO_SoJ8`t8hH!JCl$|h%>cS$#Xk2)lmk2Jt> zKSw(-z*k@Am7u=V#BHRBs7{Yuox&S?+8801jH{rimGl?LuwTngb^{_o zr@N%2?@dtYX17{tZ~*sx2bLrz;_{%9Z-u?a#<{L>8_bnhbhGmG75cUva6+#3xNv;M zYS4mNtab@oOj2DSmi=?<wni z1a(D-rIw?%LKZT`y*De8R4T$$!=1^4faMc^M@1 zzwUMDaT=&dYC%95x{ta#e;&Vl0S4|EL44lWTj$ z;jp>wgQjom+Uyq20oGNRvbT~xf#HFbWb>xug6mKDw5hlPm!uVcyg^w62_kFxqBsos z>u1vm)|NpSC_FBHP(h30K=U)mx>GEhbf*_%4m$Or%Lxy2VG29E_C>s$7%K}muQlc}&0&hT#+7u7g~f8!pR z1!orfEo0a)=tBjyiX%}4wl^rQu&Yiz-uHYpX0E(Q&boNv71;I0 zzEyi)}MxhAuRfq;q$=yrf0$l}o>Qk#qPJAtTb*FLw z9h}BJhUla$ox%aoFFMGjvp^!0A5>+Qp|6P&MM(z@NZNH*B30tO+3T%9Q_h{<|A74SDjc<5YPa%tWpo{3Y&?9xD4;XCQS z#OVUuRq4hjVvKl~AJXn6AN9B?4)e(z$G1S=_RLYd#LFmPBG`khiX`H-mTE+HU0jrW zB0Q0&$T$xdkubs0`4UQ1rtZXN_uK`-5#%kWIvF{I!4v@;H+GVsL}EcQVB#(o6hR8^ z6#e`<=c&fkCJKNwQFZ4uZgxrW)#K`1n`8qF@rS)c>CFO9iS{N)GXKVR+pjV$x3kG!hTEd5=jkWY(%ue{)2E zOA;+?<|2j{H7-64ctoH-3u$Lci2%H5( z8Q{iFnY+&-S9A0@xW08QY)B?yR(MGKR`br7)3^JiI_=I?w)9(8OhpYUsu16jPXyF) z2D_!Y`hUEvtpewi)LTW7<}SUv(b6iVWI2v!=XqQgKaO3-aYCfdef7h^NXYovygz>J6Y5Ub=Q8t5$Ht zAC#L55!Z*WoCEdEz&4+9x$vGbTfSrQ$Q45Ao#V!%7T*1ycXv&vLWHE)6;e&EZk`23 zZ;w<$RAnv0cM(v_h`waj+YhxwsbVMQlF<~b38G3GBp!ZMOhrP=$b?aaO&3K`5(IE! z)#dop_D?3#_=^IC+hYoj#Lv1-6o)7$t9&_CbL23ki^gZ?o5>vaLMV8>pke}DijMj^ zGOKQ0yX?DG$JW(#B|9aGutltf)n0ogPLw_BMTmb?%#Q2BtqUHpmdwgo4M9rDD2p|X*hFOJ)CC>AzN zu>9A!556v)*#zi#`>S|67Xy3?Js@A(PmVJ-S!y2o+=^Z01;%mWiMlYnxWfT|HHSpa zpn|z#pkoK|+AE2)YsKusO;rOl|7%VaorX*5r$VRwh;uXkgxSLDo5SGhM&n$OT6`AO z5DNu?i~-vPik_~i>a&=t3!=1etztkCbs{o;R#XLACJ;Hg3xYE2@}2qkrP=!HO1a4K zEP1YX?K81be-RvsF32_Qqz7x&Sec*-(492c8J7)I1a!hbqrd-Ck(Bn2zgpT<)fv}o z{tl#)K|~^g%4^giALpn-ZkyJ1@wtw%Fp{0RVn(o~4E6YQVMYG$L|p;k59UibNk*lJ zY(pCmbEy|roAg@ad66f7sH+j7G(lqJOJl^CdE>1DvpT_^t5yqGm^QJgcq^ZEXHqh= zNLH~bpEW_%s%H{(;jGCvp@Of7A989tHqQ;&frZ9Lb;ZK0{H^1%3-OeA;3`1jQN^h+ zrb3l`(22B)Litnpc=DzvC!Zi*nlw+~HxH%E3=kDSkqA_@iCE)b6mr+7I$wpB+}4V36b4*jk#5NkERqU? z@=s!)JgRLI(>w7NJP`B6{B`exVkhk&`?_Jn>`~-LOc$5k6!n#4#9xY;j)T%!&58Uq z6*J^cHjPYlab2(COt&Ibl22@+Ig!s4BiUHUep=zESP=Hb(Xw^eAoN$`)A>w1TPx08 zB&uMP@4|*E7RxVru5zUo2Fwr2-@FmN`5e!9>KKlBDt5Sn7}sPB9Dmw15I&e6vdP!I zi@Lurnt{SW=h@;zHByQN)fB>N{#(40_d}L&@o(Z^!WuWnJWrl}`so)>?znwicup(; zftKC7zJ0?64Ruw^7YSL;+1LHVPzpyKZ(B~qA zaDv}p$c{~2gDOickLjFD9O@213=64Mm#3mCZ5<@0ZnKUnfH|km)p#VbcvuSH&m0!mcPPh~Hi%S6sqg*;!$D#j^=l7Qp>t|De8 z0P?32PZxDnEOaw<$Z_+F;>9bnb&e5R%JOj~=*2HpxC-++)>{OnM<;e9RE6cE>SW#-M0_UAGURS}nRRWY7=>fy7>`6`|&pQb9Y zb5XaJ+&f*o{P*&`B&M97#4)S#tqqVpqp6gf+%t!G;#c5~-3xm8t2WP8N z=hJr+tkD6~-SS-_8ZmlMw{QyZDh@PnSJo(OSR6GGfuu!POfENoIzd=>WL-SETC%g=b z0&H&eXoXM3XgRHkqCTg832qg4^o?w;K$X0-i}01j!tocj;i?knpiPu8WS=g~s^G}L z(h7|dFz&ZmimIAqB0^sQ$*$)3lMks&7Z11>t&1xp^aan=bt{$^5~)Obv&vS4)J1;X z*CCrwxAtq@qq3|nR>Buvk{|HQr^Z{6d&eUhnI^3wGA7hccxnK&g%R8nD^z8ZULi#V zn;m9hP}qpKYzW$pNH8gn6{Jc6yT!JSJJ_x1VZjT`LvTM>tYaZG20o)J`4id1Zcr z`-?bk9;?P=+0N=}V=WwAmYU$^zC^c&WYUV2#?j}?3PLrRY8s|o(0U^`3X^K?>935# zp}~-CSitL14#FN|f%fWa%2p{an>^XReBvwM@&kP;USVU^{;OCMj@-t=bjKT-RTT3` z?d&9^gpv$?5Qa=h8`HdC4NRf%F6Ps*OUxTN9ojfbh9b>sw5`|>_dE#~wl1y3_Uy864 z{Cb}hV^G}OTM)-V`7XlOyK?H@_S`J}$MGeh2i~GE)mEw!nhG~t-c~#({;GiWf-AA3 zZCN%YrH6Qi+Y8;*Yuf{3WWvVHq=~g&ldlyNyid~}#SUX|D*lD9=CGPm`E@D`70>z! zgeG@&qP0ap`MBC3Y~B=owThOydf^{Uqqg2`<$Q^GVmk`^V-?5?do@nFE^$@&o-M^j z!t?xVF2xFp^q6?l3p^$6E-H;w*;H%AL#y_R0pUsWW-LLrh^ABwvPgHn z>~mElf~(_t$Br_Hg zbc(8-6uttF1WzESz|b>ZmcXkO83ltn2RcOn=gNq>;y9*ag{u|1#)+8;K(Z$=lpyPV z5?x3A+j(U;jWu?p)k#gddO;>xmm4dKsFTQRRbK+g z3l$QLim#L#=eG}wTy(wLn#8@V02I$ES;!IJZ`EWOv56 zY^8Hp{G`4prt@5^J~uzxO|hM{YsIqtQCz^>7vuMRn-#~BfyE%lTvqtB3WJ#NoX6bY zSXO-96s=exUy2`FITaTZdpC;+@gYd4>(?5;xI|zWwcQe~}5BMMM&Q z5pq{v1sw2VjMlHX-( zKj!u$z!;cX`fI=7&U@KOdTK8Bg=0WTfW<&BMOJVut9^B^4gDzjX=~x0KGUk6U)!Ww zg?P$rD_~6+Md(wE>AIWZFNUk`V!}6V#QT!+M-)*+H!*WLI#yE3CM3ip;v(uMm|AtA zZNk=G81g}3!Zxu+GIavtN}!T~5|}3$%BzlB38oWC#BZ$fRk4ufNAp2E@d29Jg2_3w zDvTuQg_!iD%-vO@h+CR2yJ6YmQGTV~alI#Na&CVMgheQmgpyEfGsTZ#MnW#!as^DX zaPFJJ3W-uOgv?s8T9Qr`F61c{#(i!1W%-(HHIpnx-5!dqUb(_v?YZqVWL}?>pL}NCQRtHKu<~DOJiTBp3lB#VRDzS1tFYcD4TSZsS zUkTE;QCZmKwUxXSTMG|X=k6rR_p&WXx?>d$APc=tjwmiCqUL$Tn(W*BTfQVtJeKr6 zc}L$^3Nw`q8lSO94ohF?z7l;UcqoXu%0%C=iF9nL2*@AhL(#>8bJ5vWsKupIPT+OI zr;0b}tmgww@x1T`V#YBb9Oz&7m+Mc?P>x$}ld!I6hmT1=kBPW88?w4rN{x>SjkKSw zmMQi+-t;&V%ctZP$*A$gPrCJB`4@bWv8PxmY*Am2|2MtweeZiiPTx7A6IB&6Qe+|Z zN_+&G#?$ruQARpdMrO4pqdCA&KDsX7d2rH*1QN%ijFOGy=62wer&+mLiLran_*m~f_5 z4qkG_f%lh zzDl0?gNg^yaBEH1PBA*+%Hvmf5T>Z_#3Ay3&WEM-wnaS$!;3OuTJsab&LvZl-)(Q8xL~_cmJ{NhHyyk`2q$A^yzU4N3UU&R0$x=m3ajd?{ z<-Fi{QH;hg&a{VnOFpZ^<72G7q^ug&*b?@~z~e{JJLm+t0E>@hX{POctLz zULii)#`s3+f>~Qc(X~(B@s4-AxJxQDh9?CDOnzQlA-+F21+~VZvVI=l3yAClbi6^T zuVU58fC!vq;#K+7Svcr*4#|a%omQ0`D3q08bz<5%Svs(|n2IkIMLNdwBcZGiNxt(0% zIB$p~Mwuu@eq28FnBn=Hha@UI$Uc2=nwIbz%~AjOo3{#Pr_nEj^U~hy(dr<8Zs5 z+{NO8w%`2#vGXgjrenmwq@Qw!D(=JfFy^DYB@-q+zCsI;T* zPpXwz$F$F@F{uM}eX|ET1@@rOApAU)uZP*u_&it6;8qHS&~=o>0n0#>!$rv1Jz%L> zM)o-*H;v&sDu6thyK`JWl7xV-WJO0SP^AyajllLmV^N}U7e^K#^qK6ZbEoA>?>L#D zrew#U)oX#DK-?{j$}j51NM`P<_HA`xJ|^wPq%s9NNs&6zRvK?Nj}yK0_M|ffAmhS` z&;8uj+r4FyHT)UfkKQ|$J=UD4D4*um7+l4iVvo}s!yI6IcIN#j!jVDPj)?FUS$vHItE>Zb$@_}A6>C@j6 z-rI)t4MoN~xr97&4-3o{yO?v1)%(c~&Ue%yUhCUN!i8dGDh{T^&UkXp_d<*33O_7{ zTsD{8xijU*)~)QN7}ETFh$OFx-ej@oN-oLLh>E?#(nL%!RwUNC$^2; z`8shclyyo}h=DaN#|l8Z$0mj`8B$I6Ff0WTdS8Om?IG zP73$ro{sHEf#dQV&Hb3`CfhM#dhEz%#3=Qj3U-nd?c%R@m|_xUapJggo9jLQC7vhy zarM_@fO1e);>c|`#XRvS;ud!>Vd%9lf4iQ}k2~&ioN62uZ6fMjoZiC)$9A2kdENI+ zAWZJ^2XRUaP=|-)W+GBjQ^U!acRO(0DISOgaAkQMV=DfXPia5;YvjZCzyJMj zI61gdo}fuCyK|k$V{eYhc#U~kXe&V|5lw`y>v@c?Nw^c%-6t$ec>Xk|$SY*#N{`10 zZM%y{mvgcaeKzUsxZB0e#DkJ+YJhY;@kJhDGV#w9>nyw`e|r4v<{}@v%(U~az?^Kv zxybuo@KJ7$MJ9V6kK;^OV8QnoJGhPSVQRvOZ1WKJc%GW(xi^-}NuSVOnuq`TTyA^C z%Tz$PjfrW+^i&8>aWTm>O-dj}RD#~tSeyjK)VBs2kKNBT|xe(ghnB5-(8VsSH#K|guW$S+PT^w&KbQYR-F z`g8J+lieh{2j31yOolrfcp~tGeUDJ4;PXK9q(Iw9?tA~<)Bhp;CM;?GDXHlENPH?( zclev^;+#NRa9+vnaW-L!^XTSfPsUDMF7w1mBIEd%+eJH{GQM2?d-%H-zwBZ?wsx@* z<9Sgvo$F&y{6pDxSlPv+^M@B<9p1@x9?y^APoBdsQryc6T6rU1 zOt|yo{(i!;V{MVIzD>%{oIiGc^>Kuydp2@x>s-aQj{B;T<87A{G~N!wUeNCHiRSC# zj>XGlP!04D5FM~PlJbh}-keh~?uchfNIQoS2nv?Ro=ZpEbKZ1}o%U|tDFOJLldKQv zH2KF11j^(@%VP5$A>Q-Py`)akniBm(cK0M1=kLgNDvY$!q=4PcHzhHWJdev}59ux4 zo#Z^J+|!4IGx=vngp-~sY-p!laqr{qFhu#7h&)NV?9L;yHF?8*?<-CB$dkBxXm012 z$)+UU9j83@^T|$AG05a1-5qmNff8f+N~_!Zp#oNM#^S~G;~3%Zm^0?#%8~O|j6rNn zyh04@{CMy4$M|0U+^uYpS0&FBHxn45z*qMB};~ITF`OOPX z*<-TnV{}TrKKQ{89^;%(W%7h2#bYpE67ouzPLx0-jfohXh)9rAuz6tZ47<~Vj#QE& zAvy7Q1-)}BZJ{|BSQ7#4fa-JZh`_;iZwtb~rtbD0iQWT{6OEHPlev!hcuq#{vz;$E zH_ve!@9;AvAWsOi3w80&U8j38@5p#J_Y`yY?9NzoY(ErBzGpq@=~(gPNZdbkE_Hq^ zQBAr}7@{4Rcy=*3am5tF&R-tCyLg_iBc>+YJC}y+O8WOWkI94lGsXEm+fDa0k^db} zJHFk;s_Z)z#5;dHr1uni_k25Xx#t&;&FQ%8Jn=T?P&|tV+@ANin0br%-d*Fl!DDRK uL^~!tZ%kXP55>j3F?aU$&$%_m`TjruAdLQmi&ypl0000 - -%BOOK_ENTITIES; -]> - -
- Configuring Network Devices in Inline and Side by Side Modes - The external network elements, such as load balancer and firewall devices, supported in - &PRODUCT; can be deployed in either of the following modes: Side by Side and Inline. Inline mode - was originally supported in &PRODUCT; 2.2.x versions, and is now added back in the 3.0.6 - release. - In Inline mode, one firewall device is placed in front of a load balancing device. The - firewall acts as the gateway for all incoming traffic, then redirect the load balancing traffic - to the load balancer behind it. The load balancer in this case will not have the direct access - to the public network. Deploying network devices in Inline mode ensures that the resources are - protected. - - - - - - parallel-inline-mode.png: external networks in different deployment modes - - - In Side by Side mode, a firewall device is deployed in parallel with the load balancer - device. So the traffic to the load balancer public IP is not routed through the firewall, and - therefore, is exposed to the public network. - - - - - - parallel-mode.png: adding a firewall and load balancer in side by side mode - - - The following table gives you an overview of the supported services and devices for inline - and side by side mode. - - - - - - - - - Mode - Firewall - Load Balancer - Supported - - - - - Side by Side - Virtual Router - F5 - Yes - - - Side by Side - Virtual Router - Virtual Router - Yes - - - Side by Side - Virtual Router - NetScaler - Yes - - - Side by Side - Juniper SRX - F5 - Yes - - - Side by Side - Juniper SRX - NetScaler - Yes - - - Inline - Virtual Router - F5 - No - - - Inline - Virtual Router - NetScaler - No - - - Inline - Juniper SRX - F5 - Yes - - - Inline - Juniper SRX - NetScaler - No - - - Inline - Juniper SRX - Virtual Router - No - - - - - To configure SRX and F5 in Inline mode: - - - Configure F5 Big IP and Juniper SRX. - See the respective product documentation for more information. - - - Add SRX and F5 to the same zone in &PRODUCT;. - - Ensure that you select per zone sourceNAT when creating the network offering. When - adding F5 BigIP, do not make it a dedicated device. - - - - Enable both the devices. - - - Create a network offering: - Use SRX as provider for Firewall, Port Forwarding, SourceNAT, and StaticNat. Select F5 - BigIP as the service provider for Load Balancing. Use Virtual Router as the service provider - for DNS, DHCP, user data. - - - Select Inline mode. - For more information, see . - Creating Network Offerings in the Administration Guide. - - - - Start a new VM with this new network offering. - - - Add firewall and load balancing rules. For more information, see - Adding a Load Balancer Rule and . - IP Forwarding and Firewalling in the Administration - Guide. - - - -
diff --git a/docs/en-US/lb-services.xml b/docs/en-US/lb-services.xml deleted file mode 100644 index 3bb79dbd335..00000000000 --- a/docs/en-US/lb-services.xml +++ /dev/null @@ -1,25 +0,0 @@ - - -%BOOK_ENTITIES; -]> - -
- Load Balancing Services - - -
diff --git a/docs/en-US/management-server-lb.xml b/docs/en-US/management-server-lb.xml index f4275786be7..85a86221c80 100644 --- a/docs/en-US/management-server-lb.xml +++ b/docs/en-US/management-server-lb.xml @@ -19,12 +19,12 @@ under the License. -->
- Management Server Load Balancing - &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management Servers. - The administrator is responsible for creating the load balancer rules for the Management - Servers. The application requires persistence or stickiness across multiple sessions. The - following chart lists the ports that should be load balanced and whether or not persistence is - required. + Setting Zone VLAN and Running VM Maximums + &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management + Servers. The administrator is responsible for creating the load balancer rules for the + Management Servers. The application requires persistence or stickiness across multiple sessions. + The following chart lists the ports that should be load balanced and whether or not persistence + is required. Even if persistence is not required, enabling it is permitted. diff --git a/docs/en-US/network-setup.xml b/docs/en-US/network-setup.xml index 192c8e23d2f..ceee190d4ca 100644 --- a/docs/en-US/network-setup.xml +++ b/docs/en-US/network-setup.xml @@ -20,16 +20,16 @@ --> Network Setup - Achieving the correct networking setup is crucial to a successful &PRODUCT; installation. - This section contains information to help you make decisions and follow the right procedures to - get your network set up correctly. + Achieving the correct networking setup is crucial to a successful &PRODUCT; + installation. This section contains information to help you make decisions and follow the right + procedures to get your network set up correctly. + - + - + From 106730ccdde30450e96d080ed6c9791682fb7300 Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 11 Jan 2013 15:54:00 +0530 Subject: [PATCH 30/92] SRX and f5 inline mode documentation: Reviewed-By: Jessica Tomechak --- .../external-guest-firewall-integration.xml | 53 +++--- docs/en-US/external-guest-lb-integration.xml | 4 +- docs/en-US/hardware-firewall.xml | 9 +- docs/en-US/images/add-netscaler.png | Bin 0 -> 22777 bytes docs/en-US/images/parallel-inline-mode.png | Bin 0 -> 145392 bytes docs/en-US/inline-config-lb-fw.xml | 173 ++++++++++++++++++ docs/en-US/lb-services.xml | 25 +++ docs/en-US/management-server-lb.xml | 12 +- docs/en-US/network-setup.xml | 12 +- 9 files changed, 240 insertions(+), 48 deletions(-) create mode 100644 docs/en-US/images/add-netscaler.png create mode 100644 docs/en-US/images/parallel-inline-mode.png create mode 100644 docs/en-US/inline-config-lb-fw.xml create mode 100644 docs/en-US/lb-services.xml diff --git a/docs/en-US/external-guest-firewall-integration.xml b/docs/en-US/external-guest-firewall-integration.xml index 0b34dca1065..bd9ac604970 100644 --- a/docs/en-US/external-guest-firewall-integration.xml +++ b/docs/en-US/external-guest-firewall-integration.xml @@ -21,23 +21,16 @@
External Guest Firewall Integration for Juniper SRX (Optional) - Available only for guests using advanced networking. + Available only for guests using advanced networking, both shared and isolated. &PRODUCT; provides for direct management of the Juniper SRX series of firewalls. This - enables &PRODUCT; to establish static NAT mappings from public IPs to guest VMs, and to use - the Juniper device in place of the virtual router for firewall services. You can have one or - more Juniper SRX per zone. This feature is optional. If Juniper integration is not provisioned, - &PRODUCT; will use the virtual router for these services. + enables &PRODUCT; to establish staticNAT mappings from public IPs to guest VMs, and to use the + Juniper device in place of the virtual router for firewall services. You can have only one + Juniper SRX device per zone. This feature is optional. If Juniper integration is not + provisioned, &PRODUCT; will use the virtual router for these services. The Juniper SRX can optionally be used in conjunction with an external load balancer. - External Network elements can be deployed in a side-by-side or inline configuration. - - - - - - parallel-mode.png: adding a firewall and load balancer in parallel mode. - - + External Network elements can be deployed in a side-by-side or inline configuration. For more + information, see . &PRODUCT; requires the Juniper to be configured as follows: Supported SRX software version is 10.3 or higher. @@ -58,22 +51,22 @@ Record the public and private interface names. If you used a VLAN for the public interface, add a ".[VLAN TAG]" after the interface name. For example, if you are using ge-0/0/3 for your public interface and VLAN tag 301, your public interface name would be - "ge-0/0/3.301". Your private interface name should always be untagged because the - &PRODUCT; software automatically creates tagged logical interfaces. + "ge-0/0/3.301". Your private interface name should always be untagged because the &PRODUCT; + software automatically creates tagged logical interfaces. - Create a public security zone and a private security zone. By default, these will - already exist and will be called "untrust" and "trust". Add the public interface to the - public zone and the private interface to the private zone. Note down the security zone - names. + Create a public security zone and a private security zone. By default, these already + exist and are called "untrust" and "trust" zones. Add the public interface to the public + zone. &PRODUCT;automatically adds the private interface to private zone (trusted zone). Note + down the security zone names. Make sure there is a security policy from the private zone to the public zone that allows all traffic. - Note the username and password of the account you want the &PRODUCT; software to log - in to when it is programming rules. + Note the username and password of the account you want the &PRODUCT; software to log in + to when it is programming rules. Make sure the "ssh" and "xnm-clear-text" system services are enabled. @@ -124,13 +117,13 @@ filter untrust { In the left navigation bar, click Infrastructure. - In Zones, click View More. + In Zones, click View All. Choose the zone you want to work with. - Click the Network tab. + Click the Physical Network tab. In the Network Service Providers node of the diagram, click Configure. (You might have @@ -159,10 +152,6 @@ filter untrust { Private Interface: The name of the private interface on the SRX. For example, ge-0/0/1. - - Usage Interface: (Optional) Typically, the public interface is used to meter - traffic. If you want to use a different interface, specify its name here - Number of Retries: The number of times to attempt a command on the SRX before failing. The default value is 2. @@ -180,12 +169,12 @@ filter untrust { untrust. - Capacity: The number of networks the device can handle + Capacity: The number of networks the device can handle. Dedicated: When marked as dedicated, this device will be dedicated to a single account. When Dedicated is checked, the value in the Capacity field has no significance - implicitly, its value is 1 + implicitly, its value is 1. @@ -194,8 +183,8 @@ filter untrust { Click Global Settings. Set the parameter external.network.stats.interval to indicate how - often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you - are not using the SRX to gather network usage statistics, set to 0. + often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you are + not using the SRX to gather network usage statistics, set to 0.
diff --git a/docs/en-US/external-guest-lb-integration.xml b/docs/en-US/external-guest-lb-integration.xml index 5760f9559e6..acbb514207c 100644 --- a/docs/en-US/external-guest-lb-integration.xml +++ b/docs/en-US/external-guest-lb-integration.xml @@ -20,10 +20,12 @@ -->
External Guest Load Balancer Integration (Optional) + + External load balancer devices are not supported in shared networks. + &PRODUCT; can optionally use a Citrix NetScaler or BigIP F5 load balancer to provide load balancing services to guests. If this is not enabled, &PRODUCT; will use the software load balancer in the virtual router. - To install and enable an external load balancer for &PRODUCT; management: Set up the appliance according to the vendor's directions. diff --git a/docs/en-US/hardware-firewall.xml b/docs/en-US/hardware-firewall.xml index df0568aa2c2..28269cccf31 100644 --- a/docs/en-US/hardware-firewall.xml +++ b/docs/en-US/hardware-firewall.xml @@ -22,8 +22,11 @@ Hardware Firewall All deployments should have a firewall protecting the management server; see Generic Firewall Provisions. Optionally, some deployments may also have a Juniper SRX firewall that will - be the default gateway for the guest networks; see . + be the default gateway for the guest networks; see . - - + + +
diff --git a/docs/en-US/images/add-netscaler.png b/docs/en-US/images/add-netscaler.png new file mode 100644 index 0000000000000000000000000000000000000000..53c1344b9ddd49bebc276af347206ba97948b428 GIT binary patch literal 22777 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 W{~Om+ralt@KQ$%IyX6WNf&T^X{FKQ6 literal 0 HcmV?d00001 diff --git a/docs/en-US/images/parallel-inline-mode.png b/docs/en-US/images/parallel-inline-mode.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c1555365ec7fad20412bbe8d605ea2739c12e0 GIT binary patch literal 145392 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 + +%BOOK_ENTITIES; +]> + +
+ Configuring Network Devices in Inline and Side by Side Modes + The external network elements, such as load balancer and firewall devices, supported in + &PRODUCT; can be deployed in either of the following modes: Side by Side and Inline. Inline mode + was originally supported in &PRODUCT; 2.2.x versions, and is now added back in the 3.0.6 + release. + In Inline mode, one firewall device is placed in front of a load balancing device. The + firewall acts as the gateway for all incoming traffic, then redirect the load balancing traffic + to the load balancer behind it. The load balancer in this case will not have the direct access + to the public network. Deploying network devices in Inline mode ensures that the resources are + protected. + + + + + + parallel-inline-mode.png: external networks in different deployment modes + + + In Side by Side mode, a firewall device is deployed in parallel with the load balancer + device. So the traffic to the load balancer public IP is not routed through the firewall, and + therefore, is exposed to the public network. + + + + + + parallel-mode.png: adding a firewall and load balancer in side by side mode + + + The following table gives you an overview of the supported services and devices for inline + and side by side mode. + + + + + + + + + Mode + Firewall + Load Balancer + Supported + + + + + Side by Side + Virtual Router + F5 + Yes + + + Side by Side + Virtual Router + Virtual Router + Yes + + + Side by Side + Virtual Router + NetScaler + Yes + + + Side by Side + Juniper SRX + F5 + Yes + + + Side by Side + Juniper SRX + NetScaler + Yes + + + Inline + Virtual Router + F5 + No + + + Inline + Virtual Router + NetScaler + No + + + Inline + Juniper SRX + F5 + Yes + + + Inline + Juniper SRX + NetScaler + No + + + Inline + Juniper SRX + Virtual Router + No + + + + + To configure SRX and F5 in Inline mode: + + + Configure F5 Big IP and Juniper SRX. + See the respective product documentation for more information. + + + Add SRX and F5 to the same zone in &PRODUCT;. + + Ensure that you select per zone sourceNAT when creating the network offering. When + adding F5 BigIP, do not make it a dedicated device. + + + + Enable both the devices. + + + Create a network offering: + Use SRX as provider for Firewall, Port Forwarding, SourceNAT, and StaticNat. Select F5 + BigIP as the service provider for Load Balancing. Use Virtual Router as the service provider + for DNS, DHCP, user data. + + + Select Inline mode. + For more information, see . + Creating Network Offerings in the Administration Guide. + + + + Start a new VM with this new network offering. + + + Add firewall and load balancing rules. For more information, see + Adding a Load Balancer Rule and . + IP Forwarding and Firewalling in the Administration + Guide. + + + +
diff --git a/docs/en-US/lb-services.xml b/docs/en-US/lb-services.xml new file mode 100644 index 00000000000..3bb79dbd335 --- /dev/null +++ b/docs/en-US/lb-services.xml @@ -0,0 +1,25 @@ + + +%BOOK_ENTITIES; +]> + +
+ Load Balancing Services + + +
diff --git a/docs/en-US/management-server-lb.xml b/docs/en-US/management-server-lb.xml index 85a86221c80..f4275786be7 100644 --- a/docs/en-US/management-server-lb.xml +++ b/docs/en-US/management-server-lb.xml @@ -19,12 +19,12 @@ under the License. -->
- Setting Zone VLAN and Running VM Maximums - &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management - Servers. The administrator is responsible for creating the load balancer rules for the - Management Servers. The application requires persistence or stickiness across multiple sessions. - The following chart lists the ports that should be load balanced and whether or not persistence - is required. + Management Server Load Balancing + &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management Servers. + The administrator is responsible for creating the load balancer rules for the Management + Servers. The application requires persistence or stickiness across multiple sessions. The + following chart lists the ports that should be load balanced and whether or not persistence is + required. Even if persistence is not required, enabling it is permitted. diff --git a/docs/en-US/network-setup.xml b/docs/en-US/network-setup.xml index ceee190d4ca..192c8e23d2f 100644 --- a/docs/en-US/network-setup.xml +++ b/docs/en-US/network-setup.xml @@ -20,16 +20,16 @@ --> Network Setup - Achieving the correct networking setup is crucial to a successful &PRODUCT; - installation. This section contains information to help you make decisions and follow the right - procedures to get your network set up correctly. + Achieving the correct networking setup is crucial to a successful &PRODUCT; installation. + This section contains information to help you make decisions and follow the right procedures to + get your network set up correctly. - - + - + From eb40d2337e0ae10876a27dfbc22575be8e9d593d Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 11 Jan 2013 17:03:24 +0530 Subject: [PATCH 31/92] apidoc: fixing the api doc failure remove api-discovery_commands.properties since the plugin returns the listApis call as a map directly. not needed for api doc generation. Signed-off-by: Prasanna Santhanam --- tools/apidoc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml index e0b02bc5dc6..bc7411f7013 100644 --- a/tools/apidoc/pom.xml +++ b/tools/apidoc/pom.xml @@ -57,7 +57,7 @@ ${client.config.jars} ./target -f - ${client.config.conf}/commands.properties,${client.config.conf}/commands-ext.properties,${client.config.conf}/virtualrouter_commands.properties,${client.config.conf}/nicira-nvp_commands.properties,${client.config.conf}/api-discovery_commands.properties + ${client.config.conf}/commands.properties,${client.config.conf}/commands-ext.properties,${client.config.conf}/virtualrouter_commands.properties,${client.config.conf}/nicira-nvp_commands.properties From 499c474ed0123865f3f4feca5f6320ac322b6f37 Mon Sep 17 00:00:00 2001 From: Radhika PC Date: Fri, 11 Jan 2013 17:53:09 +0530 Subject: [PATCH 32/92] Autoscale Documentation : Reviewed-By: Jessica Tomechak --- docs/en-US/autoscale.xml | 284 ++++++++++++++++++ docs/en-US/configure-snmp-rhel.xml | 86 ++++++ .../external-firewalls-and-load-balancers.xml | 43 +-- ...ion-of-external-firewalls-loadbalancer.xml | 46 +++ 4 files changed, 440 insertions(+), 19 deletions(-) create mode 100644 docs/en-US/autoscale.xml create mode 100644 docs/en-US/configure-snmp-rhel.xml create mode 100644 docs/en-US/ongoing-configuration-of-external-firewalls-loadbalancer.xml diff --git a/docs/en-US/autoscale.xml b/docs/en-US/autoscale.xml new file mode 100644 index 00000000000..d63281f9e7e --- /dev/null +++ b/docs/en-US/autoscale.xml @@ -0,0 +1,284 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Configuring AutoScale + AutoScaling allows you to scale your back-end services or application VMs up or down + seamlessly and automatically according to the conditions you define. With AutoScaling enabled, + you can ensure that the number of VMs you are using seamlessly scale up when demand increases, + and automatically decreases when demand subsides. Thus it helps you save compute costs by + terminating underused VMs automatically and launching new VMs when you need them, without the + need for manual intervention. + NetScaler AutoScaling is designed to seamlessly launch or terminate VMs based on + user-defined conditions. Conditions for triggering a scaleup or scaledown action can vary from a + simple use case like monitoring the CPU usage of a server to a complex use case of monitoring a + combination of server's responsiveness and its CPU usage. For example, you can configure + AutoScaling to launch an additional VM whenever CPU usage exceeds 80 percent for 15 minutes, or + to remove a VM whenever CPU usage is less than 20 percent for 30 minutes. + &PRODUCT; uses the NetScaler load balancer to monitor all aspects of a system's health and + work in unison with &PRODUCT; to initiate scale-up or scale-down actions. The supported + NetScaler version is 10.0. + + Prerequisites + Before you configure an AutoScale rule, consider the following: + + + + Ensure that the necessary template is prepared before configuring AutoScale. When a VM + is deployed by using a template and when it comes up, the application should be up and + running. + + If the application is not running, the NetScaler device considers the VM as + ineffective and continues provisioning the VMs unconditionally until the resource limit is + exhausted. + + + + Deploy the templates you prepared. Ensure that the applications come up on the first + boot and is ready to take the traffic. Observe the time requires to deploy the template. + Consider this time when you specify the quiet time while configuring AutoScale. + + + The AutoScale feature supports the SNMP counters that can be used to define conditions + for taking scale up or scale down actions. To monitor the SNMP-based counter, ensure that + the SNMP agent is installed in the template used for creating the AutoScale VMs, and the + SNMP operations work with the configured SNMP community and port by using standard SNMP + managers. For example, see to configure SNMP on a RHEL + machine. + + + Ensure that the endpointe.url parameter present in the Global Settings is set to the + Management Server API URL. For example, http://10.102.102.22:8080/client/api. In a + multi-node Management Server deployment, use the virtual IP address configured in the load + balancer for the management server’s cluster. Additionally, ensure that the NetScaler device + has access to this IP address to provide AutoScale support. + If you update the endpointe.url, disable the AutoScale functionality of the load + balancer rules in the system, then enable them back to reflect the changes. For more + information see + + + If the API Key and Secret Key are regenerated for an AutoScale user, ensure that the + AutoScale functionality of the load balancers that the user participates in are disabled and + then enabled to reflect the configuration changes in the NetScaler. + + + In an advanced Zone, ensure that at least one VM should be present before configuring a + load balancer rule with AutoScale. Having one VM in the network ensures that the network is + in implemented state for configuring AutoScale. + + + + Configuration + Specify the following: + + + + + + + autoscaleateconfig.png: Configuring AutoScale + + + + + Template: A template consists of a base OS image and + application. A template is used to provision the new instance of an application on a scaleup + action. When a VM is deployed from a template, the VM can start taking the traffic from the + load balancer without any admin intervention. For example, if the VM is deployed for a Web + service, it should have the Web server running, the database connected, and so on. + + + Compute offering: A predefined set of virtual hardware + attributes, including CPU speed, number of CPUs, and RAM size, that the user can select when + creating a new virtual machine instance. Choose one of the compute offerings to be used + while provisioning a VM instance as part of scaleup action. + + + Min Instance: The minimum number of active VM instances + that is assigned to a load balancing rule. The active VM instances are the application + instances that are up and serving the traffic, and are being load balanced. This parameter + ensures that a load balancing rule has at least the configured number of active VM instances + are available to serve the traffic. + + If an application, such as SAP, running on a VM instance is down for some reason, the + VM is then not counted as part of Min Instance parameter, and the AutoScale feature + initiates a scaleup action if the number of active VM instances is below the configured + value. Similarly, when an application instance comes up from its earlier down state, this + application instance is counted as part of the active instance count and the AutoScale + process initiates a scaledown action when the active instance count breaches the Max + instance value. + + + + Max Instance: Maximum number of active VM instances + that should be assigned to a load balancing rule. This + parameter defines the upper limit of active VM instances that can be assigned to a load + balancing rule. + Specifying a large value for the maximum instance parameter might result in provisioning + large number of VM instances, which in turn leads to a single load balancing rule exhausting + the VM instances limit specified at the account or domain level. + + If an application, such as SAP, running on a VM instance is down for some reason, the + VM is not counted as part of Max Instance parameter. So there may be scenarios where the + number of VMs provisioned for a scaleup action might be more than the configured Max + Instance value. Once the application instances in the VMs are up from an earlier down + state, the AutoScale feature starts aligning to the configured Max Instance value. + + + + Specify the following scale-up and scale-down policies: + + + Duration: The duration, in seconds, for which the + conditions you specify must be true to trigger a scaleup action. The conditions defined + should hold true for the entire duration you specify for an AutoScale action to be invoked. + + + + Counter: The performance counters expose the state of + the monitored instances. By default, &PRODUCT; offers four performance counters: Three SNMP + counters and one NetScaler counter. The SNMP counters are Linux User CPU, Linux System CPU, + and Linux CPU Idle. The NetScaler counter is ResponseTime. The root administrator can add + additional counters into &PRODUCT; by using the &PRODUCT; API. + + + Operator: The following five relational operators are + supported in AutoScale feature: Greater than, Less than, Less than or equal to, Greater than + or equal to, and Equal to. + + + Threshold: Threshold value to be used for the counter. + Once the counter defined above breaches the threshold value, the AutoScale feature initiates + a scaleup or scaledown action. + + + Add: Click Add to add the condition. + + + Additionally, if you want to configure the advanced settings, click Show advanced settings, + and specify the following: + + + Polling interval: Frequency in which the conditions, + combination of counter, operator and threshold, are to be evaluated before taking a scale up + or down action. The default polling interval is 30 seconds. + + + Quiet Time: This is the cool down period after an + AutoScale action is initiated. The time includes the time taken to complete provisioning a + VM instance from its template and the time taken by an application to be ready to serve + traffic. This quiet time allows the fleet to come up to a stable state before any action can + take place. The default is 300 seconds. + + + Destroy VM Grace Period: The duration in seconds, after + a scaledown action is initiated, to wait before the VM is destroyed as part of scaledown + action. This is to ensure graceful close of any pending sessions or transactions being + served by the VM marked for destroy. The default is 120 seconds. + + + Security Groups: Security groups provide a way to + isolate traffic to the VM instances. A security group is a group of VMs that filter their + incoming and outgoing traffic according to a set of rules, called ingress and egress rules. + These rules filter network traffic according to the IP address that is attempting to + communicate with the VM. + + + Disk Offerings: A predefined set of disk size for + primary data storage. + + + SNMP Community: The SNMP community string to be used by + the NetScaler device to query the configured counter value from the provisioned VM + instances. Default is public. + + + SNMP Port: The port number on which the SNMP agent that + run on the provisioned VMs is listening. Default port is 161. + + + User: This is the user that the NetScaler device use to + invoke scaleup and scaledown API calls to the cloud. If no option is specified, the user who + configures AutoScaling is applied. Specify another user name to override. + + + Apply: Click Apply to create the AutoScale + configuration. + + + + Disabling and Enabling an AutoScale Configuration + If you want to perform any maintenance operation on the AutoScale VM instances, disable + the AutoScale configuration. When the AutoScale configuration is disabled, no scaleup or + scaledown action is performed. You can use this downtime for the maintenance activities. To + disable the AutoScale configuration, click the Disable AutoScale + + + + + EnableDisable.png: button to enable or disable AutoScale. + + button. + + The button toggles between enable and disable, depending on whether AutoScale is currently + enabled or not. After the maintenance operations are done, you can enable the AutoScale + configuration back. To enable, open the AutoScale configuration page again, then click the + Enable AutoScale + + + + + EnableDisable.png: button to enable or disable AutoScale. + + button. + + Updating an AutoScale Configuration + You can update the various parameters and add or delete the conditions in a scaleup or + scaledown rule. Before you update an AutoScale configuration, ensure that you disable the + AutoScale load balancer rule by clicking the Disable AutoScale button. + + After you modify the required AutoScale parameters, click Apply. To apply the new AutoScale + policies, open the AutoScale configuration page again, then click the Enable AutoScale + button. + + Runtime Considerations + + + + + An administrator should not assign a VM to a load balancing rule which is configured for + AutoScale. + + + Before a VM provisioning is completed if NetScaler is shutdown or restarted, the + provisioned VM cannot be a part of the load balancing rule though the intent was to assign + it to a load balancing rule. To workaround, rename the AutoScale provisioned VMs based on + the rule name or ID so at any point of time the VMs can be reconciled to its load balancing + rule. + + + Making API calls outside the context of AutoScale, such as destroyVM, on an autoscaled + VM leaves the load balancing configuration in an inconsistent state. Though VM is destroyed + from the load balancer rule, NetScaler continues to show the VM as a service assigned to a + rule. + + +
diff --git a/docs/en-US/configure-snmp-rhel.xml b/docs/en-US/configure-snmp-rhel.xml new file mode 100644 index 00000000000..bd227ff8ed5 --- /dev/null +++ b/docs/en-US/configure-snmp-rhel.xml @@ -0,0 +1,86 @@ + + +%BOOK_ENTITIES; +]> + +
+ Configuring SNMP Community String on a RHEL Server + The SNMP Community string is similar to a user id or password that provides access to a + network device, such as router. This string is sent along with all SNMP requests. If the + community string is correct, the device responds with the requested information. If the + community string is incorrect, the device discards the request and does not respond. + The NetScaler device uses SNMP to communicate with the VMs. You must install SNMP and + configure SNMP Community string for a secure communication between the NetScaler device and the + RHEL machine. + + + Ensure that you installed SNMP on RedHat. If not, run the following command: + yum install net-snmp-utils + + + Edit the /etc/snmp/snmpd.conf file to allow the SNMP polling from the NetScaler + device. + + + Map the community name into a security name (local and mynetwork, depending on where + the request is coming from): + + Use a strong password instead of public when you edit the following table. + + # sec.name source community +com2sec local localhost public +com2sec mynetwork 0.0.0.0 public + + Setting to 0.0.0.0 allows all IPs to poll the NetScaler server. + + + + Map the security names into group names: + # group.name sec.model sec.name +group MyRWGroup v1 local +group MyRWGroup v2c local +group MyROGroup v1 mynetwork +group MyROGroup v2c mynetwork + + + Create a view to allow the groups to have the permission to: + incl/excl subtree mask view all included .1 + + + Grant access with different write permissions to the two groups to the view you + created. + # context sec.model sec.level prefix read write notif + access MyROGroup "" any noauth exact all none none + access MyRWGroup "" any noauth exact all all all + + + + + Unblock SNMP in iptables. + iptables -A INPUT -p udp --dport 161 -j ACCEPT + + + Start the SNMP service: + service snmpd start + + + Ensure that the SNMP service is started automatically during the system startup: + chkconfig snmpd on + + +
diff --git a/docs/en-US/external-firewalls-and-load-balancers.xml b/docs/en-US/external-firewalls-and-load-balancers.xml index 1452804885d..6ca49f0ef03 100644 --- a/docs/en-US/external-firewalls-and-load-balancers.xml +++ b/docs/en-US/external-firewalls-and-load-balancers.xml @@ -3,26 +3,31 @@ %BOOK_ENTITIES; ]> - -
- External Firewalls and Load Balancers - &PRODUCT; is capable of replacing its Virtual Router with an external Juniper SRX device and an optional external NetScaler or F5 load balancer for gateway and load balancing services. In this case, the VMs use the SRX as their gateway. + External Firewalls and Load Balancers + &PRODUCT; is capable of replacing its Virtual Router with an external Juniper SRX device and + an optional external NetScaler or F5 load balancer for gateway and load balancing services. In + this case, the VMs use the SRX as their gateway. + + + + +
diff --git a/docs/en-US/ongoing-configuration-of-external-firewalls-loadbalancer.xml b/docs/en-US/ongoing-configuration-of-external-firewalls-loadbalancer.xml new file mode 100644 index 00000000000..c90c7ada622 --- /dev/null +++ b/docs/en-US/ongoing-configuration-of-external-firewalls-loadbalancer.xml @@ -0,0 +1,46 @@ + + +%BOOK_ENTITIES; +]> + +
+ Ongoing Configuration of External Firewalls and Load Balancers + Additional user actions (e.g. setting a port forward) will cause further programming of the + firewall and load balancer. A user may request additional public IP addresses and forward + traffic received at these IPs to specific VMs. This is accomplished by enabling static NAT for a + public IP address, assigning the IP to a VM, and specifying a set of protocols and port ranges + to open. When a static NAT rule is created, &PRODUCT; programs the zone's external firewall with + the following objects: + + + A static NAT rule that maps the public IP address to the private IP address of a + VM. + + + A security policy that allows traffic within the set of protocols and port ranges that + are specified. + + + A firewall filter counter that measures the number of bytes of incoming traffic to the + public IP. + + + The number of incoming and outgoing bytes through source NAT, static NAT, and load balancing + rules is measured and saved on each external element. This data is collected on a regular basis + and stored in the &PRODUCT; database. +
From 2b3084bba09f631d93c233238b80756b7395f938 Mon Sep 17 00:00:00 2001 From: Chip Childers Date: Fri, 11 Jan 2013 10:19:38 -0500 Subject: [PATCH 33/92] Per my veto vote on the dev list, reverting "SRX and f5 inline mode documentation: Reviewed-By: Jessica Tomechak" This reverts commit 106730ccdde30450e96d080ed6c9791682fb7300. --- .../external-guest-firewall-integration.xml | 53 +++--- docs/en-US/external-guest-lb-integration.xml | 4 +- docs/en-US/hardware-firewall.xml | 9 +- docs/en-US/images/add-netscaler.png | Bin 22777 -> 0 bytes docs/en-US/images/parallel-inline-mode.png | Bin 145392 -> 0 bytes docs/en-US/inline-config-lb-fw.xml | 173 ------------------ docs/en-US/lb-services.xml | 25 --- docs/en-US/management-server-lb.xml | 12 +- docs/en-US/network-setup.xml | 12 +- 9 files changed, 48 insertions(+), 240 deletions(-) delete mode 100644 docs/en-US/images/add-netscaler.png delete mode 100644 docs/en-US/images/parallel-inline-mode.png delete mode 100644 docs/en-US/inline-config-lb-fw.xml delete mode 100644 docs/en-US/lb-services.xml diff --git a/docs/en-US/external-guest-firewall-integration.xml b/docs/en-US/external-guest-firewall-integration.xml index bd9ac604970..0b34dca1065 100644 --- a/docs/en-US/external-guest-firewall-integration.xml +++ b/docs/en-US/external-guest-firewall-integration.xml @@ -21,16 +21,23 @@
External Guest Firewall Integration for Juniper SRX (Optional) - Available only for guests using advanced networking, both shared and isolated. + Available only for guests using advanced networking. &PRODUCT; provides for direct management of the Juniper SRX series of firewalls. This - enables &PRODUCT; to establish staticNAT mappings from public IPs to guest VMs, and to use the - Juniper device in place of the virtual router for firewall services. You can have only one - Juniper SRX device per zone. This feature is optional. If Juniper integration is not - provisioned, &PRODUCT; will use the virtual router for these services. + enables &PRODUCT; to establish static NAT mappings from public IPs to guest VMs, and to use + the Juniper device in place of the virtual router for firewall services. You can have one or + more Juniper SRX per zone. This feature is optional. If Juniper integration is not provisioned, + &PRODUCT; will use the virtual router for these services. The Juniper SRX can optionally be used in conjunction with an external load balancer. - External Network elements can be deployed in a side-by-side or inline configuration. For more - information, see . + External Network elements can be deployed in a side-by-side or inline configuration. + + + + + + parallel-mode.png: adding a firewall and load balancer in parallel mode. + + &PRODUCT; requires the Juniper to be configured as follows: Supported SRX software version is 10.3 or higher. @@ -51,22 +58,22 @@ Record the public and private interface names. If you used a VLAN for the public interface, add a ".[VLAN TAG]" after the interface name. For example, if you are using ge-0/0/3 for your public interface and VLAN tag 301, your public interface name would be - "ge-0/0/3.301". Your private interface name should always be untagged because the &PRODUCT; - software automatically creates tagged logical interfaces. + "ge-0/0/3.301". Your private interface name should always be untagged because the + &PRODUCT; software automatically creates tagged logical interfaces. - Create a public security zone and a private security zone. By default, these already - exist and are called "untrust" and "trust" zones. Add the public interface to the public - zone. &PRODUCT;automatically adds the private interface to private zone (trusted zone). Note - down the security zone names. + Create a public security zone and a private security zone. By default, these will + already exist and will be called "untrust" and "trust". Add the public interface to the + public zone and the private interface to the private zone. Note down the security zone + names. Make sure there is a security policy from the private zone to the public zone that allows all traffic. - Note the username and password of the account you want the &PRODUCT; software to log in - to when it is programming rules. + Note the username and password of the account you want the &PRODUCT; software to log + in to when it is programming rules. Make sure the "ssh" and "xnm-clear-text" system services are enabled. @@ -117,13 +124,13 @@ filter untrust { In the left navigation bar, click Infrastructure. - In Zones, click View All. + In Zones, click View More. Choose the zone you want to work with. - Click the Physical Network tab. + Click the Network tab. In the Network Service Providers node of the diagram, click Configure. (You might have @@ -152,6 +159,10 @@ filter untrust { Private Interface: The name of the private interface on the SRX. For example, ge-0/0/1. + + Usage Interface: (Optional) Typically, the public interface is used to meter + traffic. If you want to use a different interface, specify its name here + Number of Retries: The number of times to attempt a command on the SRX before failing. The default value is 2. @@ -169,12 +180,12 @@ filter untrust { untrust. - Capacity: The number of networks the device can handle. + Capacity: The number of networks the device can handle Dedicated: When marked as dedicated, this device will be dedicated to a single account. When Dedicated is checked, the value in the Capacity field has no significance - implicitly, its value is 1. + implicitly, its value is 1 @@ -183,8 +194,8 @@ filter untrust { Click Global Settings. Set the parameter external.network.stats.interval to indicate how - often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you are - not using the SRX to gather network usage statistics, set to 0. + often you want &PRODUCT; to fetch network usage statistics from the Juniper SRX. If you + are not using the SRX to gather network usage statistics, set to 0.
diff --git a/docs/en-US/external-guest-lb-integration.xml b/docs/en-US/external-guest-lb-integration.xml index acbb514207c..5760f9559e6 100644 --- a/docs/en-US/external-guest-lb-integration.xml +++ b/docs/en-US/external-guest-lb-integration.xml @@ -20,12 +20,10 @@ -->
External Guest Load Balancer Integration (Optional) - - External load balancer devices are not supported in shared networks. - &PRODUCT; can optionally use a Citrix NetScaler or BigIP F5 load balancer to provide load balancing services to guests. If this is not enabled, &PRODUCT; will use the software load balancer in the virtual router. + To install and enable an external load balancer for &PRODUCT; management: Set up the appliance according to the vendor's directions. diff --git a/docs/en-US/hardware-firewall.xml b/docs/en-US/hardware-firewall.xml index 28269cccf31..df0568aa2c2 100644 --- a/docs/en-US/hardware-firewall.xml +++ b/docs/en-US/hardware-firewall.xml @@ -22,11 +22,8 @@ Hardware Firewall All deployments should have a firewall protecting the management server; see Generic Firewall Provisions. Optionally, some deployments may also have a Juniper SRX firewall that will - be the default gateway for the guest networks; see . + be the default gateway for the guest networks; see . - - - + +
diff --git a/docs/en-US/images/add-netscaler.png b/docs/en-US/images/add-netscaler.png deleted file mode 100644 index 53c1344b9ddd49bebc276af347206ba97948b428..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22777 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 W{~Om+ralt@KQ$%IyX6WNf&T^X{FKQ6 diff --git a/docs/en-US/images/parallel-inline-mode.png b/docs/en-US/images/parallel-inline-mode.png deleted file mode 100644 index c0c1555365ec7fad20412bbe8d605ea2739c12e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145392 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 - -%BOOK_ENTITIES; -]> - -
- Configuring Network Devices in Inline and Side by Side Modes - The external network elements, such as load balancer and firewall devices, supported in - &PRODUCT; can be deployed in either of the following modes: Side by Side and Inline. Inline mode - was originally supported in &PRODUCT; 2.2.x versions, and is now added back in the 3.0.6 - release. - In Inline mode, one firewall device is placed in front of a load balancing device. The - firewall acts as the gateway for all incoming traffic, then redirect the load balancing traffic - to the load balancer behind it. The load balancer in this case will not have the direct access - to the public network. Deploying network devices in Inline mode ensures that the resources are - protected. - - - - - - parallel-inline-mode.png: external networks in different deployment modes - - - In Side by Side mode, a firewall device is deployed in parallel with the load balancer - device. So the traffic to the load balancer public IP is not routed through the firewall, and - therefore, is exposed to the public network. - - - - - - parallel-mode.png: adding a firewall and load balancer in side by side mode - - - The following table gives you an overview of the supported services and devices for inline - and side by side mode. - - - - - - - - - Mode - Firewall - Load Balancer - Supported - - - - - Side by Side - Virtual Router - F5 - Yes - - - Side by Side - Virtual Router - Virtual Router - Yes - - - Side by Side - Virtual Router - NetScaler - Yes - - - Side by Side - Juniper SRX - F5 - Yes - - - Side by Side - Juniper SRX - NetScaler - Yes - - - Inline - Virtual Router - F5 - No - - - Inline - Virtual Router - NetScaler - No - - - Inline - Juniper SRX - F5 - Yes - - - Inline - Juniper SRX - NetScaler - No - - - Inline - Juniper SRX - Virtual Router - No - - - - - To configure SRX and F5 in Inline mode: - - - Configure F5 Big IP and Juniper SRX. - See the respective product documentation for more information. - - - Add SRX and F5 to the same zone in &PRODUCT;. - - Ensure that you select per zone sourceNAT when creating the network offering. When - adding F5 BigIP, do not make it a dedicated device. - - - - Enable both the devices. - - - Create a network offering: - Use SRX as provider for Firewall, Port Forwarding, SourceNAT, and StaticNat. Select F5 - BigIP as the service provider for Load Balancing. Use Virtual Router as the service provider - for DNS, DHCP, user data. - - - Select Inline mode. - For more information, see . - Creating Network Offerings in the Administration Guide. - - - - Start a new VM with this new network offering. - - - Add firewall and load balancing rules. For more information, see - Adding a Load Balancer Rule and . - IP Forwarding and Firewalling in the Administration - Guide. - - - -
diff --git a/docs/en-US/lb-services.xml b/docs/en-US/lb-services.xml deleted file mode 100644 index 3bb79dbd335..00000000000 --- a/docs/en-US/lb-services.xml +++ /dev/null @@ -1,25 +0,0 @@ - - -%BOOK_ENTITIES; -]> - -
- Load Balancing Services - - -
diff --git a/docs/en-US/management-server-lb.xml b/docs/en-US/management-server-lb.xml index f4275786be7..85a86221c80 100644 --- a/docs/en-US/management-server-lb.xml +++ b/docs/en-US/management-server-lb.xml @@ -19,12 +19,12 @@ under the License. -->
- Management Server Load Balancing - &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management Servers. - The administrator is responsible for creating the load balancer rules for the Management - Servers. The application requires persistence or stickiness across multiple sessions. The - following chart lists the ports that should be load balanced and whether or not persistence is - required. + Setting Zone VLAN and Running VM Maximums + &PRODUCT; can use a load balancer to provide a virtual IP for multiple Management + Servers. The administrator is responsible for creating the load balancer rules for the + Management Servers. The application requires persistence or stickiness across multiple sessions. + The following chart lists the ports that should be load balanced and whether or not persistence + is required. Even if persistence is not required, enabling it is permitted. diff --git a/docs/en-US/network-setup.xml b/docs/en-US/network-setup.xml index 192c8e23d2f..ceee190d4ca 100644 --- a/docs/en-US/network-setup.xml +++ b/docs/en-US/network-setup.xml @@ -20,16 +20,16 @@ --> Network Setup - Achieving the correct networking setup is crucial to a successful &PRODUCT; installation. - This section contains information to help you make decisions and follow the right procedures to - get your network set up correctly. + Achieving the correct networking setup is crucial to a successful &PRODUCT; + installation. This section contains information to help you make decisions and follow the right + procedures to get your network set up correctly. + - + - + From 66514c00efad5c93a2b0996f1e79222cbff9bd48 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 09:45:04 -0800 Subject: [PATCH 34/92] apidoc: Remove api discovery from toc Based on eb40d2337e0ae10876a27dfbc22575be8e9d593d Signed-off-by: Rohit Yadav --- tools/apidoc/gen_toc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 7739aea633f..0b281a29c1d 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -129,7 +129,6 @@ known_categories = { 'AutoScale': 'AutoScale', 'Counter': 'AutoScale', 'Condition': 'AutoScale', - 'Api': 'API Discovery', } From d8ebd5e4f9d96e8abb7a64c728ac8d8445aac3a4 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Fri, 11 Jan 2013 11:52:46 -0700 Subject: [PATCH 35/92] Summary: Change url of tiny linux in devcloud-kvm.sql Signed-off-by: Marcus Sorensen 1357930366 -0700 --- tools/devcloud-kvm/devcloud-kvm.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/devcloud-kvm/devcloud-kvm.sql b/tools/devcloud-kvm/devcloud-kvm.sql index eeba64153a3..97478834bf3 100644 --- a/tools/devcloud-kvm/devcloud-kvm.sql +++ b/tools/devcloud-kvm/devcloud-kvm.sql @@ -37,4 +37,4 @@ INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'se UPDATE `cloud`.`configuration` SET value='10' where name = 'storage.overprovisioning.factor'; UPDATE `cloud`.`configuration` SET value='10' where name = 'cpu.overprovisioning.factor'; UPDATE `cloud`.`configuration` SET value='10' where name = 'mem.overprovisioning.factor'; -UPDATE `cloud`.`vm_template` SET unique_name="tiny Linux",name="tiny Linux",url="https://dl.dropbox.com/u/678991/cloudstack-extras/ttylinux_pv.qcow2",checksum="81dcf4b4ca05a3b637a040e851568f29",display_text="tiny Linux",format='QCOW2',hypervisor_type='KVM' where id=5; +UPDATE `cloud`.`vm_template` SET unique_name="tiny Linux",name="tiny Linux",url="http://marcus.mlsorensen.com/cloudstack-extras/ttylinux_pv.qcow2",checksum="81dcf4b4ca05a3b637a040e851568f29",display_text="tiny Linux",format='QCOW2',hypervisor_type='KVM' where id=5; From 1033200b0b5943cc21d5397d12d3b54b69aa2273 Mon Sep 17 00:00:00 2001 From: Noa Resare Date: Wed, 9 Jan 2013 16:39:10 +0100 Subject: [PATCH 36/92] CLOUDSTACK-933: CglibThrowableRendererTest writing stack traces... Improve CglibThrowableRenderer test case Log to a separate Logger instead of the default one to avoid spurious stack traces in test run output. Actually verify that registering CglibThrowableRenderer with the alternative log hierarchy actually removes call trace lines that contains the string --- .../utils/log/CglibThrowableRendererTest.java | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/utils/test/com/cloud/utils/log/CglibThrowableRendererTest.java b/utils/test/com/cloud/utils/log/CglibThrowableRendererTest.java index 5a9501dcc9c..c1cd81ef08a 100644 --- a/utils/test/com/cloud/utils/log/CglibThrowableRendererTest.java +++ b/utils/test/com/cloud/utils/log/CglibThrowableRendererTest.java @@ -18,14 +18,21 @@ package com.cloud.utils.log; import junit.framework.TestCase; -import org.apache.log4j.Logger; +import org.apache.log4j.*; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.log4j.spi.RootLogger; +import org.apache.log4j.spi.ThrowableRenderer; + +import java.io.CharArrayWriter; +import java.io.Writer; public class CglibThrowableRendererTest extends TestCase { + static Logger another = Logger.getLogger("TEST"); + private final static Logger s_logger = Logger.getLogger(CglibThrowableRendererTest.class); public static class Test { @DB @@ -48,13 +55,40 @@ public class CglibThrowableRendererTest extends TestCase { } } } + + private Logger getAlternateLogger(Writer writer, ThrowableRenderer renderer) { + Hierarchy hierarchy = new Hierarchy(new RootLogger(Level.INFO)); + if (renderer != null) { + hierarchy.setThrowableRenderer(renderer); + } + Logger alternateRoot = hierarchy.getRootLogger(); + alternateRoot.addAppender(new WriterAppender(new SimpleLayout(), writer)); + return alternateRoot; + } public void testException() { + Writer w = new CharArrayWriter(); + Logger alt = getAlternateLogger(w, null); + Test test = ComponentLocator.inject(Test.class); try { test.exception(); } catch (Exception e) { - s_logger.warn("exception caught", e); + alt.warn("exception caught", e); } + // first check that we actually have some call traces containing "" + assertTrue(w.toString().contains("")); + + w = new CharArrayWriter(); + alt = getAlternateLogger(w, new CglibThrowableRenderer()); + + try { + test.exception(); + } catch (Exception e) { + alt.warn("exception caught", e); + } + // then we check that CglibThrowableRenderer indeed remove those occurrences + assertFalse(w.toString().contains("")); + } } From 7960dd429b2d59382845f664a81c72e4024442b5 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 14:03:05 -0800 Subject: [PATCH 37/92] utils: Fix getByUuid to accept string arg, it's not gonna be anything else Due to generic programming, most classes declare Daos with ID as Long, so they get the getUuid(Long) definition, it has to be getUuid(String), uuid is not gonna be anything else. Fix GenericDaoBase and GenericDao. Signed-off-by: Rohit Yadav --- utils/src/com/cloud/utils/db/GenericDao.java | 2 +- utils/src/com/cloud/utils/db/GenericDaoBase.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/src/com/cloud/utils/db/GenericDao.java b/utils/src/com/cloud/utils/db/GenericDao.java index 2fae1afe43d..15d04b76a1c 100755 --- a/utils/src/com/cloud/utils/db/GenericDao.java +++ b/utils/src/com/cloud/utils/db/GenericDao.java @@ -56,7 +56,7 @@ public interface GenericDao { T findById(ID id, boolean fresh); // Finds one unique VO using uuid - T findByUuid(ID uuid); + T findByUuid(String uuid); /** * @return VO object ready to be used for update. It won't have any fields filled in. diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index 92e9e1c4405..880e9de22a8 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -915,7 +915,7 @@ public abstract class GenericDaoBase implements Gene @Override @DB(txn=false) @SuppressWarnings("unchecked") - public T findByUuid(final ID uuid) { + public T findByUuid(final String uuid) { SearchCriteria sc = createSearchCriteria(); sc.addAnd("uuid", SearchCriteria.Op.EQ, uuid); return findOneBy(sc); From 31dd412626ee3ab0bbdf99d8417d806b6a156582 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 14:05:41 -0800 Subject: [PATCH 38/92] DomainService: Fix getDomain by uuid string Signed-off-by: Rohit Yadav --- api/src/com/cloud/user/DomainService.java | 2 ++ server/src/com/cloud/user/DomainManagerImpl.java | 5 +++++ server/test/com/cloud/user/MockDomainManagerImpl.java | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/api/src/com/cloud/user/DomainService.java b/api/src/com/cloud/user/DomainService.java index 6fbe1b9a8db..cd20060b710 100644 --- a/api/src/com/cloud/user/DomainService.java +++ b/api/src/com/cloud/user/DomainService.java @@ -30,6 +30,8 @@ public interface DomainService { Domain getDomain(long id); + Domain getDomain(String uuid); + /** * Return whether a domain is a child domain of a given domain. * diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index 123b8951b2e..54ca2ac44bd 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -85,6 +85,11 @@ public class DomainManagerImpl implements DomainManager, DomainService, Manager return _domainDao.findById(domainId); } + @Override + public Domain getDomain(String domainUuid) { + return _domainDao.findByUuid(domainUuid); + } + @Override public String getName() { return _name; diff --git a/server/test/com/cloud/user/MockDomainManagerImpl.java b/server/test/com/cloud/user/MockDomainManagerImpl.java index 6dc4d075b9e..9f49535ce68 100644 --- a/server/test/com/cloud/user/MockDomainManagerImpl.java +++ b/server/test/com/cloud/user/MockDomainManagerImpl.java @@ -46,6 +46,12 @@ public class MockDomainManagerImpl implements Manager, DomainManager { return null; } + @Override + public Domain getDomain(String uuid) { + // TODO Auto-generated method stub + return null; + } + @Override public boolean isChildDomain(Long parentId, Long childId) { // TODO Auto-generated method stub From 24687973a8ea8e2f665945295a6b34a19d93b02b Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 14:07:27 -0800 Subject: [PATCH 39/92] ApiServer: Get rid of IdentityDao, reuse domain manager to get domain id Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 7663e8e724a..d34af67cff4 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -131,7 +131,6 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CSExceptionErrorCode; -import com.cloud.uuididentity.dao.IdentityDao; public class ApiServer implements HttpRequestHandler { private static final Logger s_logger = Logger.getLogger(ApiServer.class.getName()); @@ -680,20 +679,13 @@ public class ApiServer implements HttpRequestHandler { if (ex instanceof ServerApiException && ((ServerApiException) ex).getErrorCode() == BaseCmd.UNSUPPORTED_ACTION_ERROR) { throw (ServerApiException) ex; } - s_logger.error("unable to verifty request signature", ex); + s_logger.error("unable to verify request signature", ex); } return false; } - public Long fetchDomainId(String domainUUID){ - ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); - IdentityDao identityDao = locator.getDao(IdentityDao.class); - try{ - Long domainId = identityDao.getIdentityId("domain", domainUUID); - return domainId; - }catch(InvalidParameterValueException ex){ - return null; - } + public Long fetchDomainId(String domainUUID) { + return _domainMgr.getDomain(domainUUID).getId(); } public void loginUser(HttpSession session, String username, String password, Long domainId, String domainPath, String loginIpAddress ,Map requestParameters) throws CloudAuthenticationException { From 8cdb40a416dba0c8baac6980772c3208127811e7 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 15:27:18 -0800 Subject: [PATCH 40/92] NetworkManagerImpl: Add method to getNetwork by uuid Signed-off-by: Rohit Yadav --- server/src/com/cloud/network/NetworkManagerImpl.java | 6 ++++++ server/test/com/cloud/network/MockNetworkManagerImpl.java | 6 ++++++ server/test/com/cloud/vpc/MockNetworkManagerImpl.java | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c5003760b68..206392dce49 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2441,6 +2441,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return _networksDao.findById(id); } + @Override + @DB + public Network getNetwork(String uuid) { + return _networksDao.findByUuid(uuid); + } + @Override public List getRemoteAccessVpnElements() { List elements = new ArrayList(); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 26a6e60f714..874e01767a9 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -112,6 +112,12 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS return null; } + @Override + public Network getNetwork(String networkUuid) { + // TODO Auto-generated method stub + return null; + } + @Override public IpAddress getIp(long id) { // TODO Auto-generated method stub diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 8cb9dd53948..bd8d8bc3a69 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -156,6 +156,12 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager{ return null; } + @Override + public Network getNetwork(String networkUuid) { + // TODO Auto-generated method stub + return null; + } + /* (non-Javadoc) * @see com.cloud.network.NetworkService#getIp(long) */ From 35544f26e57ec6eaffbc6e87e3536fefbc0dbec0 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 15:29:15 -0800 Subject: [PATCH 41/92] DeployVmCmd: Remove usage of IdentityDao, use Network to get by id or uuid Signed-off-by: Rohit Yadav --- .../api/command/user/vm/DeployVMCmd.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 28bb80f72d3..e675c83dd6f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -147,10 +147,9 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { private List securityGroupNameList; @ACL(checkKeyAccess=true) - @Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, entityType={Network.class,IpAddress.class}, + @Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, entityType={Network.class, IpAddress.class}, description = "ip to network mapping. Can't be specified with networkIds parameter." + - " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].networkid=204 - requests to" + - " use ip 10.10.10.11 in network id=204") + " Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].networkid=uuid - requests to use ip 10.10.10.11 in network id=uuid") private Map ipToNetworkList; @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="the ip address for default vm's network") @@ -284,7 +283,17 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { Iterator iter = ipsCollection.iterator(); while (iter.hasNext()) { HashMap ips = (HashMap) iter.next(); - Long networkId = Long.valueOf(_responseGenerator.getIdentiyId("networks", ips.get("networkid"))); + Long networkId; + Network network = _networkService.getNetwork(ips.get("networkid")); + if (network != null) { + networkId = network.getId(); + } else { + try { + networkId = Long.parseLong(ips.get("networkid")); + } catch(NumberFormatException e) { + throw new InvalidParameterValueException("Unable to translate and find entity with networkId: " + ips.get("networkid")); + } + } String requestedIp = (String) ips.get("ip"); ipToNetworkMap.put(networkId, requestedIp); } From a35db97355470a30e2ea0979560a74afef26291e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 15:29:51 -0800 Subject: [PATCH 42/92] NetworkService: Add method to interface to get network by uuid Signed-off-by: Rohit Yadav --- api/src/com/cloud/network/NetworkService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index d5841a4692e..39a746e6776 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -60,6 +60,8 @@ public interface NetworkService { Network getNetwork(long networkId); + Network getNetwork(String networkUuid); + IpAddress getIp(long id); NetworkProfile convertNetworkToNetworkProfile(long networkId); From 8eba0ee0bbb2dbdb97aee8e672405b5e174b510d Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 15:31:03 -0800 Subject: [PATCH 43/92] ApiDispatcher: Remove helper method that proxies via ApiResponseHelper to get entity by IdentityDao Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiDispatcher.java | 6 ------ server/src/com/cloud/api/ApiResponseHelper.java | 5 ----- 2 files changed, 11 deletions(-) diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index 7bc3271523b..55d7f429ca1 100755 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -64,7 +64,6 @@ import com.cloud.utils.component.PluggableService; import com.cloud.utils.db.GenericDao; import com.cloud.utils.exception.CSExceptionErrorCode; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.uuididentity.dao.IdentityDao; // ApiDispatcher: A class that dispatches API commands to the appropriate manager for execution. public class ApiDispatcher { @@ -75,7 +74,6 @@ public class ApiDispatcher { @Inject private AsyncJobManager _asyncMgr = null; @Inject private AccountManager _accountMgr = null; @Inject EntityManager _entityMgr = null; - @Inject IdentityDao _identityDao = null; Map> _daoNameMap = new HashMap>(); // singleton class @@ -708,8 +706,4 @@ public class ApiDispatcher { throw new CloudRuntimeException("Internal error at plugService for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]"); } } - - public static Long getIdentiyId(String tableName, String token) { - return s_instance._identityDao.getIdentityId(tableName, token); - } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index edb798b812e..c346a6b86f1 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2791,11 +2791,6 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } - @Override - public Long getIdentiyId(String tableName, String token) { - return ApiDispatcher.getIdentiyId(tableName, token); - } - @Override public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) { ResourceTagJoinVO rto = ApiDBUtils.newResourceTagView(resourceTag); From 83e7214b02adf1facc8aed0f61206248de698c42 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 16:45:35 -0800 Subject: [PATCH 44/92] ConsoleProxyManagerImpl: Get rid of IdentityDao Signed-off-by: Rohit Yadav --- .../consoleproxy/ConsoleProxyManagerImpl.java | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 4994f4f526b..5bc5d27ee08 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -31,6 +31,8 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import javax.persistence.Table; +import com.cloud.offering.DiskOffering; +import com.cloud.storage.dao.DiskOfferingDao; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -107,7 +109,6 @@ import com.cloud.resource.UnableDeleteHostException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.servlet.ConsoleProxyServlet; -import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StoragePoolVO; @@ -138,7 +139,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.events.SubscriptionMgr; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; -import com.cloud.uuididentity.dao.IdentityDao; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -216,6 +216,8 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx @Inject ServiceOfferingDao _offeringDao; @Inject + DiskOfferingDao _diskOfferingDao; + @Inject NetworkOfferingDao _networkOfferingDao; @Inject StoragePoolDao _storagePoolDao; @@ -224,8 +226,6 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx @Inject ResourceManager _resourceMgr; @Inject - IdentityDao _identityDao; - @Inject NetworkDao _networkDao; @Inject RulesManager _rulesMgr; @@ -928,14 +928,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx return new ConsoleAccessAuthenticationAnswer(cmd, false); } - vmId = _identityDao.getIdentityId("vm_instance", cmd.getVmId()); - if (vmId == null) { - s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - VMInstanceVO vm = _instanceDao.findById(vmId); + VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId()); if (vm == null) { + vm = _instanceDao.findById(Long.parseLong(cmd.getVmId())); + } + if (vm == null) { + s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication"); return new ConsoleAccessAuthenticationAnswer(cmd, false); } @@ -1525,16 +1523,13 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx //check if there is a default service offering configured String cpvmSrvcOffIdStr = configs.get(Config.ConsoleProxyServiceOffering.key()); if (cpvmSrvcOffIdStr != null) { - - Long cpvmSrvcOffId = null; - try { - cpvmSrvcOffId = _identityDao.getIdentityId(DiskOfferingVO.class.getAnnotation(Table.class).name(),cpvmSrvcOffIdStr); - } catch (Exception e) { - String msg = "Can't find system service offering specified by global config, uuid=" + cpvmSrvcOffIdStr + " for console proxy vm"; - s_logger.warn(msg); - } - if(cpvmSrvcOffId != null){ - _serviceOffering = _offeringDao.findById(cpvmSrvcOffId); + DiskOffering diskOffering = _diskOfferingDao.findByUuid(cpvmSrvcOffIdStr); + if (diskOffering == null) + diskOffering = _diskOfferingDao.findById(Long.parseLong(cpvmSrvcOffIdStr)); + if (diskOffering != null) { + _serviceOffering = _offeringDao.findById(diskOffering.getId()); + } else { + s_logger.warn("Can't find system service offering specified by global config, uuid=" + cpvmSrvcOffIdStr + " for console proxy vm"); } } From 4c80684b1fffb14cea8ffd3880b278bd51dff9fc Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 16:47:02 -0800 Subject: [PATCH 45/92] StaticRoleBasedAPIAccessChecker: Fix acl cfg processing error messages Signed-off-by: Rohit Yadav --- .../acl/StaticRoleBasedAPIAccessChecker.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 740fbbc6456..380b6714517 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -43,9 +43,8 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC protected StaticRoleBasedAPIAccessChecker() { super(); - for (RoleType roleType: RoleType.values()) { + for (RoleType roleType: RoleType.values()) s_roleBasedApisMap.put(roleType, new HashSet()); - } } @Override @@ -71,16 +70,14 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC List services = locator.getAllPluggableServices(); services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); - Map configPropertiesMap = new HashMap(); for (PluggableService service : services) { - configPropertiesMap.putAll(service.getProperties()); + processConfigFiles(service.getProperties(), service.getClass().toString()); + s_logger.info("Processed role based acl for: " + service.toString()); } - - processConfigFiles(configPropertiesMap); return true; } - private void processConfigFiles(Map configMap) { + private void processConfigFiles(Map configMap, String service) { for (Map.Entry entry: configMap.entrySet()) { String apiName = entry.getKey(); String roleMask = entry.getValue(); @@ -91,7 +88,8 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC s_roleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { - s_logger.info("Malformed commands.properties permissions value, for entry: " + entry.toString()); + s_logger.info("Malformed getProperties() value for service: " + service + + " for entry: " + entry.toString()); } } } From 40779975d33c554ce488a21d84e63e635e95984e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 18:39:57 -0800 Subject: [PATCH 46/92] ExtractVolumeCmd: Fix regression, use Zone Id for getting zone Fixes regression introduced in b14b39a69fa295d1d20484170b95b97fe310af28 Signed-off-by: Rohit Yadav --- .../cloudstack/api/command/user/volume/ExtractVolumeCmd.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java index 7f6cd052470..43b25a83663 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java @@ -137,7 +137,7 @@ public class ExtractVolumeCmd extends BaseAsyncCmd { Volume vol = _entityMgr.findById(Volume.class, id); response.setId(vol.getUuid()); response.setName(vol.getName()); - DataCenter zone = _entityMgr.findById(DataCenter.class, id); + DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); response.setZoneId(zone.getUuid()); response.setZoneName(zone.getName()); response.setMode(mode); From 0dca44efe8f3adee3f18127791edac7b0e5c1f81 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 18:43:26 -0800 Subject: [PATCH 47/92] ApiServer: Debug messages, don't spam with info, remove identity helper in ResponseGenerator Signed-off-by: Rohit Yadav --- .../apache/cloudstack/api/ResponseGenerator.java | 7 ------- server/src/com/cloud/api/ApiServer.java | 13 ++++++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index e9f988ade60..63df4dc5532 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -314,13 +314,6 @@ public interface ResponseGenerator { StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result); - /** - * @param tableName TODO - * @param token - * @return - */ - Long getIdentiyId(String tableName, String token); - /** * @param resourceTag * @param keyValueOnly TODO diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index d34af67cff4..52f2aef56cb 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -601,30 +601,29 @@ public class ApiServer implements HttpRequestHandler { // if api/secret key are passed to the parameters if ((signature == null) || (apiKey == null)) { - if (s_logger.isDebugEnabled()) { - s_logger.info("expired session, missing signature, or missing apiKey -- ignoring request...sig: " + signature + ", apiKey: " + apiKey); - } + s_logger.debug("Expired session, missing signature, or missing apiKey -- ignoring request. Signature: " + signature + ", apiKey: " + apiKey); return false; // no signature, bad request } Date expiresTS = null; + // FIXME: Hard coded signature, why not have an enum if ("3".equals(signatureVersion)) { // New signature authentication. Check for expire parameter and its validity if (expires == null) { - s_logger.info("missing Expires parameter -- ignoring request...sig: " + signature + ", apiKey: " + apiKey); + s_logger.debug("Missing Expires parameter -- ignoring request. Signature: " + signature + ", apiKey: " + apiKey); return false; } synchronized (_dateFormat) { try { expiresTS = _dateFormat.parse(expires); } catch (ParseException pe) { - s_logger.info("Incorrect date format for Expires parameter", pe); + s_logger.debug("Incorrect date format for Expires parameter", pe); return false; } } Date now = new Date(System.currentTimeMillis()); if (expiresTS.before(now)) { - s_logger.info("Request expired -- ignoring ...sig: " + signature + ", apiKey: " + apiKey); + s_logger.debug("Request expired -- ignoring ...sig: " + signature + ", apiKey: " + apiKey); return false; } } @@ -635,7 +634,7 @@ public class ApiServer implements HttpRequestHandler { // verify there is a user with this api key Pair userAcctPair = _accountMgr.findUserByApiKey(apiKey); if (userAcctPair == null) { - s_logger.info("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey); + s_logger.debug("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey); return false; } From ad063ed61055ca26b23594b4c47e30a3c22974d7 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 11 Jan 2013 19:23:32 -0800 Subject: [PATCH 48/92] StaticRoleBasedAPIAccessChecker: Throw exception on failed check Plugin should not be responsible for existence of checking an API, this was wrong. Throw exception boldly when checkAccess fails. Signed-off-by: Rohit Yadav --- .../org/apache/cloudstack/acl/APIChecker.java | 5 ++--- .../acl/StaticRoleBasedAPIAccessChecker.java | 17 +++++++---------- server/src/com/cloud/api/ApiServer.java | 15 +++------------ 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/api/src/org/apache/cloudstack/acl/APIChecker.java b/api/src/org/apache/cloudstack/acl/APIChecker.java index 61dd7de75cb..b14dfe101ba 100644 --- a/api/src/org/apache/cloudstack/acl/APIChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIChecker.java @@ -16,13 +16,12 @@ // under the License. package org.apache.cloudstack.acl; +import com.cloud.exception.PermissionDeniedException; import org.apache.cloudstack.acl.RoleType; import com.cloud.utils.component.Adapter; // APIChecker checks the ownership and access control to API requests public interface APIChecker extends Adapter { // Interface for checking access for a role using apiname - boolean checkAccess(RoleType roleType, String apiCommandName); - // Interface for checking existence of an api by name - boolean checkExistence(String apiCommandName); + boolean checkAccess(RoleType roleType, String apiCommandName) throws PermissionDeniedException; } diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 380b6714517..affd69ed89c 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.acl; +import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; @@ -48,17 +49,13 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC } @Override - public boolean checkAccess(RoleType roleType, String commandName) { - return s_roleBasedApisMap.get(roleType).contains(commandName); - } - - @Override - public boolean checkExistence(String apiName) { - for (RoleType roleType: RoleType.values()) { - if (s_roleBasedApisMap.get(roleType).contains(apiName)) - return true; + public boolean checkAccess(RoleType roleType, String commandName) + throws PermissionDeniedException { + boolean isAllowed = s_roleBasedApisMap.get(roleType).contains(commandName); + if (!isAllowed) { + throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); } - return false; + return isAllowed; } @Override diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 52f2aef56cb..03462e488ef 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -556,7 +556,7 @@ public class ApiServer implements HttpRequestHandler { return true; } else { // check against every available command to see if the command exists or not - if (!doesCommandExist(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { + if (!_apiNameCmdClassMap.containsKey(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); } @@ -780,18 +780,9 @@ public class ApiServer implements HttpRequestHandler { return true; } - private boolean doesCommandExist(String apiName) { - for (APIChecker apiChecker : _apiAccessCheckers) { - // If any checker has api info on the command, return true - if (apiChecker.checkExistence(apiName)) - return true; - } - return false; - } - - private boolean isCommandAvailable(User user, String commandName) { + private boolean isCommandAvailable(User user, String commandName) throws PermissionDeniedException { if (user == null) { - return false; + throw new PermissionDeniedException("User is null for role based API access check for command" + commandName); } Account account = _accountMgr.getAccount(user.getAccountId()); From 8d3cbc82d80eb0c4ead6f68377157fd477fe2d76 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sat, 12 Jan 2013 14:38:14 +0530 Subject: [PATCH 49/92] marvin: fixes for handling multiple phy. networks zones do not qualify for vlans but phy networks should carry the underlying vlan information. moving the vlan down to physical_network in configGenerator.py. also the sandbox example has been corrected to reflect this change and includes an illustration of using traffic types with labels. Signed-off-by: Prasanna Santhanam Reported-By: Marcus Sorenson --- tools/marvin/marvin/configGenerator.py | 3 +-- tools/marvin/marvin/deployDataCenter.py | 2 +- .../marvin/sandbox/advanced/advanced_env.py | 18 +++++++++++++++--- .../marvin/sandbox/advanced/setup.properties | 16 ++++++++-------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index d494beb6444..e2a6a24d69f 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -65,8 +65,6 @@ class zone(): self.internaldns2 = None self.securitygroupenabled = None self.localstorageenabled = None - ''' Guest Vlan range - only advanced zone''' - self.vlan = None '''default public network, in advanced mode''' self.ipranges = [] self.physical_networks = [] @@ -80,6 +78,7 @@ class traffictype(): self.xen = labeldict['xen'] if 'xen' in labeldict.keys() else None self.kvm = labeldict['kvm'] if 'kvm' in labeldict.keys() else None self.vmware = labeldict['vmware'] if 'vmware' in labeldict.keys() else None + self.simulator = labeldict['simulator'] if 'simulator' in labeldict.keys() else None #{ # 'xen' : 'cloud-xen', # 'kvm' : 'cloud-kvm', diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 0d5f3bdc659..7f8c0295ad8 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -289,7 +289,7 @@ class deployDataCenters(): for pnet in zone.physical_networks: phynetwrk = self.createPhysicalNetwork(pnet, zoneId) self.configureProviders(phynetwrk, pnet.providers) - self.updatePhysicalNetwork(phynetwrk.id, "Enabled", vlan=zone.vlan) + self.updatePhysicalNetwork(phynetwrk.id, "Enabled", vlan=pnet.vlan) if zone.networktype == "Basic": listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd() diff --git a/tools/marvin/marvin/sandbox/advanced/advanced_env.py b/tools/marvin/marvin/sandbox/advanced/advanced_env.py index 1873f31d50f..db78a84b33b 100644 --- a/tools/marvin/marvin/sandbox/advanced/advanced_env.py +++ b/tools/marvin/marvin/sandbox/advanced/advanced_env.py @@ -52,10 +52,22 @@ def describeResources(config): pn = physical_network() pn.name = "Sandbox-pnet" - pn.traffictypes = [traffictype("Guest"), traffictype("Management"), traffictype("Public")] + pn.vlan = config.get('cloudstack', 'pnet.vlan') + pn.tags = ["cloud-simulator-public"] + pn.traffictypes = [traffictype("Guest"), + traffictype("Management", {"simulator" : "cloud-simulator-mgmt"}), + traffictype("Public", {"simulator":"cloud-simulator-public"})] pn.providers.append(vpcprovider) + + pn2 = physical_network() + pn2.name = "Sandbox-pnet2" + pn2.vlan = config.get('cloudstack', 'pnet2.vlan') + pn2.tags = ["cloud-simulator-guest"] + pn2.traffictypes = [traffictype('Guest', {'simulator': 'cloud-simulator-guest'})] + pn2.providers.append(vpcprovider) z.physical_networks.append(pn) + z.physical_networks.append(pn2) p = pod() p.name = 'POD0' @@ -118,11 +130,11 @@ def describeResources(config): ''''add loggers''' testClientLogger = logger() testClientLogger.name = 'TestClient' - testClientLogger.file = '/var/log/testclient.log' + testClientLogger.file = 'testclient.log' testCaseLogger = logger() testCaseLogger.name = 'TestCase' - testCaseLogger.file = '/var/log/testcase.log' + testCaseLogger.file = 'testcase.log' zs.logger.append(testClientLogger) zs.logger.append(testCaseLogger) diff --git a/tools/marvin/marvin/sandbox/advanced/setup.properties b/tools/marvin/marvin/sandbox/advanced/setup.properties index ba44d5146b6..73eacc938d4 100644 --- a/tools/marvin/marvin/sandbox/advanced/setup.properties +++ b/tools/marvin/marvin/sandbox/advanced/setup.properties @@ -24,10 +24,9 @@ storage.cleanup.interval=300 account.cleanup.interval=600 expunge.workers=3 workers=10 -use.user.concentrated.pod.allocation=false vm.allocation.algorithm=random vm.op.wait.interval=5 -guest.domain.suffix=sandbox.kvm +guest.domain.suffix=sandbox.simulator instance.name=QA direct.agent.load.size=1000 default.page.size=10000 @@ -35,15 +34,16 @@ check.pod.cidrs=true secstorage.allowed.internal.sites=10.147.28.0/24 [environment] dns=10.147.28.6 -mshost=10.147.29.111 +mshost=localhost mshost.user=root mshost.passwd=password -mysql.host=10.147.29.111 +mysql.host=localhost mysql.cloud.user=cloud mysql.cloud.passwd=cloud [cloudstack] #guest VLAN -zone.vlan=675-679 +pnet.vlan=675-679 +pnet2.vlan=800-1000 #management network private.gateway=10.147.29.1 private.pod.startip=10.147.29.150 @@ -56,9 +56,9 @@ public.vlan.startip=10.147.31.150 public.vlan.endip=10.147.31.159 public.netmask=255.255.255.0 #hypervisor host information -hypervisor=XenServer -host=10.147.29.58 +hypervisor=Simulator +host=simulator0 host.password=password #storage pools -primary.pool=nfs://10.147.28.6:/export/home/sandbox/kamakura +primary.pool=nfs://10.147.28.6:/export/home/sandbox/primary secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor From 5442df2b5eba253f2dc80e08ff97e3f22047bbae Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Sun, 13 Jan 2013 14:22:56 +0530 Subject: [PATCH 50/92] devcloud-kvm: marvin deployment config generator for devcloud-kvm The devcloud-kvm.py script will take the kvm.properties file to generate an advanced zone configuration with two physical networks with traffic labels for 'guest' and 'public' traffic going on 'eth0' and 'eth1' respectively. To generate config: $ python devcloud-kvm.py -i kvm.properties -o devcloud-kvm-advanced.cfg Signed-off-by: Prasanna Santhanam --- tools/devcloud-kvm/devcloud-kvm-advanced.cfg | 183 +++++++++++++++++++ tools/devcloud-kvm/devcloud-kvm.py | 157 ++++++++++++++++ tools/devcloud-kvm/kvm.properties | 62 +++++++ 3 files changed, 402 insertions(+) create mode 100644 tools/devcloud-kvm/devcloud-kvm-advanced.cfg create mode 100644 tools/devcloud-kvm/devcloud-kvm.py create mode 100644 tools/devcloud-kvm/kvm.properties diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg new file mode 100644 index 00000000000..b96805ede2a --- /dev/null +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -0,0 +1,183 @@ +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "Devcloud-KVM", + "guestcidraddress": "10.1.1.0/24", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "name": "eth0", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "VpcVirtualRouter" + } + ], + "broadcastdomainrange": "Zone", + "vlan": "3900-3919", + "traffictypes": [ + { + "kvm": "kvm-guest", + "typ": "Guest" + }, + { + "typ": "Management" + } + ], + "tags": [ + "devcloud-guest" + ] + }, + { + "name": "eth1", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "VpcVirtualRouter" + } + ], + "broadcastdomainrange": "Zone", + "vlan": "3920-3939", + "traffictypes": [ + { + "kvm": "kvm-public", + "typ": "Public" + } + ], + "tags": [ + "devcloud-public" + ] + } + ], + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "31", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "POD0", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "C0", + "hypervisor": "KVM", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10", + "password": "password" + } + ], + "clustertype": "CloudManaged", + "primaryStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/primary", + "name": "PS0" + } + ] + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "8.8.8.8", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "127.0.0.1", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "testclient.log" + }, + { + "name": "TestCase", + "file": "testcase.log" + } + ], + "globalConfig": [ + { + "name": "storage.cleanup.interval", + "value": "300" + }, + { + "name": "instance.name", + "value": "vm" + }, + { + "name": "workers", + "value": "10" + }, + { + "name": "vm.op.wait.interval", + "value": "5" + }, + { + "name": "account.cleanup.interval", + "value": "600" + }, + { + "name": "guest.domain.suffix", + "value": "devcloud.kvm" + }, + { + "name": "expunge.delay", + "value": "60" + }, + { + "name": "vm.allocation.algorithm", + "value": "random" + }, + { + "name": "expunge.interval", + "value": "60" + }, + { + "name": "expunge.workers", + "value": "3" + }, + { + "name": "secstorage.allowed.internal.sites", + "value": "10.147.28.0/24" + }, + { + "name": "check.pod.cidrs", + "value": "true" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "passwd": "password", + "user": "root", + "port": 8096 + } + ] +} \ No newline at end of file diff --git a/tools/devcloud-kvm/devcloud-kvm.py b/tools/devcloud-kvm/devcloud-kvm.py new file mode 100644 index 00000000000..dd551b58552 --- /dev/null +++ b/tools/devcloud-kvm/devcloud-kvm.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# 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. +''' +############################################################ +# Experimental state of scripts +# * Need to be reviewed +# * Only a sandbox +############################################################ +''' +import random +import marvin +from ConfigParser import SafeConfigParser +from optparse import OptionParser +from marvin.configGenerator import * + + +def getGlobalSettings(config): + for k, v in dict(config.items('globals')).iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + yield cfg + + +def describeDevcloudKvmResources(config): + zs = cloudstackConfiguration() + + z = zone() + z.dns1 = config.get('environment', 'dns') + z.internaldns1 = config.get('environment', 'dns') + z.name = 'Devcloud-%s'%(config.get('cloudstack', 'hypervisor')) + z.networktype = 'Advanced' + z.guestcidraddress = '10.1.1.0/24' + z.localstorageenabled = 'true' + + vpcprovider = provider() + vpcprovider.name = 'VpcVirtualRouter' + + pn = physical_network() + pn.name = "eth0" + pn.vlan = config.get('cloudstack', 'pnet.vlan') + pn.tags = ["devcloud-guest"] + pn.traffictypes = [traffictype("Guest", {"kvm" :"kvm-guest" }), traffictype("Management")] + pn.providers.append(vpcprovider) + + pn2 = physical_network() + pn2.name = "eth1" + pn2.vlan = config.get('cloudstack', 'pnet2.vlan') + pn2.tags = ["devcloud-public"] + pn2.traffictypes = [traffictype("Public", {"kvm" : "kvm-public"})] + pn2.providers.append(vpcprovider) + + z.physical_networks.append(pn) + z.physical_networks.append(pn2) + + p = pod() + p.name = 'POD0' + p.gateway = config.get('cloudstack', 'private.gateway') + p.startip = config.get('cloudstack', 'private.pod.startip') + p.endip = config.get('cloudstack', 'private.pod.endip') + p.netmask = config.get('cloudstack', 'private.netmask') + + v = iprange() + v.gateway = config.get('cloudstack', 'public.gateway') + v.startip = config.get('cloudstack', 'public.vlan.startip') + v.endip = config.get('cloudstack', 'public.vlan.endip') + v.netmask = config.get('cloudstack', 'public.netmask') + v.vlan = config.get('cloudstack', 'public.vlan') + z.ipranges.append(v) + + c = cluster() + c.clustername = 'C0' + c.hypervisor = config.get('cloudstack', 'hypervisor') + c.clustertype = 'CloudManaged' + + h = host() + h.username = 'root' + h.password = config.get('cloudstack', 'host.password') + h.url = 'http://%s'%(config.get('cloudstack', 'host')) + c.hosts.append(h) + + ps = primaryStorage() + ps.name = 'PS0' + ps.url = config.get('cloudstack', 'primary.pool') + c.primaryStorages.append(ps) + + p.clusters.append(c) + z.pods.append(p) + + secondary = secondaryStorage() + secondary.url = config.get('cloudstack', 'secondary.pool') + z.secondaryStorages.append(secondary) + + '''Add zone''' + zs.zones.append(z) + + '''Add mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = config.get('environment', 'mshost') + mgt.user = config.get('environment', 'mshost.user') + mgt.passwd = config.get('environment', 'mshost.passwd') + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = config.get('environment', 'mysql.host') + db.user = config.get('environment', 'mysql.cloud.user') + db.passwd = config.get('environment', 'mysql.cloud.passwd') + zs.dbSvr = db + + '''Add some configuration''' + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)] + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = 'TestClient' + testClientLogger.file = 'testclient.log' + + testCaseLogger = logger() + testCaseLogger.name = 'TestCase' + testCaseLogger.file = 'testcase.log' + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + return zs + + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-i', '--input', action='store', default='setup.properties', \ + dest='input', help='file containing environment setup information') + parser.add_option('-o', '--output', action='store', default='./devcloud-kvm-advanced.cfg', \ + dest='output', help='path where environment json will be generated') + + + (opts, args) = parser.parse_args() + + cfg_parser = SafeConfigParser() + cfg_parser.read(opts.input) + + cfg = describeDevcloudKvmResources(cfg_parser) + generate_setup_config(cfg, opts.output) diff --git a/tools/devcloud-kvm/kvm.properties b/tools/devcloud-kvm/kvm.properties new file mode 100644 index 00000000000..79afcd4a8ea --- /dev/null +++ b/tools/devcloud-kvm/kvm.properties @@ -0,0 +1,62 @@ +# 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. + + +[globals] +#global settings in cloudstack +expunge.delay=60 +expunge.interval=60 +storage.cleanup.interval=300 +account.cleanup.interval=600 +expunge.workers=3 +workers=10 +vm.allocation.algorithm=random +vm.op.wait.interval=5 +guest.domain.suffix=devcloud.kvm +instance.name=vm +check.pod.cidrs=true +secstorage.allowed.internal.sites=10.147.28.0/24 +[environment] +dns=8.8.8.8 +mshost=127.0.0.1 +mshost.user=root +mshost.passwd=password +mysql.host=127.0.0.1 +mysql.cloud.user=cloud +mysql.cloud.passwd=cloud +[cloudstack] +#guest VLAN +pnet.vlan=3900-3919 +pnet2.vlan=3920-3939 +#management network +private.gateway=192.168.56.1 +private.pod.startip=192.168.56.200 +private.pod.endip=192.168.56.249 +private.netmask=255.255.255.0 +#public network +public.gateway=10.0.3.2 +public.vlan=31 +public.vlan.startip=10.0.3.100 +public.vlan.endip=10.0.3.199 +public.netmask=255.255.255.0 +#hypervisor host information +hypervisor=KVM +host=192.168.56.10 +host.password=password +#storage pools +primary.pool=nfs://192.168.56.10/opt/storage/primary +secondary.pool=nfs://192.168.56.10/opt/storage/secondary From 127867cc999a7c772cdf5108b3e7432f91178cfe Mon Sep 17 00:00:00 2001 From: Noa Resare Date: Sat, 12 Jan 2013 19:07:32 +0000 Subject: [PATCH 51/92] Improved handling of unknown OS, Distribution Introduce UnknownSystemExcpetion to indicate that the system is is unknonwn. Catch said exception in cloud-setup-management, print an error and exit. CLOUDSTACK-966: Improve error reporting when running on unknown OS / version Signed-off-by: Prasanna Santhanam --- client/bindir/cloud-setup-management.in | 10 ++++++++-- python/lib/cloudutils/utilities.py | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/client/bindir/cloud-setup-management.in b/client/bindir/cloud-setup-management.in index 469c9614b41..ca1327ae725 100755 --- a/client/bindir/cloud-setup-management.in +++ b/client/bindir/cloud-setup-management.in @@ -16,8 +16,9 @@ # specific language governing permissions and limitations # under the License. +import sys from cloudutils.syscfg import sysConfigFactory -from cloudutils.utilities import initLoging +from cloudutils.utilities import initLoging, UnknownSystemException from cloudutils.cloudException import CloudRuntimeException, CloudInternalException from cloudutils.globalEnv import globalEnv from cloudutils.serviceConfigServer import cloudManagementConfig @@ -35,7 +36,12 @@ if __name__ == '__main__': glbEnv.mode = "Server" print "Starting to configure CloudStack Management Server:" - syscfg = sysConfigFactory.getSysConfigFactory(glbEnv) + try: + syscfg = sysConfigFactory.getSysConfigFactory(glbEnv) + except UnknownSystemException: + print >>sys.stderr, ("Error: CloudStack failed to detect your " + "operating system. Exiting.") + sys.exit(1) try: syscfg.registerService(cloudManagementConfig) syscfg.config() diff --git a/python/lib/cloudutils/utilities.py b/python/lib/cloudutils/utilities.py index adf81fcbd4c..3f5f2a9dc8b 100755 --- a/python/lib/cloudutils/utilities.py +++ b/python/lib/cloudutils/utilities.py @@ -96,6 +96,10 @@ def writeProgressBar(msg, result): output = "[%-6s]\n"%"Failed" sys.stdout.write(output) sys.stdout.flush() + +class UnknownSystemException(Exception): + "This Excption is raised if the current operating enviornment is unknown" + pass class Distribution: def __init__(self): @@ -120,7 +124,7 @@ class Distribution: self.arch = bash("uname -m").getStdout() else: - self.distro = "Unknown" + raise UnknownSystemException def getVersion(self): return self.distro From c06218d32f3e4b20ec86303639af847cb911ec39 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 14 Jan 2013 16:49:42 +0530 Subject: [PATCH 52/92] CLOUDSTACK-971:Error Dialog is empty --- ui/scripts/sharedFunctions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index eb78ad15da0..51c4fdb5902 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -208,12 +208,13 @@ function parseXMLHttpResponse(XMLHttpResponse) { var json = JSON.parse(XMLHttpResponse.responseText); if (json != null) { var property; - for(property in json) {} + for(property in json) { var errorObj = json[property]; if(errorObj.errorcode == 401 && errorObj.errortext == "unable to verify user credentials and/or request signature") return _l('label.session.expired'); else return _s(errorObj.errortext); + } } else { return ""; From 0293d3d665ad41ea2e49a01f9c0fd6cf4547a9bf Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Mon, 14 Jan 2013 10:51:39 -0700 Subject: [PATCH 53/92] Summary: Allow passing 'storagetype' to DiskOffering.create in marvin base.py Signed-off-by: Marcus Sorensen 1358185899 -0700 --- tools/marvin/marvin/integration/lib/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 0daea5dd579..726a628d070 100644 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -1109,6 +1109,9 @@ class DiskOffering: if domainid: cmd.domainid = domainid + if services["storagetype"]: + cmd.storagetype = services["storagetype"] + return DiskOffering(apiclient.createDiskOffering(cmd).__dict__) def delete(self, apiclient): From 9139949d966c45153899b056aa3b19da55e6931f Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Mon, 14 Jan 2013 12:57:12 -0700 Subject: [PATCH 54/92] Summary: Adding devcloud-advanced.cfg marvin config for advanced network testing Signed-off-by: Marcus Sorensen 1358193432 -0700 --- tools/devcloud/devcloud-advanced.cfg | 105 +++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tools/devcloud/devcloud-advanced.cfg diff --git a/tools/devcloud/devcloud-advanced.cfg b/tools/devcloud/devcloud-advanced.cfg new file mode 100644 index 00000000000..54cdd44f95b --- /dev/null +++ b/tools/devcloud/devcloud-advanced.cfg @@ -0,0 +1,105 @@ +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "testzone", + "guestcidraddress": "10.1.1.0/24", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "vlan": "3900-4000", + "name": "eth0", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "VpcVirtualRouter" + } + ] + }, + { + "broadcastdomainrange": "Zone", + "name": "eth1", + "traffictypes": [ + { + "xen": "Pool-wide network associated with eth1", + "typ": "Public" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + } + ] + } + ], + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "untagged", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "testpod", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "testcluster", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "8.8.4.4", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10:/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "127.0.0.1", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "192.168.56.10", + "port": 8096 + } + ] +} From 896e505da6de08e723b339e748064de10d250c8c Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 15:06:46 -0800 Subject: [PATCH 55/92] APIChecker: Make interface generic, pass user and not just role Signed-off-by: Rohit Yadav --- api/src/org/apache/cloudstack/acl/APIChecker.java | 4 ++-- .../acl/StaticRoleBasedAPIAccessChecker.java | 12 +++++++++++- server/src/com/cloud/api/ApiServer.java | 4 +--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/api/src/org/apache/cloudstack/acl/APIChecker.java b/api/src/org/apache/cloudstack/acl/APIChecker.java index b14dfe101ba..9e5c6c61108 100644 --- a/api/src/org/apache/cloudstack/acl/APIChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIChecker.java @@ -17,11 +17,11 @@ package org.apache.cloudstack.acl; import com.cloud.exception.PermissionDeniedException; -import org.apache.cloudstack.acl.RoleType; +import com.cloud.user.User; import com.cloud.utils.component.Adapter; // APIChecker checks the ownership and access control to API requests public interface APIChecker extends Adapter { // Interface for checking access for a role using apiname - boolean checkAccess(RoleType roleType, String apiCommandName) throws PermissionDeniedException; + boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException; } diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index affd69ed89c..55db2880664 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -18,6 +18,9 @@ package org.apache.cloudstack.acl; import com.cloud.exception.PermissionDeniedException; import com.cloud.server.ManagementServer; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.PluggableService; @@ -42,6 +45,8 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC private static Map> s_roleBasedApisMap = new HashMap>(); + private static AccountService s_accountService; + protected StaticRoleBasedAPIAccessChecker() { super(); for (RoleType roleType: RoleType.values()) @@ -49,8 +54,10 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC } @Override - public boolean checkAccess(RoleType roleType, String commandName) + public boolean checkAccess(User user, String commandName) throws PermissionDeniedException { + Account account = s_accountService.getAccount(user.getAccountId()); + RoleType roleType = s_accountService.getRoleType(account); boolean isAllowed = s_roleBasedApisMap.get(roleType).contains(commandName); if (!isAllowed) { throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); @@ -64,6 +71,9 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC // Read command properties files to build the static map per role. ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); + + s_accountService = locator.getManager(AccountService.class); + List services = locator.getAllPluggableServices(); services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 03462e488ef..c8511b2991d 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -785,11 +785,9 @@ public class ApiServer implements HttpRequestHandler { throw new PermissionDeniedException("User is null for role based API access check for command" + commandName); } - Account account = _accountMgr.getAccount(user.getAccountId()); - RoleType roleType = _accountMgr.getRoleType(account); for (APIChecker apiChecker : _apiAccessCheckers) { // Fail the checking if any checker fails to verify - if (!apiChecker.checkAccess(roleType, commandName)) + if (!apiChecker.checkAccess(user, commandName)) return false; } return true; From e97090a9202452a0ecdff2da55181517cb5b2364 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Mon, 14 Jan 2013 17:15:22 -0700 Subject: [PATCH 56/92] Summary: Updated devcloud-advanced.cfg and devcloud-kvm-advanced.cfg Signed-off-by: Marcus Sorensen 1358208922 -0700 --- tools/devcloud-kvm/devcloud-kvm-advanced.cfg | 144 +++++-------------- tools/devcloud/devcloud-advanced.cfg | 10 ++ 2 files changed, 48 insertions(+), 106 deletions(-) diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg index b96805ede2a..1110863d848 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -2,12 +2,24 @@ "zones": [ { "localstorageenabled": "true", - "name": "Devcloud-KVM", + "name": "testzone", "guestcidraddress": "10.1.1.0/24", "dns1": "8.8.8.8", "physical_networks": [ { - "name": "eth0", + "broadcastdomainrange": "Zone", + "vlan": "3900-4000", + "name": "eth0", + "traffictypes": [ + { + "kvm": "cloudbr0", + "typ": "Management" + }, + { + "kvm": "cloudbr0", + "typ": "Guest" + } + ], "providers": [ { "broadcastdomainrange": "ZONE", @@ -17,90 +29,62 @@ "broadcastdomainrange": "ZONE", "name": "VpcVirtualRouter" } - ], - "broadcastdomainrange": "Zone", - "vlan": "3900-3919", - "traffictypes": [ - { - "kvm": "kvm-guest", - "typ": "Guest" - }, - { - "typ": "Management" - } - ], - "tags": [ - "devcloud-guest" ] }, { + "broadcastdomainrange": "Zone", "name": "eth1", + "traffictypes": [ + { + "kvm": "cloudbr1", + "typ": "Public" + } + ], "providers": [ { "broadcastdomainrange": "ZONE", "name": "VirtualRouter" - }, - { - "broadcastdomainrange": "ZONE", - "name": "VpcVirtualRouter" } - ], - "broadcastdomainrange": "Zone", - "vlan": "3920-3939", - "traffictypes": [ - { - "kvm": "kvm-public", - "typ": "Public" - } - ], - "tags": [ - "devcloud-public" ] } ], "ipranges": [ { - "startip": "10.0.3.100", - "endip": "10.0.3.199", + "startip": "192.168.100.100", + "endip": "192.168.100.199", "netmask": "255.255.255.0", - "vlan": "31", - "gateway": "10.0.3.2" + "vlan": "untagged", + "gateway": "192.168.100.1" } ], "networktype": "Advanced", "pods": [ { - "endip": "192.168.56.249", - "name": "POD0", - "startip": "192.168.56.200", + "endip": "172.17.10.199", + "name": "testpod", + "startip": "172.17.10.100", "netmask": "255.255.255.0", "clusters": [ { - "clustername": "C0", + "clustername": "testcluster", "hypervisor": "KVM", "hosts": [ { "username": "root", - "url": "http://192.168.56.10", + "url": "http://172.17.10.10/", "password": "password" } ], - "clustertype": "CloudManaged", - "primaryStorages": [ - { - "url": "nfs://192.168.56.10/opt/storage/primary", - "name": "PS0" - } - ] + "clustertype": "CloudManaged" } ], - "gateway": "192.168.56.1" + "gateway": "172.17.10.1" } ], - "internaldns1": "8.8.8.8", + "internaldns1": "8.8.4.4", "secondaryStorages": [ { - "url": "nfs://192.168.56.10/opt/storage/secondary" + "url": "nfs://172.17.10.10:/nfs/secondary" } ] } @@ -115,69 +99,17 @@ "logger": [ { "name": "TestClient", - "file": "testclient.log" + "file": "/var/log/testclient.log" }, { "name": "TestCase", - "file": "testcase.log" - } - ], - "globalConfig": [ - { - "name": "storage.cleanup.interval", - "value": "300" - }, - { - "name": "instance.name", - "value": "vm" - }, - { - "name": "workers", - "value": "10" - }, - { - "name": "vm.op.wait.interval", - "value": "5" - }, - { - "name": "account.cleanup.interval", - "value": "600" - }, - { - "name": "guest.domain.suffix", - "value": "devcloud.kvm" - }, - { - "name": "expunge.delay", - "value": "60" - }, - { - "name": "vm.allocation.algorithm", - "value": "random" - }, - { - "name": "expunge.interval", - "value": "60" - }, - { - "name": "expunge.workers", - "value": "3" - }, - { - "name": "secstorage.allowed.internal.sites", - "value": "10.147.28.0/24" - }, - { - "name": "check.pod.cidrs", - "value": "true" + "file": "/var/log/testcase.log" } ], "mgtSvr": [ { - "mgtSvrIp": "127.0.0.1", - "passwd": "password", - "user": "root", + "mgtSvrIp": "172.17.10.10", "port": 8096 } ] -} \ No newline at end of file +} diff --git a/tools/devcloud/devcloud-advanced.cfg b/tools/devcloud/devcloud-advanced.cfg index 54cdd44f95b..ad4cdda1912 100644 --- a/tools/devcloud/devcloud-advanced.cfg +++ b/tools/devcloud/devcloud-advanced.cfg @@ -10,6 +10,16 @@ "broadcastdomainrange": "Zone", "vlan": "3900-4000", "name": "eth0", + "traffictypes": [ + { + "xen": "Pool-wide network associated with eth0", + "typ": "Management" + }, + { + "xen": "Pool-wide network associated with eth0", + "typ": "Guest" + } + ], "providers": [ { "broadcastdomainrange": "ZONE", From 3aba867e1630cf7071fb97b5f925dced1b5439d6 Mon Sep 17 00:00:00 2001 From: anthony Date: Mon, 14 Jan 2013 18:25:32 -0800 Subject: [PATCH 57/92] only basic network is pod based. it has nothing to do with shared SG enabled netwokr --- .../network/router/VirtualNetworkApplianceManagerImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 1f74c7174e8..492e1dc20b1 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1381,9 +1381,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian assert guestNetwork.getTrafficType() == TrafficType.Guest; // 1) Get deployment plan and find out the list of routers - boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || - _networkMgr.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) - && guestNetwork.getTrafficType() == TrafficType.Guest; + boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic); // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods List destinations = new ArrayList(); From 0a1e4b8cf95a3e0041e3f306c4dfad09b3b6216a Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 16:46:12 -0800 Subject: [PATCH 58/92] tomcatconf: Move apiname:mask rules in commands.properties.in, delete others Signed-off-by: Rohit Yadav --- .../cisconexusvsm_commands.properties.in | 25 ------ client/tomcatconf/commands-ext.properties.in | 28 ------- client/tomcatconf/commands.properties.in | 84 +++++++++++++++++++ .../tomcatconf/f5bigip_commands.properties.in | 32 ------- .../junipersrx_commands.properties.in | 30 ------- .../tomcatconf/netapp_commands.properties.in | 33 -------- ...tscalerloadbalancer_commands.properties.in | 26 ------ .../nicira-nvp_commands.properties.in | 29 ------- .../simulator_commands.properties.in | 19 ----- .../virtualrouter_commands.properties.in | 24 ------ 10 files changed, 84 insertions(+), 246 deletions(-) delete mode 100644 client/tomcatconf/cisconexusvsm_commands.properties.in delete mode 100644 client/tomcatconf/commands-ext.properties.in delete mode 100644 client/tomcatconf/f5bigip_commands.properties.in delete mode 100644 client/tomcatconf/junipersrx_commands.properties.in delete mode 100644 client/tomcatconf/netapp_commands.properties.in delete mode 100644 client/tomcatconf/netscalerloadbalancer_commands.properties.in delete mode 100644 client/tomcatconf/nicira-nvp_commands.properties.in delete mode 100644 client/tomcatconf/simulator_commands.properties.in delete mode 100644 client/tomcatconf/virtualrouter_commands.properties.in diff --git a/client/tomcatconf/cisconexusvsm_commands.properties.in b/client/tomcatconf/cisconexusvsm_commands.properties.in deleted file mode 100644 index 0427ba2d212..00000000000 --- a/client/tomcatconf/cisconexusvsm_commands.properties.in +++ /dev/null @@ -1,25 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### Cisco Nexus 1000v Virtual Supervisor Module (VSM) commands -deleteCiscoNexusVSM=1 -enableCiscoNexusVSM=1 -disableCiscoNexusVSM=1 -listCiscoNexusVSMs=1 diff --git a/client/tomcatconf/commands-ext.properties.in b/client/tomcatconf/commands-ext.properties.in deleted file mode 100644 index cd1d0eac066..00000000000 --- a/client/tomcatconf/commands-ext.properties.in +++ /dev/null @@ -1,28 +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. - -#### usage commands -generateUsageRecords=com.cloud.api.commands.GenerateUsageRecordsCmd;1 -listUsageRecords=com.cloud.api.commands.GetUsageRecordsCmd;1 -listUsageTypes=com.cloud.api.commands.ListUsageTypesCmd;1 - -#### traffic monitor commands -addTrafficMonitor=com.cloud.api.commands.AddTrafficMonitorCmd;1 -deleteTrafficMonitor=com.cloud.api.commands.DeleteTrafficMonitorCmd;1 -listTrafficMonitors=com.cloud.api.commands.ListTrafficMonitorsCmd;1 - - diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 3872f2a8783..99cb874a55f 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -424,3 +424,87 @@ resetVpnConnection=15 listVpnCustomerGateways=15 listVpnGateways=15 listVpnConnections=15 + +#### router commands +createVirtualRouterElement=7 +configureVirtualRouterElement=7 +listVirtualRouterElements=7 + +#### usage commands +generateUsageRecords=1 +listUsageRecords=1 +listUsageTypes=1 + +#### traffic monitor commands +addTrafficMonitor=1 +deleteTrafficMonitor=1 +listTrafficMonitors=1 + +#### Cisco Nexus 1000v Virtual Supervisor Module (VSM) commands +deleteCiscoNexusVSM=1 +enableCiscoNexusVSM=1 +disableCiscoNexusVSM=1 +listCiscoNexusVSMs=1 + +#### f5 big ip load balancer commands + +#Deprecated commands +addExternalLoadBalancer=1 +deleteExternalLoadBalancer=1 +listExternalLoadBalancers=1 + +addF5LoadBalancer=1 +configureF5LoadBalancer=1 +deleteF5LoadBalancer=1 +listF5LoadBalancers=1 +listF5LoadBalancerNetworks=1 + +#### juniper srx firewall commands +addExternalFirewall=1 +deleteExternalFirewall=1 +listExternalFirewalls=1 + +addSrxFirewall=1 +deleteSrxFirewall=1 +configureSrxFirewall=1 +listSrxFirewalls=1 +listSrxFirewallNetworks=1 + +####Netapp integration commands +createVolumeOnFiler=15 +destroyVolumeOnFiler=15 +listVolumesOnFiler=15 +createLunOnFiler=15 +destroyLunOnFiler=15 +listLunsOnFiler=15 +associateLun=15 +dissociateLun=15 +createPool=15 +deletePool=15 +modifyPool=15 +listPools=15 + +#### netscaler load balancer commands +addNetscalerLoadBalancer=1 +deleteNetscalerLoadBalancer=1 +configureNetscalerLoadBalancer=1 +listNetscalerLoadBalancers=1 +listNetscalerLoadBalancerNetworks=1 + +#### nicira nvp commands + +addNiciraNvpDevice=1 +deleteNiciraNvpDevice=1 +listNiciraNvpDevices=1 +listNiciraNvpDeviceNetworks=1 + +# Not implemented (yet) +#configureNiciraNvpDevice=1 + +#### host simulator commands + +configureSimulator=1 + +#### api discovery commands + +listApis=15 diff --git a/client/tomcatconf/f5bigip_commands.properties.in b/client/tomcatconf/f5bigip_commands.properties.in deleted file mode 100644 index 8c3cc2a145a..00000000000 --- a/client/tomcatconf/f5bigip_commands.properties.in +++ /dev/null @@ -1,32 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### f5 big ip load balancer commands - -#Deprecated commands -addExternalLoadBalancer=1 -deleteExternalLoadBalancer=1 -listExternalLoadBalancers=1 - -addF5LoadBalancer=1 -configureF5LoadBalancer=1 -deleteF5LoadBalancer=1 -listF5LoadBalancers=1 -listF5LoadBalancerNetworks=1 diff --git a/client/tomcatconf/junipersrx_commands.properties.in b/client/tomcatconf/junipersrx_commands.properties.in deleted file mode 100644 index 2cadc62c57e..00000000000 --- a/client/tomcatconf/junipersrx_commands.properties.in +++ /dev/null @@ -1,30 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### juniper srx firewall commands -addExternalFirewall=1 -deleteExternalFirewall=1 -listExternalFirewalls=1 - -addSrxFirewall=1 -deleteSrxFirewall=1 -configureSrxFirewall=1 -listSrxFirewalls=1 -listSrxFirewallNetworks=1 diff --git a/client/tomcatconf/netapp_commands.properties.in b/client/tomcatconf/netapp_commands.properties.in deleted file mode 100644 index ea17ac0560b..00000000000 --- a/client/tomcatconf/netapp_commands.properties.in +++ /dev/null @@ -1,33 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -####Netapp integration commands -createVolumeOnFiler=15 -destroyVolumeOnFiler=15 -listVolumesOnFiler=15 -createLunOnFiler=15 -destroyLunOnFiler=15 -listLunsOnFiler=15 -associateLun=15 -dissociateLun=15 -createPool=15 -deletePool=15 -modifyPool=15 -listPools=15 diff --git a/client/tomcatconf/netscalerloadbalancer_commands.properties.in b/client/tomcatconf/netscalerloadbalancer_commands.properties.in deleted file mode 100644 index 9eeb8da9987..00000000000 --- a/client/tomcatconf/netscalerloadbalancer_commands.properties.in +++ /dev/null @@ -1,26 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### netscaler load balancer commands -addNetscalerLoadBalancer=1 -deleteNetscalerLoadBalancer=1 -configureNetscalerLoadBalancer=1 -listNetscalerLoadBalancers=1 -listNetscalerLoadBalancerNetworks=1 diff --git a/client/tomcatconf/nicira-nvp_commands.properties.in b/client/tomcatconf/nicira-nvp_commands.properties.in deleted file mode 100644 index 1b2b5253394..00000000000 --- a/client/tomcatconf/nicira-nvp_commands.properties.in +++ /dev/null @@ -1,29 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### nicira nvp commands - -addNiciraNvpDevice=1 -deleteNiciraNvpDevice=1 -listNiciraNvpDevices=1 -listNiciraNvpDeviceNetworks=1 - -# Not implemented (yet) -#configureNiciraNvpDevice=1 diff --git a/client/tomcatconf/simulator_commands.properties.in b/client/tomcatconf/simulator_commands.properties.in deleted file mode 100644 index b7213a28c05..00000000000 --- a/client/tomcatconf/simulator_commands.properties.in +++ /dev/null @@ -1,19 +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. - - -configureSimulator=1 diff --git a/client/tomcatconf/virtualrouter_commands.properties.in b/client/tomcatconf/virtualrouter_commands.properties.in deleted file mode 100644 index 169496b8f4d..00000000000 --- a/client/tomcatconf/virtualrouter_commands.properties.in +++ /dev/null @@ -1,24 +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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -#### router commands -createVirtualRouterElement=7 -configureVirtualRouterElement=7 -listVirtualRouterElements=7 From b9c020fa7c80481fa9444dc6affb1beb069a8768 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:54:26 -0800 Subject: [PATCH 59/92] APIChecker: Fix interface definition to take in User Signed-off-by: Rohit Yadav --- api/src/org/apache/cloudstack/acl/APIChecker.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/src/org/apache/cloudstack/acl/APIChecker.java b/api/src/org/apache/cloudstack/acl/APIChecker.java index 9e5c6c61108..0d0dfd1be4e 100644 --- a/api/src/org/apache/cloudstack/acl/APIChecker.java +++ b/api/src/org/apache/cloudstack/acl/APIChecker.java @@ -23,5 +23,8 @@ import com.cloud.utils.component.Adapter; // APIChecker checks the ownership and access control to API requests public interface APIChecker extends Adapter { // Interface for checking access for a role using apiname + // If true, apiChecker has checked the operation + // If false, apiChecker is unable to handle the operation or not implemented + // On exception, checkAccess failed don't allow boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException; } From 0a31945ee589e2db8886fd8a01bdfaf91e6cfd26 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:54:58 -0800 Subject: [PATCH 60/92] PluggableService: Fix interface to return list of cmd classes Signed-off-by: Rohit Yadav --- utils/src/com/cloud/utils/component/PluggableService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/src/com/cloud/utils/component/PluggableService.java b/utils/src/com/cloud/utils/component/PluggableService.java index f6f72a904d0..5e0e4dfff16 100644 --- a/utils/src/com/cloud/utils/component/PluggableService.java +++ b/utils/src/com/cloud/utils/component/PluggableService.java @@ -16,11 +16,12 @@ // under the License. package com.cloud.utils.component; +import java.util.List; import java.util.Map; // This interface defines methods for pluggable code within the Cloud Stack. public interface PluggableService { // The config command properties filenames that lists allowed API commands // and role masks supported by this pluggable service - Map getProperties(); + List> getCommands(); } From 8f27c711e58e447409fb1b496dfeab9cf4cd7d63 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:56:02 -0800 Subject: [PATCH 61/92] ApiServer: Process through chain of api access checker, on failure it will throw exception Signed-off-by: Rohit Yadav --- server/src/com/cloud/api/ApiServer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index c8511b2991d..4d60215b276 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -786,9 +786,7 @@ public class ApiServer implements HttpRequestHandler { } for (APIChecker apiChecker : _apiAccessCheckers) { - // Fail the checking if any checker fails to verify - if (!apiChecker.checkAccess(user, commandName)) - return false; + apiChecker.checkAccess(user, commandName); } return true; } From c318561d6c69a2a7ac3aa7dd6df99f12637ddb27 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:57:22 -0800 Subject: [PATCH 62/92] ApiDiscovery: Get rid of redundant code, use apichecker to generate role based maps Signed-off-by: Rohit Yadav --- .../command/user/discovery/ListApisCmd.java | 10 +- .../discovery/ApiDiscoveryService.java | 4 +- .../discovery/ApiDiscoveryServiceImpl.java | 116 ++++++++---------- 3 files changed, 61 insertions(+), 69 deletions(-) diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index ed3e1751027..132416bac05 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,7 +16,10 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; +import com.cloud.user.AccountService; +import com.cloud.user.User; import com.cloud.user.UserContext; +import com.cloud.utils.component.Inject; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,14 +42,17 @@ public class ListApisCmd extends BaseCmd { @PlugService ApiDiscoveryService _apiDiscoveryService; + @Inject + private AccountService _accountService; + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="API name") private String name; @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller()); - ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType, name); + User user = _accountService.getActiveUser(UserContext.current().getCallerUserId()); + ListResponse response = (ListResponse) _apiDiscoveryService.listApis(user, name); if (response == null) { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find an api by that name or process any apis"); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index 611493bfc08..6458c5619e8 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -16,11 +16,11 @@ // under the License. package org.apache.cloudstack.discovery; +import com.cloud.user.User; import com.cloud.utils.component.PluggableService; -import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; public interface ApiDiscoveryService extends PluggableService { - ListResponse listApis(RoleType roleType, String apiName); + ListResponse listApis(User user, String apiName); } 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 5f84486ae49..7e2ed17ecdc 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -18,11 +18,15 @@ package org.apache.cloudstack.discovery; import com.cloud.serializer.Param; import com.cloud.server.ManagementServer; +import com.cloud.user.User; import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; +import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; import com.cloud.utils.component.PluggableService; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -30,6 +34,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.command.user.discovery.ListApisCmd; import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.cloudstack.api.response.ApiParameterResponse; import org.apache.cloudstack.api.response.ApiResponseResponse; @@ -49,57 +54,31 @@ import java.util.Set; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - private static Map> _roleTypeDiscoveryResponseListMap; + @Inject(adapter = APIChecker.class) + protected Adapters _apiAccessCheckers; - private static Map _apiNameDiscoveryResponseMap = - new HashMap(); - - private static Map> _apiNameRoleTypeListMap = null; + private static Map _apiNameDiscoveryResponseMap = null; protected ApiDiscoveryServiceImpl() { super(); - if (_roleTypeDiscoveryResponseListMap == null) { + if (_apiNameDiscoveryResponseMap == null) { long startTime = System.nanoTime(); - _roleTypeDiscoveryResponseListMap = new HashMap>(); - for (RoleType roleType: RoleType.values()) - _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList()); + _apiNameDiscoveryResponseMap = new HashMap(); cacheResponseMap(); long endTime = System.nanoTime(); s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms"); } } - private Map> getApiNameRoleTypeListMap() { - Map> apiNameRoleTypeMap = new HashMap>(); - ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); - List services = locator.getAllPluggableServices(); - services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); - for (PluggableService service : services) { - for (Map.Entry entry: service.getProperties().entrySet()) { - String apiName = entry.getKey(); - String roleMask = entry.getValue(); - try { - short cmdPermissions = Short.parseShort(roleMask); - if (!apiNameRoleTypeMap.containsKey(apiName)) - apiNameRoleTypeMap.put(apiName, new ArrayList()); - for (RoleType roleType: RoleType.values()) { - if ((cmdPermissions & roleType.getValue()) != 0) - apiNameRoleTypeMap.get(apiName).add(roleType); - } - } catch (NumberFormatException nfe) { - } - } - } - return apiNameRoleTypeMap; - } - private void cacheResponseMap() { Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + //TODO: Fix and use PluggableService to get the classes + Map> responseApiNameListMap = new HashMap>(); - for(Class cmdClass: cmdClasses) { + for (Class cmdClass : cmdClasses) { APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class); if (apiCmdAnnotation == null) apiCmdAnnotation = cmdClass.getSuperclass().getAnnotation(APICommand.class); @@ -123,9 +102,9 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { response.setRelated(responseName); Field[] responseFields = apiCmdAnnotation.responseObject().getDeclaredFields(); - for(Field responseField: responseFields) { + for (Field responseField : responseFields) { SerializedName serializedName = responseField.getAnnotation(SerializedName.class); - if(serializedName != null) { + if (serializedName != null) { ApiResponseResponse responseResponse = new ApiResponseResponse(); responseResponse.setName(serializedName.value()); Param param = responseField.getAnnotation(Param.class); @@ -137,14 +116,14 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } Field[] fields = ReflectUtil.getAllFieldsForClass(cmdClass, - new Class[] {BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); + new Class[]{BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); boolean isAsync = ReflectUtil.isCmdClassAsync(cmdClass, - new Class[] {BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); + new Class[]{BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); response.setAsync(isAsync); - for(Field field: fields) { + for (Field field : fields) { Parameter parameterAnnotation = field.getAnnotation(Parameter.class); if (parameterAnnotation != null && parameterAnnotation.expose() @@ -166,10 +145,10 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { _apiNameDiscoveryResponseMap.put(apiName, response); } - for (String apiName: _apiNameDiscoveryResponseMap.keySet()) { + for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { ApiDiscoveryResponse response = _apiNameDiscoveryResponseMap.get(apiName); Set processedParams = new HashSet(); - for (ApiParameterResponse param: response.getParams()) { + for (ApiParameterResponse param : response.getParams()) { if (responseApiNameListMap.containsKey(param.getRelated())) { List relatedApis = responseApiNameListMap.get(param.getRelated()); param.setRelated(StringUtils.join(relatedApis, ",")); @@ -192,41 +171,48 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } @Override - public ListResponse listApis(RoleType roleType, String name) { - // Creates roles based response list cache the first time listApis is called - // Due to how adapters work, this cannot be done when mgmt loads - if (_apiNameRoleTypeListMap == null) { - long startTime = System.nanoTime(); - _apiNameRoleTypeListMap = getApiNameRoleTypeListMap(); - for (Map.Entry> entry: _apiNameRoleTypeListMap.entrySet()) { - String apiName = entry.getKey(); - for (RoleType roleTypeInList: entry.getValue()) { - _roleTypeDiscoveryResponseListMap.get(roleTypeInList).add( - _apiNameDiscoveryResponseMap.get(apiName)); - } - } - long endTime = System.nanoTime(); - s_logger.info("Api Discovery Service: List apis cached in " + (endTime - startTime) / 1000000.0 + " ms"); - } + public ListResponse listApis(User user, String name) { ListResponse response = new ListResponse(); + List responseList = new ArrayList(); + + if (user == null) + return null; + if (name != null) { if (!_apiNameDiscoveryResponseMap.containsKey(name)) return null; - List singleResponse = new ArrayList(); - singleResponse.add(_apiNameDiscoveryResponseMap.get(name)); - response.setResponses(singleResponse); + for (APIChecker apiChecker : _apiAccessCheckers) { + try { + apiChecker.checkAccess(user, name); + } catch (Exception ex) { + return null; + } + } + responseList.add(_apiNameDiscoveryResponseMap.get(name)); } else { - response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType)); + for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { + boolean isAllowed = true; + for (APIChecker apiChecker : _apiAccessCheckers) { + try { + apiChecker.checkAccess(user, name); + } catch (Exception ex) { + isAllowed = false; + } + } + if (isAllowed) + responseList.add(_apiNameDiscoveryResponseMap.get(apiName)); + } } + response.setResponses(responseList); return response; } @Override - public Map getProperties() { - Map apiDiscoveryPropertyMap = new HashMap(); - apiDiscoveryPropertyMap.put("listApis", "15"); - return apiDiscoveryPropertyMap; + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(ListApisCmd.class); + return cmdList; } } From 3ec985f46f7f251e5fb47cc3f4aa89e57f349454 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:58:23 -0800 Subject: [PATCH 63/92] StaticRoleBased: commands.properties is actually cfg for this plugin Signed-off-by: Rohit Yadav --- .../acl/StaticRoleBasedAPIAccessChecker.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 55db2880664..16357846cba 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -21,15 +21,14 @@ import com.cloud.server.ManagementServer; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; +import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.ComponentLocator; -import com.cloud.utils.component.PluggableService; import javax.ejb.Local; import javax.naming.ConfigurationException; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -37,7 +36,7 @@ import org.apache.log4j.Logger; // This is the default API access checker that grab's the user's account // based on the account type, access is granted -@Local(value=APIChecker.class) +@Local(value = APIChecker.class) public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker { protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); @@ -49,7 +48,7 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC protected StaticRoleBasedAPIAccessChecker() { super(); - for (RoleType roleType: RoleType.values()) + for (RoleType roleType : RoleType.values()) s_roleBasedApisMap.put(roleType, new HashSet()); } @@ -57,6 +56,10 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC public boolean checkAccess(User user, String commandName) throws PermissionDeniedException { Account account = s_accountService.getAccount(user.getAccountId()); + if (account == null) { + throw new PermissionDeniedException("The account id=" + user.getAccountId() + "for user id=" + user.getId() + "is null"); + } + RoleType roleType = s_accountService.getRoleType(account); boolean isAllowed = s_roleBasedApisMap.get(roleType).contains(commandName); if (!isAllowed) { @@ -71,32 +74,26 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC // Read command properties files to build the static map per role. ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); - s_accountService = locator.getManager(AccountService.class); - List services = locator.getAllPluggableServices(); - services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); + processMapping(PropertiesUtil.processConfigFile(new String[] + {"commands.properties"})); - for (PluggableService service : services) { - processConfigFiles(service.getProperties(), service.getClass().toString()); - s_logger.info("Processed role based acl for: " + service.toString()); - } return true; } - private void processConfigFiles(Map configMap, String service) { - for (Map.Entry entry: configMap.entrySet()) { + private void processMapping(Map configMap) { + for (Map.Entry entry : configMap.entrySet()) { String apiName = entry.getKey(); String roleMask = entry.getValue(); try { short cmdPermissions = Short.parseShort(roleMask); - for (RoleType roleType: RoleType.values()) { + for (RoleType roleType : RoleType.values()) { if ((cmdPermissions & roleType.getValue()) != 0) s_roleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { - s_logger.info("Malformed getProperties() value for service: " + service - + " for entry: " + entry.toString()); + s_logger.info("Malformed key=value pair for entry: " + entry.toString()); } } } From bca2c928e87ce81f54dccb918564714189b7d46e Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 18:59:01 -0800 Subject: [PATCH 64/92] PluggableService: Fix interface definition Signed-off-by: Rohit Yadav --- .../server/ManagementServerSimulatorImpl.java | 11 ++++++----- .../network/element/CiscoNexusVSMElement.java | 11 ++++++++--- .../element/F5ExternalLoadBalancerElement.java | 15 ++++++++++++--- .../JuniperSRXExternalFirewallElement.java | 14 +++++++++++--- .../network/element/MidokuraMidonetElement.java | 9 ++------- .../cloud/network/element/NetscalerElement.java | 12 +++++++++--- .../cloud/network/element/NiciraNvpElement.java | 10 +++++++--- .../network/element/VirtualRouterElement.java | 10 +++++++--- .../com/cloud/server/ManagementServerExtImpl.java | 6 +++--- .../com/cloud/server/ManagementServerImpl.java | 6 +++--- 10 files changed, 68 insertions(+), 36 deletions(-) diff --git a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java index 44ab26a020a..c639a556cb7 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/server/ManagementServerSimulatorImpl.java @@ -17,16 +17,17 @@ package com.cloud.server; +import com.cloud.api.commands.ConfigureSimulator; import com.cloud.utils.PropertiesUtil; +import java.util.List; import java.util.Map; public class ManagementServerSimulatorImpl extends ManagementServerExtImpl { @Override - public Map getProperties() { - Map apiNameRoleMaskMapping = super.getProperties(); - apiNameRoleMaskMapping.putAll(PropertiesUtil.processConfigFile(new String[] - {"commands-simulator.properties"})); - return apiNameRoleMaskMapping; + public List> getCommands() { + List> cmdList = super.getCommands(); + cmdList.add(ConfigureSimulator.class); + return cmdList; } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java index 2cf87877859..68388a6fb18 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -17,6 +17,7 @@ package com.cloud.network.element; +import java.lang.Class; import java.lang.String; import java.util.List; import java.util.Map; @@ -239,8 +240,12 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "cisconexusvsm_commands.properties" }); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(ListCiscoNexusVSMsCmd.class); + cmdList.add(EnableCiscoNexusVSMCmd.class); + cmdList.add(DisableCiscoNexusVSMCmd.class); + cmdList.add(DeleteCiscoNexusVSMCmd.class); + return cmdList; } } diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 438498ff38c..b9739ec21df 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.Class; import java.lang.String; import java.util.ArrayList; import java.util.HashMap; @@ -262,9 +263,17 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "f5bigip_commands.properties" }); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddExternalLoadBalancerCmd.class); + cmdList.add(AddF5LoadBalancerCmd.class); + cmdList.add(ConfigureF5LoadBalancerCmd.class); + cmdList.add(DeleteExternalLoadBalancerCmd.class); + cmdList.add(DeleteF5LoadBalancerCmd.class); + cmdList.add(ListExternalLoadBalancersCmd.class); + cmdList.add(ListF5LoadBalancerNetworksCmd.class); + cmdList.add(ListF5LoadBalancersCmd.class); + return cmdList; } @Override diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 55722ae23ab..6e9d32daa99 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -404,9 +404,17 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "junipersrx_commands.properties"}); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddExternalFirewallCmd.class); + cmdList.add(AddSrxFirewallCmd.class); + cmdList.add(ConfigureSrxFirewallCmd.class); + cmdList.add(DeleteExternalFirewallCmd.class); + cmdList.add(DeleteSrxFirewallCmd.class); + cmdList.add(ListExternalFirewallsCmd.class); + cmdList.add(ListSrxFirewallNetworksCmd.class); + cmdList.add(ListSrxFirewallsCmd.class); + return cmdList; } @Override diff --git a/plugins/network-elements/midokura-midonet/src/com/cloud/network/element/MidokuraMidonetElement.java b/plugins/network-elements/midokura-midonet/src/com/cloud/network/element/MidokuraMidonetElement.java index 56734669020..a45c5c0a47c 100644 --- a/plugins/network-elements/midokura-midonet/src/com/cloud/network/element/MidokuraMidonetElement.java +++ b/plugins/network-elements/midokura-midonet/src/com/cloud/network/element/MidokuraMidonetElement.java @@ -38,15 +38,10 @@ import com.cloud.vm.VirtualMachineProfile; import org.apache.log4j.Logger; import javax.ejb.Local; +import java.lang.Class; import java.util.Map; import java.util.Set; -/** - * User: tomoe - * Date: 8/8/12 - * Time: 1:38 PM - */ - @Local(value = NetworkElement.class) public class MidokuraMidonetElement extends AdapterBase implements ConnectivityProvider, PluggableService { private static final Logger s_logger = Logger.getLogger(MidokuraMidonetElement.class); @@ -126,7 +121,7 @@ public class MidokuraMidonetElement extends AdapterBase implements ConnectivityP } @Override - public String getPropertiesFile() { + public List> getCommands() { // TODO: implement this. return null; } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index ac1619ef1f8..a1782107e19 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.element; +import java.lang.Class; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; @@ -465,9 +466,14 @@ StaticNatServiceProvider { } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "netscalerloadbalancer_commands.properties" }); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddNetscalerLoadBalancerCmd.class); + cmdList.add(ConfigureNetscalerLoadBalancerCmd.class); + cmdList.add(DeleteNetscalerLoadBalancerCmd.class); + cmdList.add(ListNetscalerLoadBalancerNetworksCmd.class); + cmdList.add(ListNetscalerLoadBalancersCmd.class); + return cmdList; } @Override diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index 22fab500fdb..6bcaeeeb235 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -541,9 +541,13 @@ public class NiciraNvpElement extends AdapterBase implements } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "nicira-nvp_commands.properties" }); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddNiciraNvpDeviceCmd.class); + cmdList.add(DeleteNiciraNvpDeviceCmd.class); + cmdList.add(ListNiciraNvpDeviceNetworksCmd.class); + cmdList.add(ListNiciraNvpDevicesCmd.class); + return cmdList; } @Override diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 823b74f269b..02a239e72d9 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -26,6 +26,7 @@ import javax.ejb.Local; import com.cloud.utils.PropertiesUtil; import org.apache.cloudstack.api.command.admin.router.ConfigureVirtualRouterElementCmd; +import org.apache.cloudstack.api.command.admin.router.CreateVirtualRouterElementCmd; import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; import org.apache.log4j.Logger; @@ -681,9 +682,12 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "virtualrouter_commands.properties" }); + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(CreateVirtualRouterElementCmd.class); + cmdList.add(ConfigureVirtualRouterElementCmd.class); + cmdList.add(ListVirtualRouterElementsCmd.class); + return cmdList; } @Override diff --git a/server/src/com/cloud/server/ManagementServerExtImpl.java b/server/src/com/cloud/server/ManagementServerExtImpl.java index 8a59d2f9c1c..c8c188b38ad 100644 --- a/server/src/com/cloud/server/ManagementServerExtImpl.java +++ b/server/src/com/cloud/server/ManagementServerExtImpl.java @@ -207,9 +207,9 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "commands.properties", "commands-ext.properties" }); + public List> getCommands() { + //TODO: Add api cmd classes + return null; } private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ, boolean adjustToDayStart) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 79ad759dd0b..bf105506b23 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2298,9 +2298,9 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public Map getProperties() { - return PropertiesUtil.processConfigFile(new String[] - { "commands.properties" }); + public List> getCommands() { + //TODO: Add cmd classes + return null; } protected class EventPurgeTask implements Runnable { From c5984278ca95b24e8f0ff9d8bfd8bbde14a42643 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 19:00:20 -0800 Subject: [PATCH 65/92] apidoc: Fix apidoc Signed-off-by: Rohit Yadav --- tools/apidoc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml index bc7411f7013..6b159ff54eb 100644 --- a/tools/apidoc/pom.xml +++ b/tools/apidoc/pom.xml @@ -57,7 +57,7 @@ ${client.config.jars} ./target -f - ${client.config.conf}/commands.properties,${client.config.conf}/commands-ext.properties,${client.config.conf}/virtualrouter_commands.properties,${client.config.conf}/nicira-nvp_commands.properties + ${client.config.conf}/commands.properties From d8b04507d8285ac5201bcae1409aeacb2de2fb95 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 19:36:27 -0800 Subject: [PATCH 66/92] maven: exclude rat license checking for devcloud advanced cfg Signed-off-by: Rohit Yadav --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index aad124b0baf..f752d266a9d 100644 --- a/pom.xml +++ b/pom.xml @@ -245,7 +245,9 @@ scripts/vm/systemvm/id_rsa.cloud tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf tools/devcloud/devcloud.cfg + tools/devcloud/devcloud-advanced.cfg tools/devcloud-kvm/devcloud-kvm.cfg + tools/devcloud-kvm/devcloud-kvm-advanced.cfg ui/lib/flot/jquery.colorhelpers.js ui/lib/flot/jquery.flot.crosshair.js ui/lib/flot/jquery.flot.fillbetween.js From 7374056493ab5beccd514d115185f73feeead223 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 14 Jan 2013 20:55:13 -0800 Subject: [PATCH 67/92] Revert "apidoc: Remove api discovery from toc" This reverts commit 66514c00efad5c93a2b0996f1e79222cbff9bd48. --- tools/apidoc/gen_toc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 0b281a29c1d..7739aea633f 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -129,6 +129,7 @@ known_categories = { 'AutoScale': 'AutoScale', 'Counter': 'AutoScale', 'Condition': 'AutoScale', + 'Api': 'API Discovery', } From 0412cb8d9225b9c9fcc2ed4cfb94e702a0ea9c70 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Tue, 15 Jan 2013 02:16:25 +0000 Subject: [PATCH 68/92] Summary: Edit devcloud cfg files for advanced networking, add comments --- tools/devcloud/devcloud-advanced.cfg | 5 +- .../devcloud-advanced_internal-mgt.cfg | 124 ++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 tools/devcloud/devcloud-advanced_internal-mgt.cfg diff --git a/tools/devcloud/devcloud-advanced.cfg b/tools/devcloud/devcloud-advanced.cfg index ad4cdda1912..cfbc815dc69 100644 --- a/tools/devcloud/devcloud-advanced.cfg +++ b/tools/devcloud/devcloud-advanced.cfg @@ -1,3 +1,6 @@ +# This configuration is meant for running advanced networking, with management server on the laptop. +# It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' + { "zones": [ { @@ -81,7 +84,7 @@ "gateway": "192.168.56.1" } ], - "internaldns1": "8.8.4.4", + "internaldns1": "192.168.56.10", "secondaryStorages": [ { "url": "nfs://192.168.56.10:/opt/storage/secondary" diff --git a/tools/devcloud/devcloud-advanced_internal-mgt.cfg b/tools/devcloud/devcloud-advanced_internal-mgt.cfg new file mode 100644 index 00000000000..e360b6b9e37 --- /dev/null +++ b/tools/devcloud/devcloud-advanced_internal-mgt.cfg @@ -0,0 +1,124 @@ +# This config is designed to run as an advanced network, with management server in devcloud +# It also requires an 'apt-get install dnsmasq' to run a resolver in devcloud for internal dns + +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "testzone", + "guestcidraddress": "10.1.1.0/24", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "vlan": "3900-4000", + "name": "eth0", + "traffictypes": [ + { + "xen": "Pool-wide network associated with eth0", + "typ": "Management" + }, + { + "xen": "Pool-wide network associated with eth0", + "typ": "Guest" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "VpcVirtualRouter" + } + ] + }, + { + "broadcastdomainrange": "Zone", + "name": "eth1", + "traffictypes": [ + { + "xen": "Pool-wide network associated with eth1", + "typ": "Public" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + } + ] + } + ], + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "untagged", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "testpod", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "testcluster", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10:/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "127.0.0.1", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "192.168.56.10", + "port": 8096 + } + ], + "globalConfig": [ + { + "name": "host", + "value": "192.168.56.10" + } + ] +} From 510450b11b611fb0112771ae56586fcbed70ecc6 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Tue, 15 Jan 2013 12:14:57 +0100 Subject: [PATCH 69/92] Remove duplicate systemUse clausule when fetching service offerings. A couple of lines back there is: if (isSystem != null) { sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem); } So it was set redundantly, this can be removed. --- server/src/com/cloud/server/ManagementServerImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index bf105506b23..4efae630f36 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -760,7 +760,6 @@ public class ManagementServerImpl implements ManagementServer { sc.addAnd("vm_type", SearchCriteria.Op.EQ, vmTypeStr); } - sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem); sc.addAnd("removed", SearchCriteria.Op.NULL); return _offeringsDao.search(sc, searchFilter); From 95222cdb6d07b16c89b9deb7d12eecbc89d8ce94 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Tue, 15 Jan 2013 13:25:48 +0100 Subject: [PATCH 70/92] Templates: Add Ubuntu 12.04 to the templates Although I still think the templates aren't well maintained, I just added 12.04 since this is an LTS and people probably want it in the list of templates. This system should be more generic I think though. --- .../hypervisor/kvm/resource/KVMGuestOsMapper.java | 2 ++ setup/db/templates.kvm.sql | 11 ++++++----- setup/db/templates.sql | 7 +++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java index b4771cacb10..bd1573c9fa9 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java @@ -91,6 +91,8 @@ public class KVMGuestOsMapper { s_mapper.put("Fedora 10", "Fedora 10"); s_mapper.put("Fedora 9", "Fedora 9"); s_mapper.put("Fedora 8", "Fedora 8"); + s_mapper.put("Ubuntu 12.04 (32-bit)", "Ubuntu 12.04"); + s_mapper.put("Ubuntu 12.04 (64-bit)", "Ubuntu 12.04"); s_mapper.put("Ubuntu 10.04 (32-bit)", "Ubuntu 10.04"); s_mapper.put("Ubuntu 10.04 (64-bit)", "Ubuntu 10.04"); s_mapper.put("Ubuntu 10.10 (32-bit)", "Ubuntu 10.10"); diff --git a/setup/db/templates.kvm.sql b/setup/db/templates.kvm.sql index bc275f5285d..8a5582540af 100644 --- a/setup/db/templates.kvm.sql +++ b/setup/db/templates.kvm.sql @@ -51,11 +51,12 @@ INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (U INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 5, 'Fedora 10', 'Fedora 10'); INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 5, 'Fedora 9', 'Fedora 9'); INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 5, 'Fedora 8', 'Fedora 8'); -INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Ubuntu 10.04', 'Ubuntu 10.04'); -INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Ubuntu 9.10', 'Ubuntu 9.10'); -INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Ubuntu 9.04', 'Ubuntu 9.04'); -INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Ubuntu 8.10', 'Ubuntu 8.10'); -INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Ubuntu 8.04', 'Ubuntu 8.04'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 12.04', 'Ubuntu 12.04'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 10.04', 'Ubuntu 10.04'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 9.10', 'Ubuntu 9.10'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 9.04', 'Ubuntu 9.04'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 8.10', 'Ubuntu 8.10'); +INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 10, 'Ubuntu 8.04', 'Ubuntu 8.04'); INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Debian Squeeze', 'Debian Squeeze'); INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Debian Lenny', 'Debian Lenny'); INSERT INTO `cloud`.`guest_os` (uuid, category_id, name, display_name) VALUES (UUID(), 2, 'Debian Etch', 'Debian Etch'); diff --git a/setup/db/templates.sql b/setup/db/templates.sql index 3867d4fe9d2..9980b159630 100755 --- a/setup/db/templates.sql +++ b/setup/db/templates.sql @@ -211,6 +211,8 @@ INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (159 INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (160, UUID(), 6, 'Windows PV'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (161, UUID(), 1, 'CentOS 5.7 (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (162, UUID(), 1, 'CentOS 5.7 (64-bit)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (200, UUID(), 1, 'Other CentOS (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (201, UUID(), 1, 'Other CentOS (64-bit)'); @@ -370,11 +372,13 @@ INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Debian GNU/Linux 4(32-bit)', 73); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Debian GNU/Linux 4(64-bit)', 74); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 12.04 (32-bit)', 162); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 10.04 (32-bit)', 121); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 9.10 (32-bit)', 122); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 9.04 (32-bit)', 123); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 8.10 (32-bit)', 124); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 8.04 (32-bit)', 125); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 12.04 (64-bit)', 163); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 10.04 (64-bit)', 126); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 9.10 (64-bit)', 127); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Ubuntu 9.04 (64-bit)', 128); @@ -385,6 +389,7 @@ INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Other Ubuntu Linux (32-bit)', 59); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Other Ubuntu (64-bit)', 100); + INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Other 2.6x Linux (32-bit)', 75); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Other 2.6x Linux (64-bit)', 76); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Other Linux (32-bit)', 98); @@ -454,6 +459,8 @@ INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Fedora 8', 120); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 10.04', 121); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 10.04', 126); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 10.04', 162); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 10.04', 163); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 9.10', 122); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 9.10', 127); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ('KVM', 'Ubuntu 9.04', 123); From 04b14ab03f089f333f4dbf7058e951a23c12a28a Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 15 Jan 2013 19:27:24 +0530 Subject: [PATCH 71/92] Marvin: physical network label not carried through in the API The label associated with the hypervisor nic to isolate traffic types by Guest/Mgmt/Public/Storage was not passed in the marvin.traffictype object and sent through to mgmt server resulting in traffic types not being applied. Signed-off-by: Prasanna Santhanam --- tools/marvin/marvin/deployDataCenter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 7f8c0295ad8..ff3b6e6d0e0 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -258,10 +258,10 @@ class deployDataCenters(): traffic_type = addTrafficType.addTrafficTypeCmd() traffic_type.physicalnetworkid = physical_network_id traffic_type.traffictype = traffictype.typ - if traffictype.labeldict is not None: - traffic_type.kvmnetworklabel = traffictype.labeldict.kvm - traffic_type.xennetworklabel = traffictype.labeldict.xen - traffic_type.vmwarenetworklabel = traffictype.labeldict.vmware + traffic_type.kvmnetworklabel = traffictype.kvm if traffictype.kvm is not None else None + traffic_type.xennetworklabel = traffictype.xen if traffictype.xen is not None else None + traffictype.vmwarenetworklabel = traffictype.vmware if traffictype.vmware is not None else None + traffictype.simulatorlabel = traffictype.simulator if traffictype.simulator is not None else None return self.apiClient.addTrafficType(traffic_type) def enableZone(self, zoneid, allocation_state="Enabled"): From bfd02c5db39ee2dad30d0edefb205b56a4248594 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 15 Jan 2013 19:36:30 +0530 Subject: [PATCH 72/92] traffic_type not traffictype Signed-off-by: Prasanna Santhanam --- tools/marvin/marvin/deployDataCenter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index ff3b6e6d0e0..e4f7eace9bd 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -260,8 +260,8 @@ class deployDataCenters(): traffic_type.traffictype = traffictype.typ traffic_type.kvmnetworklabel = traffictype.kvm if traffictype.kvm is not None else None traffic_type.xennetworklabel = traffictype.xen if traffictype.xen is not None else None - traffictype.vmwarenetworklabel = traffictype.vmware if traffictype.vmware is not None else None - traffictype.simulatorlabel = traffictype.simulator if traffictype.simulator is not None else None + traffic_type.vmwarenetworklabel = traffictype.vmware if traffictype.vmware is not None else None + traffic_type.simulatorlabel = traffictype.simulator if traffictype.simulator is not None else None return self.apiClient.addTrafficType(traffic_type) def enableZone(self, zoneid, allocation_state="Enabled"): From 8d0091d7e2e9b01df3af8deec14246f9eac1418e Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 15 Jan 2013 21:12:10 +0530 Subject: [PATCH 73/92] CLOUDSTACK-978:TypeError: instance.displayname is undefined while adding VM's to the LB rule --- ui/scripts/network.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 4103c3e2b6e..f3308bb5ba7 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -1259,12 +1259,16 @@ data.listvirtualmachinesresponse.virtualmachine : [], function(instance) { var nonAutoScale=0; + if(instance.displayname == null) + nonAutoScale = 1; + else{ if( instance.displayname.match(/AutoScale-LB-/)==null) nonAutoScale =1; else { if(instance.displayname.match(/AutoScale-LB-/).length) nonAutoScale =0; } + } var isActiveState= $.inArray(instance.state, ['Destroyed','Expunging']) == -1; return nonAutoScale && isActiveState; } @@ -2623,12 +2627,16 @@ function(instance) { //Hiding the autoScale VMs var nonAutoScale =0; + if(instance.displayname == null) + nonAutoScale = 1 + else { if(instance.displayname.match(/AutoScale-LB-/) == null) nonAutoScale = 1; else { if( instance.displayname.match(/AutoScale-LB-/).length) nonAutoScale =0; - } + } + } var isActiveState = $.inArray(instance.state, ['Destroyed','Expunging']) == -1; var notExisting = !$.grep(itemData, function(item) { return item.id == instance.id; From 101f64410adc944ea2f2b2ad9734c990c4fe0336 Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 15 Jan 2013 09:17:12 -0800 Subject: [PATCH 74/92] Do not allow add multiple VLANs or subnets into shared network CS allows to add multiple VLANs and subnets to a shared network, but it doesn't really work, for example , vm on second VLAN or subnet cannot get IP through DHCP This patch will not allow to add mulitple VLANS or subnets into shared network CLOUDSTACK-982:Do not allow add multiple VLANs or subnets into shared network --- .../ConfigurationManagerImpl.java | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 2e20c134b54..b21c5a38bb7 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2071,7 +2071,12 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Long projectId = cmd.getProjectId(); Long domainId = cmd.getDomainId(); Account vlanOwner = null; - + + // if end ip is not specified, default it to startIp + if (endIP == null && startIP != null) { + endIP = startIP; + } + if (projectId != null) { if (accountName != null) { throw new InvalidParameterValueException("Account and projectId are mutually exclusive"); @@ -2176,6 +2181,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Nework id is required for Direct vlan creation "); } networkId = network.getId(); + zoneId = network.getDataCenterId(); } } else if (network.getGuestType() == null || network.getGuestType() == Network.GuestType.Isolated) { throw new InvalidParameterValueException("Can't create direct vlan for network id=" + networkId + " with type: " + network.getGuestType()); @@ -2192,34 +2198,34 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura endIP = startIP; } - if (forVirtualNetwork || zone.getNetworkType() == DataCenter.NetworkType.Basic || zone.isSecurityGroupEnabled()) { - if (vlanGateway == null || vlanNetmask == null || zoneId == null) { - throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); - } - } else { - // check if startIp and endIp belong to network Cidr - String networkCidr = network.getCidr(); - String networkGateway = network.getGateway(); - Long networkZoneId = network.getDataCenterId(); - String networkNetmask = NetUtils.getCidrNetmask(networkCidr); - - // Check if ip addresses are in network range - if (!NetUtils.sameSubnet(startIP, networkGateway, networkNetmask)) { - throw new InvalidParameterValueException("Start ip is not in network cidr: " + networkCidr); - } - - if (endIP != null) { - if (!NetUtils.sameSubnet(endIP, networkGateway, networkNetmask)) { - throw new InvalidParameterValueException("End ip is not in network cidr: " + networkCidr); + if ( zone.getNetworkType() == DataCenter.NetworkType.Advanced ) { + if (network.getTrafficType() == TrafficType.Guest) { + if (network.getGuestType() != GuestType.Shared) { + throw new InvalidParameterValueException("Can execute createVLANIpRanges on shared guest network, but type of this guest network " + + network.getId() + " is " + network.getGuestType()); } + List vlans = _vlanDao.listVlansByNetworkId(network.getId()); + if ( vlans != null && vlans.size() > 0 ) { + VlanVO vlan = vlans.get(0); + if ( vlanId == null ) { + vlanId = vlan.getVlanTag(); + } else if ( vlan.getVlanTag() != vlanId ) { + throw new InvalidParameterValueException("there is already one vlan " + vlan.getVlanTag() + " on network :" + + + network.getId() + ", only one vlan is allowed on guest network"); + } + vlanGateway = vlan.getVlanGateway(); + vlanNetmask = vlan.getVlanNetmask(); + } + } else if (network.getTrafficType() == TrafficType.Management) { + throw new InvalidParameterValueException("Cannot execute createVLANIpRanges on management network"); } - - // set gateway, netmask, zone from network object - vlanGateway = networkGateway; - vlanNetmask = networkNetmask; - zoneId = networkZoneId; } + if (vlanGateway == null || vlanNetmask == null || zoneId == null) { + throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); + } + + // if it's an account specific range, associate ip address list to the account boolean associateIpRangeToAccount = false; From a6b902763071c70f6e530ea4b3440f5fb030090b Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 15 Jan 2013 11:15:42 -0800 Subject: [PATCH 75/92] default Security rule doesn't apply to system VMs since nic.getIsolationUri is not set use to.setSecurityGroupEnabled to indicate if securitygroup is enabled on this NIC CLOUDSTACK-983: default Security rule doesn't apply to system VMs --- .../hypervisor/kvm/resource/LibvirtComputingResource.java | 5 ++--- .../cloud/hypervisor/xen/resource/CitrixResourceBase.java | 6 ++++-- server/src/com/cloud/hypervisor/HypervisorGuruBase.java | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) 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 b52e2d8a0b0..6b5f6df3bff 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 @@ -2901,9 +2901,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements NicTO[] nics = vmSpec.getNics(); for (NicTO nic : nics) { - if (nic.getIsolationUri() != null - && nic.getIsolationUri().getScheme() - .equalsIgnoreCase(IsolationType.Ec2.toString())) { + if (nic.isSecurityGroupEnabled() || ( nic.getIsolationUri() != null + && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString()))) { if (vmSpec.getType() != VirtualMachine.Type.User) { default_network_rules_for_systemvm(conn, vmName); break; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 36a12b1b4fa..66a5918b177 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1324,7 +1324,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe NicTO[] nics = vmSpec.getNics(); boolean secGrpEnabled = false; for (NicTO nic : nics) { - if (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + if (nic.isSecurityGroupEnabled() || (nic.getIsolationUri() != null + && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString()))) { secGrpEnabled = true; break; } @@ -1342,7 +1343,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe //For user vm, program the rules for each nic if the isolation uri scheme is ec2 NicTO[] nics = vmSpec.getNics(); for (NicTO nic : nics) { - if (nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { + if ( nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null + && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) { result = callHostPlugin(conn, "vmops", "default_network_rules", "vmName", vmName, "vmIP", nic.getIp(), "vmMAC", nic.getMac(), "vmID", Long.toString(vmSpec.getId())); if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index 242852fc681..2efe6d35098 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -62,6 +62,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis to.setIsolationuri(profile.getIsolationUri()); to.setNetworkRateMbps(profile.getNetworkRate()); to.setName(profile.getName()); + to.setSecurityGroupEnabled(profile.isSecurityGroupEnabled()); // Workaround to make sure the TO has the UUID we need for Niciri integration NicVO nicVO = _nicDao.findById(profile.getId()); From 7f1486e2dc9f612af94901ab8804e24c48b8122b Mon Sep 17 00:00:00 2001 From: Min Chen Date: Tue, 15 Jan 2013 11:40:49 -0800 Subject: [PATCH 76/92] We need to catch PermissionDeniedException in checking if command is available to an user. --- server/src/com/cloud/api/ApiServer.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 4d60215b276..e106f0322ad 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -549,7 +549,10 @@ public class ApiServer implements HttpRequestHandler { // if userId not null, that mean that user is logged in if (userId != null) { User user = ApiDBUtils.findUserById(userId); - if (!isCommandAvailable(user, commandName)) { + try{ + checkCommandAvailable(user, commandName); + } + catch (PermissionDeniedException ex){ s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); } @@ -649,7 +652,10 @@ public class ApiServer implements HttpRequestHandler { UserContext.updateContext(user.getId(), account, null); - if (!isCommandAvailable(user, commandName)) { + try{ + checkCommandAvailable(user, commandName); + } + catch (PermissionDeniedException ex){ s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user"); throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); } @@ -780,7 +786,7 @@ public class ApiServer implements HttpRequestHandler { return true; } - private boolean isCommandAvailable(User user, String commandName) throws PermissionDeniedException { + private void checkCommandAvailable(User user, String commandName) throws PermissionDeniedException { if (user == null) { throw new PermissionDeniedException("User is null for role based API access check for command" + commandName); } @@ -788,7 +794,6 @@ public class ApiServer implements HttpRequestHandler { for (APIChecker apiChecker : _apiAccessCheckers) { apiChecker.checkAccess(user, commandName); } - return true; } private Class getCmdClass(String cmdName) { From 354c56a9887cb1a3bfdfbdfa00ce34bc96ee8037 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Tue, 15 Jan 2013 14:21:44 -0700 Subject: [PATCH 77/92] Summary: Adding apache license headers to various devcloud configs Signed-off-by: Marcus Sorensen 1358284904 -0700 --- tools/devcloud-kvm/devcloud-kvm-advanced.cfg | 19 ++++++++++++++++++ tools/devcloud-kvm/devcloud-kvm.cfg | 20 +++++++++++++++++++ tools/devcloud/devcloud-advanced.cfg | 17 ++++++++++++++++ .../devcloud-advanced_internal-mgt.cfg | 17 ++++++++++++++++ tools/devcloud/devcloud.cfg | 18 +++++++++++++++++ 5 files changed, 91 insertions(+) diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg index 1110863d848..10cbce00779 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -1,3 +1,22 @@ +# 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. +# + + { "zones": [ { diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg index 47a128fea14..b3f048aac97 100644 --- a/tools/devcloud-kvm/devcloud-kvm.cfg +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -1,3 +1,23 @@ +# 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. +# +# This is a stock devcloud config converted from the file +# tools/devcloud/devcloud.cfg. + { "zones": [ { diff --git a/tools/devcloud/devcloud-advanced.cfg b/tools/devcloud/devcloud-advanced.cfg index cfbc815dc69..75c3a4f7147 100644 --- a/tools/devcloud/devcloud-advanced.cfg +++ b/tools/devcloud/devcloud-advanced.cfg @@ -1,3 +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. +# # This configuration is meant for running advanced networking, with management server on the laptop. # It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' diff --git a/tools/devcloud/devcloud-advanced_internal-mgt.cfg b/tools/devcloud/devcloud-advanced_internal-mgt.cfg index e360b6b9e37..a1a8cb54722 100644 --- a/tools/devcloud/devcloud-advanced_internal-mgt.cfg +++ b/tools/devcloud/devcloud-advanced_internal-mgt.cfg @@ -1,3 +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. +# # This config is designed to run as an advanced network, with management server in devcloud # It also requires an 'apt-get install dnsmasq' to run a resolver in devcloud for internal dns diff --git a/tools/devcloud/devcloud.cfg b/tools/devcloud/devcloud.cfg index 8d296eb7b98..c41f8bcef58 100644 --- a/tools/devcloud/devcloud.cfg +++ b/tools/devcloud/devcloud.cfg @@ -1,3 +1,21 @@ +# 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. +# + { "zones": [ { From f7b8ad5e8bc97c01db7ece539a490e929b050f70 Mon Sep 17 00:00:00 2001 From: Chip Childers Date: Tue, 15 Jan 2013 16:28:16 -0500 Subject: [PATCH 78/92] Updating the RAT exclude list to no longer exclude devcloud .cfg files Signed-off-by: Chip Childers --- pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pom.xml b/pom.xml index f752d266a9d..c440a660322 100644 --- a/pom.xml +++ b/pom.xml @@ -244,10 +244,6 @@ dist/console-proxy/js/jquery.js scripts/vm/systemvm/id_rsa.cloud tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf - tools/devcloud/devcloud.cfg - tools/devcloud/devcloud-advanced.cfg - tools/devcloud-kvm/devcloud-kvm.cfg - tools/devcloud-kvm/devcloud-kvm-advanced.cfg ui/lib/flot/jquery.colorhelpers.js ui/lib/flot/jquery.flot.crosshair.js ui/lib/flot/jquery.flot.fillbetween.js From 47251b51a7bad37c66c0fa460723ede6a3e7b0a9 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Tue, 15 Jan 2013 14:26:30 -0700 Subject: [PATCH 79/92] Summary: Allow ssh keypairs to be created if developer flag set and user ! cloud Detail: Previously in the code we allowed the configuration to create ssh keypairs and put them in the configuration table so that systemvms could have ssh key auth and work properly if the user was 'cloud' or if the developer configuration item was set to true. It got changed to requiring both the cloud user and the developer flag (using an || on a negative) somwhere along the way. This changes it back to && on a negative to allow us to run as non-cloud users with the dev flag set, and for cloud to deploy properly without the developer flag. Signed-off-by: Marcus Sorensen 1358285190 -0700 --- server/src/com/cloud/server/ConfigurationServerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index b25c63f6d7f..7e5f42445d5 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -549,7 +549,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { String username = System.getProperty("user.name"); Boolean devel = Boolean.valueOf(_configDao.getValue("developer")); - if (!username.equalsIgnoreCase("cloud") || !devel) { + if (!username.equalsIgnoreCase("cloud") && !devel) { s_logger.warn("Systemvm keypairs could not be set. Management server should be run as cloud user, or in development mode."); return; } From c32dbec468b176d4a6019d9e642eb9adc593bf36 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 15 Jan 2013 14:51:59 -0800 Subject: [PATCH 80/92] CLOUDSTACK-985: Revert "Using different MAC for a pair of redundant routers" The different MAC address for a pair of redundant router have issues when short time network outrage happened. When this happened: 1. BACKUP(r-2) cannot receive the broadcast from MASTER(r-1). 2. Then r-2 would announce it's MASTER after 3 seconds, and send gratuitous ARP to the gateway of public ip(usually a rack router). 3. The gateway of public ip would update it's ARP cache to associate the public ip of the network to the MAC of r-2. 4. In the meantime, r-1 still sending out VRRP broadcast(due to network issue, the broadcast never arrived at r-2), and acting as MASTER. 5. After network outrage, r-2 would receive the higher priority VRRP broadcast from MASTER again, then receded as BACKUP. 6. But the public gateway would still associate public ip with MAC of r-2, thus caused the issue. r-1 would no longer able to receive any packets from public network. And there is no way for r-1 to send gratuitous ARP again, because it's always consider itself as MASTER, no state changed, and no hook existed for receiving lower priority broadcast. So I would revert this change, and introduce another commit to ensure the newly create redundant router would share the same MAC as the first one. This reverts commit 9f257aa60b62f24193bba3f7c902e7779632e01e. --- .../VirtualNetworkApplianceManagerImpl.java | 26 ++++--------------- server/src/com/cloud/vm/dao/NicDao.java | 2 -- server/src/com/cloud/vm/dao/NicDaoImpl.java | 8 ------ 3 files changed, 5 insertions(+), 31 deletions(-) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 492e1dc20b1..c8fd86e821c 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1469,31 +1469,15 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian offeringId = _offering.getId(); } + PublicIp sourceNatIp = null; + if (publicNetwork) { + sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork); + } + // 3) deploy virtual router(s) int count = routerCount - routers.size(); DeploymentPlan plan = planAndRouters.first(); for (int i = 0; i < count; i++) { - PublicIp sourceNatIp = null; - if (publicNetwork) { - int failCount = 0; - // Generate different MAC for VR - while (sourceNatIp == null) { - sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork); - NicVO nic = _nicDao.findByMacAddress(sourceNatIp.getMacAddress()); - // We got duplicate MAC here, so regenerate the mac - if (nic != null) { - s_logger.debug("Failed to find a different mac for redundant router. Try again. The current mac is " + sourceNatIp.getMacAddress()); - sourceNatIp = null; - failCount ++; - } - //Prevent infinite loop - if (failCount > 3) { - s_logger.error("Failed to find a different mac for redundant router! Abort operation!"); - throw new InsufficientAddressCapacityException("Failed to find a different mac for redundant router", null, offeringId); - } - } - } - List> networks = createRouterNetworks(owner, isRedundant, plan, guestNetwork, new Pair(publicNetwork, sourceNatIp)); //don't start the router as we are holding the network lock that needs to be released at the end of router allocation diff --git a/server/src/com/cloud/vm/dao/NicDao.java b/server/src/com/cloud/vm/dao/NicDao.java index af3c7b379c1..762048b65bf 100644 --- a/server/src/com/cloud/vm/dao/NicDao.java +++ b/server/src/com/cloud/vm/dao/NicDao.java @@ -58,6 +58,4 @@ public interface NicDao extends GenericDao { NicVO findByNetworkIdInstanceIdAndBroadcastUri(long networkId, long instanceId, String broadcastUri); NicVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId, long instanceId, String ip4Address); - - NicVO findByMacAddress(String macAddress); } diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java b/server/src/com/cloud/vm/dao/NicDaoImpl.java index 00da2eb96a4..3cd7fa6b488 100644 --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java @@ -50,7 +50,6 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { AllFieldsSearch.and("address", AllFieldsSearch.entity().getIp4Address(), Op.EQ); AllFieldsSearch.and("isDefault", AllFieldsSearch.entity().isDefaultNic(), Op.EQ); AllFieldsSearch.and("broadcastUri", AllFieldsSearch.entity().getBroadcastUri(), Op.EQ); - AllFieldsSearch.and("macAddress", AllFieldsSearch.entity().getMacAddress(), Op.EQ); AllFieldsSearch.done(); IpSearch = createSearchBuilder(String.class); @@ -200,11 +199,4 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { sc.setParameters("address", ip4Address); return findOneBy(sc); } - - @Override - public NicVO findByMacAddress(String macAddress) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("macAddress", macAddress); - return findOneBy(sc); - } } From 4f889bd426ea841918b570bb008cf5e348715730 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 15 Jan 2013 15:22:41 -0800 Subject: [PATCH 81/92] CLOUDSTACK-985: Make sure RvR would always have same MAC address Even with newly created RvR using "restartNetwork&cleanup=false" API. --- .../network/router/VirtualNetworkApplianceManagerImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c8fd86e821c..717da054ac5 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1699,6 +1699,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } NetworkOfferingVO publicOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork).get(0); List publicNetworks = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false); + String publicIp = defaultNic.getIp4Address(); + // We want to use the identical MAC address for RvR on public interface if possible + NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetworks.get(0).getId()); + if (peerNic != null) { + s_logger.info("Use same MAC as previous RvR, the MAC is " + peerNic.getMacAddress()); + defaultNic.setMacAddress(peerNic.getMacAddress()); + } networks.add(new Pair(publicNetworks.get(0), defaultNic)); } From f6a8b45de52ad57646adb71dc55ddf3ee9dbd194 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 15 Jan 2013 16:06:21 -0800 Subject: [PATCH 82/92] ApiDiscovery: Use UserContext getCallerUser, do a lazy eval to get account service Impl. and use UserContext to get User. CloudStack's @Inject is horrible, it may sometimes fail to inject account service during startup. Do a lazy injection using ComponentLocator when needed. Signed-off-by: Rohit Yadav --- api/src/com/cloud/user/UserContext.java | 4 ++ .../command/user/discovery/ListApisCmd.java | 8 +--- .../discovery/ApiDiscoveryServiceImpl.java | 41 +++++++++---------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/api/src/com/cloud/user/UserContext.java b/api/src/com/cloud/user/UserContext.java index b140728e596..539e11812af 100644 --- a/api/src/com/cloud/user/UserContext.java +++ b/api/src/com/cloud/user/UserContext.java @@ -50,6 +50,10 @@ public class UserContext { return userId; } + public User getCallerUser() { + return _accountMgr.getActiveUser(userId); + } + public void setCallerUserId(long userId) { this.userId = userId; } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index 132416bac05..bad7ca7b5f6 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,11 +16,8 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; -import com.cloud.user.AccountService; import com.cloud.user.User; import com.cloud.user.UserContext; -import com.cloud.utils.component.Inject; -import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -42,16 +39,13 @@ public class ListApisCmd extends BaseCmd { @PlugService ApiDiscoveryService _apiDiscoveryService; - @Inject - private AccountService _accountService; - @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="API name") private String name; @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - User user = _accountService.getActiveUser(UserContext.current().getCallerUserId()); + User user = UserContext.current().getCallerUser(); ListResponse response = (ListResponse) _apiDiscoveryService.listApis(user, name); if (response == null) { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find an api by that name or process any apis"); 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 7e2ed17ecdc..f06e2005552 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -17,17 +17,13 @@ package org.apache.cloudstack.discovery; import com.cloud.serializer.Param; -import com.cloud.server.ManagementServer; import com.cloud.user.User; import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; -import com.cloud.utils.component.Inject; -import com.cloud.utils.component.PluggableService; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.acl.APIChecker; -import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -54,16 +50,14 @@ import java.util.Set; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - @Inject(adapter = APIChecker.class) - protected Adapters _apiAccessCheckers; - - private static Map _apiNameDiscoveryResponseMap = null; + protected static Adapters s_apiAccessCheckers = null; + private static Map s_apiNameDiscoveryResponseMap = null; protected ApiDiscoveryServiceImpl() { super(); - if (_apiNameDiscoveryResponseMap == null) { + if (s_apiNameDiscoveryResponseMap == null) { long startTime = System.nanoTime(); - _apiNameDiscoveryResponseMap = new HashMap(); + s_apiNameDiscoveryResponseMap = new HashMap(); cacheResponseMap(); long endTime = System.nanoTime(); s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms"); @@ -142,11 +136,11 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } } response.setObjectName("api"); - _apiNameDiscoveryResponseMap.put(apiName, response); + s_apiNameDiscoveryResponseMap.put(apiName, response); } - for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { - ApiDiscoveryResponse response = _apiNameDiscoveryResponseMap.get(apiName); + for (String apiName : s_apiNameDiscoveryResponseMap.keySet()) { + ApiDiscoveryResponse response = s_apiNameDiscoveryResponseMap.get(apiName); Set processedParams = new HashSet(); for (ApiParameterResponse param : response.getParams()) { if (responseApiNameListMap.containsKey(param.getRelated())) { @@ -166,7 +160,7 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } else { response.setRelated(null); } - _apiNameDiscoveryResponseMap.put(apiName, response); + s_apiNameDiscoveryResponseMap.put(apiName, response); } } @@ -175,34 +169,39 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { ListResponse response = new ListResponse(); List responseList = new ArrayList(); + if (s_apiAccessCheckers == null) { + ComponentLocator locator = ComponentLocator.getCurrentLocator(); + s_apiAccessCheckers = locator.getAdapters(APIChecker.class); + } + if (user == null) return null; if (name != null) { - if (!_apiNameDiscoveryResponseMap.containsKey(name)) + if (!s_apiNameDiscoveryResponseMap.containsKey(name)) return null; - for (APIChecker apiChecker : _apiAccessCheckers) { + for (APIChecker apiChecker : s_apiAccessCheckers) { try { apiChecker.checkAccess(user, name); } catch (Exception ex) { return null; } } - responseList.add(_apiNameDiscoveryResponseMap.get(name)); + responseList.add(s_apiNameDiscoveryResponseMap.get(name)); } else { - for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { + for (String apiName : s_apiNameDiscoveryResponseMap.keySet()) { boolean isAllowed = true; - for (APIChecker apiChecker : _apiAccessCheckers) { + for (APIChecker apiChecker : s_apiAccessCheckers) { try { - apiChecker.checkAccess(user, name); + apiChecker.checkAccess(user, apiName); } catch (Exception ex) { isAllowed = false; } } if (isAllowed) - responseList.add(_apiNameDiscoveryResponseMap.get(apiName)); + responseList.add(s_apiNameDiscoveryResponseMap.get(apiName)); } } response.setResponses(responseList); From 8608925216e87691bc49fa4417d3446c2b81a5a7 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Tue, 15 Jan 2013 18:07:08 -0800 Subject: [PATCH 83/92] Consolidate RuntimeCloudException and CloudRuntimeException into one class CloudRuntimeException, and removed RuntimeCloudException to avoid confusion. --- .../CloudAuthenticationException.java | 4 +- .../exception/CloudExecutionException.java | 4 +- .../cloudstack/api/ServerApiException.java | 4 +- .../simulator/SimulatorRuntimeException.java | 4 +- .../com/cloud/async/AsyncCommandQueued.java | 4 +- .../exception/CloudRuntimeException.java | 48 ++++++++++-- .../HypervisorVersionChangedException.java | 4 +- .../exception/RuntimeCloudException.java | 75 ------------------- 8 files changed, 55 insertions(+), 92 deletions(-) delete mode 100644 utils/src/com/cloud/utils/exception/RuntimeCloudException.java diff --git a/api/src/com/cloud/exception/CloudAuthenticationException.java b/api/src/com/cloud/exception/CloudAuthenticationException.java index 2bba79bab1e..0bf114c0394 100644 --- a/api/src/com/cloud/exception/CloudAuthenticationException.java +++ b/api/src/com/cloud/exception/CloudAuthenticationException.java @@ -17,9 +17,9 @@ package com.cloud.exception; import com.cloud.utils.SerialVersionUID; -import com.cloud.utils.exception.RuntimeCloudException; +import com.cloud.utils.exception.CloudRuntimeException; -public class CloudAuthenticationException extends RuntimeCloudException { +public class CloudAuthenticationException extends CloudRuntimeException { private static final long serialVersionUID = SerialVersionUID.CloudAuthenticationException; public CloudAuthenticationException(String message) { diff --git a/api/src/com/cloud/exception/CloudExecutionException.java b/api/src/com/cloud/exception/CloudExecutionException.java index d8d70f8ddb5..c19fc459a8d 100755 --- a/api/src/com/cloud/exception/CloudExecutionException.java +++ b/api/src/com/cloud/exception/CloudExecutionException.java @@ -17,14 +17,14 @@ package com.cloud.exception; import java.util.HashMap; -import com.cloud.utils.exception.RuntimeCloudException; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.SerialVersionUID; /** * */ -public class CloudExecutionException extends RuntimeCloudException { +public class CloudExecutionException extends CloudRuntimeException { private final static long serialVersionUID = SerialVersionUID.CloudExecutionException; private final ErrorCode code; diff --git a/api/src/org/apache/cloudstack/api/ServerApiException.java b/api/src/org/apache/cloudstack/api/ServerApiException.java index 70fd34e5cf7..1f57b74745d 100644 --- a/api/src/org/apache/cloudstack/api/ServerApiException.java +++ b/api/src/org/apache/cloudstack/api/ServerApiException.java @@ -15,10 +15,10 @@ // specific language governing permissions and limitations // under the License. package org.apache.cloudstack.api; -import com.cloud.utils.exception.RuntimeCloudException; +import com.cloud.utils.exception.CloudRuntimeException; @SuppressWarnings("serial") -public class ServerApiException extends RuntimeCloudException { +public class ServerApiException extends CloudRuntimeException { private int _errorCode; private String _description; diff --git a/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorRuntimeException.java b/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorRuntimeException.java index 9891bc82556..9f24bbd0cfc 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorRuntimeException.java +++ b/plugins/hypervisors/simulator/src/com/cloud/simulator/SimulatorRuntimeException.java @@ -18,12 +18,12 @@ package com.cloud.simulator; import com.cloud.utils.SerialVersionUID; -import com.cloud.utils.exception.RuntimeCloudException; +import com.cloud.utils.exception.CloudRuntimeException; /** * wrap exceptions that you know there's no point in dealing with. */ -public class SimulatorRuntimeException extends RuntimeCloudException { +public class SimulatorRuntimeException extends CloudRuntimeException { private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; diff --git a/server/src/com/cloud/async/AsyncCommandQueued.java b/server/src/com/cloud/async/AsyncCommandQueued.java index 200b40e71b5..f01c214564b 100644 --- a/server/src/com/cloud/async/AsyncCommandQueued.java +++ b/server/src/com/cloud/async/AsyncCommandQueued.java @@ -17,9 +17,9 @@ package com.cloud.async; import com.cloud.utils.SerialVersionUID; -import com.cloud.utils.exception.RuntimeCloudException; +import com.cloud.utils.exception.CloudRuntimeException; -public class AsyncCommandQueued extends RuntimeCloudException { +public class AsyncCommandQueued extends CloudRuntimeException { private static final long serialVersionUID = SerialVersionUID.AsyncCommandQueued; private SyncQueueVO _queue = null; diff --git a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java index 78075947d3f..3862e2223d6 100755 --- a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java +++ b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java @@ -16,24 +16,62 @@ // under the License. package com.cloud.utils.exception; +import java.util.ArrayList; + +import com.cloud.utils.AnnotationHelper; import com.cloud.utils.SerialVersionUID; /** * wrap exceptions that you know there's no point in dealing with. */ -public class CloudRuntimeException extends RuntimeCloudException { +public class CloudRuntimeException extends RuntimeException { private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; - + + // This holds a list of uuids and their names. Add uuid:fieldname pairs + protected ArrayList idList = new ArrayList(); + + protected int csErrorCode; + + public CloudRuntimeException(String message) { super(message); + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); } - + public CloudRuntimeException(String message, Throwable th) { super(message, th); + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); } - - protected CloudRuntimeException() { + + public CloudRuntimeException() { super(); + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); + } + + public void addProxyObject(String uuid) { + idList.add(uuid); + return; + } + + public void addProxyObject(Object voObj, Long id, String idFieldName) { + // Get the VO object's table name. + String tablename = AnnotationHelper.getTableName(voObj); + if (tablename != null) { + addProxyObject(tablename, id, idFieldName); + } + return; + } + + public ArrayList getIdProxyList() { + return idList; + } + + public void setCSErrorCode(int cserrcode) { + this.csErrorCode = cserrcode; + } + + public int getCSErrorCode() { + return this.csErrorCode; } } diff --git a/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java b/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java index 4f637cb46be..2c0c1ccd68b 100755 --- a/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java +++ b/utils/src/com/cloud/utils/exception/HypervisorVersionChangedException.java @@ -18,10 +18,10 @@ package com.cloud.utils.exception; import com.cloud.utils.SerialVersionUID; -public class HypervisorVersionChangedException extends RuntimeCloudException { +public class HypervisorVersionChangedException extends CloudRuntimeException { private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; - + public HypervisorVersionChangedException(String message) { super(message); } diff --git a/utils/src/com/cloud/utils/exception/RuntimeCloudException.java b/utils/src/com/cloud/utils/exception/RuntimeCloudException.java deleted file mode 100644 index 52229800785..00000000000 --- a/utils/src/com/cloud/utils/exception/RuntimeCloudException.java +++ /dev/null @@ -1,75 +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 -// 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.utils.exception; - -import com.cloud.utils.AnnotationHelper; -import java.util.ArrayList; - -/** - * by the API response serializer. Any exceptions that are thrown by - * class, which extends Exception instead of RuntimeException like this - * class does. - */ - -public class RuntimeCloudException extends RuntimeException { - - // This holds a list of uuids and their names. Add uuid:fieldname pairs - protected ArrayList idList = new ArrayList(); - - protected int csErrorCode; - - public void addProxyObject(String uuid) { - idList.add(uuid); - return; - } - - public RuntimeCloudException(String message) { - super(message); - setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); - } - - public RuntimeCloudException(String message, Throwable cause) { - super(message, cause); - setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); - } - - public void addProxyObject(Object voObj, Long id, String idFieldName) { - // Get the VO object's table name. - String tablename = AnnotationHelper.getTableName(voObj); - if (tablename != null) { - addProxyObject(tablename, id, idFieldName); - } - return; - } - - public RuntimeCloudException() { - super(); - setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); - } - - public ArrayList getIdProxyList() { - return idList; - } - - public void setCSErrorCode(int cserrcode) { - this.csErrorCode = cserrcode; - } - - public int getCSErrorCode() { - return this.csErrorCode; - } -} From 939acb0f4c951f8c04de78cf897c8f6a25b1f05d Mon Sep 17 00:00:00 2001 From: Min Chen Date: Tue, 15 Jan 2013 18:17:35 -0800 Subject: [PATCH 84/92] Remove unused CloudExecutionException. --- .../exception/CloudExecutionException.java | 57 ------------------- api/src/com/cloud/exception/ErrorCode.java | 52 ----------------- 2 files changed, 109 deletions(-) delete mode 100755 api/src/com/cloud/exception/CloudExecutionException.java delete mode 100755 api/src/com/cloud/exception/ErrorCode.java diff --git a/api/src/com/cloud/exception/CloudExecutionException.java b/api/src/com/cloud/exception/CloudExecutionException.java deleted file mode 100755 index c19fc459a8d..00000000000 --- a/api/src/com/cloud/exception/CloudExecutionException.java +++ /dev/null @@ -1,57 +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.exception; - -import java.util.HashMap; - -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.SerialVersionUID; - -/** - * - */ -public class CloudExecutionException extends CloudRuntimeException { - private final static long serialVersionUID = SerialVersionUID.CloudExecutionException; - - private final ErrorCode code; - private final HashMap details; - - public CloudExecutionException(ErrorCode code, String message, Throwable cause) { - super(message, cause); - this.code = code; - details = new HashMap(); - } - - public ErrorCode getErrorCode() { - return code; - } - - public String getErrorMessage() { - return new StringBuilder("Error Code=").append(code).append("; Error Message=").append(super.toString()).toString(); - } - - @Override - public String toString() { - StringBuilder buff = new StringBuilder(); - buff.append("Error Code=").append(code); - buff.append("; Error Message=").append(super.toString()); - if (details.size() > 0) { - buff.append("; Error Details=").append(details.toString()); - } - return buff.toString(); - } -} diff --git a/api/src/com/cloud/exception/ErrorCode.java b/api/src/com/cloud/exception/ErrorCode.java deleted file mode 100755 index 8f048b84800..00000000000 --- a/api/src/com/cloud/exception/ErrorCode.java +++ /dev/null @@ -1,52 +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.exception; - -import java.util.HashSet; - -/** - */ -public class ErrorCode { - String code; - private static HashSet s_codes = new HashSet(); - - public ErrorCode(String code) { - this.code = code; - assert !s_codes.contains(this) : "There is already an error code registered for this code: " + code; - s_codes.add(this); - } - - public String getCode() { - return code; - } - - @Override - public int hashCode() { - return code.hashCode(); - } - - @Override - public boolean equals(Object that) { - if (!(that instanceof ErrorCode)) { - return false; - } - - return this.code.equals(((ErrorCode)that).code); - } - - public final static ErrorCode UnableToReachResource = new ErrorCode("resource.unavailable"); -} From c7840cf91f215988f8e02d2d33f389e461afc49b Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 16 Jan 2013 15:10:27 +0530 Subject: [PATCH 85/92] reverting the earlier commit 432ea9c7d4aff3f7e682f2951f49ed3e95778d9f done for bug CLOUDSTACK-265 due to IP clearence issues. --- api/src/com/cloud/network/Network.java | 1 - .../com/cloud/offering/NetworkOffering.java | 2 - .../ConfigurationManagerImpl.java | 34 +++------- .../cloud/network/rules/RulesManagerImpl.java | 35 ++-------- .../cloud/offerings/NetworkOfferingVO.java | 28 +------- .../cloud/server/ConfigurationServerImpl.java | 3 +- .../com/cloud/upgrade/dao/Upgrade40to41.java | 40 +---------- .../src/com/cloud/vm/UserVmManagerImpl.java | 68 ++++++------------- setup/db/create-schema.sql | 1 - setup/db/db/schema-40to410.sql | 1 - 10 files changed, 39 insertions(+), 174 deletions(-) diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 39a0b26c76a..c91f6a9b80d 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -170,7 +170,6 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity { public static final Capability AllowDnsSuffixModification = new Capability("AllowDnsSuffixModification"); public static final Capability RedundantRouter = new Capability("RedundantRouter"); public static final Capability ElasticIp = new Capability("ElasticIp"); - public static final Capability AssociatePublicIP = new Capability("AssociatePublicIP"); public static final Capability ElasticLb = new Capability("ElasticLb"); public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters"); public static final Capability InlineMode = new Capability("InlineMode"); diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index b69ad886eaa..f2c4de520a1 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -105,8 +105,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean getElasticIp(); - boolean getAssociatePublicIP(); - boolean getElasticLb(); boolean getSpecifyIpRanges(); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index b21c5a38bb7..95262797c0d 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3163,33 +3163,20 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura void validateStaticNatServiceCapablities(Map staticNatServiceCapabilityMap) { if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) { - if (staticNatServiceCapabilityMap.keySet().size() > 2) { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); + if (staticNatServiceCapabilityMap.keySet().size() > 1) { + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); } - boolean eipEnabled = false; - boolean eipDisabled = false; - boolean associatePublicIP = true; + for (Capability capability : staticNatServiceCapabilityMap.keySet()) { String value = staticNatServiceCapabilityMap.get(capability); if (capability == Capability.ElasticIp) { - eipEnabled = value.contains("true"); - eipDisabled = value.contains("false"); - if (!eipEnabled && !eipDisabled) { + boolean enabled = value.contains("true"); + boolean disabled = value.contains("false"); + if (!enabled && !disabled) { throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticIp.getName()); } - } else if (capability == Capability.AssociatePublicIP) { - if (value.contains("true")) { - associatePublicIP = true; - } else if (value.contains("false")) { - associatePublicIP = false; - } else { - throw new InvalidParameterValueException("Unknown specified value for " + Capability.AssociatePublicIP.getName()); - } } else { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); - } - if (eipDisabled && associatePublicIP) { - throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"); + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); } } } @@ -3243,7 +3230,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura boolean sharedSourceNat = false; boolean redundantRouter = false; boolean elasticIp = false; - boolean associatePublicIp = false; boolean inline = false; if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) { Map lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb); @@ -3293,17 +3279,13 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura String param = staticNatServiceCapabilityMap.get(Capability.ElasticIp); if (param != null) { elasticIp = param.contains("true"); - String associatePublicIP = staticNatServiceCapabilityMap.get(Capability.AssociatePublicIP); - if (associatePublicIP != null) { - associatePublicIp = associatePublicIP.contains("true"); - } } } } NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, - sharedSourceNat, redundantRouter, elasticIp, elasticLb, associatePublicIp, specifyIpRanges, inline); + sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline); if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index dd091740021..a75aca3a522 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -16,18 +16,6 @@ // under the License. package com.cloud.network.rules; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; -import org.apache.log4j.Logger; - import com.cloud.configuration.ConfigurationManager; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; @@ -65,13 +53,8 @@ import com.cloud.utils.Pair; import com.cloud.utils.Ternary; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.*; import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; import com.cloud.vm.Nic; @@ -80,6 +63,7 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; +import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; import org.apache.log4j.Logger; import javax.ejb.Local; @@ -1189,12 +1173,11 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { Network guestNetwork = _networkMgr.getNetwork(ipAddress.getAssociatedWithNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { - if (offering.getAssociatePublicIP()) { - getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); - return true; - } + getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); + return true; + } else { + return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); } - return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); } @Override @@ -1380,11 +1363,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { Network guestNetwork = _networkMgr.getNetwork(nic.getNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { - boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); - // for user VM's associate public IP only if offering is marked to associate a public IP by default on start of VM - if (!isSystemVM && !offering.getAssociatePublicIP()) { - continue; - } // check if there is already static nat enabled if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null && !getNewIp) { s_logger.debug("Vm " + vm + " already has ip associated with it in guest network " + guestNetwork); @@ -1399,6 +1377,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { s_logger.debug("Allocated system ip " + ip + ", now enabling static nat on it for vm " + vm); + boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); try { success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM); } catch (NetworkRuleConflictException ex) { diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java index 8de93d87b54..efaca764020 100755 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -16,26 +16,10 @@ // under the License. package com.cloud.offerings; -import com.cloud.network.Networks; - -import java.util.Date; -import java.util.UUID; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; - -import org.apache.cloudstack.api.Identity; import com.cloud.network.Network; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.NetworkOffering; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; import javax.persistence.*; import java.util.Date; @@ -129,9 +113,6 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "elastic_lb_service") boolean elasticLb; - @Column(name = "eip_associate_public_ip") - boolean eipAssociatePublicIp; - @Column(name = "inline") boolean inline; @@ -295,21 +276,19 @@ public class NetworkOfferingVO implements NetworkOffering { this.redundantRouter = false; this.elasticIp = false; this.elasticLb = false; - this.eipAssociatePublicIp = true; this.inline = false; this.specifyIpRanges = specifyIpRanges; } public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, - boolean associatePublicIP, boolean specifyIpRanges, boolean inline) { + boolean specifyIpRanges, boolean inline) { this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges); this.dedicatedLB = dedicatedLb; this.sharedSourceNat = sharedSourceNat; this.redundantRouter = redundantRouter; this.elasticIp = elasticIp; this.elasticLb = elasticLb; - this.eipAssociatePublicIp = associatePublicIP; this.inline = inline; } @@ -372,11 +351,6 @@ public class NetworkOfferingVO implements NetworkOffering { return elasticIp; } - @Override - public boolean getAssociatePublicIP() { - return eipAssociatePublicIp; - } - @Override public boolean getElasticLb() { return elasticLb; diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 7e5f42445d5..5d246281630 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -70,7 +70,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; -import com.cloud.uuididentity.dao.IdentityDao; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; @@ -972,7 +971,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Shared, true, false, false, false, true, true, true, true, false); + null, Network.GuestType.Shared, true, false, false, false, true, true, true, false); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); diff --git a/server/src/com/cloud/upgrade/dao/Upgrade40to41.java b/server/src/com/cloud/upgrade/dao/Upgrade40to41.java index e23837d49f8..cd9e20c6a46 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade40to41.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade40to41.java @@ -22,12 +22,6 @@ import com.cloud.utils.script.Script; import java.io.File; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; /** * @author htrippaers @@ -84,7 +78,7 @@ public class Upgrade40to41 implements DbUpgrade { */ @Override public void performDataMigration(Connection conn) { - upgradeEIPNetworkOfferings(conn); + } /* (non-Javadoc) @@ -95,36 +89,4 @@ public class Upgrade40to41 implements DbUpgrade { return new File[0]; } - private void upgradeEIPNetworkOfferings(Connection conn) { - PreparedStatement pstmt = null; - ResultSet rs = null; - - try { - pstmt = conn.prepareStatement("select id, elastic_ip_service from `cloud`.`network_offerings` where traffic_type='Guest'"); - rs = pstmt.executeQuery(); - while (rs.next()) { - long id = rs.getLong(1); - // check if elastic IP service is enabled for network offering - if (rs.getLong(2) != 0) { - //update network offering with eip_associate_public_ip set to true - pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set eip_associate_public_ip=? where id=?"); - pstmt.setBoolean(1, true); - pstmt.setLong(2, id); - pstmt.executeUpdate(); - } - } - } catch (SQLException e) { - throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e); - } finally { - try { - if (rs != null) { - rs.close(); - } - if (pstmt != null) { - pstmt.close(); - } - } catch (SQLException e) { - } - } - } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f3aca68172f..a6fbdb17915 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -16,32 +16,6 @@ // under the License. package com.cloud.vm; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; -import org.apache.cloudstack.api.command.user.vm.*; -import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; -import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; -import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.agent.AgentManager; import com.cloud.agent.api.*; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; @@ -53,17 +27,6 @@ import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.vo.UserVmJoinVO; - -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; -import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; -import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; -import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; -import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; -import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; -import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd; -import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; import com.cloud.async.AsyncJobExecutor; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; @@ -151,12 +114,7 @@ import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.crypt.RSAHelper; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.GlobalLock; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.*; import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExecutionException; @@ -164,6 +122,26 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.*; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; +import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; +import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd; +import org.apache.cloudstack.api.command.user.vm.*; +import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; +import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @Local(value = { UserVmManager.class, UserVmService.class }) public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager { @@ -2788,10 +2766,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (ip != null && ip.getSystem()) { UserContext ctx = UserContext.current(); try { - long networkId = ip.getAssociatedWithNetworkId(); - Network guestNetwork = _networkMgr.getNetwork(networkId); - NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); - assert (offering.getAssociatePublicIP() == true) : "User VM should not have system owned public IP associated with it when offering configured not to associate public IP."; _rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true); } catch (Exception ex) { s_logger.warn("Failed to disable static nat and release system ip " + ip + " as a part of vm " + profile.getVirtualMachine() + " stop due to exception ", ex); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 37d52539f16..174f53cd7ba 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -306,7 +306,6 @@ CREATE TABLE `cloud`.`network_offerings` ( `state` char(32) COMMENT 'state of the network offering that has Disabled value by default', `guest_type` char(32) COMMENT 'type of guest network that can be shared or isolated', `elastic_ip_service` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network offering provides elastic ip service', - `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.', `elastic_lb_service` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network offering provides elastic lb service', `specify_ip_ranges` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network offering provides an ability to define ip ranges', `inline` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is this network offering LB provider is in inline mode', diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index bf3fb303e5b..c115135d006 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -58,7 +58,6 @@ ALTER TABLE `cloud`.`snapshots` ADD COLUMN `s3_id` bigint unsigned COMMENT 'S3 t ALTER TABLE `cloud`.`snapshots` ADD CONSTRAINT `fk_snapshots__s3_id` FOREIGN KEY `fk_snapshots__s3_id` (`s3_id`) REFERENCES `s3` (`id`); -ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`; ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `inline` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is this network offering LB provider is in inline mode'; ALTER TABLE `cloud`.`external_load_balancer_devices` DROP COLUMN `is_inline`; From 156ed7a336643963040aa485406da8cd0e0564ed Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 16 Jan 2013 15:58:44 +0530 Subject: [PATCH 86/92] Revert "Summary: partical check-in for L4-L7 network services in the shared" Reverting due to IP clearance issued for the commit done as part of CLOUDSTACK-312 This reverts commit d4c604cfd8ec6b385de7abf694a936e89add0f38. --- .../com/cloud/network/NetworkManagerImpl.java | 80 +++++++------------ 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 206392dce49..47db4cb82ae 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -980,14 +980,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true) - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { - if (networkId != null) { Network network = _networksDao.findById(networkId); if (network == null) { throw new InvalidParameterValueException("Invalid network id is given"); } + if (network.getGuestType() == Network.GuestType.Shared) { DataCenter zone = _configMgr.getZone(zoneId); if (zone == null) { @@ -1002,9 +1002,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } - return allocateIp(ipOwner, false, caller, zone); + return allocateIp(ipOwner, false, caller, callerUserId, zone); } else { - throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" + + throw new InvalidParameterValueException("Associate IP address can only called on the shared networks in the advanced zone" + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled"); } } @@ -1022,11 +1022,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag DataCenter zone = _configMgr.getZone(zoneId); - return allocateIp(ipOwner, isSystem, caller, zone); + return allocateIp(ipOwner, isSystem, caller, callerUserId, zone); } @DB - public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, DataCenter zone) + public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerUserId, DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { @@ -1047,7 +1047,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Account accountToLock = null; try { if (s_logger.isDebugEnabled()) { - s_logger.debug("Associate IP address called by the user " + caller.getId()); + s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } accountToLock = _accountDao.acquireInLockTable(ipOwner.getId()); if (accountToLock == null) { @@ -1133,13 +1133,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced) { - if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); - } else { - throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if" + - "network service Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network"); - } + if (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced && isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { + _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); } else { _accountMgr.checkAccess(caller, null, true, ipToAssoc); } @@ -2011,11 +2006,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - @Override - public boolean equals(Object o) { - return super.equals(o); //To change body of overridden methods use File | Settings | File Templates. - } - private void implementNetworkElementsAndResources(DeployDestination dest, ReservationContext context, NetworkVO network, NetworkOfferingVO offering) throws ConcurrentOperationException, InsufficientAddressCapacityException, ResourceUnavailableException, InsufficientCapacityException { @@ -2510,36 +2500,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - private void checkSharedNetworkCidrOverlap(Long zoneId, long physicalNetworkId, String cidr) { - if (zoneId == null || cidr == null) { + private void checkSharedNetworkCidrOverlap(Long zoneId, String cidr) { + if (zoneId == null) { return; } - DataCenter zone = _dcDao.findById(zoneId); - List networks = _networksDao.listByZone(zoneId); - Map networkToCidr = new HashMap(); - - // check for CIDR overlap with all possible CIDR for isolated guest networks - // in the zone when using external networking - PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); - if (pNetwork.getVnet() != null) { - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); - int highestVlanTag = Integer.valueOf(vlanRange[1]); - for (int vlan=lowestVlanTag; vlan <= highestVlanTag; ++vlan) { - int offset = vlan - lowestVlanTag; - String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); - int cidrSize = 8 + Integer.parseInt(globalVlanBits); - String guestNetworkCidr = zone.getGuestNetworkCidr(); - String[] cidrTuple = guestNetworkCidr.split("\\/"); - long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize)); - if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) { - throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan); - } - } + if (cidr == null) { + return; } - // check for CIDR overlap with all CIDR's of the shared networks in the zone + List networks = _networksDao.listByZone(zoneId); + Map networkToCidr = new HashMap(); for (NetworkVO network : networks) { if (network.getGuestType() == GuestType.Isolated) { continue; @@ -2548,15 +2519,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag networkToCidr.put(network.getId(), network.getCidr()); } } - if (networkToCidr != null && !networkToCidr.isEmpty()) { - for (long networkId : networkToCidr.keySet()) { - String ntwkCidr = networkToCidr.get(networkId); - if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { - throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR of a shared network in the zone."); - } + + //TODO: check for CIDR overlap with all possible CIDR for guest networks in the zone + //when using external networking + + if (networkToCidr == null || networkToCidr.isEmpty()) { + return; + } + + for (long networkId : networkToCidr.keySet()) { + String ntwkCidr = networkToCidr.get(networkId); + if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { + throw new InvalidParameterValueException("Warning: The specified existing network has conflict CIDR subnets with new network!"); } } } + public void checkVirtualNetworkCidrOverlap(Long zoneId, String cidr) { if (zoneId == null) { return; @@ -2784,7 +2762,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (ntwkOff.getGuestType() == GuestType.Shared && (zone.getNetworkType() == NetworkType.Advanced) && isSharedNetworkOfferingWithServices(networkOfferingId)) { // validate if CIDR specified overlaps with any of the CIDR's allocated for isolated networks and shared networks in the zone - checkSharedNetworkCidrOverlap(zoneId, pNtwk.getId(), cidr); + checkSharedNetworkCidrOverlap(zoneId, cidr); } else { throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!"); } From 316c5267ccc182e18c4201a72cdf8ccc739e130a Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 16 Jan 2013 16:04:14 +0530 Subject: [PATCH 87/92] Revert " Summary: check-in for L4-L7 network services in the shared network in" This reverts commit 7fcfcdf91e49d64375171c9ae7fe61067aa59b6e. Reverting due to IP clearance issued for the commit done as part of CLOUDSTACK-312 --- .../com/cloud/network/NetworkManagerImpl.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 47db4cb82ae..f378aa4fd5a 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2951,11 +2951,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId); } } else { - //don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or - //shared network with same Vlan ID in the zone - if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 || - _networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Shared) > 0) { - throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " + vlanId + " already exists " + "in zone " + zoneId); + //don't allow to create Shared network with Vlan that already exists in the zone for Isolated networks + if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0) { + throw new InvalidParameterValueException("Isolated network with vlan " + vlanId + " already exists " + + "in zone " + zoneId); } } } @@ -3543,13 +3542,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag applyProfileToNetwork(network, profile); - DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); - if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && (zone.getNetworkType() == NetworkType.Advanced)) { - network.setState(Network.State.Setup); - } else { - network.setState(Network.State.Allocated); - } - + network.setState(Network.State.Allocated); network.setRestartRequired(false); _networksDao.update(network.getId(), network); _networksDao.clearCheckForGc(networkId); From 88a0b5ac488c6ec3b8a501ee1254a6a962db47fe Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 16 Jan 2013 16:05:17 +0530 Subject: [PATCH 88/92] Revert "Summary: partical check-in for L4-L7 network services in the shared" This reverts commit 6657246cd44629c30e6ea21cc4bbd43a42788e12. Reverting due to IP clearance issued for the commit done as part of CLOUDSTACK-312 --- .../cloud/network/element/F5ExternalLoadBalancerElement.java | 2 +- .../network/element/JuniperSRXExternalFirewallElement.java | 3 +-- .../src/com/cloud/network/element/NetscalerElement.java | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index b9739ec21df..70faaccc461 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -122,7 +122,7 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan ConfigurationDao _configDao; private boolean canHandle(Network config) { - if ((config.getGuestType() != Network.GuestType.Isolated && config.getGuestType() != Network.GuestType.Shared) || config.getTrafficType() != TrafficType.Guest) { + if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) { s_logger.trace("Not handling network with Type " + config.getGuestType() + " and traffic type " + config.getTrafficType()); return false; } diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 6e9d32daa99..ead2af9396d 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -130,8 +130,7 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan private boolean canHandle(Network network, Service service) { DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if ((zone.getNetworkType() == NetworkType.Advanced && !(network.getGuestType() == Network.GuestType.Isolated || network.getGuestType() == Network.GuestType.Shared )) - || (zone.getNetworkType() == NetworkType.Basic && network.getGuestType() != Network.GuestType.Shared)) { + if ((zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() != Network.GuestType.Isolated) || (zone.getNetworkType() == NetworkType.Basic && network.getGuestType() != Network.GuestType.Shared)) { s_logger.trace("Element " + getProvider().getName() + "is not handling network type = " + network.getGuestType()); return false; } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index a1782107e19..c0f91bb42d2 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -154,8 +154,7 @@ StaticNatServiceProvider { private boolean canHandle(Network config, Service service) { DataCenter zone = _dcDao.findById(config.getDataCenterId()); - boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced && - (config.getGuestType() == Network.GuestType.Isolated || config.getGuestType() == Network.GuestType.Shared) && config.getTrafficType() == TrafficType.Guest); + boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced && config.getGuestType() == Network.GuestType.Isolated && config.getTrafficType() == TrafficType.Guest); boolean handleInBasicZone = (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() == Network.GuestType.Shared && config.getTrafficType() == TrafficType.Guest); if (!(handleInAdvanceZone || handleInBasicZone)) { From 4b67340d8cda021394892d8e4b0adfba493b42dd Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Wed, 16 Jan 2013 16:43:37 +0530 Subject: [PATCH 89/92] Revert "Summary: partical check-in for L4-L7 network services in the shared" This reverts commits 0de5a145e4f06420a4eb1867309af674c16ace7c, 28bbf6c52798c9bd298952844250fbc3cb92dce0 Reverting due to IP clearance issues for the commits done as part of CLOUDSTACK-312 --- api/src/com/cloud/network/NetworkService.java | 2 +- .../user/address/AssociateIPAddrCmd.java | 2 +- .../com/cloud/network/NetworkManagerImpl.java | 251 +++--------------- .../cloud/network/MockNetworkManagerImpl.java | 2 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 35 +-- 5 files changed, 51 insertions(+), 241 deletions(-) diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 39a746e6776..b3332a345b3 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -41,7 +41,7 @@ public interface NetworkService { List getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner); - IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, + IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException; boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 024ba74e8b4..93bb2401d8f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -213,7 +213,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException{ try { - IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId()); + IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), false, getZoneId()); if (ip != null) { this.setEntityId(ip.getId()); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index f378aa4fd5a..0a1fcd7e66d 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -16,58 +16,19 @@ // under the License. package com.cloud.network; -import java.net.URI; -import java.security.InvalidParameterException; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import com.cloud.utils.db.*; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.*; import com.cloud.agent.api.to.NicTO; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; - -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.*; import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.Pod; -import com.cloud.dc.PodVlanMapVO; -import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.PodVlanMapDao; @@ -110,13 +71,6 @@ import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.rules.*; import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.PortForwardingRule; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.rules.RulesManager; -import com.cloud.network.rules.StaticNat; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StaticNatRuleImpl; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.NetworkACLManager; import com.cloud.network.vpc.PrivateIpVO; @@ -145,30 +99,38 @@ import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.*; import com.cloud.utils.db.JoinBuilder.JoinType; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; -import com.cloud.vm.Nic; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; -import com.cloud.vm.ReservationContext; -import com.cloud.vm.ReservationContextImpl; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; +import com.cloud.vm.*; import com.cloud.vm.VirtualMachine.Type; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import edu.emory.mathcs.backport.java.util.Collections; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.log4j.Logger; +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.net.URI; +import java.security.InvalidParameterException; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * NetworkManagerImpl implements NetworkManager. @@ -980,39 +942,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true) - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) - throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { - if (networkId != null) { - Network network = _networksDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Invalid network id is given"); - } - - if (network.getGuestType() == Network.GuestType.Shared) { - DataCenter zone = _configMgr.getZone(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Invalid zone Id is given"); - } - - // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' - if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && zone.getNetworkType() == NetworkType.Advanced) { - Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); - _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); - } - return allocateIp(ipOwner, false, caller, callerUserId, zone); - } else { - throw new InvalidParameterValueException("Associate IP address can only called on the shared networks in the advanced zone" + - " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled"); - } - } - } - - return allocateIP(ipOwner, false, zoneId); - } - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = UserContext.current().getCaller(); @@ -1127,17 +1056,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag IPAddressVO ipToAssoc = _ipAddressDao.findById(ipId); if (ipToAssoc != null) { - Network network = _networksDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Invalid network id is given"); - } - - DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced && isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, network); - } else { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); - } + _accountMgr.checkAccess(caller, null, true, ipToAssoc); owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { s_logger.debug("Unable to find ip address by id: " + ipId); @@ -1164,20 +1083,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + TrafficType.Guest); } - // Check that network belongs to IP owner - skip this check - // - if zone is basic zone as there is just one guest network, - // - if shared network in Advanced zone - // - and it belongs to the system - if (network.getAccountId() != owner.getId()) { - if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) { - throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP"); - } + // Check that network belongs to IP owner - skip this check for Basic zone as there is just one guest network, + // and it belongs to the system + if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != owner.getId()) { + throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP"); } - // In Advance zone only allow to do IP assoc - // - for Isolated networks with source nat service enabled - // - for shared networks with source nat service enabled - if (zone.getNetworkType() == NetworkType.Advanced && (!areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) { + // In Advance zone only allow to do IP assoc for Isolated networks with source nat service enabled + if (zone.getNetworkType() == NetworkType.Advanced && + !(network.getGuestType() == GuestType.Isolated && areServicesSupportedInNetwork(network.getId(), + Service.SourceNat))) { throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the " + Service.SourceNat.getName() + " enabled"); @@ -1948,21 +1863,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag try { NetworkGuru guru = _networkGurus.get(network.getGuruName()); Network.State state = network.getState(); - if (state == Network.State.Implemented || state == Network.State.Implementing) { + if (state == Network.State.Implemented || state == Network.State.Setup || state == Network.State.Implementing) { s_logger.debug("Network id=" + networkId + " is already implemented"); implemented.set(guru, network); return implemented; } - if (state == Network.State.Setup) { - DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); - if (!isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) || (zone.getNetworkType() == NetworkType.Basic)) { - s_logger.debug("Network id=" + networkId + " is already implemented"); - implemented.set(guru, network); - return implemented; - } - } - if (s_logger.isDebugEnabled()) { s_logger.debug("Asking " + guru.getName() + " to implement " + network); } @@ -2010,16 +1916,15 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkVO network, NetworkOfferingVO offering) throws ConcurrentOperationException, InsufficientAddressCapacityException, ResourceUnavailableException, InsufficientCapacityException { - // Associate a source NAT IP (if one isn't already associated with the network) if this is a - // 1) 'Isolated' or 'Shared' guest virtual network in the advance zone - // 2) network has sourceNat service - // 3) network offering does not support a shared source NAT rule + // If this is a 1) guest virtual network 2) network has sourceNat service 3) network offering does not support a + // Shared source NAT rule, + // associate a source NAT IP (if one isn't already associated with the network) boolean sharedSourceNat = offering.getSharedSourceNat(); DataCenter zone = _dcDao.findById(network.getDataCenterId()); - if (!sharedSourceNat && areServicesSupportedInNetwork(network.getId(), Service.SourceNat) - && (network.getGuestType() == Network.GuestType.Isolated || - (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) { + if (network.getGuestType() == Network.GuestType.Isolated + && areServicesSupportedInNetwork(network.getId(), Service.SourceNat) + && !sharedSourceNat) { List ips = null; if (network.getVpcId() != null) { @@ -2500,70 +2405,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } - private void checkSharedNetworkCidrOverlap(Long zoneId, String cidr) { - if (zoneId == null) { - return; - } - - if (cidr == null) { - return; - } - - List networks = _networksDao.listByZone(zoneId); - Map networkToCidr = new HashMap(); - for (NetworkVO network : networks) { - if (network.getGuestType() == GuestType.Isolated) { - continue; - } - if (network.getCidr() != null) { - networkToCidr.put(network.getId(), network.getCidr()); - } - } - - //TODO: check for CIDR overlap with all possible CIDR for guest networks in the zone - //when using external networking - - if (networkToCidr == null || networkToCidr.isEmpty()) { - return; - } - - for (long networkId : networkToCidr.keySet()) { - String ntwkCidr = networkToCidr.get(networkId); - if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { - throw new InvalidParameterValueException("Warning: The specified existing network has conflict CIDR subnets with new network!"); - } - } - } - - public void checkVirtualNetworkCidrOverlap(Long zoneId, String cidr) { - if (zoneId == null) { - return; - } - if (cidr == null) { - return; - } - List networks = _networksDao.listByZone(zoneId); - Map networkToCidr = new HashMap(); - for (NetworkVO network : networks) { - if (network.getGuestType() != GuestType.Isolated) { - continue; - } - if (network.getCidr() != null) { - networkToCidr.put(network.getId(), network.getCidr()); - } - } - if (networkToCidr == null || networkToCidr.isEmpty()) { - return; - } - - for (long networkId : networkToCidr.keySet()) { - String ntwkCidr = networkToCidr.get(networkId); - if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { - throw new InvalidParameterValueException("Warning: The specified existing network has conflict CIDR subnets with new network!"); - } - } - } - @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network") @@ -2759,16 +2600,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Collection ntwkProviders = finalizeServicesAndProvidersForNetwork(ntwkOff, physicalNetworkId).values(); if (cidr != null && providersConfiguredForExternalNetworking(ntwkProviders)) { - if (ntwkOff.getGuestType() == GuestType.Shared && (zone.getNetworkType() == NetworkType.Advanced) && - isSharedNetworkOfferingWithServices(networkOfferingId)) { - // validate if CIDR specified overlaps with any of the CIDR's allocated for isolated networks and shared networks in the zone - checkSharedNetworkCidrOverlap(zoneId, cidr); - } else { - throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!"); - } + throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!"); } - // Vlan is created in 2 cases - works in Advance zone only: // 1) GuestType is Shared // 2) GuestType is Isolated, but SourceNat service is disabled @@ -4488,19 +4322,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return false; } - public boolean isSharedNetworkOfferingWithServices(long networkOfferingId) { - NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); - if ( (networkOffering.getGuestType() == Network.GuestType.Shared) && ( - areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) || - areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) || - areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) || - areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || - areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) { - return true; - } - return false; - } - @Override public boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services) { return (_ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(networkOfferingId, services)); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 874e01767a9..28d1a604c44 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -797,7 +797,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, long, Long) */ @Override - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index bd8d8bc3a69..642ea10c7ca 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -16,22 +16,6 @@ // under the License. package com.cloud.vpc; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; import com.cloud.dc.DataCenter; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; @@ -48,12 +32,7 @@ import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.element.LoadBalancingServiceProvider; -import com.cloud.network.element.NetworkElement; -import com.cloud.network.element.RemoteAccessVPNServiceProvider; -import com.cloud.network.element.Site2SiteVpnServiceProvider; -import com.cloud.network.element.StaticNatServiceProvider; -import com.cloud.network.element.UserDataServiceProvider; +import com.cloud.network.element.*; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; @@ -70,6 +49,16 @@ import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.vm.*; import com.cloud.vpc.dao.MockVpcVirtualRouterElement; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.*; @Local(value = { NetworkManager.class, NetworkService.class }) public class MockNetworkManagerImpl implements NetworkManager, Manager{ @@ -1481,7 +1470,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager{ * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, boolean, long) */ @Override - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; } From 310d35f88edd6d75499b2089813cfc8b3dd08652 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Wed, 16 Jan 2013 10:24:14 -0700 Subject: [PATCH 90/92] Summary: Change template details in devcloud-kvm sql file Signed-off-by: Marcus Sorensen 1358357054 -0700 --- tools/devcloud-kvm/devcloud-kvm.sql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/devcloud-kvm/devcloud-kvm.sql b/tools/devcloud-kvm/devcloud-kvm.sql index 97478834bf3..6d559a9c91a 100644 --- a/tools/devcloud-kvm/devcloud-kvm.sql +++ b/tools/devcloud-kvm/devcloud-kvm.sql @@ -17,7 +17,7 @@ INSERT INTO `cloud`.`disk_offering` (id, name, uuid, display_text, created, use_local_storage, type, disk_size) VALUES (17, 'tinyOffering', UUID(), 'tinyOffering', NOW(), 1, 'Service', 0); -INSERT INTO `cloud`.`service_offering` (id, cpu, speed, ram_size) VALUES (17, 1, 100, 100); +INSERT INTO `cloud`.`service_offering` (id, cpu, speed, ram_size) VALUES (17, 1, 100, 128); INSERT INTO `cloud`.`disk_offering` (id, name, uuid, display_text, created, type, disk_size) VALUES (18, 'tinyDiskOffering', UUID(), 'tinyDiskOffering', NOW(), 'Disk', 1073741824); INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','router.ram.size', '100'); INSERT INTO `cloud`.`configuration` (instance, name,value) VALUE('DEFAULT','router.cpu.mhz','100'); @@ -37,4 +37,5 @@ INSERT INTO `cloud`.`configuration` (instance, name, value) VALUE('DEFAULT', 'se UPDATE `cloud`.`configuration` SET value='10' where name = 'storage.overprovisioning.factor'; UPDATE `cloud`.`configuration` SET value='10' where name = 'cpu.overprovisioning.factor'; UPDATE `cloud`.`configuration` SET value='10' where name = 'mem.overprovisioning.factor'; -UPDATE `cloud`.`vm_template` SET unique_name="tiny Linux",name="tiny Linux",url="http://marcus.mlsorensen.com/cloudstack-extras/ttylinux_pv.qcow2",checksum="81dcf4b4ca05a3b637a040e851568f29",display_text="tiny Linux",format='QCOW2',hypervisor_type='KVM' where id=5; +UPDATE `cloud`.`vm_template` SET unique_name="tiny CentOS 6.3",name="tiny CentOS 6.3",url="http://marcus.mlsorensen.com/cloudstack-extras/tiny-centos-63.qcow2",checksum="4bbb806aa8570f4dfac13b4c38ea1603",display_text="tiny CentOS 6.3",format='QCOW2',hypervisor_type='KVM' where id=5; +UPDATE `cloud`.`vm_template` SET url="http://dontdownloadthistemplate" where id=4; From 4f479e2b23cbbc42247531bd8abb005fc1b89591 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Wed, 16 Jan 2013 10:30:31 -0700 Subject: [PATCH 91/92] Summary: Modifying integration tests to use 128MB service offerings Detail: The default devcloud tiny template is set up via devcloud.sql to have at least 100MB RAM, changing the tests as well. This will also allow the builtin devcloud-kvm tiny template to work for tests as it requires a bit more. Signed-off-by: Marcus Sorensen 1358357431 -0700 --- test/integration/smoke/test_routers.py | 2 +- test/integration/smoke/test_service_offerings.py | 2 +- test/integration/smoke/test_templates.py | 2 +- test/integration/smoke/test_vm_life_cycle.py | 2 +- test/integration/smoke/test_volumes.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 93dc7606ace..435c7e41a43 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -41,7 +41,7 @@ class Services: "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "memory": 128, # In MBs }, "virtual_machine": { diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 3a8a9e156b9..7f4d130ee80 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -39,7 +39,7 @@ class Services: "displaytext": "Service Offering", "cpunumber": 1, "cpuspeed": 100, # MHz - "memory": 64, # in MBs + "memory": 128, # in MBs }, } diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index d450a5d8122..663b174ed78 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -52,7 +52,7 @@ class Services: "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "memory": 128, # In MBs }, "disk_offering": { "displaytext": "Small", diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index f6fe4e002a1..0bd4f959bc3 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -80,7 +80,7 @@ class Services: "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "memory": 128, # In MBs }, "small": { diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 2d0cd491672..3fe68ec5621 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -53,7 +53,7 @@ class Services: "displaytext": "Tiny Instance", "cpunumber": 1, "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "memory": 128, # In MBs }, "disk_offering": { "displaytext": "Small", From a69e7f9bf605079968a7e3a7facdede167504aa4 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Thu, 17 Jan 2013 00:02:11 +0530 Subject: [PATCH 92/92] CLOUDSTACK-972:The template will disappear after reordering in template section --- ui/scripts/ui/widgets/listView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 85523ea5e7a..9e16ec2ae54 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -560,8 +560,8 @@ return $(this).index() == index; }); - if ($target.index() > $tr.index()) $target.after($tr); - else $target.before($tr); + // if ($target.index() > $tr.index()) $target.after($tr); + // else $target.before($tr); $tr.closest('.list-view').scrollTop($tr.position().top - $tr.height() * 2);