Updated Branches: refs/heads/master 69fb0208e -> 0d1393a2d refs/heads/vpc 60f1dbe57 -> 6cddd1e76
Removed trailing whitespaces and fixed line endings in some files Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/6cddd1e7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/6cddd1e7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/6cddd1e7 Branch: refs/heads/vpc Commit: 6cddd1e767691de1ab4a63972dd318411e0ecb0f Parents: 97e4906 Author: Alena Prokharchyk <[email protected]> Authored: Thu Aug 9 22:33:10 2012 -0700 Committer: Alena Prokharchyk <[email protected]> Committed: Thu Aug 9 23:30:33 2012 -0700 ---------------------------------------------------------------------- api/src/com/cloud/api/BaseCmd.java | 928 +- .../kvm/resource/LibvirtComputingResource.java | 7501 +++++++-------- server/src/com/cloud/vm/UserVmManagerImpl.java | 382 +- .../com/cloud/vm/VirtualMachineManagerImpl.java | 4812 +++++----- 4 files changed, 6807 insertions(+), 6816 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6cddd1e7/api/src/com/cloud/api/BaseCmd.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index fc6b2a5..91c2035 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -14,9 +14,9 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - -package com.cloud.api; - + +package com.cloud.api; + import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -67,464 +67,464 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentLocator; import com.cloud.vm.BareMetalVmService; import com.cloud.vm.UserVmService; - -public abstract class BaseCmd { - private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName()); - - public static final String USER_ERROR_MESSAGE = "Internal error executing command, please contact your system administrator"; - public static final int PROGRESS_INSTANCE_CREATED = 1; - - public static final String RESPONSE_TYPE_XML = "xml"; - public static final String RESPONSE_TYPE_JSON = "json"; - - public enum CommandType { - BOOLEAN, DATE, FLOAT, INTEGER, SHORT, LIST, LONG, OBJECT, MAP, STRING, TZDATE - } - - // FIXME: Extract these out into a separate file - // Client error codes - public static final int MALFORMED_PARAMETER_ERROR = 430; - public static final int PARAM_ERROR = 431; - public static final int UNSUPPORTED_ACTION_ERROR = 432; - public static final int PAGE_LIMIT_EXCEED = 433; - - // Server error codes - public static final int INTERNAL_ERROR = 530; - public static final int ACCOUNT_ERROR = 531; - public static final int ACCOUNT_RESOURCE_LIMIT_ERROR = 532; - public static final int INSUFFICIENT_CAPACITY_ERROR = 533; - public static final int RESOURCE_UNAVAILABLE_ERROR = 534; - public static final int RESOURCE_ALLOCATION_ERROR = 534; - public static final int RESOURCE_IN_USE_ERROR = 536; - public static final int NETWORK_RULE_CONFLICT_ERROR = 537; - - public static final DateFormat INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - public static final DateFormat NEW_INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - public static Pattern newInputDateFormat = Pattern.compile("[\\d]+-[\\d]+-[\\d]+ [\\d]+:[\\d]+:[\\d]+"); - private static final DateFormat _outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - - private Object _responseObject = null; - private Map<String, String> fullUrlParams; - - @Parameter(name = "response", type = CommandType.STRING) - private String responseType; - - public static ComponentLocator s_locator; - public static ConfigurationService _configService; - public static AccountService _accountService; - public static UserVmService _userVmService; - public static ManagementService _mgr; - public static StorageService _storageService; - public static ResourceService _resourceService; - public static NetworkService _networkService; - public static TemplateService _templateService; - public static SecurityGroupService _securityGroupService; - public static SnapshotService _snapshotService; - public static ConsoleProxyService _consoleProxyService; - public static VpcVirtualNetworkApplianceService _routerService; - public static ResponseGenerator _responseGenerator; - public static EntityManager _entityMgr; - public static RulesService _rulesService; - public static LoadBalancingRulesService _lbService; - public static RemoteAccessVpnService _ravService; - public static BareMetalVmService _bareMetalVmService; - public static ProjectService _projectService; - public static FirewallService _firewallService; - public static DomainService _domainService; - public static ResourceLimitService _resourceLimitService; - public static IdentityService _identityService; - public static StorageNetworkService _storageNetworkService; - public static TaggedResourceService _taggedResourceService; - public static VpcService _vpcService; - public static NetworkACLService _networkACLService; - public static Site2SiteVpnService _s2sVpnService; - - static void setComponents(ResponseGenerator generator) { - ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); - _mgr = (ManagementService) ComponentLocator.getComponent(ManagementService.Name); - _accountService = locator.getManager(AccountService.class); - _configService = locator.getManager(ConfigurationService.class); - _userVmService = locator.getManager(UserVmService.class); - _storageService = locator.getManager(StorageService.class); - _resourceService = locator.getManager(ResourceService.class); - _networkService = locator.getManager(NetworkService.class); - _templateService = locator.getManager(TemplateService.class); - _securityGroupService = locator.getManager(SecurityGroupService.class); - _snapshotService = locator.getManager(SnapshotService.class); - _consoleProxyService = locator.getManager(ConsoleProxyService.class); - _routerService = locator.getManager(VpcVirtualNetworkApplianceService.class); - _entityMgr = locator.getManager(EntityManager.class); - _rulesService = locator.getManager(RulesService.class); - _lbService = locator.getManager(LoadBalancingRulesService.class); - _ravService = locator.getManager(RemoteAccessVpnService.class); - _responseGenerator = generator; - _bareMetalVmService = locator.getManager(BareMetalVmService.class); - _projectService = locator.getManager(ProjectService.class); - _firewallService = locator.getManager(FirewallService.class); - _domainService = locator.getManager(DomainService.class); - _resourceLimitService = locator.getManager(ResourceLimitService.class); - _identityService = locator.getManager(IdentityService.class); - _storageNetworkService = locator.getManager(StorageNetworkService.class); - _taggedResourceService = locator.getManager(TaggedResourceService.class); - _vpcService = locator.getManager(VpcService.class); - _networkACLService = locator.getManager(NetworkACLService.class); - _s2sVpnService = locator.getManager(Site2SiteVpnService.class); - } - - public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException; - - public String getResponseType() { - if (responseType == null) { - return RESPONSE_TYPE_XML; - } - return responseType; - } - - public void setResponseType(String responseType) { - this.responseType = responseType; - } - - public abstract String getCommandName(); - - /** - * For commands the API framework needs to know the owner of the object being acted upon. This method is - * used to determine that information. - * - * @return the id of the account that owns the object being acted upon - */ - public abstract long getEntityOwnerId(); - - public Object getResponseObject() { - return _responseObject; - } - - public void setResponseObject(Object responseObject) { - _responseObject = responseObject; - } - - public ManagementService getMgmtServiceRef() { - return _mgr; - } - - public static String getDateString(Date date) { - if (date == null) { - return ""; - } - String formattedString = null; - synchronized (_outputFormat) { - formattedString = _outputFormat.format(date); - } - return formattedString; - } - - // FIXME: move this to a utils method so that maps can be unpacked and integer/long values can be appropriately cast - @SuppressWarnings({ "unchecked", "rawtypes" }) - public Map<String, Object> unpackParams(Map<String, String> params) { - Map<String, Object> lowercaseParams = new HashMap<String, Object>(); - for (String key : params.keySet()) { - int arrayStartIndex = key.indexOf('['); - int arrayStartLastIndex = key.lastIndexOf('['); - if (arrayStartIndex != arrayStartLastIndex) { - throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key - + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); - } - - if (arrayStartIndex > 0) { - int arrayEndIndex = key.indexOf(']'); - int arrayEndLastIndex = key.lastIndexOf(']'); - if ((arrayEndIndex < arrayStartIndex) || (arrayEndIndex != arrayEndLastIndex)) { - // malformed parameter - throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key - + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); - } - - // Now that we have an array object, check for a field name in the case of a complex object - int fieldIndex = key.indexOf('.'); - String fieldName = null; - if (fieldIndex < arrayEndIndex) { - throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key - + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); - } else { - fieldName = key.substring(fieldIndex + 1); - } - - // parse the parameter name as the text before the first '[' character - String paramName = key.substring(0, arrayStartIndex); - paramName = paramName.toLowerCase(); - - Map<Integer, Map> mapArray = null; - Map<String, Object> mapValue = null; - String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex); - int index = 0; - boolean parsedIndex = false; - try { - if (indexStr != null) { - index = Integer.parseInt(indexStr); - parsedIndex = true; - } - } catch (NumberFormatException nfe) { - s_logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error."); - } - - if (!parsedIndex) { - throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key - + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); - } - - Object value = lowercaseParams.get(paramName); - if (value == null) { - // for now, assume object array with sub fields - mapArray = new HashMap<Integer, Map>(); - mapValue = new HashMap<String, Object>(); - mapArray.put(Integer.valueOf(index), mapValue); - } else if (value instanceof Map) { - mapArray = (HashMap) value; - mapValue = mapArray.get(Integer.valueOf(index)); - if (mapValue == null) { - mapValue = new HashMap<String, Object>(); - mapArray.put(Integer.valueOf(index), mapValue); - } - } - - // we are ready to store the value for a particular field into the map for this object - mapValue.put(fieldName, params.get(key)); - - lowercaseParams.put(paramName, mapArray); - } else { - lowercaseParams.put(key.toLowerCase(), params.get(key)); - } - } - return lowercaseParams; - } - - public String buildResponse(ServerApiException apiException, String responseType) { - StringBuffer sb = new StringBuffer(); - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - // JSON response - sb.append("{ \"" + getCommandName() + "\" : { " + "\"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},"); - sb.append("\"errorcode\" : \"" + apiException.getErrorCode() + "\", \"description\" : \"" + apiException.getDescription() + "\" } }"); - } else { - sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); - sb.append("<" + getCommandName() + ">"); - sb.append("<errorcode>" + apiException.getErrorCode() + "</errorcode>"); - sb.append("<description>" + escapeXml(apiException.getDescription()) + "</description>"); - sb.append("</" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">"); - } - return sb.toString(); - } - - public String buildResponse(List<Pair<String, Object>> tagList, String responseType) { - StringBuffer prefixSb = new StringBuffer(); - StringBuffer suffixSb = new StringBuffer(); - - // set up the return value with the name of the response - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - prefixSb.append("{ \"" + getCommandName() + "\" : { \"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},"); - } else { - prefixSb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); - prefixSb.append("<" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">"); - } - - int i = 0; - for (Pair<String, Object> tagData : tagList) { - String tagName = tagData.first(); - Object tagValue = tagData.second(); - if (tagValue instanceof Object[]) { - Object[] subObjects = (Object[]) tagValue; - if (subObjects.length < 1) { - continue; - } - writeObjectArray(responseType, suffixSb, i++, tagName, subObjects); - } else { - writeNameValuePair(suffixSb, tagName, tagValue, responseType, i++); - } - } - - if (suffixSb.length() > 0) { - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { // append comma only if we have some suffix else -// not as per strict Json syntax. - prefixSb.append(","); - } - prefixSb.append(suffixSb); - } - // close the response - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - prefixSb.append("} }"); - } else { - prefixSb.append("</" + getCommandName() + ">"); - } - return prefixSb.toString(); - } - - private void writeNameValuePair(StringBuffer sb, String tagName, Object tagValue, String responseType, int propertyCount) { - if (tagValue == null) { - return; - } - - if (tagValue instanceof Object[]) { - Object[] subObjects = (Object[]) tagValue; - if (subObjects.length < 1) { - return; - } - writeObjectArray(responseType, sb, propertyCount, tagName, subObjects); - } else { - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - String seperator = ((propertyCount > 0) ? ", " : ""); - sb.append(seperator + "\"" + tagName + "\" : \"" + escapeJSON(tagValue.toString()) + "\""); - } else { - sb.append("<" + tagName + ">" + escapeXml(tagValue.toString()) + "</" + tagName + ">"); - } - } - } - - @SuppressWarnings("rawtypes") - private void writeObjectArray(String responseType, StringBuffer sb, int propertyCount, String tagName, Object[] subObjects) { - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - String separator = ((propertyCount > 0) ? ", " : ""); - sb.append(separator); - } - int j = 0; - for (Object subObject : subObjects) { - if (subObject instanceof List) { - List subObjList = (List) subObject; - writeSubObject(sb, tagName, subObjList, responseType, j++); - } - } - - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - sb.append("]"); - } - } - - @SuppressWarnings("rawtypes") - private void writeSubObject(StringBuffer sb, String tagName, List tagList, String responseType, int objectCount) { - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - sb.append(((objectCount == 0) ? "\"" + tagName + "\" : [ { " : ", { ")); - } else { - sb.append("<" + tagName + ">"); - } - - int i = 0; - for (Object tag : tagList) { - if (tag instanceof Pair) { - Pair nameValuePair = (Pair) tag; - writeNameValuePair(sb, (String) nameValuePair.first(), nameValuePair.second(), responseType, i++); - } - } - - if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { - sb.append("}"); - } else { - sb.append("</" + tagName + ">"); - } - } - - /** - * Escape xml response set to false by default. API commands to override this method to allow escaping - */ - public boolean requireXmlEscape() { - return true; - } - - private String escapeXml(String xml) { - if (!requireXmlEscape()) { - return xml; - } - int iLen = xml.length(); - if (iLen == 0) { - return xml; - } - StringBuffer sOUT = new StringBuffer(iLen + 256); - int i = 0; - for (; i < iLen; i++) { - char c = xml.charAt(i); - if (c == '<') { - sOUT.append("<"); - } else if (c == '>') { - sOUT.append(">"); - } else if (c == '&') { - sOUT.append("&"); - } else if (c == '"') { - sOUT.append("""); - } else if (c == '\'') { - sOUT.append("'"); - } else { - sOUT.append(c); - } - } - return sOUT.toString(); - } - - private static String escapeJSON(String str) { - if (str == null) { - return str; - } - - return str.replace("\"", "\\\""); - } - - protected long getInstanceIdFromJobSuccessResult(String result) { - s_logger.debug("getInstanceIdFromJobSuccessResult not overridden in subclass " + this.getClass().getName()); - return 0; - } - - public static boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); - } - - public static boolean isRootAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN)); - } - - public void setFullUrlParams(Map<String, String> map) { - this.fullUrlParams = map; - } - - public Map<String, String> getFullUrlParams() { - return this.fullUrlParams; - } - - public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { - if (accountName != null) { - if (domainId == null) { - throw new InvalidParameterValueException("Account must be specified with domainId parameter"); - } - - Domain domain = _domainService.getDomain(domainId); - if (domain == null) { - throw new InvalidParameterValueException("Unable to find domain by id"); - } - - Account account = _accountService.getActiveAccountByName(accountName, domainId); - if (account != null && account.getType() != Account.ACCOUNT_TYPE_PROJECT) { - if (!enabledOnly || account.getState() == Account.State.enabled) { - return account.getId(); - } else { - throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); - } - } else { - List<IdentityProxy> idList = new ArrayList<IdentityProxy>(); - idList.add(new IdentityProxy("domain", domainId, "domainId")); - throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain with specified id"); - } - } - - if (projectId != null) { - Project project = _projectService.getProject(projectId); - if (project != null) { - if (!enabledOnly || project.getState() == Project.State.Active) { - return project.getProjectAccountId(); - } else { - PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); - throw ex; - } - } else { - throw new InvalidParameterValueException("Unable to find project by id"); - } - } - return null; - } -} + +public abstract class BaseCmd { + private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName()); + + public static final String USER_ERROR_MESSAGE = "Internal error executing command, please contact your system administrator"; + public static final int PROGRESS_INSTANCE_CREATED = 1; + + public static final String RESPONSE_TYPE_XML = "xml"; + public static final String RESPONSE_TYPE_JSON = "json"; + + public enum CommandType { + BOOLEAN, DATE, FLOAT, INTEGER, SHORT, LIST, LONG, OBJECT, MAP, STRING, TZDATE + } + + // FIXME: Extract these out into a separate file + // Client error codes + public static final int MALFORMED_PARAMETER_ERROR = 430; + public static final int PARAM_ERROR = 431; + public static final int UNSUPPORTED_ACTION_ERROR = 432; + public static final int PAGE_LIMIT_EXCEED = 433; + + // Server error codes + public static final int INTERNAL_ERROR = 530; + public static final int ACCOUNT_ERROR = 531; + public static final int ACCOUNT_RESOURCE_LIMIT_ERROR = 532; + public static final int INSUFFICIENT_CAPACITY_ERROR = 533; + public static final int RESOURCE_UNAVAILABLE_ERROR = 534; + public static final int RESOURCE_ALLOCATION_ERROR = 534; + public static final int RESOURCE_IN_USE_ERROR = 536; + public static final int NETWORK_RULE_CONFLICT_ERROR = 537; + + public static final DateFormat INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + public static final DateFormat NEW_INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public static Pattern newInputDateFormat = Pattern.compile("[\\d]+-[\\d]+-[\\d]+ [\\d]+:[\\d]+:[\\d]+"); + private static final DateFormat _outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + + private Object _responseObject = null; + private Map<String, String> fullUrlParams; + + @Parameter(name = "response", type = CommandType.STRING) + private String responseType; + + public static ComponentLocator s_locator; + public static ConfigurationService _configService; + public static AccountService _accountService; + public static UserVmService _userVmService; + public static ManagementService _mgr; + public static StorageService _storageService; + public static ResourceService _resourceService; + public static NetworkService _networkService; + public static TemplateService _templateService; + public static SecurityGroupService _securityGroupService; + public static SnapshotService _snapshotService; + public static ConsoleProxyService _consoleProxyService; + public static VpcVirtualNetworkApplianceService _routerService; + public static ResponseGenerator _responseGenerator; + public static EntityManager _entityMgr; + public static RulesService _rulesService; + public static LoadBalancingRulesService _lbService; + public static RemoteAccessVpnService _ravService; + public static BareMetalVmService _bareMetalVmService; + public static ProjectService _projectService; + public static FirewallService _firewallService; + public static DomainService _domainService; + public static ResourceLimitService _resourceLimitService; + public static IdentityService _identityService; + public static StorageNetworkService _storageNetworkService; + public static TaggedResourceService _taggedResourceService; + public static VpcService _vpcService; + public static NetworkACLService _networkACLService; + public static Site2SiteVpnService _s2sVpnService; + + static void setComponents(ResponseGenerator generator) { + ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name); + _mgr = (ManagementService) ComponentLocator.getComponent(ManagementService.Name); + _accountService = locator.getManager(AccountService.class); + _configService = locator.getManager(ConfigurationService.class); + _userVmService = locator.getManager(UserVmService.class); + _storageService = locator.getManager(StorageService.class); + _resourceService = locator.getManager(ResourceService.class); + _networkService = locator.getManager(NetworkService.class); + _templateService = locator.getManager(TemplateService.class); + _securityGroupService = locator.getManager(SecurityGroupService.class); + _snapshotService = locator.getManager(SnapshotService.class); + _consoleProxyService = locator.getManager(ConsoleProxyService.class); + _routerService = locator.getManager(VpcVirtualNetworkApplianceService.class); + _entityMgr = locator.getManager(EntityManager.class); + _rulesService = locator.getManager(RulesService.class); + _lbService = locator.getManager(LoadBalancingRulesService.class); + _ravService = locator.getManager(RemoteAccessVpnService.class); + _responseGenerator = generator; + _bareMetalVmService = locator.getManager(BareMetalVmService.class); + _projectService = locator.getManager(ProjectService.class); + _firewallService = locator.getManager(FirewallService.class); + _domainService = locator.getManager(DomainService.class); + _resourceLimitService = locator.getManager(ResourceLimitService.class); + _identityService = locator.getManager(IdentityService.class); + _storageNetworkService = locator.getManager(StorageNetworkService.class); + _taggedResourceService = locator.getManager(TaggedResourceService.class); + _vpcService = locator.getManager(VpcService.class); + _networkACLService = locator.getManager(NetworkACLService.class); + _s2sVpnService = locator.getManager(Site2SiteVpnService.class); + } + + public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException; + + public String getResponseType() { + if (responseType == null) { + return RESPONSE_TYPE_XML; + } + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + public abstract String getCommandName(); + + /** + * For commands the API framework needs to know the owner of the object being acted upon. This method is + * used to determine that information. + * + * @return the id of the account that owns the object being acted upon + */ + public abstract long getEntityOwnerId(); + + public Object getResponseObject() { + return _responseObject; + } + + public void setResponseObject(Object responseObject) { + _responseObject = responseObject; + } + + public ManagementService getMgmtServiceRef() { + return _mgr; + } + + public static String getDateString(Date date) { + if (date == null) { + return ""; + } + String formattedString = null; + synchronized (_outputFormat) { + formattedString = _outputFormat.format(date); + } + return formattedString; + } + + // FIXME: move this to a utils method so that maps can be unpacked and integer/long values can be appropriately cast + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Map<String, Object> unpackParams(Map<String, String> params) { + Map<String, Object> lowercaseParams = new HashMap<String, Object>(); + for (String key : params.keySet()) { + int arrayStartIndex = key.indexOf('['); + int arrayStartLastIndex = key.lastIndexOf('['); + if (arrayStartIndex != arrayStartLastIndex) { + throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key + + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); + } + + if (arrayStartIndex > 0) { + int arrayEndIndex = key.indexOf(']'); + int arrayEndLastIndex = key.lastIndexOf(']'); + if ((arrayEndIndex < arrayStartIndex) || (arrayEndIndex != arrayEndLastIndex)) { + // malformed parameter + throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key + + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); + } + + // Now that we have an array object, check for a field name in the case of a complex object + int fieldIndex = key.indexOf('.'); + String fieldName = null; + if (fieldIndex < arrayEndIndex) { + throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key + + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); + } else { + fieldName = key.substring(fieldIndex + 1); + } + + // parse the parameter name as the text before the first '[' character + String paramName = key.substring(0, arrayStartIndex); + paramName = paramName.toLowerCase(); + + Map<Integer, Map> mapArray = null; + Map<String, Object> mapValue = null; + String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex); + int index = 0; + boolean parsedIndex = false; + try { + if (indexStr != null) { + index = Integer.parseInt(indexStr); + parsedIndex = true; + } + } catch (NumberFormatException nfe) { + s_logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error."); + } + + if (!parsedIndex) { + throw new ServerApiException(MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key + + "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup"); + } + + Object value = lowercaseParams.get(paramName); + if (value == null) { + // for now, assume object array with sub fields + mapArray = new HashMap<Integer, Map>(); + mapValue = new HashMap<String, Object>(); + mapArray.put(Integer.valueOf(index), mapValue); + } else if (value instanceof Map) { + mapArray = (HashMap) value; + mapValue = mapArray.get(Integer.valueOf(index)); + if (mapValue == null) { + mapValue = new HashMap<String, Object>(); + mapArray.put(Integer.valueOf(index), mapValue); + } + } + + // we are ready to store the value for a particular field into the map for this object + mapValue.put(fieldName, params.get(key)); + + lowercaseParams.put(paramName, mapArray); + } else { + lowercaseParams.put(key.toLowerCase(), params.get(key)); + } + } + return lowercaseParams; + } + + public String buildResponse(ServerApiException apiException, String responseType) { + StringBuffer sb = new StringBuffer(); + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + // JSON response + sb.append("{ \"" + getCommandName() + "\" : { " + "\"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},"); + sb.append("\"errorcode\" : \"" + apiException.getErrorCode() + "\", \"description\" : \"" + apiException.getDescription() + "\" } }"); + } else { + sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); + sb.append("<" + getCommandName() + ">"); + sb.append("<errorcode>" + apiException.getErrorCode() + "</errorcode>"); + sb.append("<description>" + escapeXml(apiException.getDescription()) + "</description>"); + sb.append("</" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">"); + } + return sb.toString(); + } + + public String buildResponse(List<Pair<String, Object>> tagList, String responseType) { + StringBuffer prefixSb = new StringBuffer(); + StringBuffer suffixSb = new StringBuffer(); + + // set up the return value with the name of the response + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + prefixSb.append("{ \"" + getCommandName() + "\" : { \"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},"); + } else { + prefixSb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); + prefixSb.append("<" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">"); + } + + int i = 0; + for (Pair<String, Object> tagData : tagList) { + String tagName = tagData.first(); + Object tagValue = tagData.second(); + if (tagValue instanceof Object[]) { + Object[] subObjects = (Object[]) tagValue; + if (subObjects.length < 1) { + continue; + } + writeObjectArray(responseType, suffixSb, i++, tagName, subObjects); + } else { + writeNameValuePair(suffixSb, tagName, tagValue, responseType, i++); + } + } + + if (suffixSb.length() > 0) { + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { // append comma only if we have some suffix else +// not as per strict Json syntax. + prefixSb.append(","); + } + prefixSb.append(suffixSb); + } + // close the response + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + prefixSb.append("} }"); + } else { + prefixSb.append("</" + getCommandName() + ">"); + } + return prefixSb.toString(); + } + + private void writeNameValuePair(StringBuffer sb, String tagName, Object tagValue, String responseType, int propertyCount) { + if (tagValue == null) { + return; + } + + if (tagValue instanceof Object[]) { + Object[] subObjects = (Object[]) tagValue; + if (subObjects.length < 1) { + return; + } + writeObjectArray(responseType, sb, propertyCount, tagName, subObjects); + } else { + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + String seperator = ((propertyCount > 0) ? ", " : ""); + sb.append(seperator + "\"" + tagName + "\" : \"" + escapeJSON(tagValue.toString()) + "\""); + } else { + sb.append("<" + tagName + ">" + escapeXml(tagValue.toString()) + "</" + tagName + ">"); + } + } + } + + @SuppressWarnings("rawtypes") + private void writeObjectArray(String responseType, StringBuffer sb, int propertyCount, String tagName, Object[] subObjects) { + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + String separator = ((propertyCount > 0) ? ", " : ""); + sb.append(separator); + } + int j = 0; + for (Object subObject : subObjects) { + if (subObject instanceof List) { + List subObjList = (List) subObject; + writeSubObject(sb, tagName, subObjList, responseType, j++); + } + } + + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + sb.append("]"); + } + } + + @SuppressWarnings("rawtypes") + private void writeSubObject(StringBuffer sb, String tagName, List tagList, String responseType, int objectCount) { + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + sb.append(((objectCount == 0) ? "\"" + tagName + "\" : [ { " : ", { ")); + } else { + sb.append("<" + tagName + ">"); + } + + int i = 0; + for (Object tag : tagList) { + if (tag instanceof Pair) { + Pair nameValuePair = (Pair) tag; + writeNameValuePair(sb, (String) nameValuePair.first(), nameValuePair.second(), responseType, i++); + } + } + + if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { + sb.append("}"); + } else { + sb.append("</" + tagName + ">"); + } + } + + /** + * Escape xml response set to false by default. API commands to override this method to allow escaping + */ + public boolean requireXmlEscape() { + return true; + } + + private String escapeXml(String xml) { + if (!requireXmlEscape()) { + return xml; + } + int iLen = xml.length(); + if (iLen == 0) { + return xml; + } + StringBuffer sOUT = new StringBuffer(iLen + 256); + int i = 0; + for (; i < iLen; i++) { + char c = xml.charAt(i); + if (c == '<') { + sOUT.append("<"); + } else if (c == '>') { + sOUT.append(">"); + } else if (c == '&') { + sOUT.append("&"); + } else if (c == '"') { + sOUT.append("""); + } else if (c == '\'') { + sOUT.append("'"); + } else { + sOUT.append(c); + } + } + return sOUT.toString(); + } + + private static String escapeJSON(String str) { + if (str == null) { + return str; + } + + return str.replace("\"", "\\\""); + } + + protected long getInstanceIdFromJobSuccessResult(String result) { + s_logger.debug("getInstanceIdFromJobSuccessResult not overridden in subclass " + this.getClass().getName()); + return 0; + } + + public static boolean isAdmin(short accountType) { + return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || + (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || + (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); + } + + public static boolean isRootAdmin(short accountType) { + return ((accountType == Account.ACCOUNT_TYPE_ADMIN)); + } + + public void setFullUrlParams(Map<String, String> map) { + this.fullUrlParams = map; + } + + public Map<String, String> getFullUrlParams() { + return this.fullUrlParams; + } + + public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { + if (accountName != null) { + if (domainId == null) { + throw new InvalidParameterValueException("Account must be specified with domainId parameter"); + } + + Domain domain = _domainService.getDomain(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id"); + } + + Account account = _accountService.getActiveAccountByName(accountName, domainId); + if (account != null && account.getType() != Account.ACCOUNT_TYPE_PROJECT) { + if (!enabledOnly || account.getState() == Account.State.enabled) { + return account.getId(); + } else { + throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); + } + } else { + List<IdentityProxy> idList = new ArrayList<IdentityProxy>(); + idList.add(new IdentityProxy("domain", domainId, "domainId")); + throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain with specified id"); + } + } + + if (projectId != null) { + Project project = _projectService.getProject(projectId); + if (project != null) { + if (!enabledOnly || project.getState() == Project.State.Active) { + return project.getProjectAccountId(); + } else { + PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active"); + ex.addProxyObject(project, projectId, "projectId"); + throw ex; + } + } else { + throw new InvalidParameterValueException("Unable to find project by id"); + } + } + return null; + } +}
