@Test public void testExecuteForNullResult() { ResourceService resourceService = Mockito.mock(ResourceService.class); try { Mockito.when(resourceService.discoverCluster(addClusterCmd)).thenReturn(null); } catch (ResourceInUseException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (DiscoveryException e) { // TODO Auto-generated catch block e.printStackTrace(); } addClusterCmd._resourceService = resourceService; try { addClusterCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to add cluster", exception.getDescription()); } }
@Test public void testExecuteWithNullPassword() { ReflectionTestUtils.setField(createAccountCmd, "password", null); try { createAccountCmd.execute(); Assert.fail("should throw exception for a null password"); } catch (ServerApiException e) { Assert.assertEquals(ApiErrorCode.PARAM_ERROR, e.getErrorCode()); Assert.assertEquals("Empty passwords are not allowed", e.getMessage()); } Mockito.verify(accountService, Mockito.never()) .createUserAccount( null, null, null, null, null, null, null, accountType, domainId, null, null, null, null); }
@Override public String getSerializedApiError( ServerApiException ex, Map<String, Object[]> apiCommandParams, String responseType) { String responseName = null; Class<?> cmdClass = null; String responseText = null; if (ex == null) { // this call should not be invoked with null exception return getSerializedApiError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Some internal error happened", apiCommandParams, responseType); } try { if (ex.getErrorCode() == ApiErrorCode.UNSUPPORTED_ACTION_ERROR || apiCommandParams == null || apiCommandParams.isEmpty()) { responseName = "errorresponse"; } else { Object cmdObj = apiCommandParams.get("command"); // cmd name can be null when "command" parameter is missing in // the request if (cmdObj != null) { String cmdName = ((String[]) cmdObj)[0]; cmdClass = getCmdClass(cmdName); if (cmdClass != null) { responseName = ((BaseCmd) cmdClass.newInstance()).getCommandName(); } else { responseName = "errorresponse"; } } } ExceptionResponse apiResponse = new ExceptionResponse(); apiResponse.setErrorCode(ex.getErrorCode().getHttpCode()); apiResponse.setErrorText(ex.getDescription()); apiResponse.setResponseName(responseName); ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList(); if (idList != null) { for (int i = 0; i < idList.size(); i++) { apiResponse.addProxyObject(idList.get(i)); } } // Also copy over the cserror code and the function/layer in which // it was thrown. apiResponse.setCSErrorCode(ex.getCSErrorCode()); SerializationContext.current().setUuidTranslation(true); responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType); } catch (Exception e) { s_logger.error("Exception responding to http request", e); } return responseText; }
@Test public void testExecuteForEmptyResult() { ResourceService resourceService = Mockito.mock(ResourceService.class); addClusterCmd._resourceService = resourceService; try { addClusterCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to add cluster", exception.getDescription()); } }
@Test public void testCreateFailure() { UserVmService userVmService = Mockito.mock(UserVmService.class); try { UserVm uservm = Mockito.mock(UserVm.class); Mockito.when(userVmService.upgradeVirtualMachine(scaleVMCmd)).thenReturn(null); } catch (Exception e) { Assert.fail("Received exception when success expected " + e.getMessage()); } scaleVMCmd._userVmService = userVmService; try { scaleVMCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to scale vm", exception.getDescription()); } }
@Test public void testCreateFailure() { RegionService regionService = Mockito.mock(RegionService.class); Region region = Mockito.mock(Region.class); Mockito.when( regionService.addRegion( Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(null); addRegionCmd._regionService = regionService; try { addRegionCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to add Region", exception.getDescription()); } }
@Override public void execute() { try { if ((getRamOvercommitRaito().compareTo(1f) <= 0) | (getCpuOvercommitRatio().compareTo(1f) <= 0)) { throw new InvalidParameterValueException( "Cpu and ram overcommit ratios should not be less than 1"); } List<? extends Cluster> result = _resourceService.discoverCluster(this); ListResponse<ClusterResponse> response = new ListResponse<ClusterResponse>(); List<ClusterResponse> clusterResponses = new ArrayList<ClusterResponse>(); if (result != null && result.size() > 0) { for (Cluster cluster : result) { ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, false); clusterResponses.add(clusterResponse); } } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add cluster"); } response.setResponses(clusterResponses); response.setResponseName(getCommandName()); this.setResponseObject(response); } catch (DiscoveryException ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ResourceInUseException ex) { s_logger.warn("Exception: ", ex); ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); for (String proxyObj : ex.getIdProxyList()) { e.addProxyObject(proxyObj); } throw e; } }
@Override @SuppressWarnings("rawtypes") public String handleRequest(Map params, String responseType, StringBuffer auditTrailSb) throws ServerApiException { String response = null; String[] command = null; try { command = (String[]) params.get("command"); if (command == null) { s_logger.error("invalid request, no command sent"); if (s_logger.isTraceEnabled()) { s_logger.trace("dumping request parameters"); for (Object key : params.keySet()) { String keyStr = (String) key; String[] value = (String[]) params.get(key); s_logger.trace( " key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value[0])); } } throw new ServerApiException( ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "Invalid request, no command sent"); } else { Map<String, String> paramMap = new HashMap<String, String>(); Set keys = params.keySet(); Iterator keysIter = keys.iterator(); while (keysIter.hasNext()) { String key = (String) keysIter.next(); if ("command".equalsIgnoreCase(key)) { continue; } String[] value = (String[]) params.get(key); // fail if parameter value contains ASCII control (non-printable) characters if (value[0] != null) { Pattern pattern = Pattern.compile(controlCharacters); Matcher matcher = pattern.matcher(value[0]); if (matcher.find()) { throw new ServerApiException( ApiErrorCode.PARAM_ERROR, "Received value " + value[0] + " for parameter " + key + " is invalid, contains illegal ASCII non-printable characters"); } } paramMap.put(key, value[0]); } Class<?> cmdClass = getCmdClass(command[0]); if (cmdClass != null) { BaseCmd cmdObj = (BaseCmd) cmdClass.newInstance(); cmdObj = ComponentContext.inject(cmdObj); cmdObj.configure(); cmdObj.setFullUrlParams(paramMap); cmdObj.setResponseType(responseType); cmdObj.setHttpMethod(paramMap.get("httpmethod").toString()); // This is where the command is either serialized, or directly dispatched response = queueCommand(cmdObj, paramMap); buildAuditTrail(auditTrailSb, command[0], response); } else { if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) { String errorString = "Unknown API command: " + ((command == null) ? "null" : command[0]); s_logger.warn(errorString); auditTrailSb.append(" " + errorString); throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, errorString); } } } } catch (InvalidParameterValueException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (IllegalArgumentException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (PermissionDeniedException ex) { ArrayList<ExceptionProxyObject> idList = ex.getIdProxyList(); if (idList != null) { StringBuffer buf = new StringBuffer(); for (ExceptionProxyObject obj : idList) { buf.append(obj.getDescription()); buf.append(":"); buf.append(obj.getUuid()); buf.append(" "); } s_logger.info( "PermissionDenied: " + ex.getMessage() + " on objs: [" + buf.toString() + "]"); } else { s_logger.info("PermissionDenied: " + ex.getMessage()); } throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, ex.getMessage(), ex); } catch (AccountLimitException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.ACCOUNT_RESOURCE_LIMIT_ERROR, ex.getMessage(), ex); } catch (InsufficientCapacityException ex) { s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg, ex); } catch (ResourceAllocationException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage(), ex); } catch (ResourceUnavailableException ex) { s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, errorMsg, ex); } catch (ServerApiException ex) { s_logger.info(ex.getDescription()); throw ex; } catch (Exception ex) { s_logger.error( "unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex); String errorMsg = ex.getMessage(); if (CallContext.current().getCallingAccount().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg, ex); } return response; }
// NOTE: handle() only handles over the wire (OTW) requests from integration.api.port 8096 // If integration api port is not configured, actual OTW requests will be received by ApiServlet @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { // Create StringBuffer to log information in access log StringBuffer sb = new StringBuffer(); HttpServerConnection connObj = (HttpServerConnection) context.getAttribute("http.connection"); if (connObj instanceof SocketHttpServerConnection) { InetAddress remoteAddr = ((SocketHttpServerConnection) connObj).getRemoteAddress(); sb.append(remoteAddr.toString() + " -- "); } sb.append(StringUtils.cleanString(request.getRequestLine().toString())); try { List<NameValuePair> paramList = null; try { paramList = URLEncodedUtils.parse(new URI(request.getRequestLine().getUri()), "UTF-8"); } catch (URISyntaxException e) { s_logger.error("Error parsing url request", e); } // Use Multimap as the parameter map should be in the form (name=String, value=String[]) // So parameter values are stored in a list for the same name key // APITODO: Use Guava's (import com.google.common.collect.Multimap;) // (Immutable)Multimap<String, String> paramMultiMap = HashMultimap.create(); // Map<String, Collection<String>> parameterMap = paramMultiMap.asMap(); Map parameterMap = new HashMap<String, String[]>(); String responseType = BaseCmd.RESPONSE_TYPE_XML; for (NameValuePair param : paramList) { if (param.getName().equalsIgnoreCase("response")) { responseType = param.getValue(); continue; } parameterMap.put(param.getName(), new String[] {param.getValue()}); } // Get the type of http method being used. parameterMap.put("httpmethod", new String[] {request.getRequestLine().getMethod()}); // Check responseType, if not among valid types, fallback to JSON if (!(responseType.equals(BaseCmd.RESPONSE_TYPE_JSON) || responseType.equals(BaseCmd.RESPONSE_TYPE_XML))) { responseType = BaseCmd.RESPONSE_TYPE_XML; } try { // always trust commands from API port, user context will always be // UID_SYSTEM/ACCOUNT_ID_SYSTEM CallContext.register(_accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); sb.insert( 0, "(userId=" + User.UID_SYSTEM + " accountId=" + Account.ACCOUNT_ID_SYSTEM + " sessionId=" + null + ") "); String responseText = handleRequest(parameterMap, responseType, sb); sb.append(" 200 " + ((responseText == null) ? 0 : responseText.length())); writeResponse(response, responseText, HttpStatus.SC_OK, responseType, null); } catch (ServerApiException se) { String responseText = getSerializedApiError(se, parameterMap, responseType); writeResponse( response, responseText, se.getErrorCode().getHttpCode(), responseType, se.getDescription()); sb.append(" " + se.getErrorCode() + " " + se.getDescription()); } catch (RuntimeException e) { // log runtime exception like NullPointerException to help identify the source easier s_logger.error("Unhandled exception, ", e); throw e; } } finally { s_accessLogger.info(sb.toString()); CallContext.unregister(); } }
@SuppressWarnings("rawtypes") public String handleRequest( Map params, boolean decode, String responseType, StringBuffer auditTrailSb) throws ServerApiException { String response = null; String[] command = null; try { command = (String[]) params.get("command"); if (command == null) { s_logger.error("invalid request, no command sent"); if (s_logger.isTraceEnabled()) { s_logger.trace("dumping request parameters"); for (Object key : params.keySet()) { String keyStr = (String) key; String[] value = (String[]) params.get(key); s_logger.trace( " key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value[0])); } } throw new ServerApiException( ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "Invalid request, no command sent"); } else { Map<String, String> paramMap = new HashMap<String, String>(); Set keys = params.keySet(); Iterator keysIter = keys.iterator(); while (keysIter.hasNext()) { String key = (String) keysIter.next(); if ("command".equalsIgnoreCase(key)) { continue; } String[] value = (String[]) params.get(key); String decodedValue = null; if (decode) { try { decodedValue = URLDecoder.decode(value[0], "UTF-8"); } catch (UnsupportedEncodingException usex) { s_logger.warn(key + " could not be decoded, value = " + value[0]); throw new ServerApiException( ApiErrorCode.PARAM_ERROR, key + " could not be decoded, received value " + value[0]); } catch (IllegalArgumentException iae) { s_logger.warn(key + " could not be decoded, value = " + value[0]); throw new ServerApiException( ApiErrorCode.PARAM_ERROR, key + " could not be decoded, received value " + value[0] + " which contains illegal characters eg.%"); } } else { decodedValue = value[0]; } paramMap.put(key, decodedValue); } Class<?> cmdClass = getCmdClass(command[0]); if (cmdClass != null) { BaseCmd cmdObj = (BaseCmd) cmdClass.newInstance(); cmdObj.setFullUrlParams(paramMap); cmdObj.setResponseType(responseType); // This is where the command is either serialized, or directly dispatched response = queueCommand(cmdObj, paramMap); buildAuditTrail(auditTrailSb, command[0], response); } else { if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) { String errorString = "Unknown API command: " + ((command == null) ? "null" : command[0]); s_logger.warn(errorString); auditTrailSb.append(" " + errorString); throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, errorString); } } } } catch (InvalidParameterValueException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (IllegalArgumentException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (PermissionDeniedException ex) { ArrayList<String> idList = ex.getIdProxyList(); if (idList != null) { s_logger.info( "PermissionDenied: " + ex.getMessage() + " on uuids: [" + StringUtils.listToCsvTags(idList) + "]"); } else { s_logger.info("PermissionDenied: " + ex.getMessage()); } throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, ex.getMessage(), ex); } catch (AccountLimitException ex) { s_logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.ACCOUNT_RESOURCE_LIMIT_ERROR, ex.getMessage(), ex); } catch (InsufficientCapacityException ex) { s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg, ex); } catch (ResourceAllocationException ex) { s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, errorMsg, ex); } catch (ResourceUnavailableException ex) { s_logger.info(ex.getMessage()); String errorMsg = ex.getMessage(); if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, errorMsg, ex); } catch (AsyncCommandQueued ex) { s_logger.error( "unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex); throw new ServerApiException( ApiErrorCode.INTERNAL_ERROR, "Internal server error, unable to execute request."); } catch (ServerApiException ex) { s_logger.info(ex.getDescription()); throw ex; } catch (Exception ex) { s_logger.error( "unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex); String errorMsg = ex.getMessage(); if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) { // hide internal details to non-admin user for security reason errorMsg = BaseCmd.USER_ERROR_MESSAGE; } throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg, ex); } return response; }