cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t..@apache.org
Subject [01/50] [abbrv] git commit: updated refs/heads/marvin_refactor to 30e2971
Date Fri, 12 Apr 2013 11:58:34 GMT
Updated Branches:
  refs/heads/marvin_refactor 2a9906424 -> 30e297134


More API changes


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1e205a3d
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1e205a3d
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1e205a3d

Branch: refs/heads/marvin_refactor
Commit: 1e205a3d0b8856ae6329930076dd77575e38fda6
Parents: 119c5ce
Author: Prachi Damle <prachi@cloud.com>
Authored: Wed Feb 27 14:27:02 2013 -0800
Committer: Prachi Damle <prachi@cloud.com>
Committed: Thu Apr 11 13:22:30 2013 -0700

----------------------------------------------------------------------
 .../apache/cloudstack/affinity/AffinityGroup.java  |   15 ++
 .../cloudstack/affinity/AffinityGroupResponse.java |  139 +++++++++++++++
 .../cloudstack/affinity/AffinityGroupService.java  |   54 ++++++
 .../apache/cloudstack/api/ResponseGenerator.java   |   18 +--
 .../user/affinitygroup/CreateAffinityGroupCmd.java |  126 +++++++++++++
 server/src/com/cloud/api/ApiResponseHelper.java    |   62 ++++++-
 .../affinity/AffinityGroupServiceImpl.java         |   94 ++++++++++
 .../cloudstack/affinity/AffinityGroupVMMapVO.java  |   74 ++++++++
 .../cloudstack/affinity/AffinityGroupVO.java       |  107 +++++++++++
 .../cloudstack/affinity/dao/AffinityGroupDao.java  |   30 +++
 .../affinity/dao/AffinityGroupDaoImpl.java         |   97 ++++++++++
 .../affinity/dao/AffinityGroupVMMapDao.java        |   43 +++++
 .../affinity/dao/AffinityGroupVMMapDaoImpl.java    |  120 +++++++++++++
 13 files changed, 960 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/api/src/org/apache/cloudstack/affinity/AffinityGroup.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroup.java b/api/src/org/apache/cloudstack/affinity/AffinityGroup.java
