1)Implemented Suspend/Activate project

2)Email/token based invitation system
This commit is contained in:
alena 2011-10-06 16:10:10 -07:00
parent f6acda0b91
commit a17570ef51
41 changed files with 948 additions and 403 deletions

View File

@ -266,5 +266,6 @@ public class ApiConstants {
public static final String ROLE = "role";
public static final String USER = "user";
public static final String ACTIVE_ONLY = "activeonly";
public static final String TOKEN = "token";
}

View File

@ -480,7 +480,12 @@ public abstract class BaseCmd {
Project project = _projectService.getProject(projectId);
if (project != null) {
return project.getProjectAccountId();
if (project.getState() == Project.State.Active) {
return project.getProjectAccountId();
} else {
throw new InvalidParameterValueException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active");
}
} else {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}

View File

@ -0,0 +1,87 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.ProjectResponse;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.projects.Project;
import com.cloud.user.UserContext;
@Implementation(description="Activates a project", responseObject=ProjectResponse.class)
public class ActivateProjectCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(ActivateProjectCmd.class.getName());
private static final String s_name = "activaterojectresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="id of the project to be modified")
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Project project= _projectService.getProject(id);
//verify input parameters
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + id);
}
return _projectService.getProjectOwner(id).getId();
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute(){
UserContext.current().setEventDetails("Project id: "+ getId());
Project project = _projectService.activateProject(id);
if (project != null) {
ProjectResponse response = _responseGenerator.createProjectResponse(project);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to activate a project");
}
}
}

View File