new file mode 100644
index 0000000..b8215a2
--- /dev/null
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroup.java
@@ -0,0 +1,15 @@
+package org.apache.cloudstack.affinity;
+
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface AffinityGroup extends ControlledEntity, InternalIdentity, Identity {
+
+    String getName();
+
+    String getDescription();
+
+    String getType();
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
new file mode 100644
index 0000000..073a82c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
@@ -0,0 +1,139 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.api.response.ControlledEntityResponse;
+import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
+
+import com.cloud.network.security.SecurityGroup;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@SuppressWarnings("unused")
+@EntityReference(value = AffinityGroup.class)
+public class AffinityGroupResponse extends BaseResponse implements ControlledEntityResponse
{
+
+    @SerializedName(ApiConstants.ID) @Param(description="the ID of the affinity group")
+    private String id;
+
+    @SerializedName(ApiConstants.NAME) @Param(description="the name of the affinity group")
+    private String name;
+
+    @SerializedName(ApiConstants.DESCRIPTION) @Param(description="the description of the
affinity group")
+    private String description;
+
+    @SerializedName(ApiConstants.ACCOUNT) @Param(description="the account owning the affinity
group")
+    private String accountName;
+
+    @SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID of the affinity
group")
+    private String domainId;
+
+    @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the affinity
group")
+    private String domainName;
+
+    @SerializedName(ApiConstants.TYPE)
+    @Param(description = "the type of the affinity group")
+    private String type;
+
+
+    public AffinityGroupResponse() {
+    }
+
+    @Override
+    public String getObjectId() {
+        return this.getId();
+    }
+
+
+    public String getId() {
+        return id;
+     }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public void setDomainId(String domainId) {
+        this.domainId = domainId;
+    }
+
+    public void setDomainName(String domainName) {
+        this.domainName = domainName;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        AffinityGroupResponse other = (AffinityGroupResponse) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        return true;
+    }
+
+    @Override
+    public void setProjectId(String projectId) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setProjectName(String projectName) {
+        // TODO Auto-generated method stub
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
new file mode 100644
index 0000000..8323176
--- /dev/null
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
@@ -0,0 +1,54 @@
+package org.apache.cloudstack.affinity;
+
+import java.util.List;
+
+public interface AffinityGroupService {
+
+    /**
+     * Creates an affinity/anti-affinity group for the given account/domain.
+     *
+     * @param account
+     * @param domainId
+     * @param name
+     * @param type
+     * @param description
+     * @return AffinityGroup
+     */
+
+    AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName,
+            String affinityGroupType, String description);
+
+    /**
+     * Creates an affinity/anti-affinity group.
+     *
+     * @param affinityGroupId
+     * @param account
+     * @param domainId
+     * @param affinityGroupName
+     * @param vmId
+     */
+    void deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String
affinityGroupName, Long vmId);
+
+    /**
+     * Lists Affinity Groups
+     *
+     * @param account
+     * @param domainId
+     * @param affinityGroupId
+     * @param affinityGroupName
+     * @param affinityGroupType
+     * @param vmId
+     * @return
+     */
+    List<AffinityGroup> listAffinityGroups(String account, Long domainId, Long affinityGroupId,
+            String affinityGroupName, String affinityGroupType, Long vmId);
+
+
+    /**
+     * List group types available in deployment
+     *
+     * @return
+     */
+    List<String> listAffinityGroupTypes();
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/api/src/org/apache/cloudstack/api/ResponseGenerator.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index d1e1302..f09f8ae 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -20,8 +20,8 @@ import java.text.DecimalFormat;
 import java.util.EnumSet;
 import java.util.List;
 
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
 import org.apache.cloudstack.api.response.AccountResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
@@ -138,7 +138,6 @@ import com.cloud.org.Cluster;
 import com.cloud.projects.Project;
 import com.cloud.projects.ProjectAccount;
 import com.cloud.projects.ProjectInvitation;
-import com.cloud.region.ha.GlobalLoadBalancerRule;
 import com.cloud.server.ResourceTag;
 import com.cloud.storage.*;
 import com.cloud.storage.snapshot.SnapshotPolicy;
@@ -153,15 +152,7 @@ import com.cloud.vm.Nic;
 import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.snapshot.VMSnapshot;
 import com.cloud.vm.VirtualMachine;
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
 import org.apache.cloudstack.api.response.*;
-import org.apache.cloudstack.region.Region;
-
-import java.text.DecimalFormat;
-import java.util.EnumSet;
-import java.util.List;
 
 public interface ResponseGenerator {
     UserResponse createUserResponse(UserAccount user);
@@ -384,12 +375,15 @@ public interface ResponseGenerator {
     GuestOSResponse createGuestOSResponse(GuestOS os);
 
     SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule sched);
-    
+
     UsageRecordResponse createUsageResponse(Usage usageRecord);
 
     TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor);
     VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot);
+
     NicSecondaryIpResponse createSecondaryIPToNicResponse(String ip,
             Long nicId, Long networkId);
     public NicResponse createNicResponse(Nic result);
+
+    AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
new file mode 100644
index 0000000..c38bcff
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
@@ -0,0 +1,126 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.affinitygroup;
+
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description
= "Creates an affinity/anti-affinity group")
+public class CreateAffinityGroupCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName());
+
+    private static final String s_name = "createaffinitygroupresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description
= "an account for the affinity group. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, description
= "domainId of the account owning the affinity group", entityType = DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description =
"optional description of the affinity group")
+    private String description;
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description
= "name of the affinity group")
+    private String affinityGroupName;
+
+    @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description
= "Type of the affinity group from the available affinity/anti-affinity group types")
+    private String affinityGroupType;
+
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getAffinityGroupName() {
+        return affinityGroupName;
+    }
+
+    public String getAffinityGroupType() {
+        return affinityGroupType;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = UserContext.current().getCaller();
+        if ((account == null) || isAdmin(account.getType())) {
+            if ((domainId != null) && (accountName != null)) {
+                Account userAccount = _responseGenerator.findAccountByNameDomain(accountName,
domainId);
+                if (userAccount != null) {
+                    return userAccount.getId();
+                }
+            }
+        }
+
+        if (account != null) {
+            return account.getId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
+                                          // command to SYSTEM so ERROR events
+                                          // are tracked
+    }
+
+    @Override
+    public void execute() {
+        AffinityGroup group = _affinityGroupService.createAffinityGroup(accountName, domainId,
affinityGroupName,
+                affinityGroupType, description);
+        if (group != null) {
+            AffinityGroupResponse response = _responseGenerator.createAffinityGroupResponse(group);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create affinity
group:"
+                    + affinityGroupName);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 93b755a..7b23b3b 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -270,8 +270,41 @@ import com.cloud.vm.NicVO;
 import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.Type;
+<<<<<<< HEAD
 import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.snapshot.VMSnapshot;
+=======
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
+import org.apache.cloudstack.api.response.*;
+import org.apache.cloudstack.region.Region;
+import org.apache.cloudstack.usage.Usage;
+import org.apache.cloudstack.usage.UsageService;
+import org.apache.cloudstack.usage.UsageTypes;
+import com.cloud.vm.VmStats;
+import com.cloud.vm.dao.UserVmData;
+import com.cloud.vm.dao.UserVmData.NicData;
+import com.cloud.vm.dao.UserVmData.SecurityGroupData;
+import com.cloud.vm.snapshot.VMSnapshot;
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.response.VMSnapshotResponse;
+import org.apache.log4j.Logger;
+
+import java.text.DecimalFormat;
+import java.util.*;
+
+import javax.inject.Inject;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+>>>>>>> More API changes
 
 @Component
 public class ApiResponseHelper implements ResponseGenerator {
@@ -439,7 +472,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         vmSnapshotResponse.setCreated(vmSnapshot.getCreated());
         vmSnapshotResponse.setDescription(vmSnapshot.getDescription());
         vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName());
-        UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId());        
+        UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId());
         if(vm!=null)
             vmSnapshotResponse.setVirtualMachineid(vm.getUuid());
         if(vmSnapshot.getParent() != null)
@@ -449,7 +482,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         vmSnapshotResponse.setObjectName("vmsnapshot");
         return vmSnapshotResponse;
     }
-    
+
     @Override
     public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
         SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
@@ -546,7 +579,7 @@ public class ApiResponseHelper implements ResponseGenerator {
 
         vlanResponse.setIp6Gateway(vlan.getIp6Gateway());
         vlanResponse.setIp6Cidr(vlan.getIp6Cidr());
-        
+
         String ip6Range = vlan.getIp6Range();
         if (ip6Range != null) {
         	String[] range = ip6Range.split("-");
@@ -2250,7 +2283,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         if (((network.getCidr()) != null) && (network.getNetworkCidr() == null))
{
             response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
         }
-        
+
         response.setIp6Gateway(network.getIp6Gateway());
         response.setIp6Cidr(network.getIp6Cidr());
 
@@ -2445,7 +2478,7 @@ public class ApiResponseHelper implements ResponseGenerator {
 
         List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
         response.setCidrList(StringUtils.join(cidrs, ","));
-        
+
         if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) {
             IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
             response.setPublicIpAddressId(ip.getId());
@@ -3476,7 +3509,7 @@ public class ApiResponseHelper implements ResponseGenerator {
 		return usageRecResponse;
 	}
 
-	
+
     public String getDateStringInternal(Date inputDate) {
         if (inputDate == null) return null;
 
@@ -3560,7 +3593,7 @@ public class ApiResponseHelper implements ResponseGenerator {
 
         return sb.toString();
     }
-    
+
     @Override
     public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) {
         Map<String, String> tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId());
@@ -3620,4 +3653,19 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setIsDefault(result.isDefaultNic());
         return response;
     }
+
+    @Override
+    public AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group) {
+
+        AffinityGroupResponse response = new AffinityGroupResponse();
+
+        Account account = ApiDBUtils.findAccountById(group.getAccountId());
+        response.setAccountName(account.getAccountName());
+        response.setName(group.getName());
+        response.setType(group.getType());
+        response.setDescription(group.getDescription());
+        // response.setDomainId(account.)
+
+        return response;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
new file mode 100644
index 0000000..eee3e6f
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
@@ -0,0 +1,94 @@
+package org.apache.cloudstack.affinity;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.log4j.Logger;
+
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.UserContext;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.component.ManagerBase;
+
+@Local(value = { AffinityGroupService.class })
+public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService,
Manager {
+
+    public static final Logger s_logger = Logger.getLogger(AffinityGroupServiceImpl.class);
+    private String _name;
+
+    @Inject
+    AccountManager _accountMgr;
+
+    @Inject
+    AffinityGroupDao _affinityGroupDao;
+
+    @Override
+    public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName,
+            String affinityGroupType, String description) {
+
+        Account caller = UserContext.current().getCaller();
+        Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
+
+        if (_affinityGroupDao.isNameInUse(owner.getId(), owner.getDomainId(), affinityGroupName))
{
+            throw new InvalidParameterValueException("Unable to create affinity group, a
group with name "
+                    + affinityGroupName
+                    + " already exisits.");
+        }
+
+        AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType,
description, domainId,
+                owner.getId());
+        _affinityGroupDao.persist(group);
+
+        return group;
+    }
+
+    @Override
+    public void deleteAffinityGroup(Long affinityGroupId, String account, Long domainId,
String affinityGroupName,
+            Long vmId) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public List<AffinityGroup> listAffinityGroups(String account, Long domainId, Long
affinityGroupId,
+            String affinityGroupName, String affinityGroupType, Long vmId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<String> listAffinityGroupTypes() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean configure(final String name, final Map<String, Object> params) throws
ConfigurationException {
+        _name = name;
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java
new file mode 100644
index 0000000..5401b4a
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.PrimaryKeyJoinColumn;
+import javax.persistence.SecondaryTable;
+import javax.persistence.SecondaryTables;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = ("affinity_group_vm_map"))
+@SecondaryTables({ @SecondaryTable(name = "affinity_group", pkJoinColumns = { @PrimaryKeyJoinColumn(name
= "affinity_group_id", referencedColumnName = "id") }) })
+public class AffinityGroupVMMapVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "affinity_group_id")
+    private long affinityGroupId;
+
+    @Column(name = "instance_id")
+    private long instanceId;
+
+    @Column(name = "name", table = "affinity_group", insertable = false, updatable = false)
+    private String groupName;
+
+    public AffinityGroupVMMapVO() {
+    }
+
+    public AffinityGroupVMMapVO(long affinityGroupId, long instanceId) {
+        this.affinityGroupId = affinityGroupId;
+        this.instanceId = instanceId;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public long getAffinityGroupId() {
+        return affinityGroupId;
+    }
+
+
+    public long getInstanceId() {
+        return instanceId;
+    }
+
+
+    public String getGroupName() {
+        return groupName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java
new file mode 100644
index 0000000..fab3835
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+@Entity
+@Table(name = ("affinity_group"))
+public class AffinityGroupVO implements AffinityGroup {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "type")
+    private String type;
+
+    @Column(name = "description")
+    private String description;
+
+    @Column(name = "domain_id")
+    private long domainId;
+
+    @Column(name = "account_id")
+    private long accountId;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    public AffinityGroupVO() {
+    	this.uuid = UUID.randomUUID().toString();
+    }
+
+    public AffinityGroupVO(String name, String type, String description, long domainId, long
accountId) {
+        this.name = name;
+        this.description = description;
+        this.domainId = domainId;
+        this.accountId = accountId;
+    	this.uuid = UUID.randomUUID().toString();
+        this.type = type;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public long getDomainId() {
+        return domainId;
+    }
+
+    @Override
+    public long getAccountId() {
+        return accountId;
+    }
+
+    @Override
+    public String getUuid() {
+    	return this.uuid;
+    }
+
+    public void setUuid(String uuid) {
+    	this.uuid = uuid;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
new file mode 100644
index 0000000..296e7b1
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.affinity.AffinityGroupVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface AffinityGroupDao extends GenericDao<AffinityGroupVO, Long> {
+    List<AffinityGroupVO> listByAccountId(long accountId);
+    boolean isNameInUse(Long accountId, Long domainId, String name);
+    AffinityGroupVO findByAccountAndName(Long accountId, String name);
+    List<AffinityGroupVO> findByAccountAndNames(Long accountId, String... names);
+    int removeByAccountId(long accountId); 
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
new file mode 100644
index 0000000..bfa06c7
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
@@ -0,0 +1,97 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+import org.apache.cloudstack.affinity.AffinityGroupVO;
+import org.springframework.stereotype.Component;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value = { AffinityGroupDao.class })
+public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long> implements
AffinityGroupDao {
+    private SearchBuilder<AffinityGroupVO> AccountIdSearch;
+    private SearchBuilder<AffinityGroupVO> AccountIdNameSearch;
+    private SearchBuilder<AffinityGroupVO> AccountIdNamesSearch;
+
+
+    protected AffinityGroupDaoImpl() {
+        AccountIdSearch = createSearchBuilder();
+        AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        AccountIdSearch.done();
+
+        AccountIdNameSearch = createSearchBuilder();
+        AccountIdNameSearch.and("accountId", AccountIdNameSearch.entity().getAccountId(),
SearchCriteria.Op.EQ);
+        AccountIdNameSearch.and("name", AccountIdNameSearch.entity().getName(), SearchCriteria.Op.EQ);
+
+        AccountIdNamesSearch = createSearchBuilder();
+        AccountIdNamesSearch.and("accountId", AccountIdNamesSearch.entity().getAccountId(),
SearchCriteria.Op.EQ);
+        AccountIdNamesSearch.and("groupNames", AccountIdNamesSearch.entity().getName(), SearchCriteria.Op.IN);
+        AccountIdNameSearch.done();
+    }
+
+    @Override
+    public List<AffinityGroupVO> listByAccountId(long accountId) {
+        SearchCriteria<AffinityGroupVO> sc = AccountIdSearch.create();
+        sc.setParameters("accountId", accountId);
+        return listBy(sc);
+    }
+
+    @Override
+    public boolean isNameInUse(Long accountId, Long domainId, String name) {
+        SearchCriteria<AffinityGroupVO> sc = createSearchCriteria();
+        sc.addAnd("name", SearchCriteria.Op.EQ, name);
+        if (accountId != null) {
+            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
+        } else {
+            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
+            sc.addAnd("accountId", SearchCriteria.Op.NULL);
+        }
+
+        List<AffinityGroupVO> AffinityGroups = listBy(sc);
+        return ((AffinityGroups != null) && !AffinityGroups.isEmpty());
+    }
+
+	@Override
+    public AffinityGroupVO findByAccountAndName(Long accountId, String name) {
+        SearchCriteria<AffinityGroupVO> sc = AccountIdNameSearch.create();
+		sc.setParameters("accountId", accountId);
+		sc.setParameters("name", name);
+
+		return findOneIncludingRemovedBy(sc);
+	}
+
+	@Override
+    public List<AffinityGroupVO> findByAccountAndNames(Long accountId, String... names)
{
+        SearchCriteria<AffinityGroupVO> sc = AccountIdNamesSearch.create();
+		sc.setParameters("accountId", accountId);
+
+		sc.setParameters("groupNames", (Object [])names);
+
+		return listBy(sc);
+	}
+	@Override
+	public int removeByAccountId(long accountId) {
+        SearchCriteria<AffinityGroupVO> sc = AccountIdSearch.create();
+	    sc.setParameters("accountId", accountId);
+	    return expunge(sc);
+	}
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java
new file mode 100644
index 0000000..9841de4
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDao;
+import com.cloud.vm.VirtualMachine.State;
+
+public interface AffinityGroupVMMapDao extends GenericDao<AffinityGroupVMMapVO, Long>
{
+
+    List<AffinityGroupVMMapVO> listByInstanceId(long instanceId);
+
+    Pair<List<AffinityGroupVMMapVO>, Integer> listByInstanceId(long instanceId,
Filter filter);
+
+    List<AffinityGroupVMMapVO> listByAffinityGroup(long affinityGroupId);
+
+    List<Long> listVmIdsByAffinityGroup(long affinityGroupId);
+
+    AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId);
+
+    long countAffinityGroupsForVm(long instanceId);
+
+    int deleteVM(long instanceId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e205a3d/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
new file mode 100644
index 0000000..e9286db
--- /dev/null
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Func;
+
+@Component
+@Local(value = { AffinityGroupVMMapDao.class })
+public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMapVO, Long>
implements
+        AffinityGroupVMMapDao {
+    private SearchBuilder<AffinityGroupVMMapVO> ListByVmId;
+    private SearchBuilder<AffinityGroupVMMapVO> ListByVmIdGroupId;
+    protected GenericSearchBuilder<AffinityGroupVMMapVO, Long> CountSGForVm;
+    private GenericSearchBuilder<AffinityGroupVMMapVO, Long> ListVmIdByAffinityGroup;
+    private SearchBuilder<AffinityGroupVMMapVO> ListByAffinityGroup;
+
+    protected AffinityGroupVMMapDaoImpl() {
+        ListVmIdByAffinityGroup = createSearchBuilder(Long.class);
+        ListVmIdByAffinityGroup.and("affinityGroupId", ListVmIdByAffinityGroup.entity().getAffinityGroupId(),
+                SearchCriteria.Op.EQ);
+        ListVmIdByAffinityGroup.selectField(ListVmIdByAffinityGroup.entity().getInstanceId());
+        ListVmIdByAffinityGroup.done();
+
+        ListByAffinityGroup = createSearchBuilder();
+        ListByAffinityGroup.and("affinityGroupId", ListByAffinityGroup.entity().getAffinityGroupId(),
+                SearchCriteria.Op.EQ);
+        ListByAffinityGroup.done();
+
+        ListByVmId  = createSearchBuilder();
+        ListByVmId.and("instanceId", ListByVmId.entity().getInstanceId(), SearchCriteria.Op.EQ);
+        ListByVmId.done();
+
+        ListByVmIdGroupId  = createSearchBuilder();
+        ListByVmIdGroupId.and("instanceId", ListByVmIdGroupId.entity().getInstanceId(), SearchCriteria.Op.EQ);
+        ListByVmIdGroupId.and("affinityGroupId", ListByVmIdGroupId.entity().getAffinityGroupId(),
SearchCriteria.Op.EQ);
+        ListByVmIdGroupId.done();
+
+        CountSGForVm = createSearchBuilder(Long.class);
+        CountSGForVm.select(null, Func.COUNT, null);
+        CountSGForVm.and("vmId", CountSGForVm.entity().getInstanceId(), SearchCriteria.Op.EQ);
+        CountSGForVm.done();
+    }
+
+    @Override
+    public List<AffinityGroupVMMapVO> listByAffinityGroup(long affinityGroupId) {
+        SearchCriteria<AffinityGroupVMMapVO> sc = ListByAffinityGroup.create();
+        sc.setParameters("affinityGroupId", affinityGroupId);
+        return listBy(sc);
+    }
+
+    @Override
+    public List<AffinityGroupVMMapVO> listByInstanceId(long vmId) {
+        SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
+        sc.setParameters("instanceId", vmId);
+        return listBy(sc);
+    }
+
+    @Override
+    public Pair<List<AffinityGroupVMMapVO>, Integer> listByInstanceId(long instanceId,
Filter filter) {
+        SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
+        sc.setParameters("instanceId", instanceId);
+        return this.searchAndCount(sc, filter);
+    }
+
+    @Override
+    public int deleteVM(long instanceId) {
+        SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
+        sc.setParameters("instanceId", instanceId);
+        return super.expunge(sc);
+    }
+
+    @Override
+    public List<Long> listVmIdsByAffinityGroup(long affinityGroupId) {
+        SearchCriteria<Long> sc = ListVmIdByAffinityGroup.create();
+        sc.setParameters("affinityGroupId", affinityGroupId);
+        return customSearchIncludingRemoved(sc, null);
+    }
+
+	@Override
+    public AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId)
{
+        SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmIdGroupId.create();
+        sc.setParameters("affinityGroupId", affinityGroupId);
+        sc.setParameters("instanceId", instanceId);
+		return findOneIncludingRemovedBy(sc);
+	}
+
+	@Override
+    public long countAffinityGroupsForVm(long instanceId) {
+		SearchCriteria<Long> sc = CountSGForVm.create();
+    	sc.setParameters("vmId", instanceId);
+        return customSearch(sc, null).get(0);
+	}
+}


Mime
View raw message