@ -43,8 +43,11 @@ public class AddAccountToProjectCmd extends BaseCmd {
@Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, required=true, description="id of the project to add the account to")
private Long projectId;
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, required=true, description="name of the account to be added to the project")
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="name of the account to be added to the project")
private String accountName;
@Parameter(name=ApiConstants.EMAIL, type=CommandType.STRING, description="email to which invitation to the project is going to be sent")
private String email;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -59,8 +62,9 @@ public class AddAccountToProjectCmd extends BaseCmd {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
public String getEmail() {
return email;
}
@Override
@ -75,7 +79,7 @@ public class AddAccountToProjectCmd extends BaseCmd {
@Override
public void execute(){
UserContext.current().setEventDetails("Project id: "+ projectId + "; accountName " + accountName);
boolean result = _projectService.addAccountToProject(getProjectId(), getAccountName());
boolean result = _projectService.addAccountToProject(getProjectId(), getAccountName(), getEmail());
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -45,7 +45,7 @@ public class CreateProjectCmd extends BaseCmd {
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account who will own the project")
private String accountName;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, required=true, description="domain ID of the account owning a project")
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="domain ID of the account owning a project")
private Long domainId;
@Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="name of the project")

View File

@ -44,6 +44,9 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account who will own the VLAN. If VLAN is Zone wide, this parameter should be ommited")
private String accountName;
@Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="project who will own the VLAN. If VLAN is Zone wide, this parameter should be ommited")
private Long projectId;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="domain ID of the account owning a VLAN")
private Long domainId;
@ -119,7 +122,9 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
return zoneId;
}
public Long getProjectId() {
return projectId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -36,12 +36,14 @@ public class JoinProjectCmd extends BaseCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PROJECT_ID, required=true, type=CommandType.LONG, description="list by project id")
@Parameter(name=ApiConstants.PROJECT_ID, required=true, type=CommandType.LONG, description="id of the project to join")
private Long projectId;
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="list invitations for specified account; this parameter has to be specified with domainId")
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, required=true, description="account that is joining the project")
private String accountName;
@Parameter(name=ApiConstants.TOKEN, type=CommandType.STRING, description="list invitations for specified account; this parameter has to be specified with domainId")
private String token;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -59,6 +61,10 @@ public class JoinProjectCmd extends BaseCmd {
return s_name;
}
public String getToken() {
return token;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -73,7 +79,7 @@ public class JoinProjectCmd extends BaseCmd {
@Override
public void execute(){
UserContext.current().setEventDetails("Project id: "+ projectId + "; accountName " + accountName);
boolean result = _projectService.joinProject(projectId, accountName);
boolean result = _projectService.joinProject(projectId, accountName, token);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -68,6 +68,9 @@ public class ListEventsCmd extends BaseListCmd {
@Parameter(name=ApiConstants.TYPE, type=CommandType.STRING, description="the event type (see event types)")
private String type;
@Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="list events by projectId")
private Long projectId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -108,6 +111,10 @@ public class ListEventsCmd extends BaseListCmd {
public String getType() {
return type;
}
public Long getProjectId() {
return projectId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////

View File

@ -54,6 +54,9 @@ public class ListProjectsCmd extends BaseListCmd {
@Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="list projects by display text")
private String displayText;
@Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="list projects by state")
private String state;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -89,7 +92,7 @@ public class ListProjectsCmd extends BaseListCmd {
@Override
public void execute(){
List<? extends Project> projects = _projectService.listProjects(id, name, displayText, accountName, domainId, this.getKeyword(), this.getStartIndex(), this.getPageSizeVal());
List<? extends Project> projects = _projectService.listProjects(id, name, displayText, state, accountName, domainId, this.getKeyword(), this.getStartIndex(), this.getPageSizeVal());
ListResponse<ProjectResponse> response = new ListResponse<ProjectResponse>();
List<ProjectResponse> projectResponses = new ArrayList<ProjectResponse>();
for (Project project : projects) {

View File

@ -43,6 +43,9 @@ public class ListVlanIpRangesCmd extends BaseListCmd {
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account with which the VLAN IP range is associated. Must be used with the domainId parameter.")
private String accountName;
@Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="project who will own the VLAN")
private Long projectId;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the domain ID with which the VLAN IP range is associated. If used with the account parameter, returns all VLAN IP ranges for that account in the specified domain.")
private Long domainId;
@ -101,7 +104,10 @@ public class ListVlanIpRangesCmd extends BaseListCmd {
return forVirtualNetwork;
}
public Long getProjectId() {
return projectId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,103 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.ProjectResponse;
import com.cloud.api.response.SuccessResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.projects.Project;
import com.cloud.user.UserContext;
@Implementation(description="Suspends a project", responseObject=ProjectResponse.class)
public class SuspendProjectCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(SuspendProjectCmd.class.getName());
private static final String s_name = "suspendprojectresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="id of the project to be suspended")
private Long id;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long geId() {
return id;
}
@Override
public String getCommandName() {
return s_name;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() throws ConcurrentOperationException, ResourceUnavailableException{
UserContext.current().setEventDetails("Project Id: " + id);
Project project = _projectService.suspendProject(id);
if (project != null) {
ProjectResponse response = _responseGenerator.createProjectResponse(project);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to suspend a project");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_PROJECT_SUSPEND;
}
@Override
public String getEventDescription() {
return "Suspending project: " + id;
}
@Override
public long getEntityOwnerId() {
Project project= _projectService.getProject(id);
//verify input parameters
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + id);
}
return _projectService.getProjectOwner(id).getId();
}
}

View File

@ -32,7 +32,7 @@ import com.cloud.user.UserContext;
@Implementation(description="Updates a project", responseObject=ProjectResponse.class)
public class UpdateProjectCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(CreateProjectCmd.class.getName());
public static final Logger s_logger = Logger.getLogger(UpdateProjectCmd.class.getName());
private static final String s_name = "updateprojectresponse";

View File

@ -23,6 +23,7 @@ import com.cloud.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
public class AlertResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="the id of the alert")
private Long id;
@ -36,34 +37,18 @@ public class AlertResponse extends BaseResponse {
@SerializedName(ApiConstants.SENT) @Param(description="the date and time the alert was sent")
private Date lastSent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Short getAlertType() {
return alertType;
}
public void setAlertType(Short alertType) {
this.alertType = alertType;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getLastSent() {
return lastSent;
}
public void setLastSent(Date lastSent) {
this.lastSent = lastSent;
}

View File

@ -24,7 +24,8 @@ import com.cloud.event.Event;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class EventResponse extends BaseResponse {
@SuppressWarnings("unused")
public class EventResponse extends BaseResponse implements ControlledEntityResponse{
@SerializedName(ApiConstants.ID) @Param(description="the ID of the event")
private Long id;
@ -42,6 +43,12 @@ public class EventResponse extends BaseResponse {
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account name for the account that owns the object being acted on in the event (e.g. the owner of the virtual machine, ip address, or security group)")
private String accountName;
@SerializedName(ApiConstants.PROJECT_ID) @Param(description="the project id of the ipaddress")
private Long projectId;
@SerializedName(ApiConstants.PROJECT) @Param(description="the project name of the address")
private String projectName;
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the id of the account's domain")
private Long domainId;
@ -58,91 +65,60 @@ public class EventResponse extends BaseResponse {
@SerializedName("parentid") @Param(description="whether the event is parented")
private Long parentId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAccountName() {
return accountName;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getDomainId() {
return domainId;
}
@Override
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
public String getDomainName() {
return domainName;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Event.State getState() {
return state;
}
public void setState(Event.State state) {
this.state = state;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
@Override
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
@Override
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@ -114,14 +114,17 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
this.sourceNat = sourceNat;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}

View File

@ -16,11 +16,14 @@ public class ProjectInvitationResponse extends BaseResponse implements Controlle
private Long domainId;
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name where the project belongs to")
private String domain;
private String domainName;
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account name of the project's owner")
private String accountName;
@SerializedName(ApiConstants.EMAIL) @Param(description="the email the invitation was sent to")
private String email;
@SerializedName(ApiConstants.STATE) @Param(description="the invitation state")
private String invitationState;
@ -37,7 +40,7 @@ public class ProjectInvitationResponse extends BaseResponse implements Controlle
}
public void setDomainName(String domain) {
this.domain = domain;
this.domainName = domain;
}
public void setAccountName(String accountName) {
@ -48,5 +51,7 @@ public class ProjectInvitationResponse extends BaseResponse implements Controlle
this.invitationState = invitationState;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -42,6 +42,9 @@ public class ProjectResponse extends BaseResponse{
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account name of the project's owner")
private String ownerName;
@SerializedName(ApiConstants.STATE) @Param(description="the state of the project")
private String state;
public void setId(Long id) {
this.id = id;
@ -66,5 +69,8 @@ public class ProjectResponse extends BaseResponse{
public void setOwner(String owner) {
this.ownerName = owner;
}
public void setState(String state) {
this.state = state;
}
}

View File

@ -17,62 +17,65 @@
*/
package com.cloud.api.response;
import com.cloud.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class ResourceCountResponse extends BaseResponse {
@SerializedName("account") @Param(description="the account for which resource count's are updated")
@SuppressWarnings("unused")
public class ResourceCountResponse extends BaseResponse implements ControlledEntityResponse{
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account for which resource count's are updated")
private String accountName;
@SerializedName(ApiConstants.PROJECT_ID) @Param(description="the project id for which resource count's are updated")
private Long projectId;
@SerializedName(ApiConstants.PROJECT) @Param(description="the project name for which resource count's are updated")
private String projectName;
@SerializedName("domainid") @Param(description="the domain ID for which resource count's are updated")
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID for which resource count's are updated")
private Long domainId;
@SerializedName("domain") @Param(description="the domain name for which resource count's are updated")
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name for which resource count's are updated")
private String domainName;
@SerializedName("resourcetype") @Param(description="resource type. Values include 0, 1, 2, 3, 4. See the resourceType parameter for more information on these values.")
@SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4. See the resourceType parameter for more information on these values.")
private String resourceType;
@SerializedName("resourcecount") @Param(description="resource count")
private long resourceCount;
public String getAccountName() {
return accountName;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getDomainId() {
return domainId;
}
@Override
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
public String getDomainName() {
return domainName;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public String getResourceType() {
return resourceType;
}
public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}
public Long getResourceCount() {
return resourceCount;
}
public void setResourceCount(Long resourceCount) {
this.resourceCount = resourceCount;
}
@Override
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
@Override
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@ -23,16 +23,16 @@ import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
public class ResourceLimitResponse extends BaseResponse implements ControlledEntityResponse {
@SerializedName("account") @Param(description="the account of the resource limit")
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account of the resource limit")
private String accountName;
@SerializedName("domainid") @Param(description="the domain ID of the resource limit")
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID of the resource limit")
private Long domainId;
@SerializedName("domain") @Param(description="the domain name of the resource limit")
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the resource limit")
private String domainName;
@SerializedName("resourcetype") @Param(description="resource type. Values include 0, 1, 2, 3, 4. See the resourceType parameter for more information on these values.")
@SerializedName(ApiConstants.RESOURCE_TYPE) @Param(description="resource type. Values include 0, 1, 2, 3, 4. See the resourceType parameter for more information on these values.")
private String resourceType;
@SerializedName("max") @Param(description="the maximum number of the resource. A -1 means the resource currently has no limit.")

View File

@ -17,172 +17,130 @@
*/
package com.cloud.api.response;
import com.cloud.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class VlanIpRangeResponse extends BaseResponse {
@SerializedName("id") @Param(description="the ID of the VLAN IP range")
@SuppressWarnings("unused")
public class VlanIpRangeResponse extends BaseResponse implements ControlledEntityResponse{
@SerializedName(ApiConstants.ID) @Param(description="the ID of the VLAN IP range")
private Long id;
@SerializedName("forvirtualnetwork") @Param(description="the virtual network for the VLAN IP range")
private Boolean forVirtualNetwork;
@SerializedName("zoneid") @Param(description="the Zone ID of the VLAN IP range")
@SerializedName(ApiConstants.ZONE_ID) @Param(description="the Zone ID of the VLAN IP range")
private Long zoneId;
@SerializedName("vlan") @Param(description="the ID or VID of the VLAN.")
@SerializedName(ApiConstants.VLAN) @Param(description="the ID or VID of the VLAN.")
private String vlan;
@SerializedName("account") @Param(description="the account of the VLAN IP range")
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account of the VLAN IP range")
private String accountName;
@SerializedName("domainid") @Param(description="the domain ID of the VLAN IP range")
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID of the VLAN IP range")
private Long domainId;
@SerializedName("domain") @Param(description="the domain name of the VLAN IP range")
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the VLAN IP range")
private String domainName;
@SerializedName("podid") @Param(description="the Pod ID for the VLAN IP range")
@SerializedName(ApiConstants.POD_ID) @Param(description="the Pod ID for the VLAN IP range")
private Long podId;
@SerializedName("podname") @Param(description="the Pod name for the VLAN IP range")
private String podName;
@SerializedName("gateway") @Param(description="the gateway of the VLAN IP range")
@SerializedName(ApiConstants.GATEWAY) @Param(description="the gateway of the VLAN IP range")
private String gateway;
@SerializedName("netmask") @Param(description="the netmask of the VLAN IP range")
@SerializedName(ApiConstants.NETMASK) @Param(description="the netmask of the VLAN IP range")
private String netmask;
@SerializedName("description") @Param(description="the description of the VLAN IP range")
@SerializedName(ApiConstants.DESCRIPTION) @Param(description="the description of the VLAN IP range")
private String description;
@SerializedName("startip") @Param(description="the start ip of the VLAN IP range")
@SerializedName(ApiConstants.START_IP) @Param(description="the start ip of the VLAN IP range")
private String startIp;
@SerializedName("endip") @Param(description="the end ip of the VLAN IP range")
@SerializedName(ApiConstants.END_IP) @Param(description="the end ip of the VLAN IP range")
private String endIp;
@SerializedName("networkid") @Param(description="the network id of vlan range")
@SerializedName(ApiConstants.NETWORK_ID) @Param(description="the network id of vlan range")
private Long networkId;
public Long getId() {
return id;
}
@SerializedName(ApiConstants.PROJECT_ID) @Param(description="the project id of the vlan range")
private Long projectId;
@SerializedName(ApiConstants.PROJECT) @Param(description="the project name of the vlan range")
private String projectName;
public void setId(Long id) {
this.id = id;
}
public Boolean getForVirtualNetwork() {
return forVirtualNetwork;
}
public void setForVirtualNetwork(Boolean forVirtualNetwork) {
this.forVirtualNetwork = forVirtualNetwork;
}
public Long getZoneId() {
return zoneId;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public String getVlan() {
return vlan;
}
public void setVlan(String vlan) {
this.vlan = vlan;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getDomainId() {
return domainId;
}
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getPodName() {
return podName;
}
public void setPodName(String podName) {
this.podName = podName;
}
public String getGateway() {
return gateway;
}
public void setGateway(String gateway) {
this.gateway = gateway;
}
public String getNetmask() {
return netmask;
}
public void setNetmask(String netmask) {
this.netmask = netmask;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStartIp() {
return startIp;
}
public void setStartIp(String startIp) {
this.startIp = startIp;
}
public String getEndIp() {
return endIp;
}
public void setEndIp(String endIp) {
this.endIp = endIp;
}
public Long getNetworkId() {
return networkId;
}
public void setNetworkId(Long networkId) {
this.networkId = networkId;
}
@Override
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
@Override
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@ -19,7 +19,9 @@ package com.cloud.event;
import java.util.Date;
public interface Event {
import com.cloud.acl.ControlledEntity;
public interface Event extends ControlledEntity{
public enum State {
Created,
Scheduled,

View File

@ -207,6 +207,8 @@ public class EventTypes {
public static final String EVENT_PROJECT_CREATE = "PROJECT.CREATE";
public static final String EVENT_PROJECT_UPDATE = "PROJECT.UPDATE";
public static final String EVENT_PROJECT_DELETE = "PROJECT.DELETE";
public static final String EVENT_PROJECT_ACTIVATE = "PROJECT.ACTIVATE";
public static final String EVENT_PROJECT_SUSPEND = "PROJECT.SUSPEND";
public static final String EVENT_PROJECT_ACCOUNT_ADD = "PROJECT.ACCOUNT.ADD";
public static final String EVENT_PROJECT_ACCOUNT_REMOVE = "PROJECT.ACCOUNT.REMOVE";
}

View File

@ -22,7 +22,7 @@ import java.util.Date;
import com.cloud.domain.PartOf;
public interface Project extends PartOf{
public enum State {Active, Inactive, Suspended}
public enum State {Active, Disabled, Suspended}
String getDisplayText();

View File

@ -2,7 +2,9 @@ package com.cloud.projects;
import java.util.List;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.projects.ProjectAccount.Role;
import com.cloud.user.Account;
@ -36,7 +38,7 @@ public interface ProjectService {
*/
Project getProject(long id);
List<? extends Project> listProjects(Long id, String name, String displayText, String accountName, Long domainId, String keyword, Long startIndex, Long pageSize);
List<? extends Project> listProjects(Long id, String name, String displayText, String state, String accountName, Long domainId, String keyword, Long startIndex, Long pageSize);
ProjectAccount assignAccountToProject(Project project, long accountId, Role accountRole);
@ -50,7 +52,7 @@ public interface ProjectService {
Project updateProject(long id, String displayText, String newOwnerName);
boolean addAccountToProject(long projectId, String accountName);
boolean addAccountToProject(long projectId, String accountName, String email);
boolean deleteAccountFromProject(long projectId, String accountName);
@ -58,5 +60,9 @@ public interface ProjectService {
List<? extends ProjectInvitation> listProjectInvitations(Long projectId, String accountName, Long domainId, String state, boolean activeOnly, Long startIndex, Long pageSizeVal);
boolean joinProject(long projectId, String accountName);
boolean joinProject(long projectId, String accountName, String token);
Project activateProject(long projectId);
Project suspendProject(long projectId) throws ConcurrentOperationException, ResourceUnavailableException;
}

View File

@ -269,6 +269,8 @@ listSSHKeyPairs=com.cloud.api.commands.ListSSHKeyPairsCmd;15
createProject=com.cloud.api.commands.CreateProjectCmd;15
deleteProject=com.cloud.api.commands.DeleteProjectCmd;15
updateProject=com.cloud.api.commands.UpdateProjectCmd;15
activateProject=com.cloud.api.commands.ActivateProjectCmd;15
suspendProject=com.cloud.api.commands.SuspendProjectCmd;15
listProjects=com.cloud.api.commands.ListProjectsCmd;15
addAccountToProject=com.cloud.api.commands.AddAccountToProjectCmd;15
deleteAccountFromProject=com.cloud.api.commands.DeleteAccountFromProjectCmd;15

View File

@ -405,13 +405,11 @@ public class ApiResponseHelper implements ResponseGenerator {
if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Account) {
Account accountTemp = ApiDBUtils.findAccountById(resourceCount.getOwnerId());
if (accountTemp != null) {
resourceCountResponse.setAccountName(accountTemp.getAccountName());
resourceCountResponse.setDomainId(accountTemp.getDomainId());
resourceCountResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
populateAccount(resourceCountResponse, accountTemp.getId());
populateDomain(resourceCountResponse, accountTemp.getDomainId());
}
} else if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Domain) {
resourceCountResponse.setDomainId(resourceCount.getOwnerId());
resourceCountResponse.setDomainName(ApiDBUtils.findDomainById(resourceCount.getOwnerId()).getName());
populateDomain(resourceCountResponse, resourceCount.getOwnerId());
}
resourceCountResponse.setResourceType(Integer.valueOf(resourceCount.getType().getOrdinal()).toString());
@ -629,9 +627,8 @@ public class ApiResponseHelper implements ResponseGenerator {
vlanResponse.setNetworkId(vlan.getNetworkId());
Account owner = ApiDBUtils.getVlanAccount(vlan.getId());
if (owner != null) {
vlanResponse.setAccountName(owner.getAccountName());
vlanResponse.setDomainId(owner.getDomainId());
vlanResponse.setDomainName(ApiDBUtils.findDomainById(owner.getDomainId()).getName());
populateAccount(vlanResponse, owner.getId());
populateDomain(vlanResponse, owner.getDomainId());
}
vlanResponse.setObjectName("vlan");
@ -1475,12 +1472,9 @@ public class ApiResponseHelper implements ResponseGenerator {
isoResponse.setCreated(iso.getCreated());
isoResponse.setChecksum(iso.getChecksum());
isoResponse.setPasswordEnabled(false);
Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
if (owner != null) {
isoResponse.setAccountName(owner.getAccountName());
isoResponse.setDomainId(owner.getDomainId());
isoResponse.setDomainName(ApiDBUtils.findDomainById(owner.getDomainId()).getName());
}
populateOwner(isoResponse, iso);
isoResponse.setObjectName("iso");
isoResponses.add(isoResponse);
return isoResponses;
@ -1529,15 +1523,8 @@ public class ApiResponseHelper implements ResponseGenerator {
isoResponse.setOsTypeId(-1L);
isoResponse.setOsTypeName("");
}
// add account ID and name
Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
if (owner != null) {
isoResponse.setAccountName(owner.getAccountName());
isoResponse.setDomainId(owner.getDomainId());
// TODO: implement
isoResponse.setDomainName(ApiDBUtils.findDomainById(owner.getDomainId()).getName());
}
populateOwner(isoResponse, iso);
Account account = UserContext.current().getCaller();
boolean isAdmin = false;
@ -1592,12 +1579,8 @@ public class ApiResponseHelper implements ResponseGenerator {
netGrpResponse.setId(networkGroup.getId());
netGrpResponse.setName(networkGroup.getName());
netGrpResponse.setDescription(networkGroup.getDescription());
netGrpResponse.setAccountName(networkGroup.getAccountName());
populateOwner(netGrpResponse, networkGroup);
netGrpResponse.setDomainId(networkGroup.getDomainId());
netGrpResponse.setDomainName(ApiDBUtils.findDomainById(networkGroup.getDomainId()).getName());
List<IngressRuleResultObject> ingressRules = networkGroup.getIngressRules();
if ((ingressRules != null) && !ingressRules.isEmpty()) {
@ -1639,12 +1622,10 @@ public class ApiResponseHelper implements ResponseGenerator {
@Override
public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) {
SecurityGroupResponse response = new SecurityGroupResponse();
Account account = ApiDBUtils.findAccountById(group.getAccountId());
populateOwner(response, group);
response.setAccountName(account.getAccountName());
response.setDomainId(group.getDomainId());
response.setDescription(group.getDescription());
response.setDomainName(ApiDBUtils.findDomainById(group.getDomainId()).getName());
response.setId(group.getId());
response.setName(group.getName());
@ -1721,16 +1702,16 @@ public class ApiResponseHelper implements ResponseGenerator {
@Override
public EventResponse createEventResponse(Event event) {
EventResponse responseEvent = new EventResponse();
responseEvent.setAccountName(event.getAccountName());
responseEvent.setCreated(event.getCreateDate());
responseEvent.setDescription(event.getDescription());
responseEvent.setDomainId(event.getDomainId());
responseEvent.setEventType(event.getType());
responseEvent.setId(event.getId());
responseEvent.setLevel(event.getLevel());
responseEvent.setParentId(event.getStartId());
responseEvent.setState(event.getState());
responseEvent.setDomainName(ApiDBUtils.findDomainById(event.getDomainId()).getName());
populateOwner(responseEvent, event);
User user = ApiDBUtils.findUserById(event.getUserId());
if (user != null) {
responseEvent.setUsername(user.getUsername());
@ -1998,10 +1979,9 @@ public class ApiResponseHelper implements ResponseGenerator {
account = ApiDBUtils.findAccountById(securityGroup.getAccountId());
securiytGroupAccounts.put(securityGroup.getAccountId(), account);
}
response.setAccountName(account.getAccountName());
response.setDomainId(account.getDomainId());
response.setDomainName(ApiDBUtils.findDomainById(securityGroup.getDomainId()).getName());
populateAccount(response, account.getId());
populateDomain(response, account.getDomainId());
List<IngressRuleResponse> responses = new ArrayList<IngressRuleResponse>();
for (IngressRule ingressRule : ingressRules) {
@ -2068,9 +2048,9 @@ public class ApiResponseHelper implements ResponseGenerator {
securiytGroupAccounts.put(securityGroup.getAccountId(), account);
}
response.setAccountName(account.getAccountName());
response.setDomainId(account.getDomainId());
response.setDomainName(ApiDBUtils.findDomainById(securityGroup.getDomainId()).getName());
populateAccount(response, account.getId());
populateDomain(response, account.getDomainId());
List<EgressRuleResponse> responses = new ArrayList<EgressRuleResponse>();
for (EgressRule egressRule : egressRules) {
@ -2258,6 +2238,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setId(project.getId());
response.setName(project.getName());
response.setDisplaytext(project.getDisplayText());
response.setState(project.getState().toString());
Domain domain = ApiDBUtils.findDomainById(project.getDomainId());
response.setDomainId(domain.getId());
@ -2384,9 +2365,11 @@ public class ApiResponseHelper implements ResponseGenerator {
sgr.setId(sgd.getId());
sgr.setName(sgd.getName());
sgr.setDescription(sgd.getDescription());
sgr.setAccountName(sgd.getAccountName());
sgr.setDomainId(sgd.getDomainId());
sgr.setDomainName(sgd.getDomainName());
Account account = ApiDBUtils.findAccountByNameDomain(sgd.getAccountName(), sgd.getDomainId());
populateAccount(sgr, account.getId());
populateDomain(sgr, sgd.getDomainId());
sgr.setObjectName(sgd.getObjectName());
securityGroupResponse.add(sgr);
}
@ -2425,7 +2408,7 @@ public class ApiResponseHelper implements ResponseGenerator {
}
private void populateOwner(ControlledEntityResponse response, ControlledEntity object) {
Account account = ApiDBUtils.findAccountById(object.getAccountId());
Account account = ApiDBUtils.findAccountByIdIncludingRemoved(object.getAccountId());
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
//find the project
@ -2442,7 +2425,7 @@ public class ApiResponseHelper implements ResponseGenerator {
}
private void populateAccount(ControlledEntityResponse response, long accountId) {
Account account = ApiDBUtils.findAccountById(accountId);
Account account = ApiDBUtils.findAccountByIdIncludingRemoved(accountId);
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
//find the project
Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
@ -2497,9 +2480,15 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setProjectName(ApiDBUtils.findProjectById(invite.getProjectId()).getName());
response.setInvitationState(invite.getState().toString());
Account account = ApiDBUtils.findAccountById(invite.getAccountId());
response.setAccountName(account.getAccountName());
populateDomain(response, account.getDomainId());
if (invite.getAccountId() != null) {
Account account = ApiDBUtils.findAccountById(invite.getAccountId());
response.setAccountName(account.getAccountName());
} else {
response.setEmail(invite.getEmail());
}
populateDomain(response, invite.getDomainId());
response.setObjectName("projectinvitation");
return response;

View File

@ -30,15 +30,16 @@ import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.ListResponse;
import com.cloud.projects.Project;
import com.cloud.server.ManagementServerExt;
import com.cloud.server.api.response.UsageRecordResponse;
import com.cloud.usage.UsageTypes;
import com.cloud.usage.UsageVO;
import com.cloud.user.Account;
@Implementation(description="Lists usage records for accounts", responseObject=UsageRecordResponse.class)
public class GetUsageRecordsCmd extends BaseListCmd {
@ -65,6 +66,9 @@ public class GetUsageRecordsCmd extends BaseListCmd {
@Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.LONG, description="List usage records for the specified account")
private Long accountId;
@Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="List usage records for specified project")
private Long projectId;
@Parameter(name=ApiConstants.TYPE, type=CommandType.LONG, description="List usage records for the specified usage type")
private Long usageType;
@ -95,6 +99,10 @@ public class GetUsageRecordsCmd extends BaseListCmd {
public Long getUsageType() {
return usageType;
}
public Long getProjectId() {
return projectId;
}
/////////////////////////////////////////////////////
/////////////// Misc parameters ///////////////////
@ -213,10 +221,20 @@ public class GetUsageRecordsCmd extends BaseListCmd {
UsageRecordResponse usageRecResponse = new UsageRecordResponse();
if (usageRecordGeneric instanceof UsageVO) {
UsageVO usageRecord = (UsageVO)usageRecordGeneric;
usageRecResponse.setAccountName(ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId()).getAccountName());
usageRecResponse.setAccountId(usageRecord.getAccountId());
usageRecResponse.setDomainId(usageRecord.getDomainId());
Account account = ApiDBUtils.findAccountByIdIncludingRemoved(usageRecord.getAccountId());
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
//find the project
Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
usageRecResponse.setProjectId(project.getId());
usageRecResponse.setProjectName(project.getName());
} else {
usageRecResponse.setAccountId(account.getId());
usageRecResponse.setAccountName(account.getAccountName());
}
usageRecResponse.setDomainId(usageRecord.getDomainId());
usageRecResponse.setZoneId(usageRecord.getZoneId());
usageRecResponse.setDescription(usageRecord.getDescription());
usageRecResponse.setUsage(usageRecord.getUsageDisplay());

View File

@ -289,7 +289,14 @@ public enum Config {
DefaultMaxProjectVolumes("Project Defaults", ManagementServer.class, Long.class, "max.project.volumes", "20", "The default maximum number of volumes that can be created for a project", null),
ProjectInviteRequired("Project Defaults", ManagementServer.class, Boolean.class, "project.invite.required", "false", "If invitation confirmation is required when add account to project. Default value is false", null),
ProjectInvitationExpirationTime("Project Defaults", ManagementServer.class, Long.class, "project.invite.timeout", "86400", "Invitation expiration time (in seconds). Default is 1 day - 86400 seconds", null);
ProjectInvitationExpirationTime("Project Defaults", ManagementServer.class, Long.class, "project.invite.timeout", "86400", "Invitation expiration time (in seconds). Default is 1 day - 86400 seconds", null),
ProjectEmailSender("Project Defaults", ManagementServer.class, String.class, "project.email.sender", null, "Sender of project invitation email (will be in the From header of the email)", null),
ProjectSMTPHost("Project Defaults", ManagementServer.class, String.class, "project.smtp.host", null, "SMTP hostname used for sending out email project invitations", null),
ProjectSMTPPassword("Project Defaults", ManagementServer.class, String.class, "project.smtp.password", null, "Password for SMTP authentication (applies only if project.smtp.useAuth is true)", null),
ProjectSMTPPort("Project Defaults", ManagementServer.class, Integer.class, "project.smtp.port", "465", "Port the SMTP server is listening on", null),
ProjectSMTPUseAuth("Project Defaults", ManagementServer.class, String.class, "project.smtp.useAuth", null, "If true, use SMTP authentication when sending emails", null),
ProjectSMTPUsername("Project Defaults", ManagementServer.class, String.class, "project.smtp.username", null, "Username for SMTP authentication (applies only if project.smtp.useAuth is true)", null);
private final String _category;
private final Class<?> _componentClass;

View File

@ -110,6 +110,8 @@ import com.cloud.offering.ServiceOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.org.Grouping;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
@ -202,6 +204,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
CapacityDao _capacityDao;
@Inject
ResourceLimitService _resourceLimitMgr;
@Inject
ProjectManager _projectMgr;
// FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
protected static final DataCenterLinkLocalIpAddressDaoImpl _LinkLocalIpAllocDao = ComponentLocator.inject(DataCenterLinkLocalIpAddressDaoImpl.class);
@ -1932,11 +1936,25 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
Boolean forVirtualNetwork = cmd.isForVirtualNetwork();
Long networkId = cmd.getNetworkID();
String networkVlanId = null;
// If an account name and domain ID are specified, look up the account
//projectId and accountName can't be specified together
String accountName = cmd.getAccountName();
Long projectId = cmd.getProjectId();
Long domainId = cmd.getDomainId();
Account account = null;
if (projectId != null) {
if (accountName != null) {
throw new InvalidParameterValueException("Account and projectId are mutually exclusive");
}
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
account = _accountMgr.getAccount(project.getProjectAccountId());
}
if ((accountName != null) && (domainId != null)) {
account = _accountDao.findActiveAccount(accountName, domainId);
if (account == null) {

View File

@ -17,11 +17,21 @@
*/
package com.cloud.projects;
import java.io.UnsupportedEncodingException;
import java.sql.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import javax.ejb.Local;
import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
@ -36,9 +46,11 @@ import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.projects.Project.State;
import com.cloud.projects.ProjectAccount.Role;
import com.cloud.projects.dao.ProjectAccountDao;
@ -51,6 +63,7 @@ import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.UserContext;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.DB;
@ -60,11 +73,16 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.sun.mail.smtp.SMTPMessage;
import com.sun.mail.smtp.SMTPSSLTransport;
import com.sun.mail.smtp.SMTPTransport;
@Local(value = { ProjectService.class, ProjectManager.class })
public class ProjectManagerImpl implements ProjectManager, Manager{
public static final Logger s_logger = Logger.getLogger(ProjectManagerImpl.class);
private String _name;
private EmailInvite _emailInvite;
@Inject
private DomainDao _domainDao;
@ -98,7 +116,25 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
Map<String, String> configs = _configDao.getConfiguration(params);
_invitationRequired = Boolean.valueOf(configs.get(Config.ProjectInviteRequired.key()));
_invitationTimeOut = Long.valueOf(configs.get(Config.ProjectInvitationExpirationTime.key()));
// set up the email system for project invitations
String smtpHost = configs.get("project.smtp.host");
int smtpPort = NumbersUtil.parseInt(configs.get("project.smtp.port"), 25);
String useAuthStr = configs.get("project.smtp.useAuth");
boolean useAuth = ((useAuthStr == null) ? false : Boolean.parseBoolean(useAuthStr));
String smtpUsername = configs.get("project.smtp.username");
String smtpPassword = configs.get("project.smtp.password");
String emailSender = configs.get("project.email.sender");
String smtpDebugStr = configs.get("project.smtp.debug");
boolean smtpDebug = false;
if (smtpDebugStr != null) {
smtpDebug = Boolean.parseBoolean(smtpDebugStr);
}
_emailInvite = new EmailInvite(smtpHost, smtpPort, useAuth, smtpUsername, smtpPassword, emailSender, smtpDebug);
return true;
}
@ -171,7 +207,8 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_DELETE, eventDescription = "deleting project", async = true)
@DB
public boolean deleteProject (long projectId) {
Account caller = UserContext.current().getCaller();
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
ProjectVO project= getProject(projectId);
//verify input parameters
@ -184,45 +221,57 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
//mark project as inactive first, so you can't add resources to it
Transaction txn = Transaction.currentTxn();
txn.start();
s_logger.debug("Marking project id=" + projectId + " with state " + State.Inactive + " as a part of project delete...");
project.setState(State.Inactive);
s_logger.debug("Marking project id=" + projectId + " with state " + State.Disabled + " as a part of project delete...");
project.setState(State.Disabled);
boolean updateResult = _projectDao.update(projectId, project);
_resourceLimitMgr.decrementResourceCount(project.getProjectAccountId(), ResourceType.project);
txn.commit();
if (updateResult) {
if (!cleanupProject(project, null, null)) {
if (!cleanupProject(project, _accountDao.findById(caller.getId()), ctx.getCallerUserId())) {
s_logger.warn("Failed to cleanup project's id=" + projectId + " resources, not removing the project yet");
return false;
} else {
return _projectDao.remove(projectId);
}
} else {
s_logger.warn("Failed to mark the project id=" + projectId + " with state " + State.Inactive);
s_logger.warn("Failed to mark the project id=" + projectId + " with state " + State.Disabled);
return false;
}
}
@DB
private boolean cleanupProject(Project project, AccountVO caller, Long callerUserId) {
boolean result=true;
//Unassign all users from the project
s_logger.debug("Unassigning all accounts from project " + project + " as a part of project cleanup...");
List<? extends ProjectAccount> projectAccounts = _projectAccountDao.listByProjectId(project.getId());
for (ProjectAccount projectAccount : projectAccounts) {
result = result && unassignAccountFromProject(projectAccount.getProjectId(), projectAccount.getAccountId());
}
if (result) {
s_logger.debug("Accounts are unassign successfully from project " + project + " as a part of project cleanup...");
}
boolean result=true;
//Delete project's account
AccountVO account = _accountDao.findById(project.getProjectAccountId());
s_logger.debug("Deleting projects " + project + " internal account id=" + account.getId() + " as a part of project cleanup...");
result = result && _accountMgr.deleteAccount(account, callerUserId, caller);
if (result) {
//Unassign all users from the project
Transaction txn = Transaction.currentTxn();
txn.start();
s_logger.debug("Unassigning all accounts from project " + project + " as a part of project cleanup...");
List<? extends ProjectAccount> projectAccounts = _projectAccountDao.listByProjectId(project.getId());
for (ProjectAccount projectAccount : projectAccounts) {
result = result && unassignAccountFromProject(projectAccount.getProjectId(), projectAccount.getAccountId());
}
s_logger.debug("Removing all invitations for the project " + project + " as a part of project cleanup...");
_projectInvitationDao.cleanupInvitations(project.getId());
txn.commit();
if (result) {
s_logger.debug("Accounts are unassign successfully from project " + project + " as a part of project cleanup...");
}
} else {
s_logger.warn("Failed to cleanup project's internal account");
}
return result;
}
@ -248,7 +297,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
@Override
public List<? extends Project> listProjects(Long id, String name, String displayText, String accountName, Long domainId, String keyword, Long startIndex, Long pageSize) {
public List<? extends Project> listProjects(Long id, String name, String displayText, String state, String accountName, Long domainId, String keyword, Long startIndex, Long pageSize) {
Account caller = UserContext.current().getCaller();
Long accountId = null;
String path = null;
@ -314,6 +363,10 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
sc.addAnd("accountId", Op.EQ, accountId);
}
if (state != null) {
sc.addAnd("state", Op.EQ, state);
}
if (keyword != null) {
SearchCriteria<ProjectVO> ssc = _projectDao.createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
@ -438,7 +491,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
@Override
public boolean addAccountToProject(long projectId, String accountName) {
public boolean addAccountToProject(long projectId, String accountName, String email) {
Account caller = UserContext.current().getCaller();
//check that the project exists
@ -449,30 +502,26 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
//check that account-to-add exists
Account account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId());
if (account == null) {
throw new InvalidParameterValueException("Unable to find account name=" + accountName + " in domain id=" + project.getDomainId());
}
//verify permissions
_accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject);
//Check if the account already added to the project
ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId());
if (projectAccount != null) {
s_logger.debug("Account " + accountName + " already added to the project id=" + projectId);
return true;
Account account = null;
if (accountName != null) {
account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId());
if (account == null) {
throw new InvalidParameterValueException("Unable to find account name=" + accountName + " in domain id=" + project.getDomainId());
}
//verify permissions
_accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject);
//Check if the account already added to the project
ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId());
if (projectAccount != null) {
s_logger.debug("Account " + accountName + " already added to the project id=" + projectId);
return true;
}
}
if (_invitationRequired) {
//TODO - token based registration
if (generateInvitation(projectId, account.getId()) != null) {
return true;
} else {
s_logger.warn("Failed to generate invitation for account " + accountName + " to project id=" + projectId);
return false;
}
return inviteAccountToProject(project, account, email);
} else {
if (assignAccountToProject(project, account.getId(), ProjectAccount.Role.Regular) != null) {
return true;
@ -483,6 +532,30 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
}
private boolean inviteAccountToProject(Project project, Account account, String email) {
if (account != null) {
if (createAccountInvitation(project, account.getId()) != null) {
return true;
} else {
s_logger.warn("Failed to generate invitation for account " + account.getAccountName() + " to project id=" + project);
return false;
}
}
if (email != null) {
//generate the token
String token = generateToken(10);
if (generateTokenBasedInvitation(project, email, token) != null) {
return true;
} else {
s_logger.warn("Failed to generate invitation for email " + email + " to project id=" + project);
return false;
}
}
return false;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACCOUNT_REMOVE, eventDescription = "removing account from project")
public boolean deleteAccountFromProject(long projectId, String accountName) {
@ -557,13 +630,13 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
return _projectAccountDao.search(sc, searchFilter);
}
public ProjectInvitation generateInvitation(long projectId, Long accountId) {
public ProjectInvitation createAccountInvitation(Project project, Long accountId) {
//verify if the invitation was already generated
ProjectInvitationVO invite = _projectInvitationDao.findPendingByAccountIdProjectId(accountId, projectId);
ProjectInvitationVO invite = _projectInvitationDao.findPendingByAccountIdProjectId(accountId, project.getId());
if (invite != null) {
if (_projectInvitationDao.isActive(invite.getId(), _invitationTimeOut)) {
throw new InvalidParameterValueException("There is already a pending invitation for account id=" + accountId + " to the project id=" + projectId);
throw new InvalidParameterValueException("There is already a pending invitation for account id=" + accountId + " to the project id=" + project);
} else {
if (invite.getState() == ProjectInvitation.State.Pending) {
expireInvitation(invite);
@ -571,7 +644,33 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
}
return _projectInvitationDao.persist(new ProjectInvitationVO(projectId, accountId, _accountMgr.getAccount(accountId).getDomainId(), null, null));
return _projectInvitationDao.persist(new ProjectInvitationVO(project.getId(), accountId, project.getDomainId(), null, null));
}
public ProjectInvitation generateTokenBasedInvitation(Project project, String email, String token) {
//verify if the invitation was already generated
ProjectInvitationVO invite = _projectInvitationDao.findPendingByEmailAndProjectId(email, project.getId());
if (invite != null) {
if (_projectInvitationDao.isActive(invite.getId(), _invitationTimeOut)) {
throw new InvalidParameterValueException("There is already a pending invitation for email=" + email + " to the project id=" + project);
} else {
if (invite.getState() == ProjectInvitation.State.Pending) {
expireInvitation(invite);
}
}
}
ProjectInvitation projectInvitation = _projectInvitationDao.persist(new ProjectInvitationVO(project.getId(), null, project.getDomainId(), email, token));
try {
_emailInvite.sendInvite(token, email, project.getId());
} catch (Exception ex){
s_logger.warn("Failed to send project id=" + project + " invitation to the email " + email + "; removing the invitation record from the db", ex);
_projectInvitationDao.remove(projectInvitation.getId());
return null;
}
return projectInvitation;
}
private boolean expireInvitation(ProjectInvitationVO invite) {
@ -656,7 +755,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
@Override @DB
public boolean joinProject(long projectId, String accountName) {
public boolean joinProject(long projectId, String accountName, String token) {
Account caller = UserContext.current().getCaller();
Long accountId = null;
boolean result = true;
@ -683,7 +782,13 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
}
//check that invitation exists
ProjectInvitationVO invite = _projectInvitationDao.findPendingByAccountIdProjectId(accountId, projectId);
ProjectInvitationVO invite = null;
if (token == null) {
invite = _projectInvitationDao.findPendingByAccountIdProjectId(accountId, projectId);
} else {
invite = _projectInvitationDao.findPendingByTokenAndProjectId(token, projectId);
}
if (invite != null) {
if (!_projectInvitationDao.isActive(invite.getId(), _invitationTimeOut)) {
expireInvitation(invite);
@ -721,4 +826,172 @@ public class ProjectManagerImpl implements ProjectManager, Manager{
public List<Long> listPermittedProjectAccounts(long accountId) {
return _projectAccountDao.listPermittedAccountIds(accountId);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACTIVATE, eventDescription = "activating project")
public Project activateProject(long projectId) {
Account caller = UserContext.current().getCaller();
//check that the project exists
ProjectVO project = getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find the project id=" + projectId);
}
//verify permissions
_accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject);
//allow project activation only when it's in Suspended state
Project.State currentState = project.getState();
if (currentState == State.Active) {
s_logger.debug("The project id=" + projectId + " is already active, no need to activate it again");
return project;
}
if (currentState != State.Suspended) {
throw new InvalidParameterValueException("Can't activate the project in " + currentState + " state");
}
project.setState(Project.State.Active);
_projectDao.update(projectId, project);
return _projectDao.findById(projectId);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_SUSPEND, eventDescription = "suspending project", async = true)
public Project suspendProject (long projectId) throws ConcurrentOperationException, ResourceUnavailableException {
Account caller = UserContext.current().getCaller();
ProjectVO project= getProject(projectId);
//verify input parameters
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
_accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject);
if (suspendProject(project)) {
s_logger.debug("Successfully suspended project id=" + projectId);
return _projectDao.findById(projectId);
} else {
throw new CloudRuntimeException("Failed to suspend project id=" + projectId);
}
}
private boolean suspendProject(ProjectVO project) throws ConcurrentOperationException, ResourceUnavailableException{
s_logger.debug("Marking project " + project + " with state " + State.Suspended + " as a part of project suspend...");
project.setState(State.Suspended);
boolean updateResult = _projectDao.update(project.getId(), project);
if (updateResult) {
long projectAccountId = project.getProjectAccountId();
if (!_accountMgr.disableAccount(projectAccountId)) {
s_logger.warn("Failed to suspend all project's " + project + " resources; the resources will be suspended later by background thread");
}
} else {
throw new CloudRuntimeException("Failed to mark the project " + project + " with state " + State.Suspended);
}
return true;
}
public static String generateToken(int length) {
String charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rand = new Random(System.currentTimeMillis());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int pos = rand.nextInt(charset.length());
sb.append(charset.charAt(pos));
}
return sb.toString();
}
class EmailInvite {
private Session _smtpSession;
private final String _smtpHost;
private int _smtpPort = -1;
private boolean _smtpUseAuth = false;
private final String _smtpUsername;
private final String _smtpPassword;
private final String _emailSender;
public EmailInvite(String smtpHost, int smtpPort, boolean smtpUseAuth, final String smtpUsername, final String smtpPassword, String emailSender, boolean smtpDebug) {
_smtpHost = smtpHost;
_smtpPort = smtpPort;
_smtpUseAuth = smtpUseAuth;
_smtpUsername = smtpUsername;
_smtpPassword = smtpPassword;
_emailSender = emailSender;
if (_smtpHost != null) {
Properties smtpProps = new Properties();
smtpProps.put("mail.smtp.host", smtpHost);
smtpProps.put("mail.smtp.port", smtpPort);
smtpProps.put("mail.smtp.auth", ""+smtpUseAuth);
if (smtpUsername != null) {
smtpProps.put("mail.smtp.user", smtpUsername);
}
smtpProps.put("mail.smtps.host", smtpHost);
smtpProps.put("mail.smtps.port", smtpPort);
smtpProps.put("mail.smtps.auth", "" + smtpUseAuth);
if (smtpUsername != null) {
smtpProps.put("mail.smtps.user", smtpUsername);
}
if ((smtpUsername != null) && (smtpPassword != null)) {
_smtpSession = Session.getInstance(smtpProps, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(smtpUsername, smtpPassword);
}
});
} else {
_smtpSession = Session.getInstance(smtpProps);
}
_smtpSession.setDebug(smtpDebug);
} else {
_smtpSession = null;
}
}
public void sendInvite(String token, String email, long projectId) throws MessagingException, UnsupportedEncodingException {
if (_smtpSession != null) {
InternetAddress address = null;
if (email != null) {
try {
address= new InternetAddress(email, email);
} catch (Exception ex) {
s_logger.error("Exception creating address for: " + email, ex);
}
}
String content = "You've been invited to join the CloudStack project id=" + projectId + ". Please use token " + token + " to complete registration";
SMTPMessage msg = new SMTPMessage(_smtpSession);
msg.setSender(new InternetAddress(_emailSender, _emailSender));
msg.setFrom(new InternetAddress(_emailSender, _emailSender));
msg.addRecipient(RecipientType.TO, address);
msg.setSubject("You are invited to join the cloud stack project id=" + projectId);
msg.setSentDate(new Date(System.currentTimeMillis() >> 10));
msg.setContent(content, "text/plain");
msg.saveChanges();
SMTPTransport smtpTrans = null;
if (_smtpUseAuth) {
smtpTrans = new SMTPSSLTransport(_smtpSession, new URLName("smtp", _smtpHost, _smtpPort, null, _smtpUsername, _smtpPassword));
} else {
smtpTrans = new SMTPTransport(_smtpSession, new URLName("smtp", _smtpHost, _smtpPort, null, _smtpUsername, _smtpPassword));
}
smtpTrans.connect();
smtpTrans.sendMessage(msg, msg.getAllRecipients());
smtpTrans.close();
}
}
}
}

View File

@ -50,16 +50,16 @@ public class ProjectVO implements Project{
@Column(name="project_account_id")
long projectAccountId;
@Column(name="state")
@Enumerated(value=EnumType.STRING)
private State state;
@Column(name=GenericDao.CREATED_COLUMN)
private Date created;
@Column(name=GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name="state")
@Enumerated(value=EnumType.STRING)
private State state;
protected ProjectVO(){
}
@ -68,7 +68,7 @@ public class ProjectVO implements Project{
this.displayText = displayText;
this.projectAccountId = projectAccountId;
this.domainId = domainId;
this.state = State.Inactive;
this.state = State.Active;
}
@Override

View File

@ -17,6 +17,9 @@
*/
package com.cloud.projects.dao;
import java.util.List;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectVO;
import com.cloud.utils.db.GenericDao;
@ -27,5 +30,7 @@ public interface ProjectDao extends GenericDao<ProjectVO, Long>{
Long countProjectsForDomain(long domainId);
ProjectVO findByProjectAccountId(long projectAccountId);
List<ProjectVO> listByState(Project.State state);
}

View File

@ -1,9 +1,13 @@
package com.cloud.projects.dao;
import java.util.List;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectInvitationVO;
import com.cloud.projects.ProjectVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
@ -24,6 +28,7 @@ public class ProjectDaoImpl extends GenericDaoBase<ProjectVO, Long> implements P
AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("domainId", AllFieldsSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("projectAccountId", AllFieldsSearch.entity().getProjectAccountId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.done();
CountByDomain = createSearchBuilder(Long.class);
@ -75,4 +80,12 @@ public class ProjectDaoImpl extends GenericDaoBase<ProjectVO, Long> implements P
return findOneBy(sc);
}
@Override
public List<ProjectVO> listByState(Project.State state) {
SearchCriteria<ProjectVO> sc = AllFieldsSearch.create();
sc.setParameters("state", state);
return listBy(sc);
}
}

View File

@ -27,4 +27,7 @@ public interface ProjectInvitationDao extends GenericDao<ProjectInvitationVO, Lo
List<ProjectInvitationVO> listExpiredInvitations();
boolean expirePendingInvitations(long timeOut);
boolean isActive(long id, long timeout);
ProjectInvitationVO findPendingByEmailAndProjectId(String email, long projectId);
ProjectInvitationVO findPendingByTokenAndProjectId(String token, long projectId);
void cleanupInvitations(long projectId);
}

View File

@ -26,6 +26,8 @@ public class ProjectInvitationDaoImpl extends GenericDaoBase<ProjectInvitationVO
AllFieldsSearch.and("created", AllFieldsSearch.entity().getCreated(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("projectAccountId", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("email", AllFieldsSearch.entity().getEmail(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("token", AllFieldsSearch.entity().getToken(), SearchCriteria.Op.EQ);
AllFieldsSearch.done();
InactiveSearch = createSearchBuilder();
@ -95,5 +97,33 @@ public class ProjectInvitationDaoImpl extends GenericDaoBase<ProjectInvitationVO
return false;
}
}
@Override
public ProjectInvitationVO findPendingByEmailAndProjectId(String email, long projectId) {
SearchCriteria<ProjectInvitationVO> sc = AllFieldsSearch.create();
sc.setParameters("email", email);
sc.setParameters("projectId", projectId);
sc.setParameters("state", State.Pending);
return findOneBy(sc);
}
@Override
public ProjectInvitationVO findPendingByTokenAndProjectId(String token, long projectId) {
SearchCriteria<ProjectInvitationVO> sc = AllFieldsSearch.create();
sc.setParameters("token", token);
sc.setParameters("projectId", projectId);
sc.setParameters("state", State.Pending);
return findOneBy(sc);
}
@Override
public void cleanupInvitations(long projectId) {
SearchCriteria<ProjectInvitationVO> sc = AllFieldsSearch.create();
sc.setParameters("projectId", projectId);
int numberRemoved = remove(sc);
s_logger.debug("Removed " + numberRemoved + " invitations for project id=" + projectId);
}
}

View File

@ -31,6 +31,7 @@ import com.cloud.api.commands.GetUsageRecordsCmd;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.projects.Project;
import com.cloud.server.api.response.UsageTypeResponse;
import com.cloud.usage.UsageJobVO;
import com.cloud.usage.UsageTypes;
@ -102,12 +103,24 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man
Long domainId = cmd.getDomainId();
String accountName = cmd.getAccountName();
Account userAccount = null;
Account account = (Account)UserContext.current().getCaller();
Account caller = (Account)UserContext.current().getCaller();
Long usageType = cmd.getUsageType();
Long projectId = cmd.getProjectId();
if (projectId != null) {
if (accountId != null) {
throw new InvalidParameterValueException("Projectid and accountId can't be specified together");
}
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
accountId = project.getProjectAccountId();
}
//if accountId is not specified, use accountName and domainId
if ((accountId == null) && (accountName != null) && (domainId != null)) {
if (_domainDao.isChildDomain(account.getDomainId(), domainId)) {
if (_domainDao.isChildDomain(caller.getDomainId(), domainId)) {
Filter filter = new Filter(AccountVO.class, "id", Boolean.FALSE, null, null);
List<AccountVO> accounts = _accountDao.listAccounts(accountName, domainId, filter);
if(accounts.size() > 0){
@ -127,13 +140,13 @@ public class ManagementServerExtImpl extends ManagementServerImpl implements Man
//If accountId couldn't be found using accountName and domainId, get it from userContext
if(accountId == null){
accountId = account.getId();
accountId = caller.getId();
//List records for all the accounts if the caller account is of type admin.
//If account_id or account_name is explicitly mentioned, list records for the specified account only even if the caller is of type admin
if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){
if(caller.getType() == Account.ACCOUNT_TYPE_ADMIN){
isAdmin = true;
}
s_logger.debug("Account details not available. Using userContext accountId: "+accountId);
s_logger.debug("Account details not available. Using userContext accountId: " + accountId);
}
Date startDate = cmd.getStartDate();

View File

@ -1137,8 +1137,12 @@ public class ManagementServerImpl implements ManagementServer {
Long networkId = cmd.getNetworkId();
Boolean forVirtual = cmd.getForVirtualNetwork();
String vlanType = null;
Long projectId = cmd.getProjectId();
if (accountName != null && domainId != null) {
if (projectId != null) {
throw new InvalidParameterValueException("Account and projectId can't be specified together");
}
Account account = _accountDao.findActiveAccount(accountName, domainId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
@ -1154,6 +1158,15 @@ public class ManagementServerImpl implements ManagementServer {
vlanType = VlanType.DirectAttached.toString();
}
}
//set project information
if (projectId != null) {
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
accountId = project.getProjectAccountId();
}
Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
@ -1599,33 +1612,49 @@ public class ManagementServerImpl implements ManagementServer {
@Override
public List<EventVO> searchForEvents(ListEventsCmd cmd) {
Account account = UserContext.current().getCaller();
Long accountId = null;
Account caller = UserContext.current().getCaller();
List<Long> permittedAccounts = new ArrayList<Long>();
boolean isAdmin = false;
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long projectId = cmd.getProjectId();
if ((account == null) || isAdmin(account.getType())) {
if ((caller == null) || isAdmin(caller.getType())) {
isAdmin = true;
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
if ((caller != null) && !_domainDao.isChildDomain(caller.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
}
if (accountName != null) {
Account userAccount = _accountDao.findAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
permittedAccounts.add(userAccount.getId());
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
domainId = ((caller == null) ? DomainVO.ROOT_DOMAIN : caller.getDomainId());
}
} else {
accountId = account.getId();
permittedAccounts.add(caller.getId());
}
//set project information
if (projectId != null) {
permittedAccounts.clear();
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
throw new InvalidParameterValueException("Account " + caller + " can't access project id=" + projectId);
}
permittedAccounts.add(project.getProjectAccountId());
} else if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL){
permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
}
Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());
@ -1650,7 +1679,7 @@ public class ManagementServerImpl implements ManagementServer {
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
@ -1658,7 +1687,7 @@ public class ManagementServerImpl implements ManagementServer {
sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);
if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
if ((permittedAccounts.isEmpty()) && (accountName == null) && (domainId != null) && isAdmin) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
@ -1682,8 +1711,8 @@ public class ManagementServerImpl implements ManagementServer {
sc.setParameters("levelEQ", level);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
if (!permittedAccounts.isEmpty()) {
sc.setParameters("accountId", permittedAccounts.toArray());
} else if (domainId != null) {
if (accountName != null) {
sc.setParameters("domainIdEQ", domainId);

View File

@ -21,18 +21,29 @@ package com.cloud.server.api.response;
import com.cloud.api.ApiConstants;
import com.cloud.api.response.BaseResponse;
import com.cloud.api.response.ControlledEntityResponse;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class UsageRecordResponse extends BaseResponse {
@SuppressWarnings("unused")
public class UsageRecordResponse extends BaseResponse implements ControlledEntityResponse{
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the user account name")
private String accountName;
@SerializedName(ApiConstants.ACCOUNT_ID) @Param(description="the user account Id")
private Long accountId;
@SerializedName(ApiConstants.PROJECT_ID) @Param(description="the project id of the ipaddress")
private Long projectId;
@SerializedName(ApiConstants.PROJECT) @Param(description="the project name of the address")
private String projectName;
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID number")
private Long domainId;
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain the public IP address is associated with")
private String domainName;
@SerializedName(ApiConstants.ZONE_ID) @Param(description="the zone ID number")
private Long zoneId;
@ -88,163 +99,84 @@ public class UsageRecordResponse extends BaseResponse {
@SerializedName("issourcenat") @Param(description="source Nat flag for IPAddress")
private Boolean isSourceNat;
public String getAccountName() {
return accountName;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public Long getDomainId() {
return domainId;
}
@Override
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
public Long getZoneId() {
return zoneId;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
public Integer getUsageType() {
return usageType;
}
public void setUsageType(Integer usageType) {
this.usageType = usageType;
}
public String getRawUsage() {
return rawUsage;
}
public void setRawUsage(String rawUsage) {
this.rawUsage = rawUsage;
}
public Long getVirtualMachineId() {
return virtualMachineId;
}
public void setVirtualMachineId(Long virtualMachineId) {
this.virtualMachineId = virtualMachineId;
}
public String getVmName() {
return vmName;
}
public void setVmName(String vmName) {
this.vmName = vmName;
}
public Long getServiceOfferingId() {
return serviceOfferingId;
}
public void setServiceOfferingId(Long serviceOfferingId) {
this.serviceOfferingId = serviceOfferingId;
}
public Long getTemplateId() {
return templateId;
}
public void setTemplateId(Long templateId) {
this.templateId = templateId;
}
public Long getUsageId() {
return usageId;
}
public void setUsageId(Long usageId) {
this.usageId = usageId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Long getSize() {
return size;
}
public void setSize(Long size) {
this.size = size;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getAssignedDate() {
return assignedDate;
}
public void setAssignedDate(String assignedDate) {
this.assignedDate = assignedDate;
}
public String getReleasedDate() {
return releasedDate;
}
public void setReleasedDate(String releasedDate) {
this.releasedDate = releasedDate;
}
@ -252,8 +184,19 @@ public class UsageRecordResponse extends BaseResponse {
public void setSourceNat(Boolean isSourceNat) {
this.isSourceNat = isSourceNat;
}
@Override
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public Boolean isSourceNat() {
return isSourceNat;
@Override
public void setProjectName(String projectName) {
this.projectName = projectName;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
}

View File

@ -80,6 +80,7 @@ import com.cloud.network.security.dao.SecurityGroupDao;
import com.cloud.network.vpn.RemoteAccessVpnService;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectManager;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.storage.StorageManager;
import com.cloud.storage.VMTemplateVO;
@ -180,6 +181,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
private DomainManager _domainMgr;
@Inject
private ProjectManager _projectMgr;
@Inject
private ProjectDao _projectDao;
private Adapters<UserAuthenticator> _userAuthenticators;
@ -414,7 +417,6 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
}
return cleanupAccount(account, callerUserId, caller);
}
@Override
@ -1154,7 +1156,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
List<AccountVO> disabledAccounts = _accountDao.findCleanupsForDisabledAccounts();
s_logger.info("Found " + disabledAccounts.size() + " disabled accounts to cleanup");
for (AccountVO account : disabledAccounts) {
s_logger.debug("Cleaning up " + account.getId());
s_logger.debug("Disabling account " + account.getId());
try {
if (disableAccount(account.getId())) {
account.setNeedsCleanup(false);
@ -1176,13 +1178,30 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
s_logger.debug("Removing inactive domain id=" + domainId);
_domainMgr.removeDomain(domainId);
} else {
s_logger.debug("Can't remove inactive domain id=" + domainId + " as it has accounts that need clenaup");
s_logger.debug("Can't remove inactive domain id=" + domainId + " as it has accounts that need cleanup");
}
} catch (Exception e) {
s_logger.error("Skipping due to error on domain " + domainId, e);
}
}
//cleanup inactive projects
List<? extends Project> inactiveProjects = _projectDao.listByState(Project.State.Disabled);
s_logger.info("Found " + inactiveProjects.size() + " disabled projects to cleanup");
for (Project project : inactiveProjects) {
try {
Account projectAccount = getAccount(project.getProjectAccountId());
if (projectAccount == null) {
s_logger.debug("Removing inactive project id=" + project.getId());
_projectMgr.deleteProject(project.getId());
} else {
s_logger.debug("Can't remove disabled project " + project + " as it has non removed account id=" + project.getId());
}
} catch (Exception e) {
s_logger.error("Skipping due to error on project " + project, e);
}
}
} catch (Exception e) {
s_logger.error("Exception ", e);
} finally {

View File

@ -1709,7 +1709,10 @@ CREATE TABLE `cloud`.`project_invitations` (
PRIMARY KEY (`id`),
CONSTRAINT `fk_project_invitations__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_project_invitations__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_project_invitations__project_id` FOREIGN KEY(`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE
CONSTRAINT `fk_project_invitations__project_id` FOREIGN KEY(`project_id`) REFERENCES `projects`(`id`) ON DELETE CASCADE,
UNIQUE (`project_id`, `account_id`),
UNIQUE (`project_id`, `email`),
UNIQUE (`project_id`, `token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -85,6 +85,13 @@ INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-serv
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.invite.required', 'false', 'If invitation confirmation is required when add account to project. Default value is false');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.invite.timeout', '86400', 'Invitation expiration time (in seconds). Default is 1 day - 86400 seconds');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.email.sender', null, 'Sender of project invitation email (will be in the From header of the email).');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.smtp.host', null, 'SMTP hostname used for sending out email project invitations');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.smtp.password', null, 'Password for SMTP authentication (applies only if project.smtp.useAuth is true)');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.smtp.port', '465', 'Port the SMTP server is listening on');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.smtp.useAuth', null, 'If true, use SMTP authentication when sending emails');
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'project.smtp.username', null, 'Username for SMTP authentication (applies only if project.smtp.useAuth is true)');
ALTER TABLE `cloud`.`domain_router` ADD COLUMN `template_version` varchar(100) COMMENT 'template version' AFTER role;
ALTER TABLE `cloud`.`domain_router` ADD COLUMN `scripts_version` varchar(100) COMMENT 'scripts version' AFTER template_version